// Imports are kinda messy due to name overlaps with java.lang import compiler.structure.*; import compiler.structure.I; import compiler.structure.E; import compiler.structure.C; import compiler.structure.Minus; import compiler.structure.Times; import compiler.structure.Plus; import compiler.structure.Compiler; import edu.neu.ccs.demeter.Ident; import transform.*; // Main Functional Compiler Class public class FuncCompile implements Compiler{ public OpList compile(E e){ util.Util.addBuiltIn(Ident.class); Traversal pre = new Traversal(new PreCode2()); Traversal fix = new Traversal(new FixLet()); Traversal comp = new Traversal(new Code3()); e = pre.traverse(fix.traverse(e),new VEmpty()); //util.Util.setDebug(true); return comp.traverse(e, new VEmpty()); } } // Helper Structures to Reorder Let Expressions class RevLet extends E{ E e; BB bb; RevLet(E ee, BB bbb){ e = ee; bb = bbb; } } class BB{ Ident v; E b; BB(Ident vv, E bb){ v = vv; b = bb; } } // Process Optional arguments and calculate de Bruijn Indices class PreCode extends IDfa{ E apply(C c){ return c.arg2.hasE()?c:c.arg1; } } // Reverse the binding forms so de Bruijn is correct class FixLet extends IDf{ E apply(L l){ return new RevLet(l.e, new BB(l.id, l.body)); } } // de Bruijn Indices class PreCode2 extends PreCode{ VStack update(BB b, VStack s){ return s.push(new V(b.v)); } E apply(V v, VStack s){ return new A(s.lookup(v)); } } // Generate Code for the Base Language (Arithmetic) class Code extends IDb{ static OpList empty = new OpEmpty(); static OpList single(Opcode o){ return empty.append(o); } OpList combine(S s, Integer i){ return single(new Push(i)); } OpList combine(Option_E o, OpList l){ return l; } OpList combine(P p){ return single(new Plus()); } OpList combine(M m){ return single(new Minus()); } OpList combine(T t){ return single(new Times()); } OpList combine(D d){ return single(new Divide()); } OpList combine(C c, OpList op, OpList left, OpList right){ return right.append(left).append(op); } } // Generate Code with the Let/de Bruijn Extension class Code2 extends Code{ OpList combine(A a, Integer i){ return single(new Load(i)); } OpList combine(BB bb, Object id, OpList b){ return b; } OpList combine(RevLet l, OpList e, OpList body){ return e.append(new Def()).append(body).append(new Undef()); } } // Generate Code for Boolean Functions and If expressions class Code3 extends Code2{ // Side-effects make 'gen-sym' easier int lnum = 0; OpList combine(LT l){ return single(new Less()); } OpList combine(GT g){ return single(new Greater()); } OpList combine(EQ e){ return single(new Equal()); } OpList combine(AndF a){ return single(new And()); } OpList combine(OrF o){ return single(new Or()); } OpList combine(I f, OpList c, OpList t, OpList e){ Ident l1 = new Ident("else_"+lnum++), l2 = new Ident("done_"+lnum++); return c.append(new IfZ(l1)).append(t) .append(new Jmp(l2)).append(new Label(l1)) .append(e).append(new Label(l2)); } }