关于类的符号输入过程第三篇

本文深入探讨了Java编译过程中的关键步骤,包括MemberEnter后的Attr类标记方法、数据流分析、语法糖解除及字节码生成。同时,详细解析了JCFieldAccess处理流程,以及在visitImport()方法中调用的attribTree方法。通过源码级分析,解释了如何在不同的作用域内查找变量、类型和包,以及如何处理合成字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

当进行完MemberEnter后就可以调用Attr类的一些标记方法了,如下:

while (!todo.isEmpty()){
                    	Environment<AttrContext> a = todo.remove();
                    	Environment<AttrContext> b = attribute(a);  // 标注
                    	Queue<Environment<AttrContext>> c = flow(b); // 数据流分析
                    	Queue<Pair<Environment<AttrContext>, JCClassDeclaration>> d = desugar(c); // 解语法糖
                    	generate(d);  // 生成字节码
//                        generate(desugar(flow(attribute(todo.remove()))));
}

 

在之前的MemberEnter类中visitImport()方法中有如下一个方法调用,如下:

 Type type = attr.attribTree(jcFieldAccess.selected, localEnvironment, protoKind, Type.noType); // protoKind=_TYPE|_PCK,Type.noType=JCNoType

其中JCFieldAccess为java.util.ArrayList,而jcFieldAccess.selected为java.util。  

 

 其中的scope为ImportScope。

 

在标识前,所有的selected的symbol与type都为null。先要进行JCIdentifier的处理,主要经历的方法有三个:

首先visitIdentifier(),在这个方法中调用resolveIdentifier()方法,接着也会调用checkIndentifier()方法。

resolveIdentifier()中会调用findIdentifier()方法查找到name对应的符号Symbol,这个方法的具体代码实现如下:

 /** Find an unqualified identifier which matches a specified kind set.
     *  @param environment       The current environment.
     *  @param name      The identifier's name.
     *  @param kind      Indicates the possible symbol kinds (a subset of _VAL, _TYP, _PCK).
     *
     */
    public Symbol findIdentifier(Environment<AttrContext> environment, Name name, int kind) {
        Symbol bestSoFar = typeNotFound;
        Symbol symbol;

        if ((kind & _VAR) != 0) {
            symbol = findVariable(environment, name);
            if (symbol.exists()){
                return symbol;
            }else if (symbol.kind < bestSoFar.kind){
                bestSoFar = symbol;
            }
        }

        if ((kind & _TYP) != 0) {
            symbol = findType(environment, name);
            if (symbol.exists()){
                return symbol;
            }else if (symbol.kind < bestSoFar.kind){ // ??
                bestSoFar = symbol;
            }
        }

        if ((kind & _PCK) != 0){
            return classReader.enterPackage(name);
        }else{
            return bestSoFar;
        }
    }

name除了代表方法的名称外,其余就是变量、类型和包名称了。优先进行变量名的查找,由于变量名有局部变量和全局变量,所以对应的查找方法就有findVariable()与findField()。

其中findVariable()方法如下:

/** Find unqualified variable or field with given name.
     *  Synthetic fields always skipped.
     *  @param environment     The current environment.
     *  @param name    The name of the variable or field.
     */
    Symbol findVariable(Environment<AttrContext> environment, Name name) {
        Symbol bestSoFar = variableNotFound;
        Symbol symbol;
        Environment<AttrContext> env1 = environment;
        boolean staticOnly = false;
        while (env1.outer != null) {
            if (isStatic(env1)){
                staticOnly = true;
            }

            Entry entry = env1.info.scope.lookup(name);

            while (
                     entry.scope != null &&
                     (entry.symbol.kind != _VAR || (entry.symbol.flags_field & SYNTHETIC) != 0) // 非变量或者是合成的那就需要继续查找
            ){
                entry = entry.next();
            }

            // 走到这里说明entry.symbol.kind==_VAR或者(entry.symbol.flags_field & SYNTHETIC)==0(非合成的变量)

            // 如果findVariable查找不到就要调用findField进行查找
            if(entry.scope != null){
                symbol = entry.symbol;
            }else{
                symbol = findField(env1, env1.enclosingClass.classSymbol.type, name, env1.enclosingClass.classSymbol);
            }

            if( symbol.exists()) {
                if( staticOnly &&
                    symbol.kind == _VAR &&
                    symbol.ownerSymbol.kind == _TYP &&
                    (symbol.flags() & STATIC) == 0) {
                    // 静态上下文中引用非静态的变量
                    return new StaticError(symbol, this);
                }else{
                    return symbol;
                }
            } else if (symbol.kind < bestSoFar.kind) {
                bestSoFar = symbol;
            }

            if ((env1.enclosingClass.classSymbol.flags() & STATIC) != 0){
                staticOnly = true;
            }
            env1 = env1.outer;
        }// end while

        symbol = findField(environment, symbolTable.predefinedClass.type, name, symbolTable.predefinedClass);
        if (symbol.exists()){
            return symbol;
        }
        if (bestSoFar.exists()){
            return bestSoFar;
        }

        Entry entry = environment.toplevel.namedImportScope.lookup(name);
        for (; entry.scope != null; entry = entry.next()) {
            symbol = entry.symbol;
            Type origin = entry.getOrigin().owner.type;
            if (symbol.kind == _VAR) {
                if (entry.symbol.ownerSymbol.type != origin){
                    symbol = symbol.clone(entry.getOrigin().owner);
                }
                if(isAccessible(environment, origin, symbol)){
                    return symbol;
                }else{
                    return new AccessError(environment, origin, symbol, this);
                }
            }
        }

        Symbol origin = null;
        entry = environment.toplevel.starImportScope.lookup(name);
        for (; entry.scope != null; entry = entry.next()) {
            symbol = entry.symbol;
            if (symbol.kind != _VAR){
                continue;
            }
            // invariant: classSymbol.kind == _VAR
            if (bestSoFar.kind < _AMBIGUOUS && symbol.ownerSymbol != bestSoFar.ownerSymbol){
                return new AmbiguityError(bestSoFar, symbol, this);
            }
            else if (bestSoFar.kind >= _VAR) {
                origin = entry.getOrigin().owner;
                if(isAccessible(environment, origin.type, symbol)){
                    bestSoFar = symbol;
                }else{
                    bestSoFar = new AccessError(environment, origin.type, symbol, this);
                }
            }
        }

        // ???
        if (bestSoFar.kind == _VAR && bestSoFar.ownerSymbol.type != origin.type){
            return bestSoFar.clone(origin);
        }else{
            return bestSoFar;
        }
    }

而findField()方法的代码如下:

/** Find field. Synthetic fields are always skipped.
     *  @param environment The current environment.
     *  @param site    The original type from where the selection takes place.
     *  @param name    The name of the field.
     *  @param typeSymbol The class to search for the field. This is always a superclass or implemented interface of site's class.
     */
    Symbol findField(Environment<AttrContext> environment,
                     Type site,
                     Name name,
                     TypeSymbol typeSymbol) {

        while (typeSymbol.type.typeTag == TYPEVARIABLE){
            typeSymbol = typeSymbol.type.getUpperBound().typeSymbol;
        }

        Symbol bestSoFar = variableNotFound;
        Symbol symbol;

        // 查找本类
        Entry entry = typeSymbol.members().lookup(name);
        while (entry.scope != null) {
            // 符号是变量且不是合成的
            if (entry.symbol.kind == _VAR && (entry.symbol.flags_field & SYNTHETIC) == 0) {
                if(isAccessible(environment, site, entry.symbol)){
                    return entry.symbol;
                }else{
                    return new AccessError(environment, site, entry.symbol,this);
                }
            }
            entry = entry.next();
        }

        // 查找父类
        Type superType = types.supertype(typeSymbol.type);
        if (superType != null && (superType.typeTag == CLASS || superType.typeTag == TYPEVARIABLE)) {
            symbol = findField(environment, site, name, superType.typeSymbol); // 递归调用
            if (symbol.kind < bestSoFar.kind){
                bestSoFar = symbol;
            }
        }

        // 查找所有的接口类
        for (List<Type> l = types.interfaces(typeSymbol.type); bestSoFar.kind != _AMBIGUOUS && l.nonEmpty(); l = l.tail) {
            symbol = findField(environment, site, name, l.head.typeSymbol); // 递归调用
            if (bestSoFar.kind < _AMBIGUOUS && symbol.kind < _AMBIGUOUS && symbol.ownerSymbol != bestSoFar.ownerSymbol){
                bestSoFar = new AmbiguityError(bestSoFar, symbol, this);
            }
            else if (symbol.kind < bestSoFar.kind){
                bestSoFar = symbol;
            }
        }
        return bestSoFar;
    }

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

  

转载于:https://www.cnblogs.com/extjs4/p/6664414.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值