spoofax_prop/trans/prop-eval-rules.str
Glen Whitney 50dce6b265 docs: Document section 5.1.2
Note still need to implement and document command-line running
  of these strategies.
2021-01-17 10:15:32 -08:00

153 lines
6.3 KiB
Plaintext

/** md
Title: Running a Strategy
## Running a Strategy
The first example of running a Stratego strategy
in the {! ../docrefs/manual.md !} is that of _evaluating_ an AST,
via the `prop-eval-rules` module in {! ../docrefs/sec4.1.md !}. This page
describes the most straightforward way to run this same strategy
in the Spoofax Eclipse IDE.
In the current project structure, Stratego transformations and strategies go in
the `trans` directory. So, you can place the Stratego code for
this module in `trans/prop-eval-rules.str`, with the following contents:
```Stratego
[End the documentation block to avoid the comment close in the code] **/
/** md [restart processing to include the code in the documentation] */
module prop-eval-rules
imports signatures/-
rules
E : Not(True()) -> False()
E : Not(False()) -> True()
E : And(True(), x) -> x
E : And(x, True()) -> x
E : And(False(), x) -> False()
E : And(x, False()) -> False()
E : Or(True(), x) -> True()
E : Or(x, True()) -> True()
E : Or(False(), x) -> x
E : Or(x, False()) -> x
E : Impl(True(), x) -> x
E : Impl(x, True()) -> True()
E : Impl(False(), x) -> True()
E : Impl(x, False()) -> Not(x)
E : Eq(False(), x) -> Not(x)
E : Eq(x, False()) -> Not(x)
E : Eq(True(), x) -> x
E : Eq(x, True()) -> x
/* [stop to avoid the open-comment in the code block] **/
/** md [conclusion of the documentation]
```
Note an important difference between this code and the `prop-eval-rules` block
in {! ../docrefs/sec4.1.md !}: here, we import `signatures/-` rather than `prop`.
That's because the Spoofax IDE automatically generates the Spoofax Propositional
Language AST signature for us, from its concrete syntax definition. (The
evaluation rules in {! ../docrefs/sec4.1.md !} also happen to be missing the
fourth `Impl` rule, but that's less material; unsurprisingly, none of the examples
given in the manual happen to rely on that rule, but we include it here for the
sake of completeness.)
As in the {! ../docrefs/manual.md !}, we need an additional module, which we can
place in `trans/prop-eval.str`, to describe the strategy by which we want
to apply the above evaluation rules and to facilitate actually invoking
the strategy on an AST. This file starts out much like its counterpart in
{! ../docrefs/sec4.1.md !}:
```Stratego
{! prop-eval.str {terminate: '^\s*$'} !}
```
So far, we've included the evaluation rules and defined a strategy `eval` to
apply them exhaustively to an AST starting with inner subterms. Now we want to
be able to "run" this strategy on an actual AST.
### Editor Services
The most straightforward mechanism to execute a Stratego transformation
in the Spoofax IDE is by use of Editor Services (ESV). ESV is actually a full
declarative language in its own right, covering syntax coloring, menu items,
hover texts, and more, and with its own
[manual](http://www.metaborg.org/en/latest/source/langdev/meta/lang/esv.html).
We will not delve into the details of ESV here, but merely provide a recipe
for using it to add an item to the "Spoofax" Eclipse menu for running Stratego.
Actually, we'll create a submenu "Manual" for our examples. It's
cleanest to put our additions in a separate ESV module, which then must be
included into the `editor/Main.esv` file, like so:
```esv
{! ../editor/Main.esv extract:
replace: ['^\s*$']
terminate: 'provider\s*:' !} [ ... rest of file suppressed for brevity. ]
```
It's just the one line `Manual` in the `imports` section that we have added. The
`editor/Manual.esv` implementing the submenu is also very simple:
```esv
{! ../editor/Manual.esv terminate: dnf !}
```
Note that the quoted string on the `action` line is the text label of the menu
item in the "Manual" submenu, and the identifier on its right-hand side is the
Stratego action to call. But note that `do-eval` is not the same identifier as
`eval` in our last Stratego file above. That's because the Stratego invocation
caused by an ESV action item has a specific, multi-item argument list, whereas
`eval` above expects only a single Spoofax Propositional Language AST to operate
on. To bridge this gap, we must add one more item to `trans/prop-eval.str`,
namely:
```Stratego
{! prop-eval.str extract: {start: '^(.*Interface.*\s*)$'} !}
```
This "do-XXX" rule is pretty much boilerplate glue between ESV and your Stratego
strategy of interest. (Note that this "glue" being used here corresponds to
what's used in the example
[Calc language project](https://github.com/MetaBorgCube/metaborg-calc),
but is slightly different from what is described in the
[Menus section](http://www.metaborg.org/en/latest/source/langdev/meta/lang/esv.html#menus)
of the ESV Manual. I am unclear on the significance of this difference or which
form is "better" -- I simply modeled this Stratego code after the code in the
working Calc repository, and all seems to be well.)
There's one last step before you can run `eval` from inside the IDE.
Editor Services has to be able to find the `do-eval` rule. You can enable that
by importing the `prop-eval` module in the main Stratego file for our language,
in this case `trans/spoofax_propositional_language.str`:
```Stratego
{! spoofax_propositional_language.str extract:
- stop: 'prop-dnf'
- start: '^(.*rule.*)$'
terminate: debug-show
!}
[ ... rest of file suppressed. ]
```
(I am unclear on what triggers ESV to use this particular Stratego file, but
in any automatically-generated Spoofax project there will be a main language
Stratego file in the `trans` directory, and that's the file from which
the rule specified in an ESV `action` has to be visible.)
Ok, with all of these elements in place, you should now be able to invoke
the `eval` rule from the "Spoofax" menu. For example, to execute the next example
from the Spoofax Tutorial/Reference
{! ../docrefs/sec4.1.md !}, navigate to the
file `syntax/examples/sec4.1_test1.spl`:
```SPL
{! ../syntax/examples/sec4.1_test1.spl !}
```
and select "Spoofax > Manual > prop-eval" from the menu bar to produce:
```
{! ../syntax/examples/sec4.1_test1.eval.aterm !}
```
You can do the same with test2:
```SPL
{! ../syntax/examples/sec4.1_test2.spl !}
```
to produce
```
{! ../syntax/examples/sec4.1_test2.eval.aterm !}
```
Both of these results match the expected output of the `eval` transformation
as shown in {! ../docrefs/sec4.1.md !} (allowing for the typo "ATom" in the
manual in the latter case).
**/