📄 transtypes.java
字号:
/**
* @(#)TransTypes.java 1.39 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 pass translates Generic Java to conventional Java.
*/
public class TransTypes extends TreeTranslator implements Flags, Kinds, TypeTags {
/**
* The context key for the TransTypes phase.
*/
private static final Context.Key transTypesKey = new Context.Key();
/**
* Get the instance for this context.
*/
public static TransTypes instance(Context context) {
TransTypes instance = (TransTypes) context.get(transTypesKey);
if (instance == null)
instance = new TransTypes(context);
return instance;
}
private Name.Table names;
private Log log;
private Symtab syms;
private TreeMaker make;
private TransTypes(Context context) {
super();
context.put(transTypesKey, this);
names = Name.Table.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
}
/**
* A hashtable mapping bridge methods to the methods they override after
* type erasure.
*/
Hashtable overridden;
/**
* Construct an attributed tree for a cast of expression to target type,
* unless it already has precisely that type.
* @param tree The expression tree.
* @param target The target type.
*/
Tree cast(Tree tree, Type target) {
int oldpos = make.pos;
make.at(tree.pos);
if (!tree.type.isSameType(target)) {
tree = make.TypeCast(make.Type(target), tree).setType(target);
}
make.pos = oldpos;
return tree;
}
/**
* Construct an attributed tree to coerce an expression to some erased
* target type, unless the expression is already assignable to that type.
* If target type is a constant type, use its base type instead.
* @param tree The expression tree.
* @param target The target type.
*/
Tree coerce(Tree tree, Type target) {
Type btarget = target.baseType();
return tree.type.isAssignable(btarget) ? tree : cast(tree, btarget);
}
/**
* Given an erased reference type, assume this type as the tree's type.
* Then, coerce to some given target type unless target type is null.
* This operation is used in situations like the following:
*
* class Cell<A> { A value; }
* ...
* Cell<Integer> cell;
* Integer x = cell.value;
*
* Since the erasure of Cell.value is Object, but the type
* of cell.value in the assignment is Integer, we need to
* adjust the original type of cell.value to Object, and insert
* a cast to Integer. That is, the last assignment becomes:
*
* Integer x = (Integer)cell.value;
*
* @param tree The expression tree whose type might need adjustment.
* @param erasedType The expression's type after erasure.
* @param target The target type, which is usually the erasure of the
* expression's original type.
*/
Tree retype(Tree tree, Type erasedType, Type target) {
if (erasedType.tag > lastBaseTag) {
tree.type = erasedType;
if (target != null)
return coerce(tree, target);
}
return tree;
}
/**
* Translate method argument list, casting each argument
* to its corresponding type in a list of target types.
* @param trees The method argument list.
* @param targets The list of target types.
*/
List translateArgs(List trees, List targets) {
for (List l = trees; l.nonEmpty(); l = l.tail) {
l.head = translate((Tree) l.head, (Type) targets.head);
targets = targets.tail;
}
return trees;
}
/**
* Visitor argument: proto-type.
*/
private Type pt;
/**
* Visitor method: perform a type translation on tree.
*/
public Tree translate(Tree tree, Type pt) {
Type prevPt = this.pt;
try {
this.pt = pt;
if (tree == null)
result = null;
else
tree.accept(this);
}
finally { this.pt = prevPt;
} return result;
}
/**
* Visitor method: perform a type translation on list of trees.
*/
public List translate(List trees, Type pt) {
Type prevPt = this.pt;
List res;
try {
this.pt = pt;
res = translate(trees);
}
finally { this.pt = prevPt;
} return res;
}
public void visitClassDef(ClassDef tree) {
tree.typarams = TypeParameter.emptyList;
super.visitClassDef(tree);
make.at(tree.pos);
tree.type = tree.type.erasure();
result = tree;
}
public void visitMethodDef(MethodDef tree) {
tree.restype = translate(tree.restype, null);
tree.typarams = TypeParameter.emptyList;
tree.params = translateVarDefs(tree.params);
tree.thrown = translate(tree.thrown, null);
tree.body = (Block) translate(tree.body, tree.sym.erasure().restype());
tree.type = tree.type.erasure();
result = tree;
for (Scope.Entry e = tree.sym.owner.members().lookup(tree.name);
e.sym != null; e = e.next()) {
if (e.sym != tree.sym && e.sym.type.erasure().isSameType(tree.type)) {
log.error(tree.pos, "name.clash.same.erasure", tree.sym.toJava(),
e.sym.toJava());
return;
}
}
}
public void visitVarDef(VarDef tree) {
tree.vartype = translate(tree.vartype, null);
tree.init = translate(tree.init, tree.sym.erasure());
tree.type = tree.type.erasure();
result = tree;
}
public void visitDoLoop(DoLoop tree) {
tree.body = translate(tree.body);
tree.cond = translate(tree.cond, null);
result = tree;
}
public void visitWhileLoop(WhileLoop tree) {
tree.cond = translate(tree.cond, null);
tree.body = translate(tree.body);
result = tree;
}
public void visitForLoop(ForLoop tree) {
tree.init = translate(tree.init, null);
tree.cond = translate(tree.cond, null);
tree.step = translate(tree.step, null);
tree.body = translate(tree.body);
result = tree;
}
public void visitSwitch(Switch tree) {
tree.selector = translate(tree.selector, null);
tree.cases = translateCases(tree.cases);
result = tree;
}
public void visitCase(Case tree) {
tree.pat = translate(tree.pat, null);
tree.stats = translate(tree.stats);
result = tree;
}
public void visitSynchronized(Synchronized tree) {
tree.lock = translate(tree.lock, null);
tree.body = translate(tree.body);
result = tree;
}
public void visitConditional(Conditional tree) {
tree.cond = translate(tree.cond, null);
tree.truepart = translate(tree.truepart, tree.type.erasure());
tree.falsepart = translate(tree.falsepart, tree.type.erasure());
result = tree;
}
public void visitIf(If tree) {
tree.cond = translate(tree.cond, null);
tree.thenpart = translate(tree.thenpart);
tree.elsepart = translate(tree.elsepart);
result = tree;
}
public void visitExec(Exec tree) {
tree.expr = translate(tree.expr, null);
result = tree;
}
public void visitReturn(Return tree) {
tree.expr = translate(tree.expr);
result = tree;
}
public void visitThrow(Throw tree) {
tree.expr = translate(tree.expr, tree.expr.type.erasure());
result = tree;
}
public void visitAssert(Assert tree) {
tree.cond = translate(tree.cond, null);
if (tree.detail != null)
tree.detail = translate(tree.detail, null);
result = tree;
}
public void visitApply(Apply tree) {
tree.meth = translate(tree.meth, null);
Type mt = TreeInfo.symbol(tree.meth).erasure();
tree.args = translateArgs(tree.args, mt.argtypes());
result = retype(tree, mt.restype(), pt);
}
public void visitNewClass(NewClass tree) {
if (tree.encl != null)
tree.encl = translate(tree.encl, tree.encl.type.erasure());
tree.clazz = translate(tree.clazz, null);
tree.args = translateArgs(tree.args, tree.constructor.erasure().argtypes());
tree.def = (ClassDef) translate(tree.def, null);
tree.type = tree.type.erasure();
result = tree;
}
public void visitNewArray(NewArray tree) {
tree.elemtype = translate(tree.elemtype, null);
tree.dims = translate(tree.dims, null);
tree.elems = translate(tree.elems, tree.type.elemtype().erasure());
tree.type = tree.type.erasure();
result = tree;
}
public void visitParens(Parens tree) {
tree.expr = translate(tree.expr, null);
tree.type = tree.type.erasure();
result = tree;
}
public void visitAssign(Assign tree) {
tree.lhs = translate(tree.lhs, null);
tree.rhs = translate(tree.rhs, tree.lhs.type.erasure());
tree.type = tree.type.erasure();
result = tree;
}
public void visitAssignop(Assignop tree) {
tree.lhs = translate(tree.lhs, null);
tree.rhs = translate(tree.rhs, null);
tree.type = tree.type.erasure();
result = tree;
}
public void visitUnary(Unary tree) {
tree.arg = translate(tree.arg, (Type) tree.operator.type.argtypes().head);
result = tree;
}
public void visitBinary(Binary tree) {
tree.lhs = translate(tree.lhs, (Type) tree.operator.type.argtypes().head);
tree.rhs =
translate(tree.rhs, (Type) tree.operator.type.argtypes().tail.head);
result = tree;
}
public void visitTypeCast(TypeCast tree) {
tree.clazz = translate(tree.clazz, null);
tree.expr = translate(tree.expr, null);
tree.type = tree.type.erasure();
result = tree;
}
public void visitTypeTest(TypeTest tree) {
tree.expr = translate(tree.expr, null);
tree.clazz = translate(tree.clazz, null);
result = tree;
}
public void visitIndexed(Indexed tree) {
tree.indexed = translate(tree.indexed, tree.indexed.type.erasure());
tree.index = translate(tree.index, null);
result = retype(tree, tree.indexed.type.elemtype(), pt);
}
public void visitIdent(Ident tree) {
Type et = tree.sym.erasure();
if (tree.type.constValue != null) {
result = tree;
} else if (tree.sym.kind == VAR) {
result = retype(tree, et, pt);
} else {
tree.type = tree.type.erasure();
result = tree;
}
}
public void visitSelect(Select tree) {
Type t = tree.selected.type;
tree.selected = translate(tree.selected, t.erasure());
if (tree.type.constValue != null) {
result = tree;
} else if (tree.sym.kind == VAR) {
result = retype(tree, tree.sym.erasure(), pt);
} else {
tree.type = tree.type.erasure();
result = tree;
}
}
public void visitTypeArray(TypeArray tree) {
tree.elemtype = translate(tree.elemtype, null);
tree.type = tree.type.erasure();
result = tree;
}
/**
* Translate a toplevel class definition.
* @param cdef The definition to be translated.
*/
public Tree translateTopLevelClass(Tree cdef, TreeMaker make) {
try {
this.make = make;
overridden = Hashtable.make();
pt = null;
return translate(cdef, null);
}
finally { this.make = null;
overridden = null;
pt = null;
} }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -