use of com.redhat.ceylon.model.typechecker.model.Value in project ceylon-compiler by ceylon.
the class ClassTransformer method makeGetterOrSetter.
private AttributeDefinitionBuilder makeGetterOrSetter(Tree.AttributeDeclaration decl, boolean forCompanion, boolean lazy, AttributeDefinitionBuilder builder, boolean isGetter) {
at(decl);
if (forCompanion || lazy) {
SpecifierOrInitializerExpression specOrInit = decl.getSpecifierOrInitializerExpression();
if (specOrInit != null) {
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(specOrInit.getExpression());
if (error != null) {
builder.getterBlock(make().Block(0, List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error))));
} else {
Value declarationModel = decl.getDeclarationModel();
TypedReference typedRef = getTypedReference(declarationModel);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
JCExpression expr = expressionGen().transformExpression(specOrInit.getExpression(), CodegenUtil.getBoxingStrategy(declarationModel), nonWideningType);
expr = convertToIntIfHashAttribute(declarationModel, expr);
builder.getterBlock(make().Block(0, List.<JCStatement>of(make().Return(expr))));
}
} else {
JCExpression accessor = naming.makeQualifiedName(naming.makeQuotedThis(), decl.getDeclarationModel(), 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(decl.getDeclarationModel(), 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(transformAttributeGetSetDeclFlags(decl.getDeclarationModel(), forCompanion)).isFormal((Decl.isFormal(decl) || Decl.withinInterface(decl)) && !forCompanion);
}
use of com.redhat.ceylon.model.typechecker.model.Value in project ceylon-compiler by ceylon.
the class ClassTransformer method transformRefinementSpecifierStatement.
public List<JCStatement> transformRefinementSpecifierStatement(SpecifierStatement op, ClassDefinitionBuilder classBuilder) {
List<JCStatement> result = List.<JCStatement>nil();
// Check if this is a shortcut form of formal attribute refinement
if (op.getRefinement()) {
Tree.Term baseMemberTerm = op.getBaseMemberExpression();
if (baseMemberTerm instanceof Tree.ParameterizedExpression)
baseMemberTerm = ((Tree.ParameterizedExpression) baseMemberTerm).getPrimary();
Tree.BaseMemberExpression expr = (BaseMemberExpression) baseMemberTerm;
Declaration decl = expr.getDeclaration();
if (Decl.isValue(decl) || Decl.isGetter(decl)) {
// Now build a "fake" declaration for the attribute
Tree.AttributeDeclaration attrDecl = new Tree.AttributeDeclaration(null);
attrDecl.setDeclarationModel((Value) decl);
attrDecl.setIdentifier(expr.getIdentifier());
attrDecl.setScope(op.getScope());
attrDecl.setSpecifierOrInitializerExpression(op.getSpecifierExpression());
attrDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(attrDecl);
// Generate the attribute
transform(attrDecl, classBuilder);
} else if (decl instanceof Function) {
// Now build a "fake" declaration for the method
Tree.MethodDeclaration methDecl = new Tree.MethodDeclaration(null);
Function m = (Function) decl;
methDecl.setDeclarationModel(m);
methDecl.setIdentifier(expr.getIdentifier());
methDecl.setScope(op.getScope());
methDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
Tree.SpecifierExpression specifierExpression = op.getSpecifierExpression();
methDecl.setSpecifierExpression(specifierExpression);
if (specifierExpression instanceof Tree.LazySpecifierExpression == false) {
Tree.Expression expression = specifierExpression.getExpression();
Tree.Term expressionTerm = Decl.unwrapExpressionsUntilTerm(expression);
// we can optimise lambdas and static method calls
if (!CodegenUtil.canOptimiseMethodSpecifier(expressionTerm, m)) {
// we need a field to save the callable value
String name = naming.getMethodSpecifierAttributeName(m);
JCExpression specifierType = makeJavaType(expression.getTypeModel());
JCExpression specifier = expressionGen().transformExpression(expression);
classBuilder.field(PRIVATE | FINAL, name, specifierType, specifier, false);
}
}
java.util.List<Tree.ParameterList> parameterListTrees = null;
if (op.getBaseMemberExpression() instanceof Tree.ParameterizedExpression) {
parameterListTrees = new ArrayList<>(m.getParameterLists().size());
parameterListTrees.addAll(((Tree.ParameterizedExpression) op.getBaseMemberExpression()).getParameterLists());
Tree.Term term = specifierExpression.getExpression().getTerm();
// and give it the given block of expr as it's specifier
while (term instanceof Tree.FunctionArgument && m.getParameterLists().size() > 1) {
FunctionArgument functionArgument = (Tree.FunctionArgument) term;
specifierExpression.setExpression(functionArgument.getExpression());
parameterListTrees.addAll(functionArgument.getParameterLists());
term = functionArgument.getExpression().getTerm();
}
}
int plIndex = 0;
// copy from formal declaration
for (ParameterList pl : m.getParameterLists()) {
Tree.ParameterList parameterListTree = null;
if (parameterListTrees != null)
parameterListTree = parameterListTrees.get(plIndex++);
Tree.ParameterList tpl = new Tree.ParameterList(null);
tpl.setModel(pl);
int pIndex = 0;
for (Parameter p : pl.getParameters()) {
Tree.Parameter parameterTree = null;
if (parameterListTree != null)
parameterTree = parameterListTree.getParameters().get(pIndex++);
Tree.Parameter tp = null;
if (p.getModel() instanceof Value) {
Tree.ValueParameterDeclaration tvpd = new Tree.ValueParameterDeclaration(null);
if (parameterTree != null)
tvpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tvpd.setParameterModel(p);
tp = tvpd;
} else if (p.getModel() instanceof Function) {
Tree.FunctionalParameterDeclaration tfpd = new Tree.FunctionalParameterDeclaration(null);
if (parameterTree != null)
tfpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tfpd.setParameterModel(p);
tp = tfpd;
} else {
throw BugException.unhandledDeclarationCase(p.getModel());
}
tp.setScope(p.getDeclaration().getContainer());
//tp.setIdentifier(makeIdentifier(p.getName()));
tpl.addParameter(tp);
}
methDecl.addParameterList(tpl);
}
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(methDecl);
// Generate the method
classBuilder.method(methDecl, Errors.GENERATE);
}
} else {
// Normal case, just generate the specifier statement
result = result.append(expressionGen().transform(op));
}
Tree.Term term = op.getBaseMemberExpression();
if (term instanceof Tree.BaseMemberExpression) {
Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) term;
DeferredSpecification ds = statementGen().getDeferredSpecification(bme.getDeclaration());
if (ds != null && needsInnerSubstitution(term.getScope(), bme.getDeclaration())) {
result = result.append(ds.openInnerSubstitution());
}
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.Value in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationSet.
private void serializationSet(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$set$.toString());
mdb.isOverride(true);
mdb.ignoreModelAnnotations();
mdb.modifiers(PUBLIC);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
pdb.modifiers(FINAL);
pdb.type(make().Type(syms().ceylonReachableReferenceType), null);
mdb.parameter(pdb);
ParameterDefinitionBuilder pdb2 = ParameterDefinitionBuilder.systemParameter(this, Unfix.instance.toString());
pdb2.modifiers(FINAL);
pdb2.type(make().Type(syms().objectType), null);
mdb.parameter(pdb2);
//mdb.resultType(null, naming.makeQuotedFQIdent("java.util.Collection"));
/*
* public void $set$(Object reference, Object instance) {
* switch((String)reference) {
* case ("attr1")
* this.field1 = ...;
* break;
* // ... other fields of this class
* default:
* super.set(reference, instance);
*/
SyntheticName reference = naming.synthetic(Unfix.reference);
SyntheticName instance = naming.synthetic(Unfix.instance);
ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
boolean[] needsLookup = new boolean[] { false };
for (Declaration member : model.getMembers()) {
if (hasField(member)) {
if (member instanceof Function)
// TODO: This class is not serializable
continue;
ListBuffer<JCStatement> caseStmts = ListBuffer.<JCStatement>lb();
if (member instanceof Value && ((Value) member).isLate()) {
caseStmts.add(make().If(make().TypeTest(instance.makeIdent(), make().Type(syms().ceylonUninitializedLateValueType)), make().Break(null), null));
}
caseStmts.add(makeDeserializationAssignment((Value) member, needsLookup));
caseStmts.add(make().Break(null));
cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
}
}
ListBuffer<JCStatement> defaultCase = ListBuffer.lb();
if (extendsSerializable(model)) {
// super.set(reference, instance);
defaultCase.add(make().Exec(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$set$.toString()), List.<JCExpression>of(reference.makeIdent(), instance.makeIdent()))));
} else {
// throw (or pass to something else to throw, based on policy)
defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
}
cases.add(make().Case(null, defaultCase.toList()));
ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
if (needsLookup[0]) {
// if we needed to use a lookup object to reset final fields,
// prepend that variable
stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
}
JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonMemberType)), swtch, make().Throw(make().NewClass(null, null, make().Type(syms().ceylonAssertionErrorType), List.<JCExpression>of(make().Binary(JCTree.PLUS, make().Literal("unexpected reachable reference "), reference.makeIdent())), null))));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.redhat.ceylon.model.typechecker.model.Value in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
public void transform(AttributeDeclaration decl, ClassDefinitionBuilder classBuilder) {
final Value model = decl.getDeclarationModel();
boolean lazy = decl.getSpecifierOrInitializerExpression() instanceof LazySpecifierExpression;
boolean useField = Strategy.useField(model) && !lazy;
String attrName = decl.getIdentifier().getText();
// 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 createField = Strategy.createField(parameter, model) && !lazy;
boolean concrete = Decl.withinInterface(decl) && decl.getSpecifierOrInitializerExpression() != null;
if (!lazy && (concrete || (!Decl.isFormal(decl) && 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;
if (decl.getSpecifierOrInitializerExpression() != null) {
Value declarationModel = model;
initialValue = expressionGen().transformExpression(decl.getSpecifierOrInitializerExpression().getExpression(), CodegenUtil.getBoxingStrategy(declarationModel), nonWideningType);
}
int flags = 0;
if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
flags |= JT_NO_PRIMITIVES;
}
JCExpression type = makeJavaType(nonWideningType, flags);
int modifiers = (useField) ? transformAttributeFieldDeclFlags(decl) : transformLocalDeclFlags(decl);
// does it in those cases)
if (parameter == null || parameter.isHidden()) {
if (concrete) {
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
classBuilder.field(modifiers, attrName, type, initialValue, !useField, annos);
if (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
List<JCAnnotation> annots = makeJavaTypeAnnotations(decl.getDeclarationModel());
JCStatement outerSubs = statementGen().openOuterSubstitutionIfNeeded(decl.getDeclarationModel(), model.getType(), annots, 0);
if (outerSubs != null) {
classBuilder.getInitBuilder().init(outerSubs);
}
}
boolean withinInterface = Decl.withinInterface(decl);
if (useField || withinInterface || lazy) {
if (!withinInterface || model.isShared()) {
// Generate getter in main class or interface (when shared)
classBuilder.attribute(makeGetter(decl, false, lazy));
}
if (withinInterface && lazy) {
// Generate getter in companion class
classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).attribute(makeGetter(decl, true, lazy));
}
if (Decl.isVariable(decl) || Decl.isLate(decl)) {
if (!withinInterface || model.isShared()) {
// Generate setter in main class or interface (when shared)
classBuilder.attribute(makeSetter(decl, false, lazy));
}
if (withinInterface && lazy) {
// Generate setter in companion class
classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).attribute(makeSetter(decl, true, lazy));
}
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Value in project ceylon-compiler by ceylon.
the class ClassTransformer method needsCompanionDelegate.
private boolean needsCompanionDelegate(final Class model, Reference ref) {
final boolean mostRefined;
Declaration member = ref.getDeclaration();
java.util.List<Type> sig = getSignatureIfRequired(ref);
Declaration m = model.getMember(member.getName(), sig, false, true);
if (member instanceof Setter && Decl.isGetter(m)) {
mostRefined = member.equals(((Value) m).getSetter());
} else {
mostRefined = member.equals(m);
}
return mostRefined && (member.isDefault() || !member.isFormal());
}
Aggregations