// Compiler from MiniJS typed syntax (Ann) to Jasmin text // using BNFC-generated JVM instruction syntax (Ins). // Programming Language Technology // Chalmers DAT151, Gothenburg University DIT231 import java.util.*; import Ann.Absyn.*; import Code.Absyn.*; import Code.PrettyPrinter; public class Compiler { // State of the compiler // Next available local variable address. private Integer nextAddr = 0; // Map from variables to their addresses. private Map cxt = new TreeMap(); // The instruction list generated by the compiler. private List code = new ArrayList(); // Entry point public String compile (String name, Program prg) { // Compile the statements to instructions in code. prg.accept(new CompileProgram(), null); // Print code and wrapper. List output = new ArrayList(); output.add(".class public " + name + ""); output.add(".super java/lang/Object"); output.add(""); output.add(".method public ()V"); output.add(" .limit locals 1"); output.add(""); output.add(" aload_0"); output.add(" invokespecial java/lang/Object/()V"); output.add(" return"); output.add(""); output.add(".end method"); output.add(""); output.add(".method public static main([Ljava/lang/String;)V"); output.add(" .limit locals 1000"); output.add(" .limit stack 1000"); output.add(""); for (Ins ins : code) output.add (" " + PrettyPrinter.print(ins)); output.add(" return"); output.add(""); output.add(".end method"); output.add(""); return String.join("\n", output); } // Compile a program (list of statements). public class CompileProgram implements Program.Visitor { public Void visit(Prg p, Void arg) { for (Stm s: p.liststm_) s.accept(new CompileStm(), arg); return null; } } // Compile a statement. public class CompileStm implements Stm.Visitor { // Assignment public Void visit(SAssign p, Void arg) { Integer addr = cxt.get(p.ident_); // If variable has not been assigned an address yet // take the next available address. if (addr == null) { addr = nextAddr; cxt.put(p.ident_, addr); nextAddr += sizeof(p.type_); } p.exp_.accept(new CompileExp(), arg); if (p.type_ instanceof TDouble) emit (new DStore(addr)); else emit (new IStore(addr)); return null; } // Print public Void visit(SPrint p, Void arg) { p.exp_.accept(new CompileExp(), arg); if (p.type_ instanceof TDouble) emit (new DPrint()); else emit (new IPrint()); return null; } } // Compile an expression. public class CompileExp implements Exp.Visitor { public Void visit(EInt p, Void arg) { emit (new ILit (p.integer_)); return null; } public Void visit(EDouble p, Void arg) { emit (new DLit (p.double_)); return null; } public Void visit(EVar p, Void arg) { Integer addr = cxt.get(p.ident_); if (p.type_ instanceof TDouble) emit (new DLoad(addr)); else emit (new ILoad(addr)); return null; } public Void visit(EArith p, Void arg) { p.exp_1.accept(new CompileExp(), arg); p.exp_2.accept(new CompileExp(), arg); if (p.type_ instanceof TDouble) { if (p.op_ instanceof Times) emit (new DMul()); else if (p.op_ instanceof Div ) emit (new DDiv()); else if (p.op_ instanceof Plus ) emit (new DAdd()); else if (p.op_ instanceof Minus) emit (new DSub()); } else { if (p.op_ instanceof Times) emit (new IMul()); else if (p.op_ instanceof Div ) emit (new IDiv()); else if (p.op_ instanceof Plus ) emit (new IAdd()); else if (p.op_ instanceof Minus) emit (new ISub()); } return null; } public Void visit(EI2D p, Void arg) { p.exp_.accept(new CompileExp(), arg); emit (new I2D()); return null; } } // Auxiliary methods // Get the number of 32bit words a value of the given type occupies. public static int sizeof (Type t) { if (t instanceof TDouble) return 2; else return 1; } // Append a new instruction to the output. private void emit (Ins ins) { code.add(ins); } }