예제 #1
0
  public void atBinExpr(BinExpr expr) throws CompileError {
    int token = expr.getOperator();

    /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
     */
    int k = lookupBinOp(token);
    if (k >= 0) {
      expr.oprand1().accept(this);
      ASTree right = expr.oprand2();
      if (right == null) return; // see TypeChecker.atBinExpr().

      int type1 = exprType;
      int dim1 = arrayDim;
      String cname1 = className;
      right.accept(this);
      if (dim1 != arrayDim) throw new CompileError("incompatible array types");

      if (token == '+' && dim1 == 0 && (type1 == CLASS || exprType == CLASS))
        atStringConcatExpr(expr, type1, dim1, cname1);
      else atArithBinExpr(expr, token, k, type1);
    } else {
      /* equation: &&, ||, ==, !=, <=, >=, <, >
       */
      if (!booleanExpr(true, expr)) {
        bytecode.addIndex(7);
        bytecode.addIconst(0); // false
        bytecode.addOpcode(Opcode.GOTO);
        bytecode.addIndex(4);
      }

      bytecode.addIconst(1); // true
    }
  }
예제 #2
0
  protected void arrayAccess(ASTree array, ASTree index) throws CompileError {
    array.accept(this);
    int type = exprType;
    int dim = arrayDim;
    if (dim == 0) throw new CompileError("bad array access");

    String cname = className;

    index.accept(this);
    if (typePrecedence(exprType) != P_INT || arrayDim > 0)
      throw new CompileError("bad array index");

    exprType = type;
    arrayDim = dim - 1;
    className = cname;
  }
예제 #3
0
  private String checkCastExpr(CastExpr expr, String name) throws CompileError {
    final String msg = "invalid cast";
    ASTree oprand = expr.getOprand();
    int dim = expr.getArrayDim();
    int type = expr.getType();
    oprand.accept(this);
    int srcType = exprType;
    if (invalidDim(srcType, arrayDim, className, type, dim, name, true)
        || srcType == VOID
        || type == VOID) throw new CompileError(msg);

    if (type == CLASS) {
      if (!isRefType(srcType)) throw new CompileError(msg);

      return toJvmArrayName(name, dim);
    } else if (dim > 0) return toJvmTypeName(type, dim);
    else return null; // built-in type
  }
예제 #4
0
  private void atStringPlusEq(Expr expr, int type, int dim, String cname, ASTree right)
      throws CompileError {
    if (!jvmJavaLangString.equals(cname)) badAssign(expr);

    convToString(type, dim); // the value might be null.
    right.accept(this);
    convToString(exprType, arrayDim);
    bytecode.addInvokevirtual(javaLangString, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
    exprType = CLASS;
    arrayDim = 0;
    className = jvmJavaLangString;
  }
예제 #5
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);
    }
  }
예제 #6
0
  /* Produces the opcode to branch if the condition is true.
   * The oprand (branch offset) is not produced.
   *
   * @return	true if the compiled code is GOTO (always branch).
   * 			GOTO is not produced.
   */
  private boolean booleanExpr(boolean branchIf, ASTree expr) throws CompileError {
    boolean isAndAnd;
    int op = getCompOperator(expr);
    if (op == EQ) { // ==, !=, ...
      BinExpr bexpr = (BinExpr) expr;
      int type1 = compileOprands(bexpr);
      // here, arrayDim might represent the array dim. of the left oprand
      // if the right oprand is NULL.
      compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);
    } else if (op == '!') return booleanExpr(!branchIf, ((Expr) expr).oprand1());
    else if ((isAndAnd = (op == ANDAND)) || op == OROR) {
      BinExpr bexpr = (BinExpr) expr;
      if (booleanExpr(!isAndAnd, bexpr.oprand1())) {
        exprType = BOOLEAN;
        arrayDim = 0;
        return true;
      } else {
        int pc = bytecode.currentPc();
        bytecode.addIndex(0); // correct later
        if (booleanExpr(isAndAnd, bexpr.oprand2())) bytecode.addOpcode(Opcode.GOTO);

        bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);
        if (branchIf != isAndAnd) {
          bytecode.addIndex(6); // skip GOTO instruction
          bytecode.addOpcode(Opcode.GOTO);
        }
      }
    } else if (isAlwaysBranch(expr, branchIf)) {
      // Opcode.GOTO is not added here.  The caller must add it.
      exprType = BOOLEAN;
      arrayDim = 0;
      return true; // always branch
    } else { // others
      expr.accept(this);
      if (exprType != BOOLEAN || arrayDim != 0) throw new CompileError("boolean expr is required");

      bytecode.addOpcode(branchIf ? IFNE : IFEQ);
    }

    exprType = BOOLEAN;
    arrayDim = 0;
    return false;
  }
예제 #7
0
  protected void atAssignCore(Expr expr, int op, ASTree right, int type, int dim, String cname)
      throws CompileError {
    if (op == PLUS_E && dim == 0 && type == CLASS) atStringPlusEq(expr, type, dim, cname, right);
    else {
      right.accept(this);
      if (invalidDim(exprType, arrayDim, className, type, dim, cname, false)
          || (op != '=' && dim > 0)) badAssign(expr);

      if (op != '=') {
        int token = assignOps[op - MOD_E];
        int k = lookupBinOp(token);
        if (k < 0) fatal();

        atArithBinExpr(expr, token, k, type);
      }
    }

    if (op != '=' || (dim == 0 && !isRefType(type))) atNumCastExpr(exprType, type);

    // type check should be done here.
  }
예제 #8
0
 public void doTypeCheck(ASTree expr) throws CompileError {
   if (typeChecker != null) expr.accept(typeChecker);
 }
예제 #9
0
 public void compileExpr(ASTree expr) throws CompileError {
   doTypeCheck(expr);
   expr.accept(this);
 }