Labs 09
Congratulations, your front-end is complete! You are now one step (and two weeks) away from having written a complete compiler. This week's lab description and stubs are rather short. It's not that we don't want to help you anymore, it's just that the tasks should be straightforward :)
Support library
Generating class files is a tedious and not so interesting task. Therefore you will use a library for this. Please read the Cafebabe documentation pages (you'll also find jar
files there).
Concatenating and printing strings
To concatenate and print out strings, you will need to call methods from the Java library (as there are no bytecodes which do that directly). You only need to handle the cases where you print booleans, integers or strings1). Turns out that System.out.println(…) is conveniently overloaded for all these cases.
To call System.out.println(…), you need to invoke the proper method println(…) (with the signature matching what you're trying to print, that is) on the static object System.out, so you need to emit a GETSTATIC bytecode, then emit the code for the expression you're trying to print, then emit an INVOKEVIRTUAL bytecode. System.out is of type java.io.PrintStream.
Concatenation is done using java.lang.StringBuilder. The procedure consists in building a new instance of a StringBuilder, then appending to it whatever you want to concatenate together, then calling toString() on the builder. The append method is overloaded for strings and integers, and you're not asked to be able to concatenate any other type.
If in doubt, compile an example with javac
and run javap -c
on the .class
file.
Equality
We will handle equality in a simple way:
- integers and booleans are compared by value
- other types (strings, arrays and objects) are compared by reference. In the case of strings, the result may or may not be the same as calling .equals(…), depending on whether the strings are constant.
Boolean expressions
You have to apply lazy evaluation to boolean expressions (short-circuit). You may use whichever technique you want to achieve this (see compiling conditional expressions, short-circuit evaluation and compilation as tree transformation).
Notes on types in the JVM
The various naming conventions in the JVM can be confusing: some bytecodes contain a letter indicating to which type of operands they apply (eg. ILOAD which loads integers, IF_ACMPEQ which compares two references for equality or LRETURN which returns a long
value). In this convention, we have:
Letter | Corresponding type |
---|---|
I | Integer |
L | Long |
D | Double |
F | Float |
A | Reference (object or array) |
…but then there is another convention when we want to describe fields or methods types and methods signatures (see cafebabe). In particular, note that L is used for objects (but not arrays) in that second convention, but for long
operands in bytecodes.
Finally, note that returning from a void
method is done using the RETURN bytecode (no prefix letter).
Task
Complete the stub for CodeGenerator.scala such that your compiler emits class files. You should be able to run the main class with java
and get the same result as with javac
for valid MiniJava+ programs (except for the handling of escape characters in Strings, String comparison and other small details).
Your compiler should generate class files (one per class, as in Java) silently if the compilation is successful, or generate errors and warnings from the previous phases in case there was a problem. The code generation phase should not produce any error, and the generated class files should be executable on the Java Virtual Machine.
Stubs
As usual:
- Main.scala The main program. It now accepts a single argument -d outputdir to specify the output directory for the class files. The arguments parsing is done in
Main
, and the handling is done inCompiler
. - Compiler.scala Note that this week you have to complete this file (generation of the main class).
- CodeGenerator.scala Stub for the code generator.
…and you've seen this one before too:
src └── minijava ├── Compiler.scala (stub given this week) ├── Main.scala (given this week) ├── Positional.scala (given in Lab 02) ├── Reporter.scala (given in Lab 02) ├── TreePrinter.scala (completed in the Analyzer lab) │ ├── analyzer │ ├── Analyzer.scala (completed in the Type Checker lab) │ ├── Symbols.scala (completed in the Type Checker lab) │ ├── TypeChecker.scala (completed in the Type Checker lab) │ └── Types.scala (completed in the Type Checker lab) │ ├── code │ └── CodeGenerator.scala (stub given this week) │ ├── lexer │ ├── Lexer.scala (completed in the Parser lab) │ └── Tokens.scala (completed in the Parser lab) │ └── parser ├── Parser.scala (completed in the Parser lab) └── Trees.scala (completed in the Type Checker lab)
Deliverables
Submit a zip
file of your src
directory through Moodle before Nov. 26th, 8.15am.
References
- The complete JVM specification (may be hard to digest)
- opcodes arranged conveniently, in particular:by function