Example #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
    }
  }
Example #2
0
  private int compileOprands(BinExpr expr) throws CompileError {
    expr.oprand1().accept(this);
    int type1 = exprType;
    int dim1 = arrayDim;
    expr.oprand2().accept(this);
    if (dim1 != arrayDim)
      if (type1 != NULL && exprType != NULL) throw new CompileError("incompatible array types");
      else if (exprType == NULL) arrayDim = dim1;

    if (type1 == NULL) return exprType;
    else return type1;
  }
Example #3
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;
  }