use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass in project ceylon by eclipse.
the class CallableBuilder method build.
public JCExpression build() {
// Generate a subclass of Callable
ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
gen.at(node);
if (parameterDefaultValueMethods != null) {
for (MethodDefinitionBuilder mdb : parameterDefaultValueMethods) {
classBody.append(mdb.build());
}
}
transformation.appendMethods(classBody);
gen.at(node);
JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0, annotations != null ? annotations : List.<JCAnnotation>nil()), classBody.toList());
int variadicIndex = isVariadic ? numParams - 1 : -1;
Type callableType;
if (typeModel.isTypeConstructor()) {
callableType = typeModel.getDeclaration().getExtendedType();
} else {
callableType = typeModel;
}
JCNewClass callableInstance;
if (functionalInterface == null) {
callableInstance = gen.at(node).NewClass(null, null, gen.makeJavaType(callableType, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(0)), gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(1)), gen.make().Literal(callableType.asString(true)), gen.make().TypeCast(gen.syms().shortType, gen.makeInteger(variadicIndex))), classDef);
} else {
callableInstance = gen.make().NewClass(null, null, gen.makeJavaType(functionalInterface, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>nil(), classDef);
}
JCExpression result;
if (typeModel.isTypeConstructor()) {
result = buildTypeConstructor(callableType, callableInstance);
} else {
result = callableInstance;
}
gen.at(null);
if (instanceSubstitution != null) {
instanceSubstitution.close();
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass in project ceylon by eclipse.
the class ClassTransformer method transformObject.
private List<JCTree> transformObject(Node def, Tree.Declaration annotated, Tree.SatisfiedTypes satisfiesTypes, Value model, Class klass, ClassDefinitionBuilder containingClassBuilder, boolean makeLocalInstance) {
naming.clearSubstitutions(klass);
String name = klass.getName();
String javaClassName = Naming.quoteClassName(name);
ClassDefinitionBuilder objectClassBuilder = ClassDefinitionBuilder.object(this, javaClassName, name, Decl.isLocal(klass)).forDefinition(klass);
if (Strategy.introduceJavaIoSerializable(klass, typeFact().getJavaIoSerializable())) {
objectClassBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
if (def instanceof Tree.ObjectDefinition && klass.isMember() && (ModelUtil.isCaptured(klass) || model.isCaptured())) {
addWriteReplace(klass, objectClassBuilder);
}
}
makeReadResolve(def, objectClassBuilder, klass, model);
// Make sure top types satisfy reified type
addReifiedTypeInterface(objectClassBuilder, klass);
if (supportsReifiedAlias(klass))
objectClassBuilder.reifiedAlias(klass.getType());
CeylonVisitor visitor = gen().visitor;
final ListBuffer<JCTree> prevDefs = visitor.defs;
final boolean prevInInitializer = visitor.inInitializer;
final ClassDefinitionBuilder prevClassBuilder = visitor.classBuilder;
List<JCStatement> childDefs;
try {
visitor.defs = new ListBuffer<JCTree>();
visitor.inInitializer = true;
visitor.classBuilder = objectClassBuilder;
def.visitChildren(visitor);
childDefs = (List<JCStatement>) visitor.getResult().toList();
} finally {
visitor.classBuilder = prevClassBuilder;
visitor.inInitializer = prevInInitializer;
visitor.defs = prevDefs;
naming.closeScopedSubstitutions(def.getScope());
}
addMissingUnrefinedMembers(def, klass, objectClassBuilder);
satisfaction(satisfiesTypes, klass, objectClassBuilder);
serialization(klass, objectClassBuilder);
if (model != null && model.isToplevel() && def instanceof Tree.ObjectDefinition) {
// generate a field and getter
AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.wrapped(this, model.getName(), model, true, null).userAnnotations(makeAtIgnore()).userAnnotationsSetter(makeAtIgnore()).immutable().initialValue(makeNewClass(naming.makeName(model, Naming.NA_FQ | Naming.NA_WRAPPER)), BoxingStrategy.BOXED).is(PUBLIC, klass.isShared()).is(STATIC, true);
if (annotated != null) {
builder.fieldAnnotations(expressionGen().transformAnnotations(OutputElement.FIELD, annotated));
builder.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, annotated));
}
objectClassBuilder.defs(builder.build());
}
if (annotated != null) {
objectClassBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, annotated));
objectClassBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, annotated));
}
// make sure we set the container in case we move it out
addAtContainer(objectClassBuilder, klass);
objectClassBuilder.annotations(makeAtObject()).satisfies(klass.getSatisfiedTypes()).defs(childDefs);
objectClassBuilder.getInitBuilder().modifiers(PRIVATE);
objectClassBuilder.addGetTypeMethod(klass.getType());
if (model != null)
objectClassBuilder.modelAnnotations(model.getAnnotations()).modifiers(modifierTransformation().object(model));
at(def);
List<JCTree> result = objectClassBuilder.build();
if (makeLocalInstance && !model.isStatic()) {
if (model.isSelfCaptured()) {
// if it's captured we need to box it and define the var before the class, so it can access it
JCNewClass newInstance = makeNewClass(objectClassBuilder.getClassName(), false, null);
JCFieldAccess setter = naming.makeSelect(Naming.getLocalValueName(model), Naming.getSetterName(model));
JCStatement assign = make().Exec(make().Assign(setter, newInstance));
result = result.prepend(assign);
JCVariableDecl localDecl = makeVariableBoxDecl(null, model);
result = result.prepend(localDecl);
} else {
// not captured, we can define the var after the class
JCVariableDecl localDecl = makeLocalIdentityInstance(name, objectClassBuilder.getClassName(), false);
result = result.append(localDecl);
}
} else if (model != null && model.isClassOrInterfaceMember()) {
boolean generateGetter = ModelUtil.isCaptured(model);
JCExpression type = makeJavaType(klass.getType());
if (generateGetter) {
int modifiers = TRANSIENT | PRIVATE | (model.isStatic() ? STATIC : 0);
JCExpression initialValue = makeNull();
containingClassBuilder.field(modifiers, name, type, initialValue, false);
AttributeDefinitionBuilder getter = AttributeDefinitionBuilder.getter(this, name, model).modifiers(modifierTransformation().getterSetter(model, false));
if (def instanceof Tree.ObjectDefinition) {
getter.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, ((Tree.ObjectDefinition) def)));
}
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
stmts.add(make().If(make().Binary(JCTree.Tag.EQ, naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNull()), make().Exec(make().Assign(naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNewClass(makeJavaType(klass.getType()), null))), null));
stmts.add(make().Return(naming.makeUnquotedIdent(Naming.quoteFieldName(name))));
getter.getterBlock(make().Block(0, stmts.toList()));
result = result.appendList(getter.build());
} else {
int modifiers = FINAL | (model.isStatic() ? STATIC : 0);
JCExpression initialValue = makeNewClass(makeJavaType(klass.getType()), null);
containingClassBuilder.field(modifiers, name, type, initialValue, true);
}
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass in project ceylon by eclipse.
the class ClassTransformer method makeMainForClass.
/**
* Makes a {@code main()} method which calls the given top-level method
* @param def
*/
private MethodDefinitionBuilder makeMainForClass(ClassOrInterface model) {
at(null);
List<JCExpression> arguments = List.nil();
if (model.isAlias()) {
TypeDeclaration constr = ((ClassAlias) model).getConstructor();
if (constr instanceof Constructor) {
// must pass the constructor name arg
arguments = List.of(naming.makeNamedConstructorName((Constructor) constr, false));
}
model = (ClassOrInterface) model.getExtendedType().getDeclaration();
}
JCExpression nameId = makeJavaType(model.getType(), JT_RAW);
arguments = makeBottomReifiedTypeParameters(model.getTypeParameters(), arguments);
JCNewClass expr = make().NewClass(null, null, nameId, arguments, null);
return makeMainMethod(model, expr);
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass in project ceylon by eclipse.
the class CeylonVisitor method transformSingletonConstructor.
protected void transformSingletonConstructor(HashMap<Constructor, CtorDelegation> delegates, Tree.Enumerated ctor) {
// generate a constructor
transformConstructor(ctor, // ctor.getParameterList(),
null, ctor.getDelegatedConstructor(), ctor.getBlock(), ctor.getEnumerated(), delegates);
Class clz = ModelUtil.getConstructedClass(ctor.getEnumerated());
Value singletonModel = ctor.getDeclarationModel();
// generate a field
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.singleton(gen, singletonModel.getName(), singletonModel, false);
adb.modelAnnotations(gen.makeAtEnumerated());
adb.modelAnnotations(gen.makeAtIgnore());
adb.userAnnotations(gen.expressionGen().transformAnnotations(OutputElement.GETTER, ctor));
adb.fieldAnnotations(gen.expressionGen().transformAnnotations(OutputElement.FIELD, ctor));
// not setter
adb.immutable();
SyntheticName field = gen.naming.getValueConstructorFieldName(singletonModel);
if (clz.isToplevel()) {
adb.modifiers((singletonModel.isShared() ? PUBLIC : PRIVATE) | STATIC | FINAL);
adb.initialValue(gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null), BoxingStrategy.BOXED);
classBuilder.defs(adb.build());
} else if (clz.isClassMember()) {
int mods = 0;
if (!singletonModel.isShared()) {
mods |= PRIVATE;
}
if (clz.isClassOrInterfaceMember() && clz.isStatic()) {
mods |= STATIC;
}
adb.modifiers(mods);
// lazy
adb.initialValue(gen.makeNull(), BoxingStrategy.BOXED);
List<JCStatement> l = List.<JCStatement>of(gen.make().If(gen.make().Binary(JCTree.Tag.EQ, field.makeIdent(), gen.makeNull()), gen.make().Exec(gen.make().Assign(field.makeIdent(), gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null))), null), gen.make().Return(field.makeIdent()));
adb.getterBlock(gen.make().Block(0, l));
long mods2 = PRIVATE | TRANSIENT;
if (clz.isStatic()) {
mods2 |= STATIC;
}
classBuilder.getContainingClassBuilder().defs(gen.makeVar(mods2, field, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), gen.makeNull()));
classBuilder.getContainingClassBuilder().defs(adb.build());
} else {
// LOCAL
// we have to first make an empty box
JCNewClass initialValue = gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null);
JCVariableDecl box = gen.makeVariableBoxDecl(gen.makeNull(), singletonModel);
classBuilder.before(box);
// then do the class, and after that, assign our instance to the box
JCAssign assign = gen.make().Assign(gen.makeSelect(field.getName(), NamingBase.getGetterName(singletonModel)), initialValue);
classBuilder.after(gen.make().Exec(assign));
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass in project ceylon by eclipse.
the class ExpressionTransformer method transformSpreadOperator.
private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
at(expr);
boolean spreadMethodReferenceOuter = !expr.equals(spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
boolean spreadMethodReferenceInner = expr.equals(spreading) && isWithinInvocation();
Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
if (spreadMethodReferenceOuter) {
spreading = expr;
}
try {
Naming.SyntheticName varBaseName = naming.alias("spread");
ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
final Naming.SyntheticName srcIterableName;
if (spreadMethodReferenceInner) {
// use the var we initialized in the outer
srcIterableName = this.memberPrimary;
} else {
srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
}
if (spreadMethodReferenceOuter) {
// if we're in the outer, note then name of the var for use in the inner.
this.memberPrimary = srcIterableName;
}
Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
Type srcElementType = expr.getTarget().getQualifyingType();
JCExpression srcIterableExpr;
boolean isSuperOrSuperOf = false;
Type srcIterableType;
if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
srcIterableType = typeFact().getIterableType(srcElementType);
} else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
srcIterableType = typeFact().getJavaIterableDeclaration().appliedType(null, Collections.singletonList(srcElementType));
} else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
srcIterableType = expr.getPrimary().getTypeModel();
srcElementType = typeFact().getJavaArrayElementType(srcIterableType);
} else {
return makeErroneous(expr, "unhandled iterable type");
}
if (spreadMethodReferenceInner) {
srcIterableExpr = srcIterableName.makeIdent();
} else {
boolean isSuper = isSuper(expr.getPrimary());
isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
if (isSuperOrSuperOf) {
// so we just refer to it later
if (isSuper) {
Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
} else
srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
} else {
srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, srcIterableType);
}
}
// do not capture the iterable for super invocations: see above
if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
JCVariableDecl srcIterable = null;
JCExpression srcIterableTypeExpr = makeJavaType(srcIterableType, JT_NO_PRIMITIVES);
srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
letStmts.prepend(srcIterable);
}
/* public Object next() {
* Object result;
* if (!((result = iterator.next()) instanceof Finished)) {
* result = transformedMember(result);
* }
* return result;
*/
/* Any arguments in the member of the spread would get re-evaluated on each iteration
* so we need to shift them to the scope of the Let to ensure they're evaluated once.
*/
boolean aliasArguments = transformer instanceof InvocationTermTransformer && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
if (aliasArguments) {
((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
}
JCNewClass iterableClass;
boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
try {
Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
transformedElement = transformMemberExpression(expr, transformedElement, transformer);
// be handled by the previous recursion
if (spreadMethodReferenceOuter) {
return make().LetExpr(letStmts.toList(), transformedElement);
}
Type resultElementType = expr.getTarget().getType();
final Type resultAbsentType;
transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
nextMdb.isOverride(true);
nextMdb.annotationFlags(Annotations.IGNORE);
nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
nextMdb.resultType(new TransformedType(make().Type(syms().objectType)));
final List<JCTree> l;
if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
// private Iterator<srcElementType> iterator = srcIterableName.iterator();
JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.Tag.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
l = List.of(srcIterator, nextMdb.build());
} else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
// private Iterator<srcElementType> iterator = srcIterableName.iterator();
JCVariableDecl srcIterator = makeVar(Flags.PRIVATE | Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getJavaIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
resultAbsentType = typeFact().getNullType();
nextMdb.body(List.<JCStatement>of(make().If(make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "hasNext"), List.<JCExpression>nil()), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Return(transformedElement))), make().Return(makeFinished()))));
l = List.of(srcIterator, nextMdb.build());
} else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
resultAbsentType = typeFact().getNullType();
JCVariableDecl srcIndex = makeVar(Flags.PRIVATE, srcIteratorName, make().Type(syms().intType), make().Literal(0));
JCExpression indexed = make().Indexed(srcIterableName.makeIdent(), make().Unary(Tag.POSTINC, srcIteratorName.makeIdent()));
if (typeFact().isJavaPrimitiveArrayType(expr.getPrimary().getTypeModel())) {
indexed = applyErasureAndBoxing(indexed, srcElementType, false, BoxingStrategy.BOXED, srcElementType);
}
nextMdb.body(List.<JCStatement>of(make().If(make().Binary(Tag.LT, srcIteratorName.makeIdent(), // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "length")), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), indexed), make().Return(transformedElement))), make().Return(makeFinished()))));
l = List.of(srcIndex, nextMdb.build());
} else {
return makeErroneous(expr, "unhandled iterable type");
}
// new AbstractIterator()
JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), l));
MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
iteratorMdb.isOverride(true);
iteratorMdb.annotationFlags(Annotations.IGNORE);
iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
iteratorMdb.resultType(new TransformedType(makeJavaType(typeFact().getIteratorType(resultElementType)), makeAtNonNull()));
iteratorMdb.body(make().Return(iteratorClass));
// new AbstractIterable()
iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
} finally {
expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
}
if (aliasArguments) {
letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
}
JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
// Do we *statically* know the result must be a Sequence
final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
Type returnElementType = expr.getTarget().getType();
if (primaryIsSequence) {
int flags = EXPR_DOWN_CAST;
spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
}
return spread;
} finally {
spreading = oldSpreading;
}
}
Aggregations