package tool; import parser.Lexer; import parser.Parser; import trees.ExpressionTree; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; public class CodeGen { /** Pull char from where? */ InputStream in; /** Variable to local-variable number map used by code generator */ public Map variables = new HashMap(); /** Code generation output */ public StringBuffer out = new StringBuffer(); int maxStackDepth = 0; int maxLocals = 0; public static void main(String[] args) throws IOException { CodeGen generator = new CodeGen(System.in); generator.compile(); generator.emit(); } public void emit() { System.out.println(header); System.out.println(".limit stack "+maxStackDepth); // how much stack space do we need? System.out.println(".limit locals "+maxLocals); // how many locals do we need? String code = out.toString(); System.out.println(code); System.out.println(footer); } public CodeGen(InputStream in) { this.in = in; } /** Compiles code to a buffer (minus header/footer); sets this.out */ public void compile() throws IOException { Map variables = new HashMap(); Lexer lex = new Lexer(in); Parser parser = new Parser(lex); List statements = parser.prog(); computeStackSize(statements); for (int i = 0; i < statements.size(); i++) { ExpressionTree t = (ExpressionTree) statements.get(i); t.gen(this); } } private void computeStackSize(List statements) { for (int i = 0; i < statements.size(); i++) { ExpressionTree t = (ExpressionTree) statements.get(i); int height = t.height(); maxStackDepth = Math.max(maxStackDepth, height); int vars = t.countVarNodes(); maxLocals = Math.max(maxLocals, vars); } maxLocals++; // make room for args parameter to main() } // B Y T E C O D E S T U F F /** Class definition for Calc in bytecodes. Templates are * a better approach here, but for simplicity, I use strings. */ public static final String header = "; public class Calc extends Object { ...}\n" + ".class public Calc\n" + ".super java/lang/Object\n" + "\n" + "; public Calc() { super(); } // calls java.lang.Object()\n" + ".method public ()V\n" + " aload_0\n" + " invokenonvirtual java/lang/Object/()V\n" + " return\n" + ".end method\n" + "\n" + "; main(): Expr.g will generate bytecode in this method\n" + ".method public static main([Ljava/lang/String;)V"; public static final String footer = " return\n" + ".end method"; }