Example #1
0
  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();
    }
  }
Example #2
0
 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);
   }
 }
Example #3
0
 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);
 }
Example #4
0
 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);
 }
Example #5
0
  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);
  }
Example #6
0
  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);
  }
Example #7
0
  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);
  }