Javac source code Simple analysis of the parsing and filling symbol table __java

Source: Internet
Author: User
Tags abstract tree deprecated prev
I. DescriptionA symbol table is a table consisting of a set of symbolic addresses and symbolic information. The information that is enlisted in the symbol table is used at different stages of compilation. In the semantic analysis (the latter step), the symbol table registers the content to be used for the semantic examination and produces the intermediate code, in the target code generation stage, when the party carries on the address assignment to the symbol name, the symbol table is the address assignment basis.


second, the main classes and methods

Parsing and populating the symbol table this process is mainly implemented by Com.sun.tools.javac.comp.Entry and com.sun.tools.javac.comp.MemberEnter two classes.



The main methods of Com.sun.tools.javac.comp.Entry are as follows:

/** * Access class declaration/public void Visitclassdef (Jcclassdecl tree) {Symbol owner = Env.info.scope.owner;
        Scope Enclscope = EnterScope (env);
        Classsymbol C;
            if (Owner.kind = = PCK) {//We are seeing a toplevel class.
            Packagesymbol packge = (packagesymbol) owner;
            for (Symbol q = packge q!= null && q.kind = = PCK; q = q.owner) Q.flags_field |=;
            c = Reader.enterclass (Tree.name, packge);
            Packge.members (). Enterifabsent (c); if (tree.mods.flags & public)!= 0 &&!classnamematchesfilename (c, env)) {Log.error (tree.pos
            (), "Class.public.should.be.in.file", tree.name); } else {if (tree.name.len!= 0 &&!chk.checkuniqueclassname (tree.pos), Tre
                E.name, Enclscope)) {result = null;
            Return } if(Owner.kind = = TYP)
                {//We are seeing a member class.
                c = Reader.enterclass (Tree.name, (typesymbol) owner); if ((Owner.flags_field & INTERFACE)!= 0) {tree.mods.flags |= public |
                STATIC;
                } else {//We are seeing a local class.
                c = Reader.defineclass (Tree.name, owner);
                C.flatname = Chk.localclassname (c);
            if (c.name.len!= 0) Chk.checktransparentclass (Tree.pos (), C, Env.info.scope);

        } tree.sym = C;
        Enter class into ' compiled ' table and enclosing scope.
            if (Chk.compiled.get (c.flatname)!= null) {Duplicateclass (Tree.pos (), c);
            result = new ErrorType (Tree.name, (typesymbol) owner);
            Tree.sym = (classsymbol) result.tsym;
        Return
        } chk.compiled.put (C.flatname, C);

     Enclscope.enter (c);   Set up a environment for class blocks and store in ' Typeenvs '//table, to is retrieved later in Memberenter
        and attribution.
        env<attrcontext> localenv = classenv (tree, env);

        Typeenvs.put (c, localenv);
        Fill out class fields.
        C.completer = Memberenter;
        C.flags_field = Chk.checkflags (Tree.pos (), Tree.mods.flags, C, tree);
        C.sourcefile = Env.toplevel.sourcefile;

        C.members_field = new Scope (c);
        ClassType ct = (ClassType) c.type; 
            if (Owner.kind!= PCK && (C.flags_field & STATIC) = 0) {//We are seeing a local or inner class. Set Outer_field of this class to closest enclosing class//which contains this class in a non
            -static Context//(its "enclosing instance class"), provided such a class exists.
            Symbol Owner1 = owner; while (Owner1.kind & VAR | MTH)!= 0 && (owner1.flags_fIeld & STATIC) = = 0) {owner1 = Owner1.owner;
            } if (Owner1.kind = = TYP) {ct.setenclosingtype (owner1.type);
        }//Enter type parameters.

        Ct.typarams_field = Classenter (Tree.typarams, localenv);
        ADD Non-local class to uncompleted, to make sure it would be//completed later.
if (!c.islocal () && uncompleted!= null) uncompleted.append (c); System.err.println ("entering" + C.fullname + "in" + C.owner),//debug//recursively enter all member C
        Lasses.

        Classenter (Tree.defs, localenv);
    result = C.type;
     }/** Main Method:enter All classes in a list of toplevel trees.
     * @param trees the list of trees to be processed.
    */public void main (list<jccompilationunit> trees) {Complete (trees, null); }/** * Main Method:enter one class from a list of toplevel trees and * placE The rest on uncompleted for later processing.
     * @param trees the list of trees to be processed.
     * @param c the class symbol to be processed.
        * * public void complete (list<jccompilationunit> trees, Classsymbol c) {Annotate.enterstart ();
        listbuffer<classsymbol> prevuncompleted = uncompleted;

        if (memberenter.completionenabled) uncompleted = new listbuffer<classsymbol> ();

            try {//Enter all classes, and construct uncompleted list classenter (trees, NULL);  Complete all uncompleted classes in Memberenter if (memberenter.completionenabled) {while (Uncompleted.nonempty ())
                    {Classsymbol clazz = Uncompleted.next ();
                    if (c = null | | c = = Clazz | | prevuncompleted = NULL) Clazz.complete ();
  else//Put the class symbol into the prevuncompleted list (uncompleted list)                      Prevuncompleted.append (Clazz); }//If there remain any unimported toplevels (such must have/no classes at all), pro
                Cess their import statements as. /** * uncompleted symbols not in the list (except for the class symbol), according to the Improt declaration, adds a Memberenter object to the top-level abstract tree * These symbols, including the parameter type notation of the class, are is a generic, parent-class symbol, interface-type character, and so on) */for (Jccompilationunit tree:trees) {if (tree.s
                        Tarimportscope.elems = = null) {Javafileobject prev = Log.usesource (tree.sourcefile);
                        env<attrcontext> env = Typeenvs.get (tree);
                        if (env = null) env = toplevelenv (tree);
                        Memberenter.memberenter (tree, env);
                    Log.usesource (prev);
          Finally {//prevuncompleted list assignment to uncompleted list}}}}  uncompleted = prevuncompleted;
        Annotate.enterdone ();
  }
    }


The main methods of Com.sun.tools.javac.comp.MemberEnter are as follows:

/** Complete entering a class.
     * Resolves all symbols in the unhandled list to their respective class notation table * @param sym the symbol of the class to be completed. */public void complete (Symbol sym) throws Completionfailure {//Suppress some (recursive) Memberenter Invoca
            tions if (!completionenabled) {//re-install same completer for next time around and return.
            ASSERT (Sym.flags () & flags.compound) = = 0;
            Sym.completer = this;
        Return
        } classsymbol C = (classsymbol) sym;
        ClassType ct = (ClassType) c.type;
        env<attrcontext> env = Enter.typeEnvs.get (c);
        Jcclassdecl tree = (jcclassdecl) env.tree;
        Boolean wasfirst = Isfirst;

        Isfirst = false;
        Javafileobject prev = Log.usesource (env.toplevel.sourcefile);
            try {//Save class environment for later member enter (2) processing.

            Halfcompleted.append (env); If This is a toplevel-class, Make sure any preceding import//clauses have been.
                if (C.owner.kind = = PCK) {memberenter (Env.toplevel, env.enclosing (Jctree.toplevel));
            Todo.append (env);
            }//Mark class as not yet attributed.

            C.flags_field |= unattributed;

            if (C.owner.kind = = TYP) c.owner.complete ();

            Create an environment to evaluating the base clauses env<attrcontext> baseenv = baseenv (tree, ENV);
            Determine supertype. Type supertype = (tree.extending!= null)? Attr.attribbase (tree.extending, Baseenv, True, False, True): (Tree.mods.flags & Flags.enum)!= 0 &am p;&!target.compilerbootstrap (c))? Attr.attribbase (Enumbase (Tree.pos, C), Baseenv, True, False, False): (c
     . FullName = Names.java_lang_object)           ?
            Type.noType:syms.objectType;

            Ct.supertype_field = supertype;
            Determine interfaces.
            listbuffer<type> interfaces = new listbuffer<type> ();
            set<type> interfaceset = new hashset<type> ();
            list<jcexpression> interfacetrees = tree.implementing; if ((Tree.mods.flags & Flags.enum)!= 0 && Target.compilerbootstrap (c)) {//Add interface Com parable<t> interfacetrees = Interfacetrees.prepend (make.
                                                                   Type (New ClassType (Syms.comparableType.getEnclosingType (),
                List.of (C.type), syms.comparableType.tsym)); Add interface Serializable interfacetrees = Interfacetrees.prepend (make .
         Type (Syms.serializabletype));   for (Jcexpression iface:interfacetrees) {Type i = attr.attribbase (Iface, baseenv, Fals
                E, True, true);
                    if (I.tag = = CLASS) {interfaces.append (i);
                Chk.checknotrepeated (Iface.pos (), Types.erasure (i), interfaceset); } if ((C.flags_field & ANNOTATION)!= 0) Ct.interfaces_field = List.of (syms.
            Annotationtype);

            else Ct.interfaces_field = Interfaces.tolist (); if (C.fullname = = Names.java_lang_object) {if (tree.extending!= null) {Chk.checknon
                    Cyclic (Tree.extending.pos (), supertype);
                Ct.supertype_field = Type.notype; else if (Tree.implementing.nonEmpty ()) {Chk.checknoncyclic (TREE.IMPLEMENTING.HEAD.P Os (), Ct.interfaceS_field.head);
                Ct.interfaces_field = List.nil ();
            }//Annotations.  In general, we cannot fully process annotations yet, but we/can attribute the annotation types and then
            Check to the If the//@Deprecated annotation is present.
            Attr.attribannotationtypes (Tree.mods.annotations, baseenv);
            if (Hasdeprecatedannotation (tree.mods.annotations)) C.flags_field |= deprecated;

            Annotatelater (Tree.mods.annotations, baseenv, C);

            Attr.attribtypevariables (Tree.typarams, baseenv);

            Chk.checknoncyclic (Tree.pos (), c.type);
                /** * Add a default constructor (when the class has no construction method)/if ((C.flags () & INTERFACE) = = 0 && !
                Treeinfo.hasconstructors (tree.defs)) {list<type> argtypes = List.nil ();
       list<type> typarams = List.nil ();         list<type> thrown = List.nil ();
                Long ctorflags = 0;
                Boolean based = false;
                    if (C.name.len = = 0) {jcnewclass NC = (jcnewclass) env.next.tree;
                                                                if (nc.constructor!= null) {Type Superconstrtype = Types.membertype (C.type,
                        Nc.constructor);
                        Argtypes = Superconstrtype.getparametertypes ();
                        Typarams = Superconstrtype.gettypearguments ();
                        Ctorflags = Nc.constructor.flags () & VARARGS;
                            if (Nc.encl!= null) {argtypes = Argtypes.prepend (Nc.encl.type);
                        based = true;
                    } thrown = Superconstrtype.getthrowntypes (); }} Jctree Constrdef = Defaultconstructor (make.at tRee.pos), C, Typarams, Argtypes, thrown,
                Ctorflags, based);
            Tree.defs = Tree.defs.prepend (constrdef);
            }//If This is class, enter symbols for this and super to//current scope. if ((C.flags_field & INTERFACE) = = 0) {Varsymbol thissym = new Varsymbol (FINAL |
                Hasinit, Names._this, C.type, C);
                Thissym.pos = Position.firstpos;
                Env.info.scope.enter (THISSYM); if (Ct.supertype_field.tag = = CLASS) {Varsymbol supersym = new Varsymbol (FINA L |
                    Hasinit, Names._super, Ct.supertype_field, C);
                    Supersym.pos = Position.firstpos;
                Env.info.scope.enter (SUPERSYM); }//Check that no PAckage exists with same fully qualified name,//But admit classes in the unnamed package which have the same
            Name as a top-level package.
                if (checkclash && c.owner.kind = PCK && c.owner!= syms.unnamedpackage && Reader.packageexists (C.fullname)) {Log.error (Tree.pos, "clash.with.pkg.of.sa
                Me.Name ", c);
        The catch (Completionfailure ex) {Chk.completionerror (Tree.pos (), ex);
        finally {Log.usesource (prev);
        }//Enter all fields and methods of a set of half completed//classes in a second phase. if (Wasfirst) {try {while (Halfcompleted.nonempty ()) {Finish (Halfcomp
                Leted.next ());
            }} finally {Isfirst = true;
     }//Commit pending annotations       Annotate.flush (); }
    }


third, process and simple source analysis In the Enter process, the compiler finds all the definitions (definitions) found in the current scope (enclosing scope), and registers these definitions as symbols (symbols).
Enter is divided into the following two stages:


First phase:

The compiler registers all the symbols for the class and links the notation to the corresponding scope (scope). The implementation approach is to use a visitor (visitor) class, which iterates through the AST (Abstract syntax tree) to access all classes, including the inner classes inside the class. Enter adds a Memberenter object to the symbol for each class, which is invoked by the second stage.

The method call procedure for the entire operation is as follows:




The above process is an implementation of the visitor pattern.
Enter is a JCTree.Visitor.Enter.classEnter (L.head, env) call Jctree.accept (Visitor v), and the Accept method is the Visitor class inside the calling Visitxxx () method, and the implementation of these methods is in the Enter class. That is, the enter.visitclassdef (jcclassdecl tree) method, in which the class notation is put into the uncompleted list;


The Visitclassdef (jcclassdecl tree) method mainly does three things:

1, the class symbol (the current class) filled in the class itself symbol table, added a Memberenter object

        Enter class into ' compiled ' table and enclosing scope.
        if (Chk.compiled.get (c.flatname)!= null) {
            duplicateclass (Tree.pos (), c);
            result = new ErrorType (Tree.name, (typesymbol) owner);
            Tree.sym = (classsymbol) result.tsym;
            return;
        }
        Chk.compiled.put (C.flatname, c);
        Enclscope.enter (c);
		
		Set Up is environment for class blocks and store in ' Typeenvs '
        //table, to is retrieved later in Memberenter and a Ttribution.
        env<attrcontext> localenv = classenv (tree, env);
        Typeenvs.put (c, localenv);


        Fill out class fields.
        C.completer = Memberenter;
        C.flags_field = Chk.checkflags (Tree.pos (), Tree.mods.flags, C, tree);
        C.sourcefile = Env.toplevel.sourcefile;
        C.members_field = new Scope (c);



2, parse and fill in other class symbols, including the current class used in the internal classes, enumerations, variables and other abstract tree class symbols.
        Enter type parameters.
        Ct.typarams_field = Classenter (Tree.typarams, localenv);




3, put the class symbol into the uncompleted list
if (!c.islocal () && uncompleted!= null) uncompleted.append (c);





Enter adds a Memberenter object to the symbol for each class, which is invoked by the second stage.
Memberenter.memberenter (tree, env);	

Second phase:

These classes are completed by the Memberenter object (completed, which is the enter that completes the member variable of the class). First, Memberenter determines the parameters of a class, the parent class, and the interface. The symbols are then added to the scope of the class. Unlike the previous step, this step is lazy to execute. Members of a class are added to the definition of a class only when they are accessed. The implementation here is done by installing a complete object (Member object) into the symbol of the class. These objects can invoke memberenter when needed.



The method call procedure for the entire operation is as follows:



Enter is a JCTree.Visitor.Enter.classEnter (L.head, env) call Jctree.accept (Visitor v), and the Accept method is the Visitor class inside the calling Visitxxx () method, and the implementation of these methods is in the Enter class. That is, the enter.visitclassdef (jcclassdecl tree) method, in which the class symbol is parsed and filled into the symbol table of the class itself.




Finally, enter all the top-level classes (top-level classes) into a todo-queue.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.