public void compile( List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { // An act definition returns a behaviour. The bindings in the behaviour must // be constructed as recursive bindings *and* be dynamic variables so that // '.' can find them. Therefore, compile a behaviour as though it were // constructed in the context of a letrec, but force the bindings to be // dynamic... bindings = Binding.mergeBindings(bindings); for (Binding b : Binding.valueBindings(bindings)) { code.add(new Null(getLineStart()), locals, dynamics); code.add(new NewDynamic(getLineStart()), locals, dynamics); dynamics = dynamics.map(DynamicVar::incDynamic).cons(new DynamicVar(b.name, 0)); } for (Binding b : Binding.valueBindings(bindings)) { b.getValue().compile(locals, dynamics, code, false); code.add( new SetDynamic(b.getValue().getLineStart(), lookup(b.name, dynamics).getIndex()), locals, dynamics); code.add(new Pop(b.getValue().getLineStart()), locals, dynamics); } orderExports(dynamics); name.compile(locals, dynamics, code, false); compileBehaviour(locals, dynamics, code); // Remove the dynamics... for (Binding b : Binding.valueBindings(bindings)) { code.add(new PopDynamic(getLineStart()), locals, dynamics); dynamics = dynamics.getTail(); } }
public void compile( List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { if (isApplyLocal(locals)) compileApplyLocal(locals, dynamics, code, isLast); else if (isApplyDynamic(dynamics)) compileApplyDynamic(locals, dynamics, code, isLast); else if (isApplyFun()) compileApplyFun(locals, dynamics, code, isLast); else { code.add(new StartCall(getLineStart()), locals, dynamics); for (AST arg : args) arg.compile(locals, dynamics, code, false); op.compile(locals, dynamics, code, false); code.add(new instrs.apply.Apply(getLineStart(), args.length), locals, dynamics); } }
private void compileApplyDynamic( List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { code.add(new StartCall(getLineStart()), locals, dynamics); for (AST arg : args) arg.compile(locals, dynamics, code, false); Var v = (Var) op; lookup(v.name, dynamics).apply(args.length, getLineStart(), code, locals, dynamics, isLast); }
private void compileApplyFun( List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { code.add(new StartCall(getLineStart()), locals, dynamics); for (AST arg : args) arg.compile(locals, dynamics, code, false); Fun fun = (Fun) op; fun.compileApply(locals, dynamics, code, isLast); }
public void compile( List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { // The expressions matched by the case arms are set in the stack frame as // locals... int base = locals.length(); int index = 0; for (AST exp : exps) { exp.compile(locals, dynamics, code, false); locals = locals.cons(new FrameVar("$case-" + (index++), locals.length())); code.add(new SetFrame(getLineStart(), locals.length() - 1), locals, dynamics); code.add(new Pop(getLineStart()), locals, dynamics); } compileArms(base, locals, dynamics, code, isLast); }
public void compileBehaviour(List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code) { // Compilation of a behaviour produces a closure-like value that captures // the current // dynamics and waits to be transformed into an actor via 'new'. CodeBox bodyCode = new CodeBox(path, maxLocals() + 1); // Message will be local 0 in the stack frame... locals = new Nil<FrameVar>().cons(new FrameVar("$0", 0)); bodyCode.add(new instrs.vars.FrameVar(getLineStart(), 0), locals, dynamics); Case handlers = new Case(getFirstHandlerLine(), getLineEnd(), new Dec[] {}, new AST[] {}, arms); handlers.compileArms(0, locals, dynamics, bodyCode, true); bodyCode.add(new Return(getLineStart()), locals, dynamics); int initIndex = bodyCode.getCode().size(); init.compile(locals, dynamics, bodyCode, false); bodyCode.add(new PopFrame(getLineStart()), locals, dynamics); // Set the locals + 1 since the message is the first local... code.add( new instrs.data.Behaviour( getLineStart(), toKeys(exports.getStrings()), initIndex, bodyCode, handlesTime()), locals, dynamics); }
public void compileArms( int varIndex, List<FrameVar> locals, List<DynamicVar> dynamics, CodeBox code, boolean isLast) { boolean useSwitchTable = isDisjointArms() && arms.length > 3; SwitchTable switchTableInstr = new SwitchTable(getLineStart(), varIndex); if (useSwitchTable) code.add(switchTableInstr, locals, dynamics); // Define the dynamic vars up front ... then remove them at the end... // Compile each arm independently... Vector<CodeBox> armCode = new Vector<CodeBox>(); Vector<HashSet<String>> armBV = new Vector<HashSet<String>>(); Vector<HashSet<String>> armDV = new Vector<HashSet<String>>(); for (BArm arm : arms) { // Work out which variables bound by patterns should be local and which // should be dynamic... HashSet<String> DV = new HashSet<String>(); HashSet<String> BV = new HashSet<String>(); for (Pattern p : arm.patterns) p.vars(BV); arm.exp.DV(DV); arm.guard.DV(DV); armBV.add(BV); armDV.add(DV); } for (int i = 0; i < arms.length; i++) { BArm arm = arms[i]; HashSet<String> BV = armBV.get(i); HashSet<String> DV = armDV.get(i); List<FrameVar> armLocals = locals; List<DynamicVar> armDynamics = dynamics; CodeBox instrs = new CodeBox("", 0); // We have just failed to here so remove the dynamic variables from the // previous arm... if (i > 0) { for (String v : armBV.get(i - 1)) { if (armDV.get(i - 1).contains(v)) { instrs.add(new PopDynamic(getLineStart()), locals, dynamics); dynamics = dynamics.getTail(); } } } for (String v : BV) { if (DV.contains(v)) { armDynamics = armDynamics.map(DynamicVar::incDynamic).cons(new DynamicVar(v, 0)); instrs.add(new Null(getLineStart()), locals, dynamics); instrs.add(new NewDynamic(getLineStart()), locals, dynamics); } else armLocals = armLocals.cons(new FrameVar(v, armLocals.length())); } arm.compile(varIndex, armLocals, armDynamics, instrs, isLast && i == arms.length - 1); for (String v : BV) { if (DV.contains(v)) { instrs.add(new PopDynamic(getLineStart()), locals, dynamics); dynamics = dynamics.getTail(); } } armCode.add(instrs); } // Now insert the TRY...SKIP instructions between the arms... for (int i = 0; i < armCode.size(); i++) { int length = code.getCode().size(); instrs.patterns.Try tryArm = new instrs.patterns.Try(getLineStart(), 0, i == 0); code.add(tryArm, locals, dynamics); int base = code.getCode().size(); CodeBox armCodeBox = armCode.get(i); if (useSwitchTable) switchTableInstr.processArm(arms[i], code.getCode().size()); for (Instr instr : armCodeBox.getCode()) { if (instr instanceof Goto) { Goto g = (Goto) instr; g.setAddress(g.getAddress() + base); } code.add( instr, armCodeBox.getLocalsAt(armCodeBox.indexOf(instr)), armCodeBox.getDynamicsAt(armCodeBox.indexOf(instr))); } // Jump over the rest of the case arms and the end error message... int distance = distance(armCode, i + 1) + 2; Skip jmp = new Skip(getLineStart(), distance); code.add(jmp, locals, dynamics); int offset = code.getCode().size() - length; tryArm.setOffset(offset - 1); if (useSwitchTable) switchTableInstr.processError(arms[i], offset - 1); } // Add in the error at the end of the case... code.add(new instrs.patterns.CaseError(getLineStart(), this, varIndex), locals, dynamics); }