📄 typechecker.java
字号:
int type1 = exprType; right.accept(this); if (!isConstant(expr, token, left, right)) computeBinExprType(expr, token, type1); } } else { /* equation: &&, ||, ==, !=, <=, >=, <, > */ booleanExpr(expr); } } /* EXPR must be a + expression. * atPlusExpr() returns non-null if the given expression is string * concatenation. The returned value is "new StringBuffer().append..". */ private Expr atPlusExpr(BinExpr expr) throws CompileError { ASTree left = expr.oprand1(); ASTree right = expr.oprand2(); if (right == null) { // this expression has been already type-checked. // see atBinExpr() above. left.accept(this); return null; } if (isPlusExpr(left)) { Expr newExpr = atPlusExpr((BinExpr)left); if (newExpr != null) { right.accept(this); exprType = CLASS; arrayDim = 0; className = "java/lang/StringBuffer"; return makeAppendCall(newExpr, right); } } else left.accept(this); int type1 = exprType; int dim1 = arrayDim; String cname = className; right.accept(this); if (isConstant(expr, '+', left, right)) return null; if ((type1 == CLASS && dim1 == 0 && jvmJavaLangString.equals(cname)) || (exprType == CLASS && arrayDim == 0 && jvmJavaLangString.equals(className))) { ASTList sbufClass = ASTList.make(new Symbol("java"), new Symbol("lang"), new Symbol("StringBuffer")); ASTree e = new NewExpr(sbufClass, null); exprType = CLASS; arrayDim = 0; className = "java/lang/StringBuffer"; return makeAppendCall(makeAppendCall(e, left), right); } else { computeBinExprType(expr, '+', type1); return null; } } private boolean isConstant(BinExpr expr, int op, ASTree left, ASTree right) throws CompileError { left = stripPlusExpr(left); right = stripPlusExpr(right); ASTree newExpr = null; if (left instanceof StringL && right instanceof StringL && op == '+') newExpr = new StringL(((StringL)left).get() + ((StringL)right).get()); else if (left instanceof IntConst) newExpr = ((IntConst)left).compute(op, right); else if (left instanceof DoubleConst) newExpr = ((DoubleConst)left).compute(op, right); if (newExpr == null) return false; // not a constant expression else { expr.setOperator('+'); expr.setOprand1(newExpr); expr.setOprand2(null); newExpr.accept(this); // for setting exprType, arrayDim, ... return true; } } /* CodeGen.atSwitchStmnt() also calls stripPlusExpr(). */ static ASTree stripPlusExpr(ASTree expr) { if (expr instanceof BinExpr) { BinExpr e = (BinExpr)expr; if (e.getOperator() == '+' && e.oprand2() == null) return e.getLeft(); } else if (expr instanceof Expr) { // note: BinExpr extends Expr. Expr e = (Expr)expr; int op = e.getOperator(); if (op == MEMBER) { ASTree cexpr = getConstantFieldValue((Member)e.oprand2()); if (cexpr != null) return cexpr; } else if (op == '+' && e.getRight() == null) return e.getLeft(); } else if (expr instanceof Member) { ASTree cexpr = getConstantFieldValue((Member)expr); if (cexpr != null) return cexpr; } return expr; } /** * If MEM is a static final field, this method returns a constant * expression representing the value of that field. */ private static ASTree getConstantFieldValue(Member mem) { return getConstantFieldValue(mem.getField()); } public static ASTree getConstantFieldValue(CtField f) { if (f == null) return null; Object value = f.getConstantValue(); if (value == null) return null; if (value instanceof String) return new StringL((String)value); else if (value instanceof Double || value instanceof Float) { int token = (value instanceof Double) ? DoubleConstant : FloatConstant; return new DoubleConst(((Number)value).doubleValue(), token); } else if (value instanceof Number) { int token = (value instanceof Long) ? LongConstant : IntConstant; return new IntConst(((Number)value).longValue(), token); } else if (value instanceof Boolean) return new Keyword(((Boolean)value).booleanValue() ? TokenId.TRUE : TokenId.FALSE); else return null; } private static boolean isPlusExpr(ASTree expr) { if (expr instanceof BinExpr) { BinExpr bexpr = (BinExpr)expr; int token = bexpr.getOperator(); return token == '+'; } return false; } private static Expr makeAppendCall(ASTree target, ASTree arg) { return CallExpr.makeCall(Expr.make('.', target, new Member("append")), new ASTList(arg)); } private void computeBinExprType(BinExpr expr, int token, int type1) throws CompileError { // arrayDim should be 0. int type2 = exprType; if (token == LSHIFT || token == RSHIFT || token == ARSHIFT) exprType = type1; else insertCast(expr, type1, type2); if (CodeGen.isP_INT(exprType)) exprType = INT; // type1 may be BYTE, ... } private void booleanExpr(ASTree expr) throws CompileError { int op = CodeGen.getCompOperator(expr); if (op == EQ) { // ==, !=, ... BinExpr bexpr = (BinExpr)expr; bexpr.oprand1().accept(this); int type1 = exprType; int dim1 = arrayDim; bexpr.oprand2().accept(this); if (dim1 == 0 && arrayDim == 0) insertCast(bexpr, type1, exprType); } else if (op == '!') ((Expr)expr).oprand1().accept(this); else if (op == ANDAND || op == OROR) { BinExpr bexpr = (BinExpr)expr; bexpr.oprand1().accept(this); bexpr.oprand2().accept(this); } else // others expr.accept(this); exprType = BOOLEAN; arrayDim = 0; } private void insertCast(BinExpr expr, int type1, int type2) throws CompileError { if (CodeGen.rightIsStrong(type1, type2)) expr.setLeft(new CastExpr(type2, 0, expr.oprand1())); else exprType = type1; } public void atCastExpr(CastExpr expr) throws CompileError { String cname = resolveClassName(expr.getClassName()); expr.getOprand().accept(this); exprType = expr.getType(); arrayDim = expr.getArrayDim(); className = cname; } public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError { expr.getOprand().accept(this); exprType = BOOLEAN; arrayDim = 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("length")) atArrayLength(expr); else if (member.equals("class")) atClassObject(expr); // .class else atFieldRead(expr); } else if (token == MEMBER) { // field read String member = ((Symbol)expr.oprand2()).get(); if (member.equals("class")) atClassObject(expr); // .class else atFieldRead(expr); } else if (token == ARRAY) atArrayRead(oprand, expr.oprand2()); else if (token == PLUSPLUS || token == MINUSMINUS) atPlusPlus(token, oprand, expr); else if (token == '!') booleanExpr(expr); else if (token == CALL) // method call fatal(); else { oprand.accept(this); if (!isConstant(expr, token, oprand)) if (token == '-' || token == '~') if (CodeGen.isP_INT(exprType)) exprType = INT; // type may be BYTE, ... } } private boolean isConstant(Expr expr, int op, ASTree oprand) { oprand = stripPlusExpr(oprand); if (oprand instanceof IntConst) { IntConst c = (IntConst)oprand; long v = c.get(); if (op == '-') v = -v; else if (op == '~') v = ~v; else return false; c.set(v); } else if (oprand instanceof DoubleConst) { DoubleConst c = (DoubleConst)oprand; if (op == '-') c.set(-c.get()); else return false; } else return false; expr.setOperator('+'); return true; } public void atCallExpr(CallExpr expr) throws CompileError { String mname = null; CtClass targetClass = null; ASTree method = expr.oprand1(); ASTList args = (ASTList)expr.oprand2(); if (method instanceof Member) { mname = ((Member)method).get(); targetClass = thisClass; } else if (method instanceof Keyword) { // constructor mname = MethodInfo.nameInit; // <init> if (((Keyword)method).get() == SUPER) targetClass = MemberResolver.getSuperclass(thisClass); else targetClass = thisClass; } else if (method instanceof Expr) { Expr e = (Expr)method; mname = ((Symbol)e.oprand2()).get(); int op = e.getOperator(); if (op == MEMBER) // static method targetClass = resolver.lookupClass(((Symbol)e.oprand1()).get(), false); else if (op == '.') { ASTree target = e.oprand1(); try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -