Compare commits

...

13 Commits
master ... main

Author SHA1 Message Date
Glen Whitney ae0a798c7b docs: Update to reflect pending changes in the Spoofax Tutorial/Reference 2021-02-03 16:24:47 -08:00
Glen Whitney ba130ecb0f feat: Implement Chapter9
Also provides proper associativity on the operators, to avoid
  ambiguous parses.

  This completes all of the examples in the Spoofax Tutorial/Reference
  that use the propositional signature.
2021-01-22 09:29:57 -08:00
Glen Whitney fddc94a906 feat: Implement chapter 8 2021-01-20 19:35:07 -08:00
Glen Whitney 98bb2088e4 feat: implement Chapter 7 2021-01-20 11:05:33 -08:00
Glen Whitney 76456b2c21 feat: Add Chapter 6 2021-01-19 22:09:21 -08:00
Glen Whitney d5a19e0d69 feat: Finish Chapter 5 2021-01-19 21:00:56 -08:00
Glen Whitney a33c1585d6 feat: Implement Sec 5.3.1 tests
And put in generic documentation for all the remaining tests.
  If any particular tests need individual commentary, it can always be
  added later.
2021-01-19 19:29:48 -08:00
Glen Whitney 19076a5163 doc: document running strategies with the Sunshine jar 2021-01-19 18:34:00 -08:00
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
Glen Whitney 347afef2e5 feat: Add section 5.1.2 of manual 2021-01-17 08:43:03 -08:00
Glen Whitney 28a3370d03 feat: Add SPT as an alternate means of running Stratego strategies
Also completed and documented Sec 4.2 of the Stratego
Tutorial/Reference manual
2021-01-16 15:11:47 -08:00
Glen Whitney 2357e1f220 docs: Add section 4.2
Also update to latest revision of mkdocs semiliterate plugin. Up next:
  using SPT as an alternate means of running Stratego.
2021-01-15 09:57:30 -08:00
Glen Whitney 8536d6a469 fix: Get repository working again
The main actions taking to restore spoofax_prop to correct operation
   are not really reflected in this commit; they consisted of
   switching to a Spoofax distribution of Eclipse and
updating/rebuilding
   the project in various ways. However, all of the steps are now
   documented here, and the narrative is extended to include the
   first examples.

   Resolves #1.
2021-01-14 10:19:35 -08:00
36 changed files with 995 additions and 178 deletions

1
.gitignore vendored
View File

@ -5,6 +5,7 @@
/site
/.classpath
/.project
/.settings
/.factorypath

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spoofax_prop</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.metaborg.spoofax.eclipse.meta.builder.generatesources</name>
<triggers>clean,full,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.metaborg.spoofax.eclipse.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.metaborg.spoofax.eclipse.meta.builder.prejava</name>
<triggers>clean,full,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.metaborg.spoofax.eclipse.meta.builder.postjava</name>
<triggers>clean,full,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.metaborg.spoofax.eclipse.nature</nature>
<nature>org.metaborg.spoofax.eclipse.meta.nature</nature>
</natures>
</projectDescription>

View File

@ -1,26 +1,82 @@
Title: The Spoofax Propositional Language
Next: syntax/Spoofax-Propositional-Language.sdf3
# Stratego Transformations in the Spoofax Eclipse IDE
The Stratego Tutorial/Reference {! docrefs/manual.md !} in the official Spoofax documentation presents a comprehensive overview of the Stratego approach to abstract syntax tree (AST) transformations. It employs a running example of an abstract syntax intended to represent classical Propositional Logic, which we will dub here the "Spoofax Propositional Language." The manual introduces the concepts of rules and strategies for applying them, and then shows how both of those facilities can be created from more primitive operations of term matching and replacement. Every step of the way is illustrated with actual, working Stratego programs.
The Stratego Tutorial/Reference {! docrefs/manual.md !} in the official Spoofax
documentation presents a comprehensive overview of the Stratego approach to
abstract syntax tree (AST) transformations. It employs a running example of an
abstract syntax intended to represent classical Propositional Logic, which we
will dub here the "Spoofax Propositional Language." The manual introduces the
concepts of rules and strategies for applying them, and then shows how both
of those facilities can be created from more primitive operations of
term matching and replacement. Every step of the way is illustrated with actual,
working Stratego programs.
There are, however, two catches for a newcomer trying to learn Spoofax and Stratego for the first time:
This [Gitea repository](https://code.studioinfinity.org/glen/spoofax_prop)
provides a working implementation of most of the examples in the manual.
It can be cloned as an Eclipse project (note the git root
is at the project level rather than in the directory above the project, as may
be more common; in other words, this repository should be cloned within
an existing Eclipse workspace, rather than as the workspace itself). Within that
project, all of the examples from the Stratego Tutorial manual that employ the
propositional language (see below), starting from Section 4 on, can be executed
directly. This repository does not attempt to implement the portion of examples
dealing with an arithmetical/imperative language (except in a couple of
isolated instances in which the relevant phenomenon is recast in the
propositional language).
1. All of the examples are worked in an older framework ("Stratego/XT") which has a rather different collection of tools than the current implementation of Spoofax in the Eclipse IDE.
1. Unlike with the Calc example language used for the explication of the Syntax Definition Language SDF3, there does not seem to be any publicly available repository containing the worked examples to follow along with.
## Preliminaries
This [Gitea repository](https://code.studioinfinity.org/glen/spoofax_prop) aims to fill both gaps. It can be cloned as an Eclipse project (note the git root is at the project level rather than in the directory above the project, as may be more common; in other words, this repository should be cloned within an existing Eclipse workspace, rather than as the workspace itself). Within that project, (ultimately) every example from the Stratego Tutorial manual starting from Section 4 on can be executed directly. And this (Mkdocs-generated) documentation seeks to clarify the ways that Stratego transformations may be run in the Spoofax/Eclipse IDE environment, serving as a supplement/replacement for the portions of the manual that were specific to Stratego/XT.
I recommend working with a complete pre-built Eclipse installation of Spoofax
as provided by the Spoofax project,
for example one that you can download from their
[development release page](https://www.metaborg.org/en/latest/source/release/development.html).
Sometimes I have had difficulty getting the examples in this repository working
starting from plain Eclipse and installing Spoofax in it using the Spoofax
update site.
If at any point in using the examples things appear to stop working, and
especially if the Spoofax menu item disappears or the Spoofax menu turns into
a thin white rectangle with no items to select, try the following:
* Build the project and try again.
* Clean the workspace, and when it is done, build the project again and try
again.
* Right click on the project, select Maven > Update Project, make sure
everything is checked except "Offline" and
"Force update of Snapshots/Releases", and then click "OK". When it is done,
clean the workspace, then build the project and try again.
* If that still hasn't done it, restart (the Spoofax version of!) Eclipse and
clean the workspace, then build the project and try again.
Running with a version of Spoofax _later_ than 2.5.13 (I was using a 2.6.0
development snapshot), the Spoofax menu would always come back into proper
operation at some point in the above process.
## Abstract syntax
Let's begin by recalling the abstract syntax of the Spoofax Propositional Language (SPL), as defined at the top of {! docrefs/sec4.1.md !} of the manual. It consists of the following signature of constructors:
With the preliminaries out of the way, note that the examples in the Stratego
manual deal exclusively with Abstract Syntax Trees (ASTs). The trees used
are primarily for a language concerning propositional logic, which we dub the
Spoofax Propositional Language (SPL). It is defined
at the top of {! docrefs/sec4.1.md !} of the manual.
It consists of the following signature of constructors:
```stratego
{! src-gen/signatures/Spoofax-Propositional-Language-sig.str ---
{! src-gen/signatures/Spoofax-Propositional-Language-sig.str extract:
start: '(signature[\s]*)$'
end: '^(\s*Eq\s*:.*)'
stop: '^(\s*Eq\s*:.*)'
!}
```
<!-- /md -->
Continue reading in the latest released [SPL documentation](http://studioinfinity.org/SPL) to see how to define and run Stratego transformations on ASTs of this language.
Continue reading in the latest released
[SPL documentation](http://studioinfinity.org/SPL)
to see how to define and run Stratego transformations on ASTs of this language.
### Building the documentation
In order to build the documentation from a clone of this repository, you must
install [MkDocs](http://mkdocs.org) and the `semiliterate` plug-in for MkDocs,
which is available in
[pre-release form](https://code.studioinfinity.org/glen/mkdocs-semiliterate). Then
you can execute `mkdocs build` in the top-level directory of this project.

1
docrefs/sec4.2.md Normal file
View File

@ -0,0 +1 @@
[Section 4.3](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/04-term-rewriting.html#adding-rules-to-a-rewrite-system)

1
docrefs/sec5.1.2.md Normal file
View File

@ -0,0 +1 @@
[Section 5.1.2](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/05-rewriting-strategies.html#attempt-2-functionalization)

1
docrefs/sec6.2.md Normal file
View File

@ -0,0 +1 @@
[Section 6.2](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/06-rules-and-strategies.html#what-is-a-strategy)

View File

@ -1,7 +1,8 @@
module Manual
menus
menu: "Manual" (openeditor)
action: "prop-eval" = do-eval
menu: "Manual" (openeditor) (source)
action: "prop-eval" = do-eval
action: "prop-dnf" = do-dnf
action: "prop-dnf3" = do-dnf3
action: "prop-cnf3" = do-cnf3
action: "both-nf3" = do-dcnf

View File

@ -20,7 +20,6 @@ menus
action: "Format" = editor-format (source)
action: "Show parsed AST" = debug-show-aterm (source)
action: "Test action" = debug-show-aterm
views

View File

@ -11,6 +11,9 @@ nav:
- README.md
- syntax/Spoofax-Propositional-Language.md
- trans/prop-eval-rules.md
- trans/prop-dnf-rules.md
- trans/prop-dnf3.md
- test/manual-suite.md
theme:
name: readthedocs
markdown_extensions:
@ -18,3 +21,4 @@ markdown_extensions:
- pymdownx.superfences
- pymdownx.highlight:
use_pygments: true
- smarty

View File

@ -8,7 +8,7 @@ Title: Concrete Syntax
The current Spoofax/Eclipse IDE is oriented around individual language
projects. Therefore in order to work with ASTs of the SPL
[abstract syntax](../README.md#abstract-syntax) that we just saw, it's easiest to
define a concrete syntax for SPL, with the following SDF3 definition:
define a concrete syntax for SPL, via the following SDF3 definition:
*[SPL]: Spoofax Propositional Language
@ -34,10 +34,10 @@ context-free syntax
Prop.False = <0>
Prop.Atom = String
Prop.Not = <!<Prop>>
Prop.And = <<Prop> & <Prop>>
Prop.Or = <<Prop> | <Prop>>
Prop.Impl = [[Prop] -> [Prop]]
Prop.Eq = <<Prop> = <Prop>>
Prop.And = <<Prop> & <Prop>> {left}
Prop.Or = <<Prop> | <Prop>> {left}
Prop.Impl = [[Prop] -> [Prop]] {right}
Prop.Eq = <<Prop> = <Prop>> {non-assoc}
Prop = <(<Prop>)> {bracket}
String = ID
@ -68,7 +68,4 @@ you can visit the file `syntax/examples/sec4.1_A.spl` (or ...`_B.spl`) and from
Spoofax menu select "Syntax > Show parsed AST" to see the AST generation
in action.)
This concrete syntax actually makes it easier to construct the example
expressions used throughout the tutorial manual as examples for Stratego
processing.
**/

View File

@ -0,0 +1 @@
(r -> p & q) & p

View File

@ -0,0 +1 @@
(r -> p & q) & p

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

@ -0,0 +1,403 @@
/** md
Title: The Remaining Tests
## Programmable Rewriting Strategies
The manual then begins to discuss "programmable rewriting strategies" in
[Section 5.2](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/05-rewriting-strategies.html#programmable-rewriting-strategies)
and beyond to show how to use Stratego's various features to overcome the
difficulties with the last several examples.
The next example is in Section 5.3.1, which shows a unified treatment of
disjunctive and conjunctive normal forms that avoids the potential combinatorial
explosion of rules seen in the functionalized example. As usual, the example
Stratego module `prop-laws` is in `trans/prop-laws.str` and included in
`trans/spoofax_propositional_language.str`. Also as typical, some of the identifiers
in the module had to be changed to avoid namespace conflicts when they are all
imported into the main language module.
But after going through the previous examples, it seems that trying them is most
convenient with the Spoofax Testing Language:
* No glue transformation is needed and no ESV files need to be modified.
* It's not necessary to place the SPL expression to be tested in a separate file.
* The SPL expression, name of strategy to run, and results of that run are all
kept together (in the `test/manual-suite.spt` file).
Hence, the test cases for Section 5.3.1 and beyond, through the end of the
Tutorial/Reference Manual, are captured in this repository solely in terms
of SPT Test Cases. You can of course clone the repository and create menu items
for any of them if you want to try them that way. Just remember to add a
"glue" strategy for them as shown in the [first example](../trans/prop-eval-rules.md).
Hopefully these examples are helpful to your exploration and understanding of
Stratego -- certainly creating them was to mine.
Additional notes on particular sections or tests follow.
**/
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")))
test sec5_1_2_test1_ex [[
(r -> p & q) & p
]] run dnf3 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test sec5_1_2_test1_cnf_ex [[
(r -> p & q) & p
]] run cnf3 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test sec5_1_2_test1_both [[
(r -> p & q) & p
]] run dcnf to (Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p"))),
And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p")))
test sec5_3_1_test1_dnf_ex [[
(r -> p & q) & p
]] run dnf-laws to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test sec5_3_1_test1_cnf_ex [[
(r -> p & q) & p
]] run cnf-laws to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test sec5_3_2_eval_up_ex [[
(1 -> p & q) & p
]] run eval-up to And(And(Atom("p"),Atom("q")),Atom("p"))
test sec5_3_2_eval_down_ex [[
(1 -> p & q) & p
]] run eval-down to And(And(Atom("p"),Atom("q")),Atom("p"))
test sec5_3_2_desugar_ex [[
(1 -> p & q) & p
]] run desugar to And(Or(Not(True()),And(Atom("p"),Atom("q"))),Atom("p"))
test sec5_3_2_impl_nf_ex [[
(1 -> p & q) & p
]] run impl-nf to Impl(Impl(Impl(True(),Impl(Impl(Atom("p"),
Impl(Atom("q"),False())),
False())),
Impl(Atom("p"),False())),
False())
/** md
### Chapter 6
Many of the examples in
[Chapter 6](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/06-rules-and-strategies.html)
are in the form of interactive "Stratego shell" sessions. For this repository, we
have to convert them to rule definitions in a Stratego file (`chap6.str`) and
test cases for each of the executed examples.
Also, there are some examples for a Plus-Times signature; we transpose these
to Or-And for the sake of keeping everything within the SPL language project.
To illustrate extending a rule, we need to give the rule we're going to extend
a different identifier and add both definitions to that (otherwise our original
rule `SwapArgs` would already have been extended).
The `chap6.str` file also includes a solution to the exercise
in {! ../docrefs/sec6.2.md !}. On the other hand, it is not clear whether
the Spoofax Eclipse IDE has a "debug" operator for Stratego, or if so how
it would work within the IDE, so the repository does not
attempt to implement the "debug" example.
The remainder of the chapter (from section 6.3 on) consists of general information
about Stratego syntax and information about the Stratego compiler. As it's not
clear whether the latter applies to the Spoofax Eclipse IDE, there are no further test
cases in this repository beyond Section 6.2.
**/
test sec6_1_swap_ex [[
p | 0
]] run SwapArgs to Or(False(), Atom("p"))
test sec6_1_swap_fails [[
p & 0
]] run SwapArgs fails
test sec6_1_swap_subterm_fails [[
(1 | p) & 0
]] run SwapArgs fails
test sec6_1_swap_only_outer_ex [[
(1 | p) | 0
]] run SwapArgs to Or(False(), Or(True(), Atom("p")))
test sec6_1_swapboth_or_ex [[
p | 0
]] run SwapBoth to Or(False(), Atom("p"))
test sec6_1_swapboth_and_ex [[
p & 0
]] run SwapBoth to And(False(), Atom("p"))
test sec6_2_invoke_rule_ex [[
1 -> p
]] run DefI to Or(Not(True()), Atom("p"))
test sec6_2_innermost_ex [[
p = q
]] run dnf-laws to Or(Or(And(Not(Atom("p")),Not(Atom("q"))),
And(Not(Atom("p")),Atom("p"))),
Or(And(Atom("q"),Not(Atom("q"))),
And(Atom("q"),Atom("p"))))
test sec6_2_dnf_exercise_ex [[
p = q
]] run better-dnf to Or(And(Not(Atom("p")),Not(Atom("q"))),
And(Atom("q"),Atom("p")))
/** md
### Chapter 7
The content and style of chapter 7 are similar to chapter 6. Again, there is a
`trans/chap7.str` Stratego file defining several of the rules used in the examples
from the chapter. As before, the examples with a different signature are recast
into the SPL signature. Specifically, `Z` becomes `False`, `S(x)` becomes
`Impl(True(), x)`, and `P` becomes `Or`. (At least with these choices, all of the
transformations in the chapter remain valid in the usual semantics for the SPL
signature, even if a bit unorthodox.)
**/
test sec7_2_b_ex [[
(1 -> 0) | 0
]] run B to Or(False(), Impl(True(), False()))
test sec7_2_b_a_ex [[
(1 -> 0) | 0
]] run BthenA to Impl(True(), False())
test sec7_2_b_b_fails [[
(1 -> 0) | 0
]] run Btwice fails
test sec7_2_local_choice_fails [[
(1 -> 0) | 0
]] run maybeB-id-thenB fails
test sec7_2_seq_no_dist_over_choice_ex [[
(1 -> 0) | 0
]] run maybeBtwice-idthenB to Or(False(), Impl(True(), False()))
test sec7_3_repeat_small_ex [[
(1 -> 0) | 0
]] run repeatmaybeAB to Impl(True(), False())
test sec7_3_repeat_big_ex [[
(1 -> 1 -> 1 -> 1 -> 0) | 0
]] run repeatmaybeAB to Impl(True(), Impl(True(), Impl(True(),
Impl(True(), False()))))
/** md
### Chapter 8
This chapter is even more just a collection of interactive examples. In this
repository we just give some examples of swapping and variable scope using the
SPL signature, and some free-form examples of term wrapping and projecting.
There's no attempt to do any of the arithmetic examples because SPL does not have
an integer type.
**/
test sec8_3_firstswap_ex [[
p | 0
]] run SwapWithPat to Or(False(), Atom("p"))
test sec8_3_1_swap_ex [[
p | 0
]] run SwapAnon to Or(False(), Atom("p"))
test sec8_3_2_variablescope_fails [[
p | 0
]] run NoSwapTwice fails
test sec8_3_2_localscope_ex [[
p | 0
]] run OkSwapTwice to Or(Atom("p"), False())
test sec8_5_1_wrap_ex [[
p
]] run TermWrap to Or(Atom("p"), Not(Atom("p")))
test sec8_5_2_project_ex [[
p | !p
]] run TermProj to Atom("p")
/** md
### Chapter 9
This chapter is much more in the style of the early chapters: there are several
explicit Stratego modules, and we incorporate each one into this repository. As
before, we need to differentiate the names in some modules since they all end
up being loaded at once; but we also take advantage of the common sections of
some of the modules and re-use rather than repeat the code. In addition, the
disjunctive and conjunctive normal forms of the same test expression as used
in Chapter Five are used for test cases in `trans/manual-suite.spt`.
**/
test chap9_dnf4_ex [[
(r -> p & q) & p
]] run dnf4 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test chap9_dnf6_ex [[
(r -> p & q) & p
]] run dnf6 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test chap9_dnf7_ex [[
(r -> p & q) & p
]] run dnf7 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test chap9_cnf7_ex [[
(r -> p & q) & p
]] run cnf7 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test chap9_dnf8_ex [[
(r -> p & q) & p
]] run dnf8 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test chap9_cnf8_ex [[
(r -> p & q) & p
]] run cnf8 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test chap9_dnf9_ex [[
(r -> p & q) & p
]] run dnf9 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test chap9_cnf9_ex [[
(r -> p & q) & p
]] run cnf9 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test sec9_1_dnf10_ex [[
(r -> p & q) & p
]] run dnf10 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test sec9_1_cnf10_ex [[
(r -> p & q) & p
]] run cnf10 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
test sec9_1_disj-nf_fails [[
(r -> p & q) & p
]] run disj-nf fails
test sec9_1_conj-nf_fails [[
(r -> p & q) & p
]] run conj-nf fails
test sec9_1_disj-nf [[
(!r & p) | (p & q & p)
]] run disj-nf
test sec9_1_conj-nf [[
(!r | p) & (!r | q) & p
]] run conj-nf
test sec9_1_dnf11_ex [[
(r -> p & q) & p
]] run dnf11 to Or(And(Not(Atom("r")),Atom("p")),And(And(Atom("p"),Atom("q")),Atom("p")))
test sec9_1_cnf11_ex [[
(r -> p & q) & p
]] run cnf11 to And(And(Or(Not(Atom("r")), Atom("p")),
Or(Not(Atom("r")), Atom("q"))),
Atom("p"))
/** md
Note that this repository does not include `prop-dnf12` because at this
point the strategies there have become identical to the ones
in {! ../docrefs/sec6.2.md !} used to introduce the idea of splitting
transformations into local rewrite rules applied via a traversal strategy. So
they have already been implemented and tested above.
On the other hand, in `trans/sec9_1.str`, the repository does contain a
solution for the second exercise in
[Section 9.1.2](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/09-traversal-strategies.html#visiting-one-subterm).
**/
test sec9_1_2_second_exercise_inner_ex [[
!!p | (!!q | r)
]] run inner-soln to Or(Atom("p"), Or(Atom("q"), Atom("r")))
test sec9_1_2_second_exercise_outer_ex [[
!!p | (!!q | r)
]] run outer-soln to Impl(Not(Atom("p")), Impl(Not(Atom("q")), Atom("r")))
/* Note that the actual output of the following test matches
the inner application. However, according to the manual, it would
also be a correct implementation for it to produce
`Impl(Not(Atom("p")), Or(Atom("q"), Atom("r")))`, which could not
result from either outer or inner application.
*/
test sec9_1_2_second_exercise_random_ex [[
!!p | (!!q | r)
]] run random-soln to Atom("x")
test sec9_2_eval_bottomup_ex [[
1 & !(0 | 1)
]] run eval1 to False()
/* This test fails deliberately, to show that topdown evaluation
does not go all the way to completion.
*/
test sec9_2_eval_topdown [[
1 & !(0 | 1)
]] run eval2 to False()
test sec9_2_eval_exercise_bottomup_ex [[
(1 | 0) & (0 | 1)
]] run eval1 to True()
/* Ditto for this one.*/
test sec9_2_eval_exercise_topdown [[
(1 | 0) & (0 | 1)
]] run eval2 to True()
test sec9_2_desugar_topdown_ex [[
p = q
]] run desugar to And(Or(Not(Atom("p")),Atom("q")),Or(Not(Atom("q")),Atom("p")))
/* And ditto for this one. */
test sec9_2_desugar_bottomup [[
p = q
]] run desugar2 to And(Or(Not(Atom("p")),Atom("q")),Or(Not(Atom("q")),Atom("p")))
test sec9_2_impl-nf_repeated_ex [[
p & q
]] run impl-nf1 to Impl(Impl(Atom("p"),Impl(Atom("q"),False())),False())
/* And ditto for this one. */
test sec9_2_impl-nf_once [[
p & q
]] run impl-nf2 to Impl(Impl(Atom("p"),Impl(Atom("q"),False())),False())
/** md
On the other hand there is no solution provided for the
exercise just before
[Section 9.2.1](http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/strategoxt/09-traversal-strategies.html#cascading-transformations).
The rest of Chapter 9 and all of the remaining chapters deal
either with signatures other than SPL or
just with abstract principles, so that concludes the Stratego examples provided
in this repository.
**/

View File

@ -4,6 +4,7 @@ imports
nabl2/api
nabl2/runtime
nabl2/shared/-
statics
@ -11,7 +12,9 @@ imports
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

18
trans/chap6.str Normal file
View File

@ -0,0 +1,18 @@
module chap6
imports prop-laws prop-eval2 signatures/-
rules
SwapArgs : Or(e1,e2) -> Or(e2,e1)
SwapBoth : Or(e1,e2) -> Or(e2,e1)
SwapBoth : And(e1,e2) -> And(e2,e1)
ExMid: And(Not(x),x) -> False()
ExMid: And(x,Not(x)) -> False()
strategies
better-dnf =
innermost(DefI <+ DefE <+ ExMid <+ DAOL <+ DAOR <+ DN <+ DMA <+ DMO); eval-down

15
trans/chap7.str Normal file
View File

@ -0,0 +1,15 @@
module chap7
imports libstrategolib signatures/-
rules
A : Or(False(), x) -> x
B : Or(Impl(True(),x), y) -> Or(x, Impl(True(), y))
strategies
BthenA = B; A
Btwice = B; B
maybeB-id-thenB = (B <+ id); B
maybeBtwice-idthenB = Btwice <+ (id; B)
repeatmaybeAB = repeat(A <+ B)

12
trans/chap8.str Normal file
View File

@ -0,0 +1,12 @@
module chap8
imports signatures/-
rules
SwapWithPat = ?Or(e1,e2); !Or(e2,e1)
SwapAnon = (Or(e1,e2) -> Or(e2,e1))
NoSwapTwice = (Or(e1,e2) -> Or(e2,e1)); (Or(e1,e2) -> Or(e2,e1))
OkSwapTwice =
{e3,e4 : (Or(e3,e4) -> Or(e4,e3))}; {e3,e4 : (Or(e3,e4) -> Or(e4,e3))}
TermWrap = !Or(<id>, Not(<id>))
TermProj = ?Or(_, Not(<id>))

35
trans/prop-cnf3.str Normal file
View File

@ -0,0 +1,35 @@
module prop-cnf3
imports libstrategolib prop-dnf3 signatures/-
signature
constructors
Cnf : Prop -> Prop
CnfR : Prop -> Prop
rules
E3 : Cnf(Atom(x)) -> Atom(x)
E3 : Cnf(Not(x)) -> CnfR(Not(Cnf(x)))
E3 : Cnf(Or(x, y)) -> CnfR(Or(Cnf(x), Cnf(y)))
E3 : Cnf(And(x, y)) -> And(Cnf(x), Cnf(y))
E3 : Cnf(Impl(x, y)) -> Cnf(Not(And(x, Not(y))))
E3 : Cnf(Eq(x, y)) -> Cnf(And(Impl(x, y), Impl(y, x)))
E3 : CnfR(Not(Not(x))) -> x
E3 : CnfR(Not(Or(x, y))) -> And(Cnf(Not(x)), Cnf(Not(y)))
E3 : CnfR(Not(And(x, y))) -> Cnf(Or(Not(x), Not(y)))
D3 : CnfR(Not(x)) -> Not(x)
E3 : CnfR(Or(And(x, y), z)) -> And(Cnf(Or(x, z)), Cnf(Or(y, z)))
E3 : CnfR(Or(z, And(x, y))) -> And(Cnf(Or(z, x)), Cnf(Or(z, y)))
D3 : CnfR(Or(x, y)) -> Or(x, y)
strategies
cnf3 : x -> <make-nf> Cnf(x)
dcnf : x -> <make-nf> (Dnf(x), Cnf(x))
// Interface cnf3 strategy with editor services and file system
do-cnf3: (selected, _, _, path, project-path) -> (filename, result)
with filename := <guarantee-extension(|"cnf.aterm")> path
; result := <cnf3> selected
do-dcnf: (selected, _, _, path, project-path) -> (filename, result)
with filename := <guarantee-extension(|"dc.aterm")> path
; result := <dcnf> selected

22
trans/prop-desugar.str Normal file
View File

@ -0,0 +1,22 @@
module prop-desugar
imports libstrategolib signatures/-
rules
DefN : Not(x) -> Impl(x, False())
DefI : Impl(x, y) -> Or(Not(x), y)
DefE : Eq(x, y) -> And(Impl(x, y), Impl(y, x))
DefO1 : Or(x, y) -> Impl(Not(x), y)
DefO2 : Or(x, y) -> Not(And(Not(x), Not(y)))
DefA1 : And(x, y) -> Not(Or(Not(x), Not(y)))
DefA2 : And(x, y) -> Not(Impl(x, Not(y)))
IDefI : Or(Not(x), y) -> Impl(x, y)
IDefE : And(Impl(x, y), Impl(y, x)) -> Eq(x, y)
strategies
desugar = topdown(try(DefI <+ DefE))
impl-nf = topdown(repeat(DefN <+ DefA2 <+ DefO1 <+ DefE))

43
trans/prop-dnf-rules.str Normal file
View File

@ -0,0 +1,43 @@
/** md
Title: Running a Strategy, continued
## Disjunctive Normal Form
The next Stratego example, in {! ../docrefs/sec4.2.md !}, extends
`prop-eval-rules` to convert SPL propositions into disjunctive normal form (DNF).
As the manual notes, another way to see what the `dnf` strategy does to a given
AST is to add a Spoofax Test Language test that claims it transforms to
something that it definitely does **not** parse to, e.g.
```SPT
{! ../test/manual-suite.spt extract:
start: '\*\*[/]'
terminate: '(.*run dnf.*)$' !}
```
The difficulty is that in a standard Spoofax language project, the error popup
showing what the transformation actually does is nearly unreadable due to
a tremendous amount of annotation produced by the default static analysis process.
Since in this repository we are not actually doing any (meaningful) static
analysis, it includes a hack which makes the editor popup much more readable.
Namely, it strips the annotation, by modifying the
`editor-analyze` rule in `trans/analysis.str` like so:
```Stratego
{! ../trans/analysis.str terminate: Debugging!} [rest of file omitted]
```
**/
module prop-dnf-rules
imports prop-eval-rules
rules
E : Impl(x, y) -> Or(Not(x), y)
E : Eq(x, y) -> And(Impl(x, y), Impl(y, x))
E : Not(Not(x)) -> x
E : Not(And(x, y)) -> Or(Not(x), Not(y))
E : Not(Or(x, y)) -> And(Not(x), Not(y))
E : And(Or(x, y), z) -> Or(And(x, z), And(y, z))
E : And(z, Or(x, y)) -> Or(And(z, x), And(z, y))

9
trans/prop-dnf.str Normal file
View File

@ -0,0 +1,9 @@
module prop-dnf
imports libstrategolib prop-dnf-rules
strategies
dnf = innermost(E)
// Interface dnf strategy with editor services and file system
do-dnf: (selected, _, _, path, project-path) -> (filename, result)
with filename := <guarantee-extension(|"dnf.aterm")> path
; result := <dnf> selected

9
trans/prop-dnf10.str Normal file
View File

@ -0,0 +1,9 @@
module prop-dnf10
imports libstrategolib signatures/- prop-laws
strategies
proptr10(s) = Not(s) <+ And(s, s) <+ Or(s, s) <+ Impl(s, s) <+ Eq(s, s)
propbu10(s) = try(proptr10(propbu10(s))); s
strategies
dnf10 = propbu10(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf10))
cnf10 = propbu10(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DOAL <+ DOAR); cnf10))

6
trans/prop-dnf11.str Normal file
View File

@ -0,0 +1,6 @@
module prop-dnf11
imports libstrategolib prop-laws
strategies
dnf11 = bottomup(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf11))
cnf11 = bottomup(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DOAL <+ DOAR); cnf11))

112
trans/prop-dnf3.str Normal file
View File

@ -0,0 +1,112 @@
/** md
Title: Running a Strategy: the command line
## Functionalizing reduction rules
The {! ../docrefs/manual.md !} next goes on, in Chapter 5, to consider ways to
add the ability to also compute conjunctive normal forms (CNF) for propositional
ASTs. The rules for this form cannot simply be added to those from the prior
chapter for disjunctive normal form, as they would produce a non-terminating
rewrite system.
The first method for which working examples are provided is the method of
"functionalization" in {! ../docrefs/sec5.1.2.md !}. Although an anti-pattern
in the views of the Spoofax designers, the examples are still instructive and
of course they are implemented here.
In fact, the Stratego code
for the CNF is not given explicitly in the manual, but it consists of:
```
{! prop-cnf3.str !}
```
Note in particular we have not repeated the `make-nf` strategy from
`trans/prop-dnf3.str` here --- that's the
entire point of functionalization; we can use the same top-level reduction
scheme because the introduced function symbols keep track of what operations
are being performed. We also introduce a strategy `dcnf` for the simultaneous
construction of DNF and CNF, as noted in the manual.
Again, there are menu items and SPT cases for the `cnf3` and `dcnf` strategies
as well. All operate just as in the previous sections.
**/
module prop-dnf3
imports libstrategolib signatures/-
signature
constructors
Dnf : Prop -> Prop
DnfR : Prop -> Prop
rules
E3 : Dnf(Atom(x)) -> Atom(x)
E3 : Dnf(Not(x)) -> DnfR(Not(Dnf(x)))
E3 : Dnf(And(x, y)) -> DnfR(And(Dnf(x), Dnf(y)))
E3 : Dnf(Or(x, y)) -> Or(Dnf(x), Dnf(y))
E3 : Dnf(Impl(x, y)) -> Dnf(Or(Not(x), y))
E3 : Dnf(Eq(x, y)) -> Dnf(And(Impl(x, y), Impl(y, x)))
E3 : DnfR(Not(Not(x))) -> x
E3 : DnfR(Not(And(x, y))) -> Or(Dnf(Not(x)), Dnf(Not(y)))
E3 : DnfR(Not(Or(x, y))) -> Dnf(And(Not(x), Not(y)))
D3 : DnfR(Not(x)) -> Not(x)
E3 : DnfR(And(Or(x, y), z)) -> Or(Dnf(And(x, z)), Dnf(And(y, z)))
E3 : DnfR(And(z, Or(x, y))) -> Or(Dnf(And(z, x)), Dnf(And(z, y)))
D3 : DnfR(And(x, y)) -> And(x, y)
strategies
make-nf = innermost(E3 <+ D3)
dnf3 : x -> <make-nf> Dnf(x)
// Interface dnf3 strategy with editor services and file system
do-dnf3: (selected, _, _, path, project-path) -> (filename, result)
with filename := <guarantee-extension(|"dnf.aterm")> path
; result := <dnf3> selected
/** md
### Command-line Utilities
The Spoofax project offers an executable jar called
[Sunshine](http://www.metaborg.org/en/latest/source/release/development.html#command-line-utilities)
that allows several different Spoofax actions to be invoked from the command line.
Let's say you have downloaded it to the path `SUNSHINE_JAR`. Then you can see a
summary of the available actions with `java -jar $SUNSHINE_JAR -h`. In the
repository there's a convenience bash script `bin/spoofax-menu` you can use to
run the Sunshine jar:
```bash
{! ../bin/spoofax-menu extract:
- stop: --help
- start: ';;'
!}
```
(You can also get a usage explanation, elided from the listing above, via
`bin/spoofax-menu -h`.)
To use this, you must have a Spoofax menu item set up to run the strategy you
want, but then you can invoke it on an arbitrary file from the command line like
so:
```
spoofax_prop> export SUNSHINE_JAR=~/software/org.metaborg.sunshine2-2.6.0-20210119.175231-1.jar
spoofax_prop> export ECLIPSE_INSTALL=~/software/spoofax
spoofax_prop> export SPOOFAX_PROJECT=~/code/neweclipse/spoofax_prop
spoofax_prop> bin/spoofax-menu syntax/examples/sec5.1.2_test1.spl both-nf3
( Or(
And(Not(Atom("r")), Atom("p"))
, And(And(Atom("p"), Atom("q")), Atom("p"))
)
, And(
And(
Or(Not(Atom("r")), Atom("p"))
, Or(Not(Atom("r")), Atom("q"))
)
, Atom("p")
)
)
```
In our case, the Sunshine jar doesn't really give us any new capabilities, and
the ESV menu items still have to be set up, but it could make running examples
more convenient for you.
**/

14
trans/prop-dnf4.str Normal file
View File

@ -0,0 +1,14 @@
module prop-dnf4
imports libstrategolib prop-laws
rules
dnf4 : True() -> True()
dnf4 : False() -> False()
dnf4 : Atom(x) -> Atom(x)
dnf4 : Not(x) -> <dnfred4> Not (<dnf4>x)
dnf4 : And(x, y) -> <dnfred4> And (<dnf4>x, <dnf4>y)
dnf4 : Or(x, y) -> Or (<dnf4>x, <dnf4>y)
dnf4 : Impl(x, y) -> <dnfred4> Impl(<dnf4>x, <dnf4>y)
dnf4 : Eq(x, y) -> <dnfred4> Eq (<dnf4>x, <dnf4>y)
strategies
dnfred4 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf4)

12
trans/prop-dnf5.str Normal file
View File

@ -0,0 +1,12 @@
module prop-dnf5
imports libstrategolib prop-laws
rules
dnft5 : Not(x) -> <dnfred5> Not (<dnf5>x)
dnft5 : And(x, y) -> <dnfred5> And (<dnf5>x, <dnf5>y)
dnft5 : Or(x, y) -> Or (<dnf5>x, <dnf5>y)
dnft5 : Impl(x, y) -> <dnfred5> Impl(<dnf5>x, <dnf5>y)
dnft5 : Eq(x, y) -> <dnfred5> Eq (<dnf5>x, <dnf5>y)
strategies
dnf5 = try(dnft5)
dnfred5 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf5)

12
trans/prop-dnf6.str Normal file
View File

@ -0,0 +1,12 @@
module prop-dnf6
imports libstrategolib prop-laws
rules
dnft6 : Not(x) -> Not (<dnf6>x)
dnft6 : And(x, y) -> And (<dnf6>x, <dnf6>y)
dnft6 : Or(x, y) -> Or (<dnf6>x, <dnf6>y)
dnft6 : Impl(x, y) -> Impl(<dnf6>x, <dnf6>y)
dnft6 : Eq(x, y) -> Eq (<dnf6>x, <dnf6>y)
strategies
dnf6 = try(dnft6); dnfred6
dnfred6 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf6)

14
trans/prop-dnf7.str Normal file
View File

@ -0,0 +1,14 @@
module prop-dnf7
imports libstrategolib prop-laws
rules
proptr7(s) : Not(x) -> Not (<s>x)
proptr7(s) : And(x, y) -> And (<s>x, <s>y)
proptr7(s) : Or(x, y) -> Or (<s>x, <s>y)
proptr7(s) : Impl(x, y) -> Impl(<s>x, <s>y)
proptr7(s) : Eq(x, y) -> Eq (<s>x, <s>y)
strategies
dnf7 = try(proptr7(dnf7)); dnfred7
dnfred7 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf7)
cnf7 = try(proptr7(cnf7)); cnfred7
cnfred7 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DOAL <+ DOAR); cnf7)

10
trans/prop-dnf8.str Normal file
View File

@ -0,0 +1,10 @@
module prop-dnf8
imports libstrategolib prop-laws prop-dnf7
strategies
propbu8(s) = try(proptr7(propbu8(s))); s
strategies
dnf8 = propbu8(dnfred8)
dnfred8 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf8)
cnf8 = propbu8(cnfred8)
cnfred8 = try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DOAL <+ DOAR); cnf8)

6
trans/prop-dnf9.str Normal file
View File

@ -0,0 +1,6 @@
module prop-dnf9
imports libstrategolib prop-laws prop-dnf8
strategies
dnf9 = propbu8(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DAOL <+ DAOR); dnf9))
cnf9 = propbu8(try(DN <+ (DefI <+ DefE <+ DMA <+ DMO <+ DOAL <+ DOAR); cnf9))

View File

@ -4,18 +4,61 @@ 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 {! ../docrefs/manual.md !} is that of _evaluating_ an AST,
via the `prop-eval-rules` module in {! ../docrefs/sec4.1.md !}. In this
repository, we've placed those rules in `trans/prop-eval-rules.str`,
and the glue strategies that call them in `trans/prop-eval.str`. This latter
module is imported by `trans/spoofax_propositional_language.str`.
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:
(I am unclear on what triggers Editor Services 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.)
There's an Editor Services module `editor/Manual.esv` to invoke the eval strategy,
and it's included in in `editor/Main.esv.`
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 "test1"
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 !}.
One other note about the files provided in this repository. The "do-XXX" rule
used as boilerplate glue between ESV and a Stratego strategy in
`trans/prop-eval.str` is:
```Stratego
[End the documentation block to avoid the comment close in the code] **/
/** md [restart processing to include the code in the documentation] */
{! prop-eval.str extract: {start: '^(.*Interface.*\s*)$'} !}
```
The version of 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.
**/
module prop-eval-rules
imports signatures/-
rules
@ -37,99 +80,3 @@ rules
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 {terminate: 'provider\s*:', replace: ['^\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 !}
```
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 {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 including 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 {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:
[CONTINUE HERE ONCE THIS WORKS]
**/

27
trans/prop-eval2.str Normal file
View File

@ -0,0 +1,27 @@
module prop-eval2
imports libstrategolib signatures/-
rules
Eval : Not(True()) -> False()
Eval : Not(False()) -> True()
Eval : And(True(), x) -> x
Eval : And(x, True()) -> x
Eval : And(False(), x) -> False()
Eval : And(x, False()) -> False()
Eval : Or(True(), x) -> True()
Eval : Or(x, True()) -> True()
Eval : Or(False(), x) -> x
Eval : Or(x, False()) -> x
Eval : Impl(True(), x) -> x
Eval : Impl(x, True()) -> True()
Eval : Impl(False(), x) -> True()
Eval : Impl(x, False()) -> Not(x)
Eval : Eq(False(), x) -> Not(x)
Eval : Eq(x, False()) -> Not(x)
Eval : Eq(True(), x) -> x
Eval : Eq(x, True()) -> x
strategies
eval-up = bottomup(repeat(Eval))
eval-down = downup(repeat(Eval))

22
trans/prop-laws.str Normal file
View File

@ -0,0 +1,22 @@
module prop-laws
imports libstrategolib signatures/-
rules
DefI : Impl(x, y) -> Or(Not(x), y)
DefE : Eq(x, y) -> And(Impl(x, y), Impl(y, x))
DN : Not(Not(x)) -> x
DMA : Not(And(x, y)) -> Or(Not(x), Not(y))
DMO : Not(Or(x, y)) -> And(Not(x), Not(y))
DAOL : And(Or(x, y), z) -> Or(And(x, z), And(y, z))
DAOR : And(z, Or(x, y)) -> Or(And(z, x), And(z, y))
DOAL : Or(And(x, y), z) -> And(Or(x, z), Or(y, z))
DOAR : Or(z, And(x, y)) -> And(Or(z, x), Or(z, y))
strategies
dnf-laws = innermost(DefI <+ DefE <+ DAOL <+ DAOR <+ DN <+ DMA <+ DMO)
cnf-laws = innermost(DefI <+ DefE <+ DOAL <+ DOAR <+ DN <+ DMA <+ DMO)

18
trans/sec9_1.str Normal file
View File

@ -0,0 +1,18 @@
module sec9_1
imports libstrategolib signatures/- prop-laws prop-desugar
strategies
conj(s) = And(conj(s), conj(s)) <+ s
disj(s) = Or (disj(s), disj(s)) <+ s
// Conjunctive normal form
conj-nf = conj(disj(Not(Atom(id)) <+ Atom(id)))
// Disjunctive normal form
disj-nf = disj(conj(Not(Atom(id)) <+ Atom(id)))
// Second exercise, Section 9.1.2
path-dep-xform = DN <+ IDefI
inner-soln = repeat(oncebu(path-dep-xform))
outer-soln = repeat(oncetd(path-dep-xform))
random-soln = repeat(rec x(one(x) + path-dep-xform))

14
trans/sec9_2.str Normal file
View File

@ -0,0 +1,14 @@
module sec9_2
imports prop-eval2 prop-desugar
rules
DefT : True() -> Impl(False(), False())
strategies
eval1 = bottomup(try(Eval))
eval2 = topdown(try(Eval))
desugar2 = bottomup(try(DefI <+ DefE))
impl-nf1 = topdown(repeat(DefT <+ DefN <+ DefA2 <+ DefO1 <+ DefE))
impl-nf2 = topdown(try(DefT <+ DefN <+ DefA2 <+ DefO1 <+ DefE))

View File

@ -7,6 +7,25 @@ imports
outline
analysis
prop-eval
prop-dnf
prop-dnf3
prop-cnf3
prop-laws
prop-eval2
prop-desugar
chap6
chap7
chap8
prop-dnf4
prop-dnf5
prop-dnf6
prop-dnf7
prop-dnf8
prop-dnf9
prop-dnf10
sec9_1
prop-dnf11
sec9_2
rules // Debugging