⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attr.java

📁 GJC(Generic Java Compiler)编译器
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/** * @(#)Attr.java	1.93 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.tools.javac.v8.comp;import com.sun.tools.javac.v8.util.*;import com.sun.tools.javac.v8.code.*;import com.sun.tools.javac.v8.tree.*;import com.sun.tools.javac.v8.code.Symbol.*;import com.sun.tools.javac.v8.tree.Tree.*;import com.sun.tools.javac.v8.code.Type.*;/** * This is the main context-dependent analysis phase in GJC. It *  encompasses name resolution, type checking and constant folding as *  subtasks. Some subtasks involve auxiliary classes. *  @see Check *  @see Resolve *  @see ConstFold *  @see Infer */public class Attr extends Tree.Visitor implements Flags, Kinds, TypeTags {    private static final Context.Key attrKey = new Context.Key();    private Name.Table names;    private Log log;    private Symtab syms;    private Resolve rs;    private Check chk;    private TreeMaker make;    private ConstFold cfolder;    private Enter enter;    private TreeInfo treeinfo;    private Target target;    public static Attr instance(Context context) {        Attr instance = (Attr) context.get(attrKey);        if (instance == null)            instance = new Attr(context);        return instance;    }    private Attr(Context context) {        super();        context.put(attrKey, this);        names = Name.Table.instance(context);        log = Log.instance(context);        syms = Symtab.instance(context);        rs = Resolve.instance(context);        chk = Check.instance(context);        make = TreeMaker.instance(context);        enter = Enter.instance(context);        cfolder = ConstFold.instance(context);        treeinfo = TreeInfo.instance(context);        target = Target.instance(context);        Options options = Options.instance(context);        retrofit = options.get("-retrofit") != null;    }    /**      * Switch: retrofit mode?      */    boolean retrofit;    /**     * Check kind and type of given tree against protokind and prototype.     *  If check succeeds, store type in tree and return it.     *  If check fails, store errType in tree and return it.     *  No checks are performed if the prototype is a method type.     *  Its not necessary in this case since we know that kind and type     *  are correct.     *     *  @param tree     The tree whose kind and type is checked     *  @param owntype  The computed type of the tree     *  @param ownkind  The computed kind of the tree     *  @param pkind    The expected kind (or: protokind) of the tree     *  @param pt       The expected type (or: prototype) of the tree     */    Type check(Tree tree, Type owntype, int ownkind, int pkind, Type pt) {        if (owntype.tag != ERROR && pt.tag != METHOD) {            if ((ownkind & ~pkind) == 0) {                owntype = chk.checkType(tree.pos, owntype, pt);            } else {                log.error(tree.pos, "unexpected.type", Resolve.kindNames(pkind),                        Resolve.kindName(ownkind));                owntype = syms.errType;            }        }        tree.type = owntype;        return owntype;    }    /**      * Is given blank final variable assignable, i.e. in a scope where it      *  may be assigned to even though it is final?      *  @param v      The blank final variable.      *  @param env    The current environment.      */    boolean isAssignableAsBlankFinal(VarSymbol v, Env env) {        Symbol owner = ((AttrContext) env.info).scope.owner;        return v.owner == owner || ((owner.name == names.init || owner.kind == VAR ||                (owner.flags() & BLOCK) != 0) && v.owner == owner.owner &&                ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));    }    /**      * Check that variable can be assigned to.      *  @param pos    The current source code position.      *  @param v      The assigned varaible      *  @param base   If the variable is referred to in a Select, the part      *                to the left of the `.', null otherwise.      *  @env          The current environment.      */    void checkAssignable(int pos, VarSymbol v, Tree base, Env env) {        if ((v.flags() & FINAL) != 0 && ((v.flags() & HASINIT) != 0 ||                !((base == null ||                (base.tag == Tree.IDENT && TreeInfo.name(base) == names._this))                && isAssignableAsBlankFinal(v, env)))) {            log.error(pos, "cant.assign.val.to.final.var", v.toJava());        }    }    /**      * Does tree represent a static reference to an identifier?      *  It is assumed that tree is either a SELECT or an IDENT.      *  We have to weed out selects from non-type names here.      *  @param tree    The candidate tree.      */    boolean isStaticReference(Tree tree) {        if (tree.tag == Tree.SELECT) {            Symbol lsym = TreeInfo.symbol(((Select) tree).selected);            if (lsym == null || lsym.kind != TYP) {                return false;            }        }        return true;    }    /**      * Is this symbol a type?      */    static boolean isType(Symbol sym) {        return sym != null && sym.kind == TYP;    }    /**      * The current `this' symbol.      *  @param env    The current environment.      */    Symbol thisSym(Env env) {        return rs.resolveSelf(Position.NOPOS, env, env.enclClass.sym, names._this);    }    /**      * Visitor argument: the current environment.      */    Env env;    /**     * Visitor argument: the currently expected proto-kind.     */    int pkind;    /**     * Visitor argument: the currently expected proto-type.     */    Type pt;    /**     * Visitor result: the computed type.     */    Type result;    /**     * Visitor method: attribute a tree, catching any completion failure     *  exceptions. Return the tree's type.     *     *  @param tree    The tree to be visited.     *  @param env     The environment visitor argument.     *  @param pkind   The protokind visitor argument.     *  @param pt      The prototype visitor argument.     */    Type attribTree(Tree tree, Env env, int pkind, Type pt) {        Env prevEnv = this.env;        int prevPkind = this.pkind;        Type prevPt = this.pt;        try {            this.env = env;            this.pkind = pkind;            this.pt = pt;            tree.accept(this);            return result;        } catch (CompletionFailure ex) {            tree.type = syms.errType;            return chk.completionError(tree.pos, ex);        }        finally { this.env = prevEnv;                  this.pkind = prevPkind;                  this.pt = prevPt;                } }    /**      * Derived visitor method: attribute an expression tree.      */    Type attribExpr(Tree tree, Env env, Type pt) {        return attribTree(tree, env, VAL, pt);    }    /**      * Derived visitor method: attribute an expression tree with      *  no constraints on the computed type.      */    Type attribExpr(Tree tree, Env env) {        return attribTree(tree, env, VAL, Type.noType);    }    /**      * Derived visitor method: attribute a type tree.      */    Type attribType(Tree tree, Env env) {        return attribTree(tree, env, TYP, Type.noType);    }    /**      * Derived visitor method: attribute a statement or definition tree.      */    Type attribStat(Tree tree, Env env) {        return attribTree(tree, env, NIL, Type.noType);    }    /**      * Attribute a list of expressions, returning a list of types.      */    List attribExprs(List trees, Env env, Type pt) {        ListBuffer ts = new ListBuffer();        for (List l = trees; l.nonEmpty(); l = l.tail)            ts.append(attribExpr((Tree) l.head, env, pt));        return ts.toList();    }    /**      * Attribute a list of statements, returning nothing.      */    void attribStats(List trees, Env env) {        for (List l = trees; l.nonEmpty(); l = l.tail)            attribStat((Tree) l.head, env);    }    /**      * Attribute the arguments in a method call, returning a list of types.      */    List attribArgs(List trees, Env env) {        ListBuffer argtypes = new ListBuffer();        for (List l = trees; l.nonEmpty(); l = l.tail)            argtypes.append( chk.checkNonVoid(((Tree) l.head).pos,                    attribTree((Tree) l.head, env, VAL, Infer.anyPoly)));        return argtypes.toList();    }    /**      * Attribute type reference in an `extends' or `implements' clause.      *      *  @param tree              The tree making up the type reference.      *  @param env               The environment current at the reference.      *  @param classExpected     true if only a class is expected here.      *  @param interfaceExpected true if only an interface is expected here.      */    Type attribBase(Tree tree, Env env, boolean classExpected,            boolean interfaceExpected) {        Type t = attribType(tree, env);        t = chk.checkClassType(tree.pos, t);        if (interfaceExpected & (t.tsym.flags() & INTERFACE) == 0) {            log.error(tree.pos, "intf.expected.here");            return syms.errType;        } else if (classExpected & (t.tsym.flags() & INTERFACE) != 0) {            log.error(tree.pos, "no.intf.expected.here");            return syms.errType;        }        if ((t.tsym.flags() & FINAL) != 0) {            log.error(tree.pos, "cant.inherit.from.final", t.tsym.toJava());        }        return t;    }    public void visitClassDef(ClassDef tree) {        if ((((AttrContext) env.info).scope.owner.kind & (VAR | MTH)) != 0)            enter.classEnter(tree, env);        ClassSymbol c = tree.sym;        if (c == null) {            result = null;        } else {            c.complete();            if (((AttrContext) env.info).isSelfCall &&                    env.tree.tag == Tree.NEWCLASS &&                    ((NewClass) env.tree).encl == null) {                c.flags_field |= NOOUTERTHIS;            }            attribClass(tree.pos, c);            result = tree.type = c.type;        }    }    public void visitMethodDef(MethodDef tree) {        MethodSymbol m = tree.sym;        chk.checkOverride(tree, m);        Env localEnv = enter.methodEnv((MethodDef) tree, env);        for (List l = tree.params; l.nonEmpty(); l = l.tail)            attribStat((Tree) l.head, localEnv);        chk.validate(tree.restype);        for (List l = tree.thrown; l.nonEmpty(); l = l.tail)            chk.checkType(((Tree) l.head).pos, ((Tree) l.head).type,                    syms.throwableType);        ClassSymbol owner = env.enclClass.sym;        if (tree.body == null) {            if ((owner.flags() & INTERFACE) == 0 &&                    (tree.flags & (ABSTRACT | NATIVE)) == 0 && !retrofit)                log.error(tree.pos, "missing.meth.body.or.decl.abstract");        } else if ((owner.flags() & INTERFACE) != 0) {            log.error(tree.body.pos, "intf.meth.cant.have.body");        } else if ((tree.flags & ABSTRACT) != 0) {            log.error(tree.pos, "abstract.meth.cant.have.body");        } else if ((tree.flags & NATIVE) != 0) {            log.error(tree.pos, "native.meth.cant.have.body");        } else {            if (tree.name == names.init && owner.type != syms.objectType) {                Block body = tree.body;                if (body.stats.isEmpty() ||                        !TreeInfo.isSelfCall((Tree) body.stats.head)) {                    body.stats = body.stats.prepend(                            enter.SuperCall(make.at(body.pos), VarDef.emptyList,                            false));                }            }            attribStat(tree.body, localEnv);        }        ((AttrContext) localEnv.info).scope.leave();        result = tree.type = m.type;    }    public void visitVarDef(VarDef tree) {        if (((AttrContext) env.info).scope.owner.kind == MTH)            enter.phase2.memberEnter(tree, env);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -