feat: Add SPT as an alternate means of running Stratego strategies

Also completed and documented Sec 4.2 of the Stratego
Tutorial/Reference manual
This commit is contained in:
Glen Whitney 2021-01-16 15:11:47 -08:00
parent 2357e1f220
commit 28a3370d03
3 changed files with 100 additions and 5 deletions

12
test/manual-suite.spt Normal file
View File

@ -0,0 +1,12 @@
module manual-suite
language Spoofax-Propositional-Language
test sec4_2_test3 [[
(r -> p & q) & p
]] run dnf to Atom("x")
test sec4_2_test3_ex [[
(r -> p & q) & p
]] run dnf to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))

View File

@ -4,6 +4,7 @@ imports
nabl2/api nabl2/api
nabl2/runtime nabl2/runtime
nabl2/shared/-
statics statics
@ -11,7 +12,9 @@ imports
rules // Analysis rules // Analysis
editor-analyze = nabl2-analyze(id) // editor-analyze = nabl2-analyze(id)
strip-indices : AnalysisResult([(r,Full(y,a,l,m,n))]) -> AnalysisResult([(r,Full(<nabl2--erase-ast-indices>y,a,l,m,n))])
editor-analyze = nabl2-analyze(id); strip-indices
rules // Debugging rules // Debugging

View File

@ -48,12 +48,92 @@ to produce
``` ```
{! ../syntax/examples/sec4.2_test3.dnf.aterm !} {! ../syntax/examples/sec4.2_test3.dnf.aterm !}
``` ```
as verified in the manual (again, modulo the"ATom" typo in the manual). as verified in the manual (again, modulo the "ATom" typo in the manual).
However, we also want to use this second example to show another method of However, we also want to use this second example to show another method of
running Stratego strategies from the Eclipse IDE. running Stratego strategies from the Eclipse IDE.
## Spoofax Testing Language ### Spoofax Testing Language
CONTINUE FROM HERE The
[Spoofax Testing Language](http://www.metaborg.org/en/latest/source/langdev/meta/lang/spt/index.html)
(SPT) is a declarative language that provides for a full range of tests
for a Spoofax language project. As such, it includes the ability to run an
arbitrary Stratego strategy on the results of parsing an arbitrary piece of
the language you're working with -- seemingly perfect for our interest in
trying our different Stratego transformations.
So, we can just take our `test3` expression above and make it a part of
an SPT test suite, which we will call `test/manual-suite.spt`:
```SPT
{! ../test/manual-suite.spt terminate: '(.*run dnf)' !}
```
Once we have saved this file, the tests run automatically. What does this mean?
The file seems to be just "sitting there;" there's no indication that anything
is happening. That's because this test we've just written **succeeds**. All we
asked is that Spoofax run the `dnf` transformation on the results of parsing
the test expression. It did that, and the transformation succeeded. So all is
well, and no output is generated.
But of course, we want to see what the _result_ of the transformation was. One
way of arranging that is to ask that SPT compare that result to a given AST.
If we use an AST like `Atom("x")` that can't possibly be the actual output
(since "x" does not occur in the input), then the error message will show
what the transformation actually produced. So we add just a bit to
`test/manual-suite.spt`:
```SPT
{! ../test/manual-suite.spt terminate: '(.*run dnf.*)$' !}
```
and now sure enough a little error symbol appears next to the test. If you hover
over it, a popup will show up, indicating that SPT was expecting `Atom("x")`,
but got... wait! What's this monstrosity?
```
Got: Or(And(Not(Atom("r"{TermIndex("test/manual-suite.spt",1)}){TermIndex
("test/manual-suite.spt",2)}),Atom("p"{TermIndex("test/manual-suite.spt",9)})
{TermIndex("test/manual-suite.spt",10)}),And(And(Atom("p"{TermIndex("test/manual-
suite.spt",3)}){TermIndex("test/manual-suite.spt",4)},Atom("q"{TermIndex
("test/manual-suite.spt",5)}){TermIndex("test/manual-suite.spt",6)}){TermIndex
("test/manual-suite.spt",7)},Atom("p"{TermIndex("test/manual-suite.spt",9)})
{TermIndex("test/manual-suite.spt",10)}))
```
Well, it is actually the result of running the `dnf` strategy on the result of
parsing ` {! ../syntax/examples/sec4.2_test3.spl !} `. It's just that Spoofax
automatically annotates every subterm of the parsed term with its location in
the input, and those annotations are carried through the Stratego
transformation. While this can be very helpful in figuring out exactly what
happened in the course of the transformation, it can also make the output
practically unreadable.
Fortunately, we can strip this annotation if we like, by modifying the
`editor-analyze` rule in `trans/analysis.str` like so:
```Stratego
{! ../trans/analysis.str terminate: Debugging!} [rest of file omitted]
```
Now rebuild the project and re-run the SPT manual suite. (You may need to
do an irrelevant edit and save of the `test/manual-suite.spt` file, or
you can select this file in the project explorer and select the menu item
"Spoofax (meta) > Run all selected tests" to pop up a convenient window of
all test results.) Now you should see the much more readable
```
Got: Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
```
in the error message for the `sec4_2_test3` test.
Of course, if you know the AST you expect to generate with your transformation,
you can also just tell SPT to compare against that, for example in our case
by adding a test to the manual suite like this:
```SPT
{! ../test/manual-suite.spt extract:
start: '(test sec4_2_test3_ex.*\n?)$'
stop: '^(.*run.*)$'
!}
```
Now if there is no error or warning on this test then you know the
`dnf` strategy produced the result shown in the `to` clause, and otherwise,
the actual result will be shown in the error popup.
**/ **/