Javac之Environment

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javac之Environment相关的知识,希望对你有一定的参考价值。

 

关于Env的源代码如下:

/** A class for environments, instances of which are passed as
 *  arguments to tree visitors.  Environments refer to important ancestors
 *  of the subtree that‘s currently visited, such as the enclosing method,
 *  the enclosing class, or the enclosing toplevel node. They also contain
 *  a generic component, represented as a type parameter, to carry further
 *  information specific to individual passes.
 *  
 *  一个类的环境,它的实例将被作为树访问者的参数进行传递。环境涉及到重要的子树的先祖,子树是目前被访问过的。例如封闭的方法、
 *  封闭的类或者是封闭的顶层结点。它们也包含了一个一般性的组件,被描述为类型参数,针对个别的传递携带更多的信息
 *
 */
public class Environment<A> implements Iterable<Environment<A>> {

    /** The next enclosing env.
     * 
     *  下一个封闭的环境,和作用域是不同的。这个与语法树的组织嵌套是一样的
     */
    public Environment<A> next;

    /** The env enclosing the current class.
     * 
     *  封闭了当前类的环境,与语法树的组织嵌套一样的,只是只保存类的上一层嵌套结构,可能是Block,Class,JCCompilationUnit与JCNewClass
     *  因为只有这几个结构中可以定义类
     */
    public Environment<A> outer;

    /** The tree with which this env is associated.
     * 
     *  和当前环境相关联的语法树
     */
    public JCTree tree; // 查看environment主要是看tree属性,看这个环境属于哪个语法节点即可

    /** The enclosing toplevel tree.
     * 
     *  封闭的顶层语法树,语法节点类型为JCCompilationUnit
     */
    public JCCompilationUnit toplevel;

    /** The next enclosing class definition.
     * 
     *  封闭当前环境的类,也是最近的那个类。类的enclosingClass就是自己
     */
    public JCClassDeclaration enclosingClass;

    /** The next enclosing method definition.
     *  下一个封闭的方法定义
     */
    public JCMethodDeclaration enclosingMethod;

    /** A generic field for further information.
     * 
     *  一个能携带将来指定信息的通用属性。在这里一般是AttrContext
     */
    public A info;

    /** Is this an env for evaluating a base clause?
     * 
     *  这是评估一个基础子句的环境,查看 MemberEnter类中的baseEnvironment()方法
     */
    public boolean baseClause = false;

    /** Create an outermost env for a given (toplevel)tree,with a given info field.
     *  
     *  为一个给定的(顶层)节点树和一个给定的属性相关信息创建一个最外层的环境
     */
    public Environment(JCTree jcTree, A info) {
        this.next = null;
        this.outer = null;
        this.tree = jcTree;
        this.toplevel = null;
        this.enclosingClass = null;
        this.enclosingMethod = null;
        this.info = info;
    }

    /** Duplicate this env, updating with given tree and info,
     *  and copying all other fields.
     */
    public Environment<A> duplicate(JCTree jcTree, A info) {
        Environment<A> environment = new Environment<A>(jcTree, info);
        Environment<A> copy = duplicateto(environment);
        return copy;
//        return duplicateto(new Environment<A>(tree, info));
    }

    /** Duplicate this env into a given Environment,using its tree and info, and copying all other fields.
     */
    public Environment<A> duplicateto(Environment<A> that) {
        that.next = this;    // 将这个对象赋值给拷贝对象的next属性
        that.outer = this.outer;
        that.toplevel = this.toplevel;
        that.enclosingClass = this.enclosingClass;
        that.enclosingMethod = this.enclosingMethod;
        // tree和info信息用that自己的
        return that;
    }

    /** Duplicate this env, updating with given tree,and copying all other fields.
     */
    public Environment<A> duplicate(JCTree jcTree) {
        // 只更新了tree属性,其它的信息都使用这个环境的
        return duplicate(jcTree, this.info);
    }


    /** Return closest enclosing environment which points to a tree with given typeTag.
     */
    public Environment<A> enclosing(int tag) {
        Environment<A> environment1 = this;
        while (environment1 != null && environment1.tree.getTag() != tag){
            environment1 = environment1.next;
        }
        return environment1;
    }

    public String toString() {
        return "Environment[" + info + (outer == null ? "" : ",outer=" + outer) + "]";
    }

    public Iterator<Environment<A>> iterator() {

        Iterator<Environment<A>> itr = new Iterator<Environment<A>>() {
            Environment<A> next = Environment.this;
            public boolean hasNext() {
                return next.outer != null;
            }
            public Environment<A> next() {
                if (hasNext()) {
                    Environment<A> current = next;
                    next = current.outer;
                    return current;
                }
                throw new NoSuchElementException();

            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };

        return itr;
    }
}

 

举个例子,如下:

interface I{
	void m1();
}
public class Test3{
	static void t(){}
	static I a = new I(){
		@Override
		public void m1() {
			t();
		}
	};
}

那么t()的环境Env的结构如下截图。

技术分享  

 

这是outer属性,而next属性和语法树的组织结构是严格一致的,如下截图。

技术分享

而其中的info属性一般为AttrContext,源代码如下:

/** Contains information specific to the attribute and enter
 *  passes, to be used in place of the generic field in environments.
 *
 */
public class AttrContext {

    /** The scope of local symbols.
     */
    Scope scope = null;

    /** The number of enclosing `static‘ modifiers.
     */
    int staticLevel = 0;

    /** Is this an environment for a this(...) or super(...) call?
     */
    boolean isSelfCall = false;

    /** Are we evaluating the selector of a `super‘ or type name?
     */
    boolean selectSuper = false;

    /** Are arguments to current function applications boxed into an array for varargs?
     */
    boolean varArgs = false;

    /** A list of type variables that are all-quantifed in current context.
     */
    List<Type> tvars = List.nil();

    /** A record of the lint/SuppressWarnings currently in effect
     */
    Lint lint;

    /** The variable whose initializer is being attributed
     * useful for detecting self-references in variable initializers
     */
    Symbol enclVar = null;

    /** Duplicate this context, replacing scope field and copying all others.
     */
    AttrContext dup(Scope scope) {
        AttrContext info = new AttrContext();
        info.scope = scope;
        info.staticLevel = staticLevel;
        info.isSelfCall = isSelfCall;
        info.selectSuper = selectSuper;
        info.varArgs = varArgs;
        info.tvars = tvars;
        info.lint = lint;
        info.enclVar = enclVar;
        return info;
    }

    /** Duplicate this context, copying all fields.
     */
    AttrContext dup() {
        return dup(scope);
    }

    public Iterable<Symbol> getLocalElements() {
        if (scope == null)
            return List.nil();
        return scope.getElements();
    }

    public String toString() {
        return "AttrContext[" + scope.toString() + "]";
    }
}

  

在如上的例子中,JCVariableDecl节点及子结点的staticLevel都为1,而其父结节点及以上为0。再举个例子,如下:

 

public class Test3{
	static{                      // staticLevel = 1
		// 在static块中不允许再有static出现,如
		// static int a = 1;
		// static class A{}
		// class A{
		//  public static void m1(){}
		// }
		int a = 1;               // staticLevel = 1
	}
	// 这个类的staticLevel为0,与一般类没有任何区别
	static class Inner{          // staticLevel = 0 
		public static void m1(){ // staticLevel = 1
			int b = 1;           // staticLevel = 1
		}
	}
}

 

  

 

以上是关于Javac之Environment的主要内容,如果未能解决你的问题,请参考以下文章

Javac语法糖之增强for循环

C#程序员经常用到的10个实用代码片段 - 操作系统

JVM进阶之字节码文件解析指令

面向面试编程代码片段之GC

Maven之java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTags异常分析

Spring之Environment