Ejemplo n.º 1
0
 private void processDeclarations(Env<String, Type> env) {
   // The declarations type the pattern variables...
   for (Dec dec : decs) env = env.bind(dec.getName(), dec.getDeclaredType());
   for (BArm arm : arms) {
     arm.processDeclarations(env);
   }
 }
Ejemplo n.º 2
0
 public int maxLocals() {
   // Be sure to add in local slots for each of the expression values...
   int maxLocals = 0;
   for (AST exp : exps) maxLocals = Math.max(maxLocals, exp.maxLocals());
   for (BArm arm : arms) maxLocals = Math.max(maxLocals, arm.maxLocals());
   return maxLocals + exps.length;
 }
Ejemplo n.º 3
0
  public Type type(Env<String, Type> env) {

    // The case expression may include declarations that
    // type the bound variables in patterns. The pattern
    // variables are updated...

    processDeclarations(env);

    // Get the types of the supplied values...

    Type[] suppliedTypes = new Type[exps.length];
    Type[] expectedTypes = new Type[exps.length];

    for (int i = 0; i < exps.length; i++) {
      suppliedTypes[i] = exps[i].type(env);
      expectedTypes[i] = ast.types.Void.VOID;
    }

    // The return type. Any void return types are ignored...

    Type resultType = null;

    for (BArm arm : arms) {
      int lineStart = arm.patterns[0].getLineStart();
      int lineEnd = arm.patterns[0].getLineEnd();
      if (arm.patterns.length == exps.length) {
        HandlerType handlerType = arm.type(env);
        for (int i = 0; i < exps.length; i++) {
          if (!Term.equals(handlerType.getTypes()[i], suppliedTypes[i], env)) {
            throw new TypeMatchError(
                lineStart, lineEnd, suppliedTypes[i], handlerType.getTypes()[i]);
          }
        }
        if (resultType == null) resultType = handlerType.getResult();
        else if (!Type.equals(resultType, handlerType.getResult(), env))
          throw new TypeError(
              lineStart,
              lineEnd,
              "incompatible case arm return types "
                  + resultType
                  + " and "
                  + handlerType.getResult());
      } else throw new TypeError(lineStart, lineEnd, "incorrect number of arm patterns.");
    }

    return resultType;
  }
Ejemplo n.º 4
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);
  }
Ejemplo n.º 5
0
 public void setPath(String path) {
   for (AST exp : exps) exp.setPath(path);
   for (BArm arm : arms) arm.setPath(path);
 }
Ejemplo n.º 6
0
 public void DV(HashSet<String> vars) {
   for (AST exp : exps) exp.DV(vars);
   for (BArm arm : arms) arm.DV(vars);
 }