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

📄 gen.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     *  @param env         The environment current at the non-local exit.     */    Env<GenContext> unwind(JCTree target, Env<GenContext> env) {	Env<GenContext> env1 = env;	while (true) {	    genFinalizer(env1);	    if (env1.tree == target) break;	    env1 = env1.next;	}	return env1;    }    /** Mark end of gap in catch-all range for finalizer.     *  @param env   the environment which might contain the finalizer     *               (if it does, env.info.gaps != null).     */    void endFinalizerGap(Env<GenContext> env) {        if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)            env.info.gaps.append(code.curPc());    }    /** Mark end of all gaps in catch-all ranges for finalizers of environments     *  lying between, and including to two environments.     *  @param from    the most deeply nested environment to mark     *  @param to      the least deeply nested environment to mark     */    void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {	Env<GenContext> last = null;	while (last != to) {	    endFinalizerGap(from);	    last = from;	    from = from.next;	}    }    /** Do any of the structures aborted by a non-local exit have     *  finalizers that require an empty stack?     *  @param target      The tree representing the structure that's aborted     *  @param env         The environment current at the non-local exit.     */    boolean hasFinally(JCTree target, Env<GenContext> env) {	while (env.tree != target) {	    if (env.tree.getTag() == JCTree.TRY && env.info.finalize.hasFinalizer())		return true;	    env = env.next;	}	return false;    }/* ************************************************************************ * Normalizing class-members. *************************************************************************/    /** Distribute member initializer code into constructors and <clinit>     *  method.     *  @param defs         The list of class member declarations.     *  @param c            The enclosing class.     */    List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {	ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();	ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();	ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();	// Sort definitions into three listbuffers:	//  - initCode for instance initializers	//  - clinitCode for class initializers	//  - methodDefs for method definitions	for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {	    JCTree def = l.head;	    switch (def.getTag()) {	    case JCTree.BLOCK:		JCBlock block = (JCBlock)def;		if ((block.flags & STATIC) != 0)		    clinitCode.append(block);		else		    initCode.append(block);	        break;	    case JCTree.METHODDEF:		methodDefs.append(def);	        break;	    case JCTree.VARDEF:		JCVariableDecl vdef = (JCVariableDecl) def;		VarSymbol sym = vdef.sym;		checkDimension(vdef.pos(), sym.type);		if (vdef.init != null) {		    if ((sym.flags() & STATIC) == 0) {			// Always initialize instance variables.			JCStatement init = make.at(vdef.pos()).			    Assignment(sym, vdef.init);			initCode.append(init);			if (endPositions != null) {			    Integer endPos = endPositions.remove(vdef);			    if (endPos != null) endPositions.put(init, endPos);			}		    } else if (sym.getConstValue() == null) {			// Initialize class (static) variables only if			// they are not compile-time constants.			JCStatement init = make.at(vdef.pos).			    Assignment(sym, vdef.init);			clinitCode.append(init);			if (endPositions != null) {			    Integer endPos = endPositions.remove(vdef);			    if (endPos != null) endPositions.put(init, endPos);			}		    } else {			checkStringConstant(vdef.init.pos(), sym.getConstValue());		    }		}		break;	    default:		assert false;	    }	}	// Insert any instance initializers into all constructors.	if (initCode.length() != 0) {	    List<JCStatement> inits = initCode.toList();	    for (JCTree t : methodDefs) {                normalizeMethod((JCMethodDecl)t, inits);	    }	}	// If there are class initializers, create a <clinit> method	// that contains them as its body.	if (clinitCode.length() != 0) {	    MethodSymbol clinit = new MethodSymbol(		STATIC, names.clinit,		new MethodType(		    List.<Type>nil(), syms.voidType,		    List.<Type>nil(), syms.methodClass),		c);	    c.members().enter(clinit);	    List<JCStatement> clinitStats = clinitCode.toList();	    JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);	    block.endpos = TreeInfo.endPos(clinitStats.last());	    methodDefs.append(make.MethodDef(clinit, block));	}	// Return all method definitions.	return methodDefs.toList();    }    /** Check a constant value and report if it is a string that is     *  too large.     */    private void checkStringConstant(DiagnosticPosition pos, Object constValue) {	if (nerrs != 0 || // only complain about a long string once	    constValue == null ||	    !(constValue instanceof String) ||	    ((String)constValue).length() < Pool.MAX_STRING_LENGTH)	    return;	log.error(pos, "limit.string");	nerrs++;    }    /** Insert instance initializer code into initial constructor.     *  @param md        The tree potentially representing a     *                   constructor's definition.     *  @param initCode  The list of instance initializer statements.     */    void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode) {	if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {	    // We are seeing a constructor that does not call another	    // constructor of the same class.	    List<JCStatement> stats = md.body.stats;	    ListBuffer<JCStatement> newstats = new ListBuffer<JCStatement>();	    if (stats.nonEmpty()) {		// Copy initializers of synthetic variables generated in		// the translation of inner classes.		while (TreeInfo.isSyntheticInit(stats.head)) {		    newstats.append(stats.head);		    stats = stats.tail;		}		// Copy superclass constructor call		newstats.append(stats.head);		stats = stats.tail;		// Copy remaining synthetic initializers.		while (stats.nonEmpty() &&		       TreeInfo.isSyntheticInit(stats.head)) {		    newstats.append(stats.head);		    stats = stats.tail;		}		// Now insert the initializer code.		newstats.appendList(initCode);		// And copy all remaining statements.		while (stats.nonEmpty()) {		    newstats.append(stats.head);		    stats = stats.tail;		}	    }	    md.body.stats = newstats.toList();	    if (md.body.endpos == Position.NOPOS)		md.body.endpos = TreeInfo.endPos(md.body.stats.last());	}    }/* ******************************************************************** * Adding miranda methods *********************************************************************/    /** Add abstract methods for all methods defined in one of     *  the interfaces of a given class,     *  provided they are not already implemented in the class.     *     *  @param c      The class whose interfaces are searched for methods     *                for which Miranda methods should be added.     */    void implementInterfaceMethods(ClassSymbol c) {	implementInterfaceMethods(c, c);    }    /** Add abstract methods for all methods defined in one of     *  the interfaces of a given class,     *  provided they are not already implemented in the class.     *     *  @param c      The class whose interfaces are searched for methods     *                for which Miranda methods should be added.     *  @param site   The class in which a definition may be needed.     */    void implementInterfaceMethods(ClassSymbol c, ClassSymbol site) {	for (List<Type> l = types.interfaces(c.type); l.nonEmpty(); l = l.tail) {	    ClassSymbol i = (ClassSymbol)l.head.tsym;	    for (Scope.Entry e = i.members().elems;		 e != null;		 e = e.sibling)	    {		if (e.sym.kind == MTH && (e.sym.flags() & STATIC) == 0)		{		    MethodSymbol absMeth = (MethodSymbol)e.sym;		    MethodSymbol implMeth = absMeth.binaryImplementation(site, types);		    if (implMeth == null)			addAbstractMethod(site, absMeth);		    else if ((implMeth.flags() & IPROXY) != 0)			adjustAbstractMethod(site, implMeth, absMeth);		}	    }	    implementInterfaceMethods(i, site);	}    }    /** Add an abstract methods to a class     *  which implicitly implements a method defined in some interface     *  implemented by the class. These methods are called "Miranda methods".     *  Enter the newly created method into its enclosing class scope.     *  Note that it is not entered into the class tree, as the emitter     *  doesn't need to see it there to emit an abstract method.     *     *  @param c      The class to which the Miranda method is added.     *  @param m      The interface method symbol for which a Miranda method     *                is added.     */    private void addAbstractMethod(ClassSymbol c,				   MethodSymbol m) {	MethodSymbol absMeth = new MethodSymbol(	    m.flags() | IPROXY | SYNTHETIC, m.name,	    m.type, // was c.type.memberType(m), but now only !generics supported	    c);	c.members().enter(absMeth); // add to symbol table    }    private void adjustAbstractMethod(ClassSymbol c,				      MethodSymbol pm,				      MethodSymbol im) {        MethodType pmt = (MethodType)pm.type;        Type imt = types.memberType(c.type, im);	pmt.thrown = chk.intersect(pmt.getThrownTypes(), imt.getThrownTypes());    }/* ************************************************************************ * Traversal methods *************************************************************************/    /** Visitor argument: The current environment.     */    Env<GenContext> env;    /** Visitor argument: The expected type (prototype).     */    Type pt;    /** Visitor result: The item representing the computed value.     */    Item result;    /** Visitor method: generate code for a definition, catching and reporting     *  any completion failures.     *  @param tree    The definition to be visited.     *  @param env     The environment current at the definition.     */    public void genDef(JCTree tree, Env<GenContext> env) {	Env<GenContext> prevEnv = this.env;	try {	    this.env = env;	    tree.accept(this);	} catch (CompletionFailure ex) {	    chk.completionError(tree.pos(), ex);	} finally {	    this.env = prevEnv;	}    }    /** Derived visitor method: check whether CharacterRangeTable     *  should be emitted, if so, put a new entry into CRTable     *  and call method to generate bytecode.     *  If not, just call method to generate bytecode.     *  @see    #genStat(Tree, Env)     *     *  @param  tree     The tree to be visited.     *  @param  env      The environment to use.     *  @param  crtFlags The CharacterRangeTable flags     *                   indicating type of the entry.     */    public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {	if (!genCrt) {	    genStat(tree, env);	    return;	}	int startpc = code.curPc();	genStat(tree, env);	if (tree.getTag() == JCTree.BLOCK) crtFlags |= CRT_BLOCK;	code.crt.put(tree, crtFlags, startpc, code.curPc());    }    /** Derived visitor method: generate code for a statement.     */    public void genStat(JCTree tree, Env<GenContext> env) {	if (code.isAlive()) {	    code.statBegin(tree.pos);	    genDef(tree, env);	} else if (env.info.isSwitch && tree.getTag() == JCTree.VARDEF) {	    // variables whose declarations are in a switch	    // can be used even if the decl is unreachable.	    code.newLocal(((JCVariableDecl) tree).sym);	}    }    /** Derived visitor method: check whether CharacterRangeTable     *  should be emitted, if so, put a new entry into CRTable     *  and call method to generate bytecode.     *  If not, just call method to generate bytecode.     *  @see    #genStats(List, Env)     *     *  @param  trees    The list of trees to be visited.     *  @param  env      The environment to use.     *  @param  crtFlags The CharacterRangeTable flags     *                   indicating type of the entry.     */    public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {	if (!genCrt) {	    genStats(trees, env);	    return;	}	if (trees.length() == 1) {        // mark one statement with the flags	    genStat(trees.head, env, crtFlags | CRT_STATEMENT);	} else {	    int startpc = code.curPc();	    genStats(trees, env);	    code.crt.put(trees, crtFlags, startpc, code.curPc());	}    }    /** Derived visitor method: generate code for a list of statements.     */    public void genStats(List<? extends JCTree> trees, Env<GenContext> env) {	for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)	    genStat(l.head, env, CRT_STATEMENT);    }    /** Derived visitor method: check whether CharacterRangeTable     *  should be emitted, if so, put a new entry into CRTable     *  and call method to generate bytecode.     *  If not, just call method to generate bytecode.     *  @see    #genCond(Tree,boolean)     *     *  @param  tree     The tree to be visited.     *  @param  crtFlags The CharacterRangeTable flags     *                   indicating type of the entry.     */    public CondItem genCond(JCTree tree, int crtFlags) {	if (!genCrt) return genCond(tree, false);	int startpc = code.curPc();	CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);	code.crt.put(tree, crtFlags, startpc, code.curPc());	return item;    }    /** Derived visitor method: generate code for a boolean     *  expression in a control-flow context.     *  @param _tree         The expression to be visited.     *  @param markBranches The flag to indicate that the condition is     *                      a flow controller so produced conditions

⌨️ 快捷键说明

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