use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ClassTransformer method makeGetterOrSetter.
private AttributeDefinitionBuilder makeGetterOrSetter(Tree.AttributeDeclaration decl, boolean forCompanion, AttributeDefinitionBuilder builder, boolean isGetter) {
at(decl);
Value declarationModel = decl.getDeclarationModel();
boolean withinInterface = declarationModel.isInterfaceMember();
boolean isStatic = declarationModel.isStatic();
Tree.SpecifierOrInitializerExpression specOrInit = decl.getSpecifierOrInitializerExpression();
boolean lazy = specOrInit instanceof Tree.LazySpecifierExpression;
if (forCompanion || lazy || withinInterface && isStatic) {
if (specOrInit != null) {
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(specOrInit.getExpression());
if (error != null) {
builder.getterBlock(make().Block(0, List.<JCStatement>of(makeThrowUnresolvedCompilationError(error))));
} else {
TypedReference typedRef = getTypedReference(declarationModel);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
int flags = 0;
if (declarationModel.hasUncheckedNullType())
flags |= ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL;
if (CodegenUtil.downcastForSmall(specOrInit.getExpression(), declarationModel))
flags |= ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK;
JCExpression expr = expressionGen().transformExpression(specOrInit.getExpression(), CodegenUtil.getBoxingStrategy(declarationModel), nonWideningType, flags);
expr = convertToIntIfHashAttribute(declarationModel, expr);
builder.getterBlock(make().Block(0, List.<JCStatement>of(make().Return(expr))));
}
} else {
JCExpression accessor = naming.makeQualifiedName(naming.makeQuotedThis(), declarationModel, Naming.NA_MEMBER | (isGetter ? Naming.NA_GETTER : Naming.NA_SETTER));
if (isGetter) {
builder.getterBlock(make().Block(0, List.<JCStatement>of(make().Return(make().Apply(null, accessor, List.<JCExpression>nil())))));
} else {
List<JCExpression> args = List.<JCExpression>of(naming.makeName(declarationModel, Naming.NA_MEMBER | Naming.NA_IDENT));
builder.setterBlock(make().Block(0, List.<JCStatement>of(make().Exec(make().Apply(null, accessor, args)))));
}
}
}
if (forCompanion)
builder.notActual();
return builder.modifiers(modifierTransformation().getterSetter(declarationModel, forCompanion)).isFormal(declarationModel.isFormal() || withinInterface && !forCompanion && !isStatic).isJavaNative(declarationModel.isJavaNative());
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ClassTransformer method producedTypeParameterBounds.
private java.util.List<java.util.List<Type>> producedTypeParameterBounds(final Reference typedMember, Generic subMethod) {
java.util.List<java.util.List<Type>> producedTypeParameterBounds = new ArrayList<java.util.List<Type>>(subMethod.getTypeParameters().size());
for (TypeParameter tp : subMethod.getTypeParameters()) {
java.util.List<Type> satisfiedTypes = tp.getType().getSatisfiedTypes();
ArrayList<Type> bounds = new ArrayList<>(satisfiedTypes.size());
for (Type bound : satisfiedTypes) {
if (typedMember instanceof Type) {
bounds.add(bound.substitute((Type) typedMember));
} else if (typedMember instanceof TypedReference) {
bounds.add(bound.substitute((TypedReference) typedMember));
}
}
producedTypeParameterBounds.add(bounds);
}
return producedTypeParameterBounds;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference 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.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ClassTransformer method refineMethod.
/*private Class refineClass(
Scope container,
Reference pr,
ClassOrInterface classModel,
Class formalClass,
Unit unit) {
Class refined = new Class();
refined.setActual(true);
refined.setShared(formalClass.isShared());
refined.setContainer(container);
refined.setExtendedType(formalClass.getType());
refined.setDeprecated(formalClass.isDeprecated());
refined.setName(formalClass.getName());
refined.setRefinedDeclaration(formalClass.getRefinedDeclaration());
refined.setScope(container);
//refined.setType(pr.getType());
refined.setUnit(unit);
for (ParameterList formalPl : formalClass.getParameterLists()) {
ParameterList refinedPl = new ParameterList();
for (Parameter formalP : formalPl.getParameters()){
Parameter refinedP = new Parameter();
refinedP.setAtLeastOne(formalP.isAtLeastOne());
refinedP.setDeclaration(refined);
refinedP.setDefaulted(formalP.isDefaulted());
refinedP.setDeclaredAnything(formalP.isDeclaredAnything());
refinedP.setHidden(formalP.isHidden());
refinedP.setSequenced(formalP.isSequenced());
refinedP.setName(formalP.getName());
final TypedReference typedParameter = pr.getTypedParameter(formalP);
FunctionOrValue paramModel;
if (formalP.getModel() instanceof Value) {
Value paramValueModel = refineValue((Value)formalP.getModel(), typedParameter, refined, classModel.getUnit());
paramValueModel.setInitializerParameter(refinedP);
paramModel = paramValueModel;
} else {
Function paramFunctionModel = refineMethod(refined, typedParameter, classModel, (Function)formalP.getModel(), unit);
paramFunctionModel.setInitializerParameter(refinedP);
paramModel = paramFunctionModel;
}
refinedP.setModel(paramModel);
refinedPl.getParameters().add(refinedP);
}
refined.addParameterList(refinedPl);
}
return refined;
}*/
private Function refineMethod(Scope container, TypedReference pr, ClassOrInterface classModel, Function formalMethod, Unit unit) {
Function refined = new Function();
refined.setActual(true);
refined.setShared(formalMethod.isShared());
refined.setContainer(container);
// in case there are subclasses
refined.setDefault(true);
refined.setDeferred(false);
refined.setDeprecated(formalMethod.isDeprecated());
refined.setName(formalMethod.getName());
refined.setRefinedDeclaration(formalMethod.getRefinedDeclaration());
refined.setScope(container);
refined.setType(pr.getType());
refined.setUnit(unit);
refined.setUnboxed(formalMethod.getUnboxed());
refined.setUntrustedType(formalMethod.getUntrustedType());
refined.setTypeErased(formalMethod.getTypeErased());
ArrayList<TypeParameter> refinedTp = new ArrayList<TypeParameter>();
;
for (TypeParameter formalTp : formalMethod.getTypeParameters()) {
refinedTp.add(formalTp);
}
refined.setTypeParameters(refinedTp);
for (ParameterList formalPl : formalMethod.getParameterLists()) {
ParameterList refinedPl = new ParameterList();
for (Parameter formalP : formalPl.getParameters()) {
Parameter refinedP = new Parameter();
refinedP.setAtLeastOne(formalP.isAtLeastOne());
refinedP.setDeclaration(refined);
refinedP.setDefaulted(formalP.isDefaulted());
refinedP.setDeclaredAnything(formalP.isDeclaredAnything());
refinedP.setHidden(formalP.isHidden());
refinedP.setSequenced(formalP.isSequenced());
refinedP.setName(formalP.getName());
final TypedReference typedParameter = pr.getTypedParameter(formalP);
FunctionOrValue paramModel;
if (formalP.getModel() instanceof Value) {
Value paramValueModel = refineValue((Value) formalP.getModel(), typedParameter, refined, classModel.getUnit());
paramValueModel.setInitializerParameter(refinedP);
paramModel = paramValueModel;
} else {
Function paramFunctionModel = refineMethod(refined, typedParameter, classModel, (Function) formalP.getModel(), unit);
paramFunctionModel.setInitializerParameter(refinedP);
paramModel = paramFunctionModel;
}
refinedP.setModel(paramModel);
refinedPl.getParameters().add(refinedP);
}
refined.addParameterList(refinedPl);
}
return refined;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ClassTransformer method makeDelegateToCompanion.
/**
* Generates a method which delegates to the companion instance $Foo$impl
*/
private MethodDefinitionBuilder makeDelegateToCompanion(Interface iface, Reference typedMember, Type currentType, final long mods, final java.util.List<TypeParameter> typeParameters, final java.util.List<java.util.List<Type>> producedTypeParameterBounds, final Type methodType, final String methodName, final java.util.List<Parameter> parameters, boolean typeErased, final String targetMethodName, Parameter defaultedParam, boolean includeBody) {
final MethodDefinitionBuilder concreteWrapper = MethodDefinitionBuilder.systemMethod(gen(), methodName);
concreteWrapper.modifiers(mods);
concreteWrapper.ignoreModelAnnotations();
if ((mods & PRIVATE) == 0) {
concreteWrapper.isOverride(true);
}
if (typeParameters != null) {
concreteWrapper.reifiedTypeParametersFromModel(typeParameters);
}
Iterator<java.util.List<Type>> iterator = producedTypeParameterBounds.iterator();
if (typeParameters != null) {
for (TypeParameter tp : typeParameters) {
concreteWrapper.typeParameter(tp, iterator.next());
}
}
boolean explicitReturn = false;
Declaration member = (defaultedParam != null ? typedMember.getTypedParameter(defaultedParam) : typedMember).getDeclaration();
Type returnType = null;
if (!isAnything(methodType) || ((member instanceof Function || member instanceof Value) && !Decl.isUnboxedVoid(member)) || (member instanceof Function && Strategy.useBoxedVoid((Function) member))) {
explicitReturn = true;
if (CodegenUtil.isHashAttribute(member)) {
// delegates for hash attributes are int
concreteWrapper.resultType(new TransformedType(make().Type(syms().intType)));
returnType = typedMember.getType();
} else if (typedMember instanceof TypedReference && defaultedParam == null) {
TypedReference typedRef = (TypedReference) typedMember;
// This is very much like for method refinement: if the supertype is erased -> go raw.
// Except for some reason we only need to do it with multiple inheritance with different type
// arguments, so let's not go overboard
int flags = 0;
if (CodegenUtil.hasTypeErased((TypedDeclaration) member.getRefinedDeclaration()) || CodegenUtil.hasTypeErased((TypedDeclaration) member) && isInheritedTwiceWithDifferentTypeArguments(currentType, iface)) {
flags |= AbstractTransformer.JT_RAW;
}
concreteWrapper.resultTypeNonWidening(currentType, typedRef, typedMember.getType(), flags);
// FIXME: this is redundant with what we computed in the previous line in concreteWrapper.resultTypeNonWidening
TypedReference nonWideningTypedRef = gen().nonWideningTypeDecl(typedRef, currentType);
returnType = gen().nonWideningType(typedRef, nonWideningTypedRef);
} else if (defaultedParam != null) {
TypedReference typedParameter = typedMember.getTypedParameter(defaultedParam);
NonWideningParam nonWideningParam = concreteWrapper.getNonWideningParam(typedParameter, currentType.getDeclaration() instanceof Class ? WideningRules.FOR_MIXIN : WideningRules.NONE);
returnType = nonWideningParam.nonWideningType;
if (member instanceof Function)
returnType = typeFact().getCallableType(returnType);
concreteWrapper.resultType(new TransformedType(makeJavaType(returnType, nonWideningParam.flags)));
} else {
concreteWrapper.resultType(new TransformedType(makeJavaType((Type) typedMember)));
returnType = (Type) typedMember;
}
}
ListBuffer<JCExpression> arguments = new ListBuffer<JCExpression>();
if (typeParameters != null) {
for (TypeParameter tp : typeParameters) {
arguments.add(naming.makeUnquotedIdent(naming.getTypeArgumentDescriptorName(tp)));
}
}
Declaration declaration = typedMember.getDeclaration();
if (declaration instanceof Constructor && !Decl.isDefaultConstructor((Constructor) declaration) && defaultedParam == null) {
concreteWrapper.parameter(makeConstructorNameParameter((Constructor) declaration));
arguments.add(naming.makeUnquotedIdent(Unfix.$name$));
}
int ii = 0;
for (Parameter param : parameters) {
Parameter parameter;
if (declaration instanceof Functional) {
parameter = ((Functional) declaration).getFirstParameterList().getParameters().get(ii++);
} else if (declaration instanceof Setter) {
parameter = ((Setter) declaration).getParameter();
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
final TypedReference typedParameter = typedMember.getTypedParameter(parameter);
concreteWrapper.parameter(null, param, typedParameter, null, FINAL, WideningRules.FOR_MIXIN);
arguments.add(naming.makeName(param.getModel(), Naming.NA_MEMBER | Naming.NA_ALIASED));
}
if (includeBody) {
JCExpression qualifierThis = makeUnquotedIdent(getCompanionFieldName(iface));
// our impl accessor to get the expected bounds of the qualifying type
if (explicitReturn) {
Type javaType = getBestSatisfiedType(currentType, iface);
Type ceylonType = typedMember.getQualifyingType();
// don't even bother if the impl accessor is turned to raw because casting it to raw doesn't help
if (!isTurnedToRaw(ceylonType) && // if it's exactly the same we don't need any cast
!javaType.isExactly(ceylonType))
// this will add the proper cast to the impl accessor
qualifierThis = expressionGen().applyErasureAndBoxing(qualifierThis, currentType, false, true, BoxingStrategy.BOXED, ceylonType, ExpressionTransformer.EXPR_WANTS_COMPANION);
}
JCExpression expr = make().Apply(// TODO Type args
null, makeSelect(qualifierThis, (targetMethodName != null) ? targetMethodName : methodName), arguments.toList());
if (isUnimplementedMemberClass(currentType, typedMember)) {
concreteWrapper.body(makeThrowUnresolvedCompilationError(// TODO encapsulate the error message
"formal member '" + declaration.getName() + "' of '" + iface.getName() + "' not implemented in class hierarchy"));
current().broken();
} else if (!explicitReturn) {
concreteWrapper.body(gen().make().Exec(expr));
} else {
// deal with erasure and stuff
BoxingStrategy boxingStrategy;
boolean exprBoxed;
if (member instanceof TypedDeclaration) {
TypedDeclaration typedDecl = (TypedDeclaration) member;
exprBoxed = !CodegenUtil.isUnBoxed(typedDecl);
boxingStrategy = CodegenUtil.getBoxingStrategy(typedDecl);
} else {
// must be a class or interface
exprBoxed = true;
boxingStrategy = BoxingStrategy.UNBOXED;
}
// to force an additional cast
if (isTurnedToRaw(typedMember.getQualifyingType()) || // in invariant locations
needsRawCastForMixinSuperCall(iface, methodType) || needsCastForErasedInstantiator(iface, methodName, member))
typeErased = true;
expr = gen().expressionGen().applyErasureAndBoxing(expr, methodType, typeErased, exprBoxed, boxingStrategy, returnType, 0);
concreteWrapper.body(gen().make().Return(expr));
}
}
return concreteWrapper;
}
Aggregations