Overview
This topic is intended to provide an overview of the compiler in its goals, structure, and functioning. Please read and make notes to improve the clarity and quality of this document.
Broadly, the compiler follows the classical architecture in the following ways.
TheReader encompasses the scanner and parser, taking in the lisp code and spitting out a lisp style list datastructure (see lisp.common.list). The job of the compiler is to generate java byte code from this list.
Compile
The compiler is invoked by calling the 'compile' function from lisp: (compile foo). This correlates to the java class found in Compile.java under the lisp.system.compiler package. Perusing Compile.java will find the following lines (more or less):
java.util.Vector v = (java.util.Vector)icg.funcall(sa.funcall(obj));
OolongClass[] oc = (OolongClass[])v.toArray(new OolongClass[v.size()]);
classBytes = assembler.assemble(oc);
classesLoaded = loadClasses(classBytes, oc);
Here 'obj' is compiled and loaded by first passing through the
SemanticAnalyzer: sa.funcall(obj). Then through the
IntermediateCodeGeneration: icg.funcall( ... ). The resulting vector of
OolongClass? objects is converted to an array and passed to the oolong assembler: assembler.assemble(oc). The resulting java bytecode classes are loaded using the
CompilerClassLoader? : loadClasses(classBytes, oc). The classes are then passed back to the calling function where the classes can then be instantiated and funcalls made.
At the time of writing the
SemanticAnalyzer is largely unformed, but the current plan is to create a set of macros that will transform and annotate the list for the icg to process. The list will be recursively iterated through checking for proper semantics and calling the macro transformations.
The format of the
IntermediateCodeGeneration is based mostly around the emitter found in Emitter.java.
Emitter:
The function of the emitter is to provide a clean interface to constructing
OolongClass? objects (the output of the icg). The emitter allows the creation of new classes through the newClass(), new fields with the newField() method, and new methods through the newMethod() method. Classes are kept in a stack so new classes can be created before finishing with the old class. To finish the creation of a class the endClass() method is invoked, the class is popped off the stack and the emitter now emits to the class on top of the stack. Methods do not need to be ended (since they are not on a stack). Simply creating a new method will end the current one.
Emitting lines into a method is done by calling the emit...() methods. There is one emit method for each of the oolong bytecodes (mostly the same as the java bytecodes, see Engel's book) plus a few for handiness (such as emitNil()). For example, to emit 'aload_0' into the method you would call
emitter.emitAload(0);
OolongClass? :
The
OolongClass? objects represent the new oolong coded classes in the making. They are turned into streams of characters (which oolong then assembles) via the toString() method. See javadoc for further details.
References
- Programming for the Java Virtual Machine, Joshua Engel
- CLJcompiler
Implementation
Discussions
Links to Blog issues
Status:
Release Level:
Open bug count: