use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class DeclarationVisitor method visit.
@Override
public void visit(Tree.AttributeSetterDefinition that) {
Setter s = new Setter();
s.setImplemented(that.getBlock() != null);
that.setDeclarationModel(s);
visitDeclaration(that, s);
Scope o = enterScope(s);
Parameter p = new Parameter();
p.setHidden(true);
Value v = new Value();
v.setInitializerParameter(p);
p.setModel(v);
v.setName(s.getName());
p.setName(s.getName());
p.setDeclaration(s);
visitElement(that, v);
unit.addDeclaration(v);
Scope sc = getContainer(that);
sc.addMember(v);
s.setParameter(p);
super.visit(that);
exitScope(o);
if (that.getSpecifierExpression() == null && that.getBlock() == null && !isNativeHeader(s) && !isNativeHeader(s.getGetter())) {
that.addError("setter declaration must have a body or => specifier");
}
}
use of org.eclipse.ceylon.model.typechecker.model.Value 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.Value 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.Value in project ceylon by eclipse.
the class ClassTransformer method refineValue.
private Value refineValue(Value formalAttribute, TypedReference producedValue, Scope container, Unit unit) {
Value refined = new Value();
refined.setActual(true);
refined.setContainer(container);
refined.setName(formalAttribute.getName());
refined.setRefinedDeclaration(formalAttribute.getRefinedDeclaration());
refined.setScope(container);
refined.setVariable(formalAttribute.isVariable());
refined.setShared(formalAttribute.isShared());
refined.setTransient(formalAttribute.isTransient());
// TODO
refined.setType(producedValue.getType());
refined.setTypeErased(formalAttribute.getTypeErased());
refined.setUnboxed(formalAttribute.getUnboxed());
refined.setUntrustedType(formalAttribute.getUntrustedType());
refined.setUnit(unit);
return refined;
}
use of org.eclipse.ceylon.model.typechecker.model.Value 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;
}
Aggregations