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(); } }
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"; }
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)); }
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); } }
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; }