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(); } }
static int getCompOperator(ASTree expr) throws CompileError { if (expr instanceof Expr) { Expr bexpr = (Expr) expr; int token = bexpr.getOperator(); if (token == '!') return '!'; else if ((bexpr instanceof BinExpr) && token != OROR && token != ANDAND && token != '&' && token != '|') return EQ; // ==, !=, ... else return token; } return ' '; // others }
protected void atAssignExpr(AssignExpr expr, boolean doDup) throws CompileError { // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>= int op = expr.getOperator(); ASTree left = expr.oprand1(); ASTree right = expr.oprand2(); if (left instanceof Variable) atVariableAssign(expr, op, (Variable) left, ((Variable) left).getDeclarator(), right, doDup); else { if (left instanceof Expr) { Expr e = (Expr) left; if (e.getOperator() == ARRAY) { atArrayAssign(expr, op, (Expr) left, right, doDup); return; } } atFieldAssign(expr, op, left, right, doDup); } }
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 atPlusPlus(int token, ASTree oprand, Expr expr, boolean doDup) throws CompileError { boolean isPost = oprand == null; // ++i or i++? if (isPost) oprand = expr.oprand2(); if (oprand instanceof Variable) { Declarator d = ((Variable) oprand).getDeclarator(); int t = exprType = d.getType(); arrayDim = d.getArrayDim(); int var = getLocalVar(d); if (arrayDim > 0) badType(expr); if (t == DOUBLE) { bytecode.addDload(var); if (doDup && isPost) bytecode.addOpcode(DUP2); bytecode.addDconst(1.0); bytecode.addOpcode(token == PLUSPLUS ? DADD : DSUB); if (doDup && !isPost) bytecode.addOpcode(DUP2); bytecode.addDstore(var); } else if (t == LONG) { bytecode.addLload(var); if (doDup && isPost) bytecode.addOpcode(DUP2); bytecode.addLconst((long) 1); bytecode.addOpcode(token == PLUSPLUS ? LADD : LSUB); if (doDup && !isPost) bytecode.addOpcode(DUP2); bytecode.addLstore(var); } else if (t == FLOAT) { bytecode.addFload(var); if (doDup && isPost) bytecode.addOpcode(DUP); bytecode.addFconst(1.0f); bytecode.addOpcode(token == PLUSPLUS ? FADD : FSUB); if (doDup && !isPost) bytecode.addOpcode(DUP); bytecode.addFstore(var); } else if (t == BYTE || t == CHAR || t == SHORT || t == INT) { if (doDup && isPost) bytecode.addIload(var); int delta = token == PLUSPLUS ? 1 : -1; if (var > 0xff) { bytecode.addOpcode(WIDE); bytecode.addOpcode(IINC); bytecode.addIndex(var); bytecode.addIndex(delta); } else { bytecode.addOpcode(IINC); bytecode.add(var); bytecode.add(delta); } if (doDup && !isPost) bytecode.addIload(var); } else badType(expr); } else { if (oprand instanceof Expr) { Expr e = (Expr) oprand; if (e.getOperator() == ARRAY) { atArrayPlusPlus(token, isPost, e, doDup); return; } } atFieldPlusPlus(token, isPost, oprand, expr, doDup); } }