use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ClassTransformer method transform.
public void transform(Tree.AttributeDeclaration decl, ClassDefinitionBuilder classBuilder) {
final Value model = decl.getDeclarationModel();
boolean withinInterface = model.isInterfaceMember();
Tree.SpecifierOrInitializerExpression initializer = decl.getSpecifierOrInitializerExpression();
final boolean lazy = initializer instanceof Tree.LazySpecifierExpression;
String attrName = decl.getIdentifier().getText();
boolean memoized = Decl.isMemoized(decl);
boolean isStatic = model.isStatic();
// Only a non-formal or a concrete-non-lazy attribute has a corresponding field
// and if a captured class parameter exists with the same name we skip this part as well
Parameter parameter = CodegenUtil.findParamForDecl(decl);
boolean useField = !lazy && Strategy.useField(model);
boolean createField = !lazy && !model.isFormal() && Strategy.createField(parameter, model) && !model.isJavaNative();
boolean createCompanionField = !lazy && withinInterface && initializer != null;
JCThrow err = null;
JCExpression memoizedInitialValue = null;
if (createCompanionField || createField) {
TypedReference typedRef = getTypedReference(model);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
if (Decl.isIndirect(decl)) {
attrName = Naming.getAttrClassName(model, 0);
nonWideningType = getGetterInterfaceType(model);
}
JCExpression initialValue = null;
BoxingStrategy boxingStrategy = null;
if (initializer != null) {
Tree.Expression expression = initializer.getExpression();
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getTerm());
int flags = CodegenUtil.downcastForSmall(expression, model) ? ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK : 0;
flags |= model.hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0;
if (error != null) {
initialValue = null;
err = makeThrowUnresolvedCompilationError(error.getErrorMessage().getMessage());
} else {
boxingStrategy = useJavaBox(model, nonWideningType) && javaBoxExpression(expression.getTypeModel(), nonWideningType) ? BoxingStrategy.JAVA : CodegenUtil.getBoxingStrategy(model);
initialValue = expressionGen().transformExpression(expression, boxingStrategy, isStatic && nonWideningType.isTypeParameter() ? typeFact().getAnythingType() : nonWideningType, flags);
}
}
if (memoized) {
memoizedInitialValue = initialValue;
initialValue = makeDefaultExprForType(nonWideningType);
}
int flags = 0;
if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
flags |= JT_NO_PRIMITIVES;
}
long modifiers = useField ? modifierTransformation().field(decl) : modifierTransformation().localVar(decl);
// does it in those cases)
if (parameter == null || parameter.isHidden()) {
JCExpression type;
if (isStatic && nonWideningType.isTypeParameter()) {
type = make().Type(syms().objectType);
} else {
type = makeJavaType(nonWideningType, flags);
}
if (createCompanionField) {
classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).field(modifiers, attrName, type, initialValue, !useField);
} else {
List<JCAnnotation> annos = makeAtIgnore().prependList(expressionGen().transformAnnotations(OutputElement.FIELD, decl));
if (classBuilder.hasDelegatingConstructors()) {
annos = annos.prependList(makeAtNoInitCheck());
}
// fields should be ignored, they are accessed by the getters
if (err == null) {
// TODO This should really be using AttributeDefinitionBuilder somehow
if (useField) {
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.field(this, null, attrName, model, Decl.isIndirect(decl)).fieldAnnotations(annos).fieldNullability(makeNullabilityAnnotations(model)).initialValue(initialValue, boxingStrategy).fieldVisibilityModifiers(modifiers).modifiers(modifiers);
classBuilder.defs(adb.buildFields());
List<JCStatement> buildInit = adb.buildInit(false);
if (!buildInit.isEmpty()) {
if (isStatic) {
classBuilder.defs(make().Block(STATIC, buildInit));
} else {
classBuilder.getInitBuilder().init(buildInit);
}
}
} else if (!memoized) {
classBuilder.field(modifiers, attrName, type, initialValue, !useField, annos);
if (!isEe(model) && model.isLate() && CodegenUtil.needsLateInitField(model, typeFact())) {
classBuilder.field(PRIVATE | Flags.VOLATILE | Flags.TRANSIENT, Naming.getInitializationFieldName(attrName), make().Type(syms().booleanType), make().Literal(false), false, makeAtIgnore());
}
}
}
}
}
// A shared attribute might be initialized in a for statement, so
// we might need a def-assignment subst for it
JCStatement outerSubs = statementGen().openOuterSubstitutionIfNeeded(model, model.getType(), 0);
if (outerSubs != null) {
classBuilder.getInitBuilder().init(outerSubs);
}
}
if (useField || withinInterface || lazy) {
boolean generateInClassOrInterface = !withinInterface || model.isShared() || isStatic;
boolean generateInCompanionClass = withinInterface && lazy && !isStatic;
if (generateInClassOrInterface) {
// Generate getter in main class or interface (when shared)
at(decl.getType());
AttributeDefinitionBuilder getter = makeGetter(decl, false, memoizedInitialValue);
if (err != null) {
getter.getterBlock(make().Block(0, List.<JCStatement>of(err)));
}
classBuilder.attribute(getter);
}
if (generateInCompanionClass) {
Interface container = (Interface) model.getContainer();
// Generate getter in companion class
classBuilder.getCompanionBuilder(container).attribute(makeGetter(decl, true, null));
}
if (Decl.isVariable(model) || model.isLate()) {
if (generateInClassOrInterface) {
// Generate setter in main class or interface (when shared)
classBuilder.attribute(makeSetter(decl, false, memoizedInitialValue));
}
if (generateInCompanionClass) {
Interface container = (Interface) model.getContainer();
// Generate setter in companion class
classBuilder.getCompanionBuilder(container).attribute(makeSetter(decl, true, null));
}
}
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ClassTransformer method makeSerializationGetter.
private JCExpression makeSerializationGetter(Value value) {
JCExpression result;
if (value.isToplevel() || value.isLate()) {
// XXX duplicates logic in AttributeDefinitionBuilder
// We use the setter for late values, since that will allocate
// the array if needed.
result = make().Apply(null, naming.makeQualifiedName(naming.makeThis(), value, Naming.NA_MEMBER | Naming.NA_GETTER), List.<JCExpression>nil());
} else {
// We bypass the setter
// if (value.isVariable()) {
result = naming.makeQualifiedName(naming.makeThis(), value, Naming.NA_IDENT);
/*} else {
// The field will have final modifier, so we need some
// jiggery pokery to reset it.
requiredLookup[0] = true;
String fieldName = value.getName();
JCExpression fieldType = makeJavaType(value.getType());//TODO probably wrong
result = makeReassignFinalField(fieldType, fieldName, newValue);
}*/
}
BoxingStrategy boxingStrategy = useJavaBox(value, value.getType()) ? BoxingStrategy.JAVA : BoxingStrategy.BOXED;
if (boxingStrategy == BoxingStrategy.JAVA && !isJavaString(value.getType())) {
result = make().Conditional(make().Binary(JCTree.Tag.EQ, result, makeNull()), makeNull(), // FIXME!!!
boxType(unboxJavaType(result, value.getType()), simplifyType(value.getType())));
} else {
result = expressionGen().applyErasureAndBoxing(result, value.getType(), !CodegenUtil.isUnBoxed(value), boxingStrategy, value.getType());
}
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ClassTransformer method appendDefaultFieldInits.
protected void appendDefaultFieldInits(ClassDefinitionBuilder model, final ListBuffer<JCStatement> stmts, Collection<String> excludeFields) {
for (JCVariableDecl field : model.getFields()) {
String fieldName = field.name.toString();
if (excludeFields != null && excludeFields.contains(fieldName)) {
continue;
}
if (field.mods != null && (field.mods.flags & STATIC) != 0) {
continue;
}
// initialize all reference fields to null and all primitive
// fields to a default value.
JCExpression nullOrZero;
if (field.vartype instanceof JCPrimitiveTypeTree) {
switch(((JCPrimitiveTypeTree) field.vartype).typetag) {
case BYTE:
case SHORT:
case INT:
nullOrZero = make().Literal(0);
break;
case LONG:
nullOrZero = make().Literal(0L);
break;
case FLOAT:
nullOrZero = make().Literal(0.0f);
break;
case DOUBLE:
nullOrZero = make().Literal(0.0);
break;
case BOOLEAN:
nullOrZero = make().Literal(false);
break;
case CHAR:
nullOrZero = make().Literal(TypeTag.CHAR, 0);
break;
default:
throw new RuntimeException();
}
} else {
nullOrZero = makeNull();
}
stmts.add(make().Exec(make().Assign(naming.makeQualIdent(naming.makeThis(), fieldName), nullOrZero)));
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ClassTransformer method makeArrayInitializer.
/**
* Makes a new Array expression suitable for use in initializing a Java array
* using as elements the positional arguments
* of the given {@link Tree.SequencedArgument} (which must
* be {@link Tree.ListedArgument}s).
*
* <pre>
* Whatever[] w = <strong>{ listedArg1, listedArg2, ... }</strong>
* // ^---------- this bit ---------^
* </pre>
*
* @param sequencedArgument
* @return The array initializer expression
*/
JCExpression makeArrayInitializer(Tree.SequencedArgument sequencedArgument) {
JCExpression defaultLiteral;
ListBuffer<JCExpression> elements = new ListBuffer<JCExpression>();
if (sequencedArgument != null) {
for (Tree.PositionalArgument arg : sequencedArgument.getPositionalArguments()) {
if (arg instanceof Tree.ListedArgument) {
Tree.ListedArgument la = (Tree.ListedArgument) arg;
elements.append(expressionGen().transformExpression(la.getExpression().getTerm(), BoxingStrategy.UNBOXED, la.getExpression().getTypeModel()));
} else {
elements = null;
break;
}
}
}
defaultLiteral = elements == null ? null : make().NewArray(null, List.<JCExpression>nil(), elements.toList());
return defaultLiteral;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ClassTransformer method makeMethodForFunctionalParameter.
// private JCExpression makeValueDeclaration(Value value) {
// return expressionGen().makeMemberValueOrFunctionDeclarationLiteral(null, value, false);
// }
/**
* Generate a method for a shared FunctionalParameter which delegates to the Callable
* @param klass
* @param annotations
*/
private void makeMethodForFunctionalParameter(ClassDefinitionBuilder classBuilder, Tree.Parameter paramTree, Tree.TypedDeclaration memberDecl) {
Parameter paramModel = paramTree.getParameterModel();
if (Strategy.createMethod(paramModel)) {
Tree.MethodDeclaration methodDecl = (Tree.MethodDeclaration) memberDecl;
makeFieldForParameter(classBuilder, paramModel, memberDecl);
Function method = (Function) paramModel.getModel();
java.util.List<Parameter> parameters = method.getFirstParameterList().getParameters();
JCExpression fieldRef;
if (method.getMemberOrParameter(typeFact(), method.getName(), null, false) != method) {
fieldRef = naming.makeQualifiedName(naming.makeThis(), method, Naming.NA_IDENT);
} else {
fieldRef = naming.makeName(method, Naming.NA_IDENT);
}
CallBuilder callBuilder = CallBuilder.instance(this).invoke(naming.makeQualIdent(fieldRef, Naming.getCallableMethodName(method)));
for (Parameter parameter : parameters) {
JCExpression parameterExpr = naming.makeName(parameter.getModel(), Naming.NA_IDENT);
parameterExpr = expressionGen().applyErasureAndBoxing(parameterExpr, parameter.getType(), !CodegenUtil.isUnBoxed(parameter.getModel()), BoxingStrategy.BOXED, parameter.getType());
callBuilder.argument(parameterExpr);
}
JCExpression expr = callBuilder.build();
JCStatement body;
if (isVoid(memberDecl) && Decl.isUnboxedVoid(method) && !Strategy.useBoxedVoid(method)) {
body = make().Exec(expr);
} else {
expr = expressionGen().applyErasureAndBoxing(expr, paramModel.getType(), true, CodegenUtil.getBoxingStrategy(method), paramModel.getType());
body = make().Return(expr);
}
classBuilder.methods(transformMethod(method, null, methodDecl, methodDecl.getParameterLists(), methodDecl, true, method.isActual(), true, List.of(body), new DaoThis(methodDecl, methodDecl.getParameterLists().get(0)), false));
}
}
Aggregations