예제 #1
0
  public void atExpr(Expr expr) throws CompileError {
    // array access, member access,
    // (unary) +, (unary) -, ++, --, !, ~

    int token = expr.getOperator();
    ASTree oprand = expr.oprand1();
    if (token == '.') {
      String member = ((Symbol) expr.oprand2()).get();
      if (member.equals("class")) atClassObject(expr); // .class
      else atFieldRead(expr);
    } else if (token == MEMBER) { // field read
      /* MEMBER ('#') is an extension by Javassist.
       * The compiler internally uses # for compiling .class
       * expressions such as "int.class".
       */
      atFieldRead(expr);
    } else if (token == ARRAY) atArrayRead(oprand, expr.oprand2());
    else if (token == PLUSPLUS || token == MINUSMINUS) atPlusPlus(token, oprand, expr, true);
    else if (token == '!') {
      if (!booleanExpr(false, expr)) {
        bytecode.addIndex(7);
        bytecode.addIconst(1);
        bytecode.addOpcode(Opcode.GOTO);
        bytecode.addIndex(4);
      }

      bytecode.addIconst(0);
    } else if (token == CALL) // method call
    fatal();
    else {
      expr.oprand1().accept(this);
      int type = typePrecedence(exprType);
      if (arrayDim > 0) badType(expr);

      if (token == '-') {
        if (type == P_DOUBLE) bytecode.addOpcode(DNEG);
        else if (type == P_FLOAT) bytecode.addOpcode(FNEG);
        else if (type == P_LONG) bytecode.addOpcode(LNEG);
        else if (type == P_INT) {
          bytecode.addOpcode(INEG);
          exprType = INT; // type may be BYTE, ...
        } else badType(expr);
      } else if (token == '~') {
        if (type == P_INT) {
          bytecode.addIconst(-1);
          bytecode.addOpcode(IXOR);
          exprType = INT; // type may be BYTE. ...
        } else if (type == P_LONG) {
          bytecode.addLconst(-1);
          bytecode.addOpcode(LXOR);
        } else badType(expr);

      } else if (token == '+') {
        if (type == P_OTHER) badType(expr);

        // do nothing. ignore.
      } else fatal();
    }
  }
예제 #2
0
  public void atClassObject(Expr expr) throws CompileError {
    ASTree op1 = expr.oprand1();
    if (!(op1 instanceof Symbol)) throw new CompileError("fatal error: badly parsed .class expr");

    String cname = ((Symbol) op1).get();
    if (cname.startsWith("[")) {
      int i = cname.indexOf("[L");
      if (i >= 0) {
        String name = cname.substring(i + 2, cname.length() - 1);
        String name2 = resolveClassName(name);
        if (!name.equals(name2)) {
          /* For example, to obtain String[].class,
           * "[Ljava.lang.String;" (not "[Ljava/lang/String"!)
           * must be passed to Class.forName().
           */
          name2 = MemberResolver.jvmToJavaName(name2);
          StringBuffer sbuf = new StringBuffer();
          while (i-- >= 0) sbuf.append('[');

          sbuf.append('L').append(name2).append(';');
          cname = sbuf.toString();
        }
      }
    } else {
      cname = resolveClassName(MemberResolver.javaToJvmName(cname));
      cname = MemberResolver.jvmToJavaName(cname);
    }

    atClassObject2(cname);
    exprType = CLASS;
    arrayDim = 0;
    className = "java/lang/Class";
  }
예제 #3
0
  public void atArrayPlusPlus(int token, boolean isPost, Expr expr, boolean doDup)
      throws CompileError {
    arrayAccess(expr.oprand1(), expr.oprand2());
    int t = exprType;
    int dim = arrayDim;
    if (dim > 0) badType(expr);

    bytecode.addOpcode(DUP2);
    bytecode.addOpcode(getArrayReadOp(t, arrayDim));
    int dup_code = is2word(t, dim) ? DUP2_X2 : DUP_X2;
    atPlusPlusCore(dup_code, doDup, token, isPost, expr);
    bytecode.addOpcode(getArrayWriteOp(t, dim));
  }
예제 #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);
    }
  }
예제 #5
0
  private void atArrayAssign(Expr expr, int op, Expr array, ASTree right, boolean doDup)
      throws CompileError {
    arrayAccess(array.oprand1(), array.oprand2());

    if (op != '=') {
      bytecode.addOpcode(DUP2);
      bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));
    }

    int aType = exprType;
    int aDim = arrayDim;
    String cname = className;

    atAssignCore(expr, op, right, aType, aDim, cname);

    if (doDup)
      if (is2word(aType, aDim)) bytecode.addOpcode(DUP2_X2);
      else bytecode.addOpcode(DUP_X2);

    bytecode.addOpcode(getArrayWriteOp(aType, aDim));
    exprType = aType;
    arrayDim = aDim;
    className = cname;
  }