Assignment Concrete Syntax
Pt03
The goal of this assignment is to learn the use concrete syntax in Stratego for the specification of rewrite rules and to improve your term rewriting skills.
Argument Lifting with Concrete Syntax
Assignment
The assignment builds on
Assignment Term Rewriting.
The goal is to (1) specify the argument lifting transformation using concrete syntax and (2) extend that transformation to cover more cases.
The transformation pipeline that you should build has the following
components:
- tiger-xmpl -x fac-tail (or cat file.tig)
- parse-tiger
- Tiger-Desugar
- Tiger-Rename
- ./liftargs (your transformation
- Tiger-Ensugar
- pp-tiger
Remarks
-
liftargs is a better name for the transformation than simplify
- let flattening is now done by Tiger-Ensugar
To pass you should minimally cover the following
- Lifting from BinOps, RelOps, If, IfThen, For, While
- Let and seq hoisting for 'simple' cases (i.e., not involving lists)
For a higher grade you could extend this with (some of)
- Lifting from function calls, array access, record
- Hoisting lets as high up as possible
- Splitting var declarations into a non-initialized declaration and an assignment
Again: more is better than less, but correctness is more important than completeness.
Correctness
The ultimate test for the correctness of your transformation is running the transformed
program. The Tiger toolkit contains
run-tiger which interprets a Tiger program.
Some good examples for running are
- fac.tig : compute factorial of 10
- queens.tig : prints all solutions for placing 8 queens
- prettyprint.tig : prints tree structure
Testing
Compiling and running the transformation from the command-line or in a script must be getting boring by now. Write a Makefile to automate compilation of the program and testing it. The Makefile should have the following targets:
- liftargs : compile the transformation
- file.show : show (cat) a Tiger program file.tig
- file.run : run a Tiger program with run-tiger
- file.lif : result of applying the liftargs transformation pipeline
- check : run a number of correctness tests on (small) Tiger programs
- clean : remove all derived files
It should be possible to 'make fac.lif.run' to first apply the transformation and
then run the resulting program. All 'file' targets are for arbitrary files of course.
For convenience you might include sub-targets to express the results of intermediate
results.
Submit
Submit the following files
- liftargs.str : implementation of argument lifting with concrete syntax
- liftargs.meta : declaration of concrete syntax used in the program
- Makefile : with the targets as described above
- Tiger programs you have developed for testing the transformation
Syntax Definitions
Syntax of Tiger
The syntax definition of Tiger is defined in the following modules:
Lexical syntax
Desugaring turns operators into generic
BinOps and
RelOps:
Tiger in Stratego
The full syntax of the embedding of Tiger in Stratego is defined in the following modules.
Note that the
[[...]]
quotation operators are legacy and should not be used.
A Stratego module that uses concrete object syntax must specify the syntax of the module in a
.meta file. For concrete Tiger syntax in Stratego this syntax is called
StrategoTiger. Specify this syntax for a Stratego module
foo.str in a file
foo.meta using:
Meta([
Syntax("StrategoTiger")
])
Add the following argument to the call of the Stratego compiler to include the
StrategoTiger syntax in the include path:
-I ${TIGER}/share/sdf/tiger-front
where
${TIGER} points to the location where Tiger is installed. This is
/projects/stratego/tiger.
Example
Here is the result of
liftargs applied to
prettyprint.tig.
This could be further improved by recognizing that
nil is
a constant that does not have to be lifted.
--------------------------------------------------------
let type a_0 = {key : string, left : a_0, right : a_0}
function prettyprint_b_0(d_0 : a_0) : string =
let var e_0
in e_0 := "";
let function write_g_0(i_0 : string) =
e_0 := concat(e_0, i_0)
function show_h_0(k_0: int, l_0 : a_0) =
let function indent_n_0(o_0 : string) =
(write_g_0("\n");
for p_0 := 1 to k_0 do
write_g_0(" ");
e_0 := concat(e_0, o_0))
var n_0 : int
var b_0 : int
var c_0 : int
var f_0
var g_0
var h_0
var j_0
var m_0
in b_0 := l_0;
c_0 := nil;
n_0 := b_0 = c_0;
if n_0
then indent_n_0(".")
else (f_0 := l_0.key;
indent_n_0(f_0);
g_0 := k_0 + 1;
h_0 := l_0.left;
show_h_0(g_0, h_0);
j_0 := k_0 + 1;
m_0 := l_0.right;
show_h_0(j_0, m_0))
end
in show_h_0(0, d_0);
e_0
end
end
function node_c_0(q_0: string, r_0: a_0, s_0 : a_0) : a_0 =
a_0{key = q_0, left = r_0, right = s_0}
var t_0
var a_1
var u_0
var v_0
var b_1
var y_0
var z_0
var w_0
var x_0
var c_1
in u_0 := nil;
v_0 := nil;
a_1 := node_c_0("b", u_0, v_0);
y_0 := nil;
w_0 := nil;
x_0 := nil;
z_0 := node_c_0("d", w_0, x_0);
b_1 := node_c_0("c", y_0, z_0);
t_0 := node_c_0("a", a_1, b_1);
c_1 := prettyprint_b_0(t_0);
print(c_1);
print("\n")
end
--------------------------------------------------------