The goal of this project is to understand how we can encode a complicated functional language in a smaller language. In this project you will implement the translations among the Em family of languages that we saw in class Monday and Wednesday.
The system for implementing these languages is called EmIly (for Em family). You can copy EmIly from
~tvandrun/Public/cs365/proj8.tar
This project, unlike the others, is written in Java.
For each language (BoolEm, DeclEm, Em, and ListEM)
there are three packages, abssyntree
,
astvisitor
, and parser
.
The parser is generated by Antlr (version 3);
the abstract syntax tree classes and visitor super classes
are generated by a tool I wrote myself, being dissatisfied by
the existing options at the time.
The basic workings of it (operations on the program are implemented
as visitors that walk ASTs) are the same as the earlier
projects, but the big difference that Java brings is static typing.
This means that the compiler (or Eclipse or whatever) will find statically
many simple mistakes that you'd have to run the Python program to find;
it also means that the code will be more verbose.
As in other projects that involve translating from one language to another, we could do that translation either by producing the text of the program in another language or by producing new abstract syntax trees (Java's static typing prohibits us from simply modifying the syntax trees). I have set this up for producing the text of the translated program.
For BoolEm we have an InterpreterVisitor
,
along with a handful of other helper visitors
(all finished).
For the other languages we have classes each called
TranslatorVisitor
,
which you will need to finish.
You will also see a directory of sample test programs.
There are nine steps in this project, corresponding to the nine translations we have seen in class:
declem.astvisitor.TranslatorVisitor.visit(Let)
,
translate let expressions into BoolEm, which does not have lets.
declem.astvisitor.TranslatorVisitor.visit(Application)
translate applications with many actual parameters into BoolEm,
where all functions have one parameter.
declem.astvisitor.TranslatorVisitor.visit(Abstraction)
,
translate applications with many formal parameters into BoolEm.
em.astvisitor.TranslatorVisitor(FunDeclaration)
,
translate recursive functions declarations into DeclEm, which does not
have (explicit) recursion.
listem.astvisitor.TranslatorVisitor(Cons)
,
translate uses of the cons operator.
listem.astvisitor.TranslatorVisitor(Test)
,
translate tests if a list is null.
listem.astvisitor.TranslatorVisitor(List)
,
translate explicit lists (e.g., [true, false, false, true]
).
listem.astvisitor.TranslatorVisitor(Car)
,
translate uses of hd
.
listem.astvisitor.TranslatorVisitor(Cdr)
,
translate uses of tl
.
To execute a program in any of these languages, use
java -cp .:antlr3.jar em.EmIly programname
(Note the need to include the Antlr jar file.
Of course you also could simply add it to your CLASSPATH
environment variable, and if you're using
Eclipse you definitely want to add the jar file as a library.
If you need help doing either of those things, just ask.)
The EmIly
program will determine which language
is being used by the extension (so, name all of your DeclEm
tests something that ends in .declem
).
It will do the appropriate translations and then execute the final BoolEm
program.
For example,
java em.EmIly rec.em
will...
rec.em
program.
em.abssyntree.Program
.
em.astvisitor.TranslatorVisitor
to produce a (String) DeclEm program.
declem.abssyntree.Program
.
declem.astvisitor.TranslatorVisitor
to produce a (String) BoolEm program.
boolem.abssyntree.Program
.
boolem.astvisitor.InterpreterVisitor
,
to find the result of that program.
For debugging purposes, you may want to suppress execution of the program
and only print the translation.
This can be done by using the -p
flag, which
prints only the first translation of the program and then stops.
Similarly, the -pp
flag prints all translations, but does not
run the program.
I have given you a few sample programs, but an important part of this project is to write your own tests. It is much better to write many small tests. In particular, you will have best results with tests whose values are a booleans (or very simple abstractions). Since BoolEm has no lists, any ListEm program whose result is a list will appear as a (very complicated) abstraction. Hence it is better to test
hd(tl(true::[true,false,false,true]));
than
true::[true,false,false,true]
Finally, make sure you start with the DeclEm part and progress
up the family hierarchy and test as you go
If you try to write all the translations first
and then execute reverse.listem
as your
first test, you will almost certainly get unpleasant results.
Turn in your files
listem.astvisitor.TranslatorVisitor
,
declem.astvisitor.TranslatorVisitor
, and
em.astvisitor.TranslatorVisitor
,
to appropriate directories:
/cslab.all/ubuntu/cs365/turnin/xxxxxx/proj8/yyyyy
where "xxxxxx" is [elliot|payton|davidemmanuel|nathan|gill|brandon|sean|simon] and "yyyyy" is [declem|em|listem]. I will grade your project by running it against a collection of test files.
DUE: Wednesday, April 30, 5:00 pm.