Introduction
The goal of this second graded assignment is to add a closure conversion phase to your minischeme compiler. As explained in the course, closure conversion transforms all functions to close them. This is done by replacing all references to free variables by references to fields of an environment that gets passed as an additional argument to closed functions.
Free variables computation
Before implementing closure conversion itself, write (and
test) a function to compute the set of free variables of a
lambda expression. This amounts to translating the
F
function presented in the course to Scala code.
Make sure that the free variables are represented as symbols
(not as compiler trees), and please give the function a more
expressive name than simply F
.
Closure conversion
Closure conversion should be implemented as a transformation
phase that gets as argument a list of trees with possibly open
functions, and returns an equivalent list of trees containing
only closed functions. Once again, this amounts to translating
a function presented in the course (⟦⋅⟧
in this case) to Scala code.
During closure conversion, you will need to create new
identifiers for the various environments and closures. Since
closure conversion takes place after name analysis, you should
create new symbols, not simply new strings. The method
freshLocal
in object Symbol
does
precisely that.
Notice that the interpreter can deal with open functions, so
it doesn't need the closure conversion phase. Therefore, you
should only invoke closure conversion from the
MainCompiler
function.
Finally, notice that you don't need to do anything about recursive closures since in minischeme, they are always global. This implies that they are never free.
Tips and tricks
As explained above, the interpreter does not need a closure conversion phase. However, it should be able to interpret a program transformed by your closure conversion phase. Therefore, to debug your closure conversion phase, simply feed its output to the interpreter and see what comes out of it. The interpreter has a big advantage over the VM: it produces meaningful error messages instead of crashing.
Another useful trick to debug the closure conversion phase is
to print the program after transformation, using the
TreePrinter
object.
As always, it is important to test your program as thoroughly
as possible. To help you, we provide you with two test programs:
incr.scm is a small program
which contains the adder seen in the course; you can use queens.scm to test if
your transformation works on larger programs (note that it
requires both libraries/predefined.scm
and
libraries/lists.scm
), this program creates some
closures when calling the method for-all
.
Solution submission
Your solution must be submitted as a ZIP archive containing exactly the following files - not one more, not one less:
README (short description of your solution) compiler/minischeme/ClosureConverter.scala (your closure conversion phase) compiler/minischeme/Code.scala compiler/minischeme/EtaExpander.scala compiler/minischeme/FileReader.scala compiler/minischeme/Generator.scala compiler/minischeme/Instruction.scala compiler/minischeme/Interpreter.scala compiler/minischeme/Label.scala compiler/minischeme/Main.scala compiler/minischeme/NameAnalyzer.scala compiler/minischeme/Opcode.scala compiler/minischeme/Parser.scala compiler/minischeme/Primitives.scala compiler/minischeme/Register.scala compiler/minischeme/Report.scala compiler/minischeme/Representable.scala compiler/minischeme/Scanner.scala compiler/minischeme/SeqReader.scala compiler/minischeme/Symbol.scala compiler/minischeme/Token.scala compiler/minischeme/Tree.scala compiler/minischeme/TreePrinter.scala
The README
file should contain a short
description of your solution and its peculiarities, as well as
the name of all its authors. With the exception of
ClosureConverter.scala
and
Main.scala
, the files you submit should be
identical to the ones you were given. If they are not, explain
why in the README
file.
To help you check the contents of the archive, we provide you with a Scala script called SubCheck4.scala. When run with your archive as argument, this script should not report any problem.
Remember that according to our submission regulations, we do not accept solutions which fail to compile.
The archive containing your solution should be submitted on Moodle before 23:55, April 2, 2009.