Page
trans/refactoring.str
in your MiniJava project and add the following content:
strategies tutorial = try(truth) rules truth: Add(IntValue("21"), IntValue("21")) -> IntValue("42")You have just defined a very simple rewrite rule
truth
.
On its left-hand side, it matches an expression that adds the two integer constants 21
and 21
.
On its right-hand side, it instantiates a new expression, namely an integer constant 42
.
The strategy tutorial
tries to apply the rewrite rule.
That is, if the rewrite rule can be applied to an input term, its output term becomes the result of the strategy.
Otherwise, the input term becomes the output term.
trans/refactoring.str
:
rules constant-folding-refactoring: (_, selected, position, ast, path, project-path) -> ([(source, result)], [], [], []) where source := selected ; <tutorial> selected => resultand define a refactoring in
editor/MiniJava-Builders.esv
:
refactoring Exp: "Tutorial (selection)" = constant-folding-refactoring (source)You can now test the strategy and the rewrite rule. Select different expressions, choose Tutorial in the Refactoring menu and observe the different results.
refactoring.str
and adapt the definition of the strategy tutorial:
strategies tutorial = try(zero) rules zero: Add(x, IntValue("0")) -> xThe new rewrite rule
zero
includes a variable x
.
When matching the rule's left-hand side, this variable is bound to a term.
When instantiating the rule's right-hand side, the variable is replaced by the term it is bound to.
Having said this, try to understand what the rewrite rule does.
strategies tutorial = try(zero) rules zero: Add(x, IntValue("0")) -> x zero: Add(IntValue("0"), x) -> xWhenever you try to apply
zero
, Stratego tries to apply one of the rules with this name.
If more than one rules can be applied, there is no ordering of rules.
One of the rules is chosen non-deterministicly.
tutorial
:
strategies tutorial = try(zero + calc) rules zero: Add(x, IntValue("0")) -> x zero: Add(IntValue("0"), x) -> x calc: Add(IntValue(x), IntValue(y)) -> IntValue(z) where <addS> (x, y) => zThe new rewrite rule
calc
matches an expression that adds two integer constants.
The values of these constants are bound to variables x
and y
.
The rule instantiates a new expression, namely an integer constant of value z
.
This variable is bound in a condition, expressed in the where
clause of the rewrite rule.
The condition reads as follows:
Applying addS
to a tuple of x
and y
should yield z
.
More formally, <s> t
applies the strategy s
to a term t
and s => t
matches the result of s
with t
.
In our example, addS
is applied to the tuple and the result is matched with z
, which binds z
to this result.
During the instantiation of the right-hand side pattern of the rewrite rule, this binding is used to replace z
by its bound value.
The new definition of the tutorial
strategy tries to apply either zero or calc.
The choice between both is non-deterministic.
constant-folding-refactoring
before.
Try to understand what it does.
two
which replace multiplications by 2 with additions, e.g. 2*e
by e+e
.
tutorial
strategy.
tutorial
strategy deterministic.
zero
deterministic.
try(topdown(zero + two + calc))
topdown(try(zero + two + calc))
try(bottomup(zero + two + calc))
bottomup(try(zero + two + calc))
try(alltd(zero + two + calc))
alltd(try(zero + two + calc))
try(innermost(zero + two + calc))
innermost(zero + two + calc)
tutorial = innermost(try(zero + two + calc))
a good idea?
What will happen if you call it?
Why will it happen?
At the end of this day, you should clean up your code and provide only three refactorings: