use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Lower method makeOwnerThisN.
/**
* Similar to makeOwnerThis but will never pick "this".
*/
JCExpression makeOwnerThisN(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) {
Symbol c = sym.owner;
List<VarSymbol> ots = outerThisStack;
if (ots.isEmpty()) {
log.error(pos, "no.encl.instance.of.type.in.scope", c);
Assert.error();
return makeNull();
}
VarSymbol ot = ots.head;
JCExpression tree = access(make.at(pos).Ident(ot));
TypeSymbol otc = ot.type.tsym;
while (!(preciseMatch ? sym.isMemberOf(otc, types) : otc.isSubClass(sym.owner, types))) {
do {
ots = ots.tail;
if (ots.isEmpty()) {
log.error(pos, "no.encl.instance.of.type.in.scope", c);
Assert.error();
return tree;
}
ot = ots.head;
} while (ot.owner != otc);
tree = access(make.at(pos).Select(tree, ot));
otc = ot.type.tsym;
}
return tree;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Lower method classOfType.
private JCExpression classOfType(Type type, DiagnosticPosition pos) {
switch(type.getTag()) {
case BYTE:
case SHORT:
case CHAR:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case BOOLEAN:
case VOID:
// replace with <BoxedClass>.TYPE
ClassSymbol c = types.boxedClass(type);
Symbol typeSym = rs.accessBase(rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR), pos, c.type, names.TYPE, true);
if (typeSym.kind == VAR)
// ensure initializer is evaluated
((VarSymbol) typeSym).getConstValue();
return make.QualIdent(typeSym);
case CLASS:
case ARRAY:
if (target.hasClassLiterals()) {
VarSymbol sym = new VarSymbol(STATIC | PUBLIC | FINAL, names._class, syms.classType, type.tsym);
return make_at(pos).Select(make.Type(type), sym);
}
// replace with <cache == null ? cache = class$(tsig) : cache>
// where
// - <tsig> is the type signature of T,
// - <cache> is the cache variable for tsig.
String sig = writer.xClassName(type).toString().replace('/', '.');
Symbol cs = cacheSym(pos, sig);
return make_at(pos).Conditional(makeBinary(EQ, make.Ident(cs), makeNull()), make.Assign(make.Ident(cs), make.App(make.Ident(classDollarSym(pos)), List.<JCExpression>of(make.Literal(CLASS, sig).setType(syms.stringType)))).setType(types.erasure(syms.classType)), make.Ident(cs)).setType(types.erasure(syms.classType));
default:
throw new AssertionError();
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Lower method access.
/**
* Ensure that identifier is accessible, return tree accessing the identifier.
* @param sym The accessed symbol.
* @param tree The tree referring to the symbol.
* @param enclOp The closest enclosing operation node of tree,
* null if tree is not a subtree of an operation.
* @param refSuper Is access via a (qualified) C.super?
*/
JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean refSuper) {
// Access a free variable via its proxy, or its proxy's proxy
while (sym.kind == VAR && sym.owner.kind == MTH && sym.owner.enclClass() != currentClass) {
// A constant is replaced by its constant value.
Object cv = ((VarSymbol) sym).getConstValue();
if (cv != null) {
make.at(tree.pos);
return makeLit(sym.type, cv);
}
// Otherwise replace the variable by its proxy.
sym = proxies.lookup(proxyName(sym.name)).sym;
Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
tree = make.at(tree.pos).Ident(sym);
}
JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
switch(sym.kind) {
case TYP:
if (sym.owner.kind != PCK) {
// Convert type idents to
// <flat name> or <package name> . <flat name>
Name flatname = Convert.shortName(sym.flatName());
while (base != null && TreeInfo.symbol(base) != null && TreeInfo.symbol(base).kind != PCK) {
base = (base.hasTag(SELECT)) ? ((JCFieldAccess) base).selected : null;
}
if (tree.hasTag(IDENT)) {
((JCIdent) tree).name = flatname;
} else if (base == null) {
tree = make.at(tree.pos).Ident(sym);
((JCIdent) tree).name = flatname;
} else {
((JCFieldAccess) tree).selected = base;
((JCFieldAccess) tree).name = flatname;
}
}
break;
case MTH:
case VAR:
if (sym.owner.kind == TYP) {
// Access methods are required for
// - private members,
// - protected members in a superclass of an
// enclosing class contained in another package.
// - all non-private members accessed via a qualified super.
boolean protAccess = refSuper && !needsPrivateAccess(sym) || needsProtectedAccess(sym, tree);
boolean accReq = protAccess || needsPrivateAccess(sym);
// A base has to be supplied for
// - simple identifiers accessing variables in outer classes.
boolean baseReq = base == null && sym.owner != syms.predefClass && !sym.isMemberOf(currentClass, types);
if (accReq || baseReq) {
make.at(tree.pos);
// Constants are replaced by their constant value.
if (sym.kind == VAR) {
Object cv = ((VarSymbol) sym).getConstValue();
if (cv != null) {
addPrunedInfo(tree);
return makeLit(sym.type, cv);
}
}
// to their access methods.
if (accReq) {
List<JCExpression> args = List.nil();
if ((sym.flags() & STATIC) == 0) {
// as first parameter.
if (base == null)
base = makeOwnerThis(tree.pos(), sym, true);
args = args.prepend(base);
// so we don't duplicate code
base = null;
}
Symbol access = accessSymbol(sym, tree, enclOp, protAccess, refSuper);
JCExpression receiver = make.Select(base != null ? base : make.QualIdent(access.owner), access);
return make.App(receiver, args);
// Other accesses to members of outer classes get a
// qualifier.
} else if (baseReq) {
return make.at(tree.pos).Select(accessBase(tree.pos(), sym), sym).setType(tree.type);
}
}
} else if (sym.owner.kind == MTH && lambdaTranslationMap != null) {
// sym is a local variable - check the lambda translation map to
// see if sym has been translated to something else in the current
// scope (by LambdaToMethod)
Symbol translatedSym = lambdaTranslationMap.get(sym);
if (translatedSym != null) {
tree = make.at(tree.pos).Ident(translatedSym);
}
}
}
return tree;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Lower method visitEnumDef.
/**
* Translate an enum class.
*/
private void visitEnumDef(JCClassDecl tree) {
make_at(tree.pos());
// add the supertype, if needed
if (tree.extending == null)
tree.extending = make.Type(types.supertype(tree.type));
// classOfType adds a cache field to tree.defs unless
// target.hasClassLiterals().
JCExpression e_class = classOfType(tree.sym.type, tree.pos()).setType(types.erasure(syms.classType));
// process each enumeration constant, adding implicit constructor parameters
int nextOrdinal = 0;
ListBuffer<JCExpression> values = new ListBuffer<JCExpression>();
ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>();
ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>();
for (List<JCTree> defs = tree.defs; defs.nonEmpty(); defs = defs.tail) {
if (defs.head.hasTag(VARDEF) && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) {
JCVariableDecl var = (JCVariableDecl) defs.head;
visitEnumConstantDef(var, nextOrdinal++);
values.append(make.QualIdent(var.sym));
enumDefs.append(var);
} else {
otherDefs.append(defs.head);
}
}
// private static final T[] #VALUES = { a, b, c };
Name valuesName = names.fromString(target.syntheticNameChar() + "VALUES");
while (// avoid name clash
tree.sym.members().lookup(valuesName).scope != null) valuesName = names.fromString(valuesName + "" + target.syntheticNameChar());
Type arrayType = new ArrayType(types.erasure(tree.type), syms.arrayClass);
VarSymbol valuesVar = new VarSymbol(PRIVATE | FINAL | STATIC | SYNTHETIC, valuesName, arrayType, tree.type.tsym);
JCNewArray newArray = make.NewArray(make.Type(types.erasure(tree.type)), List.<JCExpression>nil(), values.toList());
newArray.type = arrayType;
enumDefs.append(make.VarDef(valuesVar, newArray));
tree.sym.members().enter(valuesVar);
Symbol valuesSym = lookupMethod(tree.pos(), names.values, tree.type, List.<Type>nil());
List<JCStatement> valuesBody;
if (useClone()) {
// return (T[]) $VALUES.clone();
JCTypeCast valuesResult = make.TypeCast(valuesSym.type.getReturnType(), make.App(make.Select(make.Ident(valuesVar), syms.arrayCloneMethod)));
valuesBody = List.<JCStatement>of(make.Return(valuesResult));
} else {
// template: T[] $result = new T[$values.length];
Name resultName = names.fromString(target.syntheticNameChar() + "result");
while (// avoid name clash
tree.sym.members().lookup(resultName).scope != null) resultName = names.fromString(resultName + "" + target.syntheticNameChar());
VarSymbol resultVar = new VarSymbol(FINAL | SYNTHETIC, resultName, arrayType, valuesSym);
JCNewArray resultArray = make.NewArray(make.Type(types.erasure(tree.type)), List.of(make.Select(make.Ident(valuesVar), syms.lengthVar)), null);
resultArray.type = arrayType;
JCVariableDecl decl = make.VarDef(resultVar, resultArray);
// template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length);
if (systemArraycopyMethod == null) {
systemArraycopyMethod = new MethodSymbol(PUBLIC | STATIC, names.fromString("arraycopy"), new MethodType(List.<Type>of(syms.objectType, syms.intType, syms.objectType, syms.intType, syms.intType), syms.voidType, List.<Type>nil(), syms.methodClass), syms.systemType.tsym);
}
JCStatement copy = make.Exec(make.App(make.Select(make.Ident(syms.systemType.tsym), systemArraycopyMethod), List.of(make.Ident(valuesVar), make.Literal(0), make.Ident(resultVar), make.Literal(0), make.Select(make.Ident(valuesVar), syms.lengthVar))));
// template: return $result;
JCStatement ret = make.Return(make.Ident(resultVar));
valuesBody = List.<JCStatement>of(decl, copy, ret);
}
JCMethodDecl valuesDef = make.MethodDef((MethodSymbol) valuesSym, make.Block(0, valuesBody));
enumDefs.append(valuesDef);
if (debugLower)
System.err.println(tree.sym + ".valuesDef = " + valuesDef);
/**
* The template for the following code is:
*
* public static E valueOf(String name) {
* return (E)Enum.valueOf(E.class, name);
* }
*
* where E is tree.sym
*/
MethodSymbol valueOfSym = lookupMethod(tree.pos(), names.valueOf, tree.sym.type, List.of(syms.stringType));
Assert.check((valueOfSym.flags() & STATIC) != 0);
VarSymbol nameArgSym = valueOfSym.params.head;
JCIdent nameVal = make.Ident(nameArgSym);
JCStatement enum_ValueOf = make.Return(make.TypeCast(tree.sym.type, makeCall(make.Ident(syms.enumSym), names.valueOf, List.of(e_class, nameVal))));
JCMethodDecl valueOf = make.MethodDef(valueOfSym, make.Block(0, List.of(enum_ValueOf)));
nameVal.sym = valueOf.params.head.sym;
if (debugLower)
System.err.println(tree.sym + ".valueOf = " + valueOf);
enumDefs.append(valueOf);
enumDefs.appendList(otherDefs.toList());
tree.defs = enumDefs.toList();
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Lower method visitNewClass.
public void visitNewClass(JCNewClass tree) {
ClassSymbol c = (ClassSymbol) tree.constructor.owner;
// Box arguments, if necessary
boolean isEnum = (tree.constructor.owner.flags() & ENUM) != 0;
List<Type> argTypes = tree.constructor.type.getParameterTypes();
if (isEnum)
argTypes = argTypes.prepend(syms.intType).prepend(syms.stringType);
tree.args = boxArgs(argTypes, tree.args, tree.varargsElement);
tree.varargsElement = null;
// explicit constructor arguments.
if (c.isLocal()) {
tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
}
// If an access constructor is used, append null as a last argument.
Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
if (constructor != tree.constructor) {
tree.args = tree.args.append(makeNull());
tree.constructor = constructor;
}
// correct outer instance as first argument.
if (c.hasOuterInstance()) {
JCExpression thisArg;
if (tree.encl != null) {
thisArg = attr.makeNullCheck(translate(tree.encl));
thisArg.type = tree.encl.type;
} else if (c.isLocal()) {
// local class
thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym);
} else {
// nested class
thisArg = makeOwnerThis(tree.pos(), c, false);
}
tree.args = tree.args.prepend(thisArg);
}
tree.encl = null;
// than the class or interface following new.
if (tree.def != null) {
translate(tree.def);
tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
tree.def = null;
} else {
tree.clazz = access(c, tree.clazz, enclOp, false);
}
result = tree;
}
Aggregations