📄 transinner.java
字号:
/**
* @(#)TransInner.java 1.92 03/04/10
*
* 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 pass maps Java with inner classes to flat Java without
* inner classes.
*/
public class TransInner extends TreeTranslator implements Flags, Kinds, TypeTags,
ByteCodes {
private static final Context.Key transInnerKey = new Context.Key();
public static TransInner instance(Context context) {
TransInner instance = (TransInner) context.get(transInnerKey);
if (instance == null)
instance = new TransInner(context);
return instance;
}
private Name.Table names;
private Log log;
private Symtab syms;
private Resolve rs;
private Check chk;
private Attr attr;
private TreeMaker make;
private ClassWriter writer;
private ClassReader reader;
private ConstFold cfolder;
private Target target;
private TransInner(Context context) {
super();
context.put(transInnerKey, this);
names = Name.Table.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
chk = Check.instance(context);
attr = Attr.instance(context);
make = TreeMaker.instance(context);
writer = ClassWriter.instance(context);
reader = ClassReader.instance(context);
cfolder = ConstFold.instance(context);
target = Target.instance(context);
}
/**
* The currently enclosing class.
*/
ClassSymbol currentClass;
/**
* A queue of all translated classes.
*/
ListBuffer translated;
/**
* Environment for symbol lookup, set by translateTopLevelClass.
*/
Env attrEnv;
/**
* A hash table mapping syntax trees to their ending source positions.
*/
Hashtable endPositions;
/**
* A hash table mapping local classes to their definitions.
*/
Hashtable classdefs;
/**
* A hash table mapping virtual accessed symbols in outer subclasses
* to the actually referred symbol in superclasses.
*/
Hashtable actualSymbols;
/**
* The currently enclosing outermost class definition.
*/
ClassDef outermostClassDef;
/**
* The currently enclosing outermost member definition.
*/
Tree outermostMemberDef;
/**
* A navigator class for assembling a mapping from local class symbols
* to class definition trees.
* There is only one case; all other cases simply traverse down the tree.
*/
class ClassMap extends TreeScanner {
ClassMap() {
super();
}
/**
* All encountered class defs are entered into classdefs table.
*/
public void visitClassDef(ClassDef tree) {
classdefs.put(tree.sym, tree);
super.visitClassDef(tree);
}
}
/**
* Map a class symbol to its definition.
* @param c The class symbol of which we want to determine the definition.
*/
ClassDef classDef(ClassSymbol c) {
ClassDef def = (Tree.ClassDef) classdefs.get(c);
if (def == null && outermostMemberDef != null) {
new ClassMap().scan(outermostMemberDef);
def = (Tree.ClassDef) classdefs.get(c);
}
if (def == null) {
new ClassMap().scan(outermostClassDef);
def = (Tree.ClassDef) classdefs.get(c);
}
return def;
}
/**
* A hash table mapping class symbols to lists of free variables.
* accessed by them. Only free variables of the method immediately containing
* a class are associated with that class.
*/
Hashtable freevarCache;
/**
* A navigator class for collecting the free variables accessed
* from a local class.
* There is only one case; all other cases simply traverse down the tree.
*/
class FreeVarCollector extends TreeScanner {
/**
* The owner of the local class.
*/
Symbol owner;
/**
* The current class.
*/
ClassSymbol clazz;
/**
* The list of owner's variables accessed from within the local class,
* without any duplicates.
*/
List fvs;
FreeVarCollector(ClassSymbol clazz) {
super();
this.clazz = clazz;
this.owner = clazz.owner;
this.fvs = VarSymbol.emptyList;
}
/**
* Add free variable to fvs list unless it is already there.
*/
private void addFreeVar(VarSymbol v) {
for (List l = fvs; l.nonEmpty(); l = l.tail)
if (l.head == v)
return;
fvs = fvs.prepend(v);
}
/**
* Add all free variables of class c to fvs list
* unless they are already there.
*/
private void addFreeVars(ClassSymbol c) {
List fvs = (List) freevarCache.get(c);
if (fvs != null) {
for (List l = fvs; l.nonEmpty(); l = l.tail) {
addFreeVar((Symbol.VarSymbol) l.head);
}
}
}
/**
* If tree refers to a variable in owner of local class, add it to
* free variables list.
*/
public void visitIdent(Ident tree) {
result = tree;
visitSymbol(tree.sym);
}
private void visitSymbol(Symbol sym) {
if (sym.kind == VAR) {
while (sym != null && sym.owner != owner)
sym = proxies.lookup(proxyName(sym.name)).sym;
if (sym != null && sym.owner == owner) {
VarSymbol v = (VarSymbol) sym;
if (v.constValue == null) {
addFreeVar(v);
}
}
}
}
/**
* If tree refers to a class instance creation expression
* add all free variables of the freshly created class.
*/
public void visitNewClass(NewClass tree) {
ClassSymbol c = (ClassSymbol) tree.constructor.owner;
addFreeVars(c);
if (tree.encl == null && c.hasOuterInstance() &&
outerThisStack.head != null)
visitSymbol((Symbol) outerThisStack.head);
super.visitNewClass(tree);
}
/**
* If tree refers to a qualified this or super expression
* for anything but the current class, add the outer this
* stack as a free variable.
*/
public void visitSelect(Select tree) {
if ((tree.name == names._this || tree.name == names._super) &&
tree.selected.type.tsym != clazz && outerThisStack.head != null)
visitSymbol((Symbol) outerThisStack.head);
super.visitSelect(tree);
}
/**
* If tree refers to a superclass constructor call,
* add all free variables of the superclass.
*/
public void visitApply(Apply tree) {
if (TreeInfo.name(tree.meth) == names._super) {
addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner);
Symbol constructor = TreeInfo.symbol(tree.meth);
ClassSymbol c = (ClassSymbol) constructor.owner;
if (c.hasOuterInstance() && tree.meth.tag != Tree.SELECT &&
outerThisStack.head != null)
visitSymbol((Symbol) outerThisStack.head);
}
super.visitApply(tree);
}
}
/**
* Return the variables accessed from within a local class, which
* are declared in the local class' owner.
* (in reverse order of first access).
*/
List freevars(ClassSymbol c) {
if ((c.owner.kind & (VAR | MTH)) != 0) {
List fvs = (List) freevarCache.get(c);
if (fvs == null) {
FreeVarCollector collector = new FreeVarCollector(c);
collector.scan(classDef(c));
fvs = collector.fvs;
freevarCache.put(c, fvs);
}
return fvs;
} else {
return VarSymbol.emptyList;
}
}
/**
* Make an attributed tree representing a literal. This will be an
* Ident node in the case of boolean literals, a Literal node in all
* other cases.
* @param type The literal's type.
* @param value The literal's value.
*/
Tree makeLit(Type type, Object value) {
if (type.tag == BOOLEAN) {
return make.Ident(((Integer) value).intValue() == 0 ?
syms.falseConst : syms.trueConst);
} else {
return make.Literal(type.tag, value).setType(type.constType(value));
}
}
/**
* Make an attributed class instance creation expression.
* @param ctype The class type.
* @param args The constructor arguments.
*/
NewClass makeNewClass(Type ctype, List args) {
NewClass tree = make.NewClass(null, make.QualIdent(ctype.tsym), args, null);
tree.constructor = rs.resolveConstructor(make.pos, attrEnv, ctype,
TreeInfo.types(args));
tree.type = ctype;
return tree;
}
/**
* Make an attributed unary expression.
* @param optag The operators tree tag.
* @param arg The operator's argument.
*/
Tree makeUnary(int optag, Tree arg) {
Unary tree = make.Unary(optag, arg);
tree.operator = rs.resolveUnaryOperator(make.pos, optag, attrEnv, arg.type);
tree.type = tree.operator.type.restype();
return tree;
}
/**
* Make an attributed binary expression.
* @param optag The operators tree tag.
* @param lhs The operator's left argument.
* @param rhs The operator's right argument.
*/
Binary makeBinary(int optag, Tree lhs, Tree rhs) {
Binary tree = make.Binary(optag, lhs, rhs);
tree.operator = rs.resolveBinaryOperator(make.pos, optag, attrEnv, lhs.type,
rhs.type);
tree.type = tree.operator.type.restype();
return tree;
}
/**
* Convert tree into string object, unless it has already a
* reference type..
*/
Tree makeString(Tree tree) {
if (tree.type.tag >= CLASS) {
return tree;
} else {
Symbol valueOfSym =
rs.resolveInternalMethod(tree.pos, attrEnv, syms.stringType,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -