标记阶段的标记类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了标记阶段的标记类相关的知识,希望对你有一定的参考价值。
.
标记类为Attr,这个类中将对第一和第二阶段未标记的如Statement和Expression进行标记,作用如下:
进行语义合法性的检查和进行逻辑判断,如:
(1)变量的类型是否匹配
(2)变量在使用前是否已经初始化
(3)能够推导出泛型方法的参数类型
(4)字符串常量的合并
其中还有其它的一些辅助类来完成一些检查:
(1)Check 检查变量类型是否正确,如二元操作符两边的操作数的类型是否匹配,方法返回的类型是否与接收的引用值类型匹配等
(2)Resolve 主要检查变量、方法或者类的访问是否合法、变量是否有静态变量、变量是否已经初始化等
(3)ConstanceFold 常量折叠。
了解下Attr中的方法。
Type attribTree(JCTree jcTree, Environment<AttrContext> environment, int protoKind, Type protoType, String errKey) { // 保存之前的环境 Environment<AttrContext> prevEnv = this.env; int prevPkind = this.protoKind; Type prevPt = this.protoType; String prevErrKey = this.errorKey; try { // 创造自己的环境 this.env = environment; this.protoKind = protoKind; this.protoType = protoType; this.errorKey = errKey; jcTree.accept(this); if (jcTree == breakTree){ throw new BreakAttr(environment); } return result; } catch (CompletionFailure ex) { jcTree.type = symbolTable.errType; return check.completionError(jcTree.position(), ex); } finally { // 还原之前的环境 this.env = prevEnv; this.protoKind = prevPkind; this.protoType = prevPt; this.errorKey = prevErrKey; } }
替换Attr中的几个属性,如下:
/** Visitor argument: the current env. */ Environment<AttrContext> env; /** Visitor argument: the currently expected proto-kind. */ int protoKind; /** Visitor argument: the currently expected proto-type. */ Type protoType; /** Visitor argument: the error key to be generated when a type error occurs */ String errorKey; /** Visitor result: the computed type. */ Type result;
这个方法主要由以下的两个方法调用,如下:
/** Visitor method: attribute a tree, catching any completion failure * exceptions. Return the tree‘s type. * * @param jcTree The tree to be visited. * @param environment The environment visitor argument. * @param protoKind The protokind visitor argument. protoKind 为Symbol的类型Kinds * @param protoType The prototype visitor argument. prototype为Type的类型TypeTags */ Type attribTree(JCTree jcTree, Environment<AttrContext> environment, int protoKind, Type protoType) { return attribTree(jcTree, environment, protoKind, protoType, "incompatible.types"); // 不兼容的类型 } public Type attribExpression(JCTree jcTree, Environment<AttrContext> environment, Type protoType, String key) { Type temp = null; if(protoType.typeTag != ERROR){ temp = protoType; }else{ temp = Type.noType; } return attribTree(jcTree, environment, _VAL_12, temp , key); }
如上两个方法由下面这几个方法调用,主要是attribStatement(),attribType()与attribExpression(),如下:
/** Derived visitor method: attribute an expression tree. */ public Type attribExpression(JCTree jcTree, Environment<AttrContext> environment, Type protoType) { Type temp = null; if(protoType.typeTag != ERROR){ temp = protoType; }else{ temp = Type.noType; } return attribTree(jcTree, environment, _VAL_12, temp); // String a = "a".toString() } /** Derived visitor method: attribute an expression tree with * no constraints on the computed type. */ Type attribExpression(JCTree jcTree, Environment<AttrContext> environment) { return attribTree(jcTree, environment, _VAL_12, Type.noType); // "a".toString(); } /** Derived visitor method: attribute a type tree. */ Type attribType(JCTree jcTree, Environment<AttrContext> environment) { Type result = attribTree(jcTree, environment, _TYP_2, Type.noType); // 类型参数相关 return result; } /** Derived visitor method: attribute a statement or definition tree. */ public Type attribStatement(JCTree jcTree, Environment<AttrContext> environment) { return attribTree(jcTree, environment, _NIL_0, Type.noType); // "a".toString() }
重点关注调用方法时为方法参数protoKind与protoType指定的值。
举例来说变量的类型是否匹配是如何检查的,如下:
package m20170409; import java.io.FileInputStream; public class TestA<T> { public Integer x(){ return new Integer(2); } public void test(int a){ Integer x = x().toString(); // 声明与初始化类型不匹配 } }
以上是关于标记阶段的标记类的主要内容,如果未能解决你的问题,请参考以下文章