예제 #1
0
  private void atSwitchStmnt(Stmnt st) throws CompileError {
    compileExpr(st.head());

    ArrayList prevBreakList = breakList;
    breakList = new ArrayList();
    int opcodePc = bytecode.currentPc();
    bytecode.addOpcode(LOOKUPSWITCH);
    int npads = 3 - (opcodePc & 3);
    while (npads-- > 0) bytecode.add(0);

    Stmnt body = (Stmnt) st.tail();
    int npairs = 0;
    for (ASTList list = body; list != null; list = list.tail())
      if (((Stmnt) list.head()).getOperator() == CASE) ++npairs;

    // opcodePc2 is the position at which the default jump offset is.
    int opcodePc2 = bytecode.currentPc();
    bytecode.addGap(4);
    bytecode.add32bit(npairs);
    bytecode.addGap(npairs * 8);

    long[] pairs = new long[npairs];
    int ipairs = 0;
    int defaultPc = -1;
    for (ASTList list = body; list != null; list = list.tail()) {
      Stmnt label = (Stmnt) list.head();
      int op = label.getOperator();
      if (op == DEFAULT) defaultPc = bytecode.currentPc();
      else if (op != CASE) fatal();
      else {
        pairs[ipairs++] =
            ((long) computeLabel(label.head()) << 32)
                + ((long) (bytecode.currentPc() - opcodePc) & 0xffffffff);
      }

      hasReturned = false;
      ((Stmnt) label.tail()).accept(this);
    }

    Arrays.sort(pairs);
    int pc = opcodePc2 + 8;
    for (int i = 0; i < npairs; ++i) {
      bytecode.write32bit(pc, (int) (pairs[i] >>> 32));
      bytecode.write32bit(pc + 4, (int) pairs[i]);
      pc += 8;
    }

    if (defaultPc < 0 || breakList.size() > 0) hasReturned = false;

    int endPc = bytecode.currentPc();
    if (defaultPc < 0) defaultPc = endPc;

    bytecode.write32bit(opcodePc2, defaultPc - opcodePc);

    patchGoto(breakList, endPc);
    breakList = prevBreakList;
  }
예제 #2
0
  private void atForStmnt(Stmnt st) throws CompileError {
    ArrayList prevBreakList = breakList;
    ArrayList prevContList = continueList;
    breakList = new ArrayList();
    continueList = new ArrayList();

    Stmnt init = (Stmnt) st.head();
    ASTList p = st.tail();
    ASTree expr = p.head();
    p = p.tail();
    Stmnt update = (Stmnt) p.head();
    Stmnt body = (Stmnt) p.tail();

    if (init != null) init.accept(this);

    int pc = bytecode.currentPc();
    int pc2 = 0;
    if (expr != null) {
      if (compileBooleanExpr(false, expr)) {
        // in case of "for (...; false; ...)"
        continueList = prevContList;
        breakList = prevBreakList;
        hasReturned = false;
        return;
      }

      pc2 = bytecode.currentPc();
      bytecode.addIndex(0);
    }

    if (body != null) body.accept(this);

    int pc3 = bytecode.currentPc();
    if (update != null) update.accept(this);

    bytecode.addOpcode(Opcode.GOTO);
    bytecode.addIndex(pc - bytecode.currentPc() + 1);

    int pc4 = bytecode.currentPc();
    if (expr != null) bytecode.write16bit(pc2, pc4 - pc2 + 1);

    patchGoto(breakList, pc4);
    patchGoto(continueList, pc3);
    continueList = prevContList;
    breakList = prevBreakList;
    hasReturned = false;
  }
예제 #3
0
  public void atMethodDecl(MethodDecl method) throws CompileError {
    ASTList mods = method.getModifiers();
    setMaxLocals(1);
    while (mods != null) {
      Keyword k = (Keyword) mods.head();
      mods = mods.tail();
      if (k.get() == STATIC) {
        setMaxLocals(0);
        inStaticMethod = true;
      }
    }

    ASTList params = method.getParams();
    while (params != null) {
      atDeclarator((Declarator) params.head());
      params = params.tail();
    }

    Stmnt s = method.getBody();
    atMethodBody(s, method.isConstructor(), method.getReturn().getType() == VOID);
  }
예제 #4
0
  public void atStmnt(Stmnt st) throws CompileError {
    if (st == null) return; // empty

    int op = st.getOperator();
    if (op == EXPR) {
      ASTree expr = st.getLeft();
      doTypeCheck(expr);
      if (expr instanceof AssignExpr) atAssignExpr((AssignExpr) expr, false);
      else if (isPlusPlusExpr(expr)) {
        Expr e = (Expr) expr;
        atPlusPlus(e.getOperator(), e.oprand1(), e, false);
      } else {
        expr.accept(this);
        if (is2word(exprType, arrayDim)) bytecode.addOpcode(POP2);
        else if (exprType != VOID) bytecode.addOpcode(POP);
      }
    } else if (op == DECL || op == BLOCK) {
      ASTList list = st;
      while (list != null) {
        ASTree h = list.head();
        list = list.tail();
        if (h != null) h.accept(this);
      }
    } else if (op == IF) atIfStmnt(st);
    else if (op == WHILE || op == DO) atWhileStmnt(st, op == WHILE);
    else if (op == FOR) atForStmnt(st);
    else if (op == BREAK || op == CONTINUE) atBreakStmnt(st, op == BREAK);
    else if (op == TokenId.RETURN) atReturnStmnt(st);
    else if (op == THROW) atThrowStmnt(st);
    else if (op == TRY) atTryStmnt(st);
    else if (op == SWITCH) atSwitchStmnt(st);
    else if (op == SYNCHRONIZED) atSyncStmnt(st);
    else {
      // LABEL, SWITCH label stament might be null?.
      hasReturned = false;
      throw new CompileError("sorry, not supported statement: TokenId " + op);
    }
  }