📄 typechecker.java
字号:
target.accept(this); } catch (NoFieldException nfe) { if (nfe.getExpr() != target) throw nfe; // it should be a static method. exprType = CLASS; arrayDim = 0; className = nfe.getField(); // JVM-internal e.setOperator(MEMBER); e.setOprand1(new Symbol(MemberResolver.jvmToJavaName( className))); } if (arrayDim > 0) targetClass = resolver.lookupClass(javaLangObject, true); else if (exprType == CLASS /* && arrayDim == 0 */) targetClass = resolver.lookupClassByJvmName(className); else badMethod(); } else badMethod(); } else fatal(); MemberResolver.Method minfo = atMethodCallCore(targetClass, mname, args); expr.setMethod(minfo); } private static void badMethod() throws CompileError { throw new CompileError("bad method"); } /** * @return a pair of the class declaring the invoked method * and the MethodInfo of that method. Never null. */ public MemberResolver.Method atMethodCallCore(CtClass targetClass, String mname, ASTList args) throws CompileError { int nargs = getMethodArgsLength(args); int[] types = new int[nargs]; int[] dims = new int[nargs]; String[] cnames = new String[nargs]; atMethodArgs(args, types, dims, cnames); MemberResolver.Method found = resolver.lookupMethod(targetClass, thisClass, thisMethod, mname, types, dims, cnames); if (found == null) { String clazz = targetClass.getName(); String signature = argTypesToString(types, dims, cnames); String msg; if (mname.equals(MethodInfo.nameInit)) msg = "cannot find constructor " + clazz + signature; else msg = mname + signature + " not found in " + clazz; throw new CompileError(msg); } String desc = found.info.getDescriptor(); setReturnType(desc); return found; } public int getMethodArgsLength(ASTList args) { return ASTList.length(args); } public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError { int i = 0; while (args != null) { ASTree a = args.head(); a.accept(this); types[i] = exprType; dims[i] = arrayDim; cnames[i] = className; ++i; args = args.tail(); } } void setReturnType(String desc) throws CompileError { int i = desc.indexOf(')'); if (i < 0) badMethod(); char c = desc.charAt(++i); int dim = 0; while (c == '[') { ++dim; c = desc.charAt(++i); } arrayDim = dim; if (c == 'L') { int j = desc.indexOf(';', i + 1); if (j < 0) badMethod(); exprType = CLASS; className = desc.substring(i + 1, j); } else { exprType = MemberResolver.descToType(c); className = null; } } private void atFieldRead(ASTree expr) throws CompileError { atFieldRead(fieldAccess(expr)); } private void atFieldRead(CtField f) throws CompileError { FieldInfo finfo = f.getFieldInfo2(); String type = finfo.getDescriptor(); int i = 0; int dim = 0; char c = type.charAt(i); while (c == '[') { ++dim; c = type.charAt(++i); } arrayDim = dim; exprType = MemberResolver.descToType(c); if (c == 'L') className = type.substring(i + 1, type.indexOf(';', i + 1)); else className = null; } /* if EXPR is to access a static field, fieldAccess() translates EXPR * into an expression using '#' (MEMBER). For example, it translates * java.lang.Integer.TYPE into java.lang.Integer#TYPE. This translation * speeds up type resolution by MemberCodeGen. */ protected CtField fieldAccess(ASTree expr) throws CompileError { if (expr instanceof Member) { Member mem = (Member)expr; String name = mem.get(); try { CtField f = thisClass.getField(name); if (Modifier.isStatic(f.getModifiers())) mem.setField(f); return f; } catch (NotFoundException e) { // EXPR might be part of a static member access? throw new NoFieldException(name, expr); } } else if (expr instanceof Expr) { Expr e = (Expr)expr; int op = e.getOperator(); if (op == MEMBER) { Member mem = (Member)e.oprand2(); CtField f = resolver.lookupField(((Symbol)e.oprand1()).get(), mem); mem.setField(f); return f; } else if (op == '.') try { e.oprand1().accept(this); if (exprType == CLASS && arrayDim == 0) return resolver.lookupFieldByJvmName(className, (Symbol)e.oprand2()); } catch (NoFieldException nfe) { if (nfe.getExpr() != e.oprand1()) throw nfe; /* EXPR should be a static field. * If EXPR might be part of a qualified class name, * lookupFieldByJvmName2() throws NoFieldException. */ Member fname = (Member)e.oprand2(); String jvmClassName = nfe.getField(); CtField f = resolver.lookupFieldByJvmName2(jvmClassName, fname, expr); e.setOperator(MEMBER); e.setOprand1(new Symbol(MemberResolver.jvmToJavaName( jvmClassName))); fname.setField(f); return f; } } throw new CompileError("bad filed access"); } public void atClassObject(Expr expr) throws CompileError { exprType = CLASS; arrayDim = 0; className =jvmJavaLangClass; } public void atArrayLength(Expr expr) throws CompileError { expr.oprand1().accept(this); exprType = INT; arrayDim = 0; } public void atArrayRead(ASTree array, ASTree index) throws CompileError { array.accept(this); int type = exprType; int dim = arrayDim; String cname = className; index.accept(this); exprType = type; arrayDim = dim - 1; className = cname; } private void atPlusPlus(int token, ASTree oprand, Expr expr) throws CompileError { boolean isPost = oprand == null; // ++i or i++? if (isPost) oprand = expr.oprand2(); if (oprand instanceof Variable) { Declarator d = ((Variable)oprand).getDeclarator(); exprType = d.getType(); arrayDim = d.getArrayDim(); } else { if (oprand instanceof Expr) { Expr e = (Expr)oprand; if (e.getOperator() == ARRAY) { atArrayRead(e.oprand1(), e.oprand2()); // arrayDim should be 0. int t = exprType; if (t == INT || t == BYTE || t == CHAR || t == SHORT) exprType = INT; return; } } atFieldPlusPlus(oprand); } } protected void atFieldPlusPlus(ASTree oprand) throws CompileError { CtField f = fieldAccess(oprand); atFieldRead(f); int t = exprType; if (t == INT || t == BYTE || t == CHAR || t == SHORT) exprType = INT; } public void atMember(Member mem) throws CompileError { atFieldRead(mem); } public void atVariable(Variable v) throws CompileError { Declarator d = v.getDeclarator(); exprType = d.getType(); arrayDim = d.getArrayDim(); className = d.getClassName(); } public void atKeyword(Keyword k) throws CompileError { arrayDim = 0; int token = k.get(); switch (token) { case TRUE : case FALSE : exprType = BOOLEAN; break; case NULL : exprType = NULL; break; case THIS : case SUPER : exprType = CLASS; if (token == THIS) className = getThisName(); else className = getSuperName(); break; default : fatal(); } } public void atStringL(StringL s) throws CompileError { exprType = CLASS; arrayDim = 0; className = jvmJavaLangString; } public void atIntConst(IntConst i) throws CompileError { arrayDim = 0; int type = i.getType(); if (type == IntConstant || type == CharConstant) exprType = (type == IntConstant ? INT : CHAR); else exprType = LONG; } public void atDoubleConst(DoubleConst d) throws CompileError { arrayDim = 0; if (d.getType() == DoubleConstant) exprType = DOUBLE; else exprType = FLOAT; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -