use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
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 org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class ClassTransformer method addWriteReplace.
/**
* Adds a write replace method which replaces value constructor instances
* with a SerializationProxy
* @param model
* @param classBuilder
*/
protected void addWriteReplace(final Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, "writeReplace");
mdb.resultType(new TransformedType(make().Type(syms().objectType), null, makeAtNonNull()));
mdb.modifiers(PRIVATE | FINAL);
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
SyntheticName name = naming.synthetic(Unfix.$name$);
stmts.add(makeVar(FINAL, name, make().Type(syms().stringType), null));
if (model.hasEnumerated()) {
JCStatement tail;
if (Decl.hasOnlyValueConstructors(model)) {
tail = make().Throw(statementGen().makeNewEnumeratedTypeError("Instance not of any constructor"));
} else {
tail = make().Return(naming.makeThis());
}
for (Declaration member : model.getMembers()) {
if (Decl.isValueConstructor(member)) {
Value val = (Value) member;
tail = make().If(make().Binary(JCTree.Tag.EQ, naming.makeThis(), naming.getValueConstructorFieldName(val).makeIdent()), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName(member)))))), tail);
}
}
stmts.add(tail);
} else if (model.isAnonymous()) {
stmts.add(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName((Value) model.getContainer().getDirectMember(model.getName(), null, false))))));
} else {
throw new BugException("Unsupported need for writeReplace()");
}
// final String name;
// if(this == instA) {
// name = "getInstA";
// } // ... else { throw new
// return new SerializationProxy(outer, Foo.clazz, name);
List<JCExpression> args = List.<JCExpression>of(name.makeIdent());
if (model.isMember() && !model.isStatic()) {
ClassOrInterface outer = (ClassOrInterface) model.getContainer();
args = args.prepend(makeClassLiteral(outer.getType()));
args = args.prepend(naming.makeQualifiedThis(naming.makeTypeDeclarationExpression(null, outer, DeclNameFlag.QUALIFIED)));
} else {
args = args.prepend(makeClassLiteral(model.getType()));
}
stmts.add(make().Return(make().NewClass(null, null, make().QualIdent(syms().ceylonSerializationProxyType.tsym), args, null)));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class ExpressionTransformer method appendDeclarationLiteralForAnnotation.
/**
* Appends into the given builder a String representation of the given
* declaration, suitable for parsing my the DeclarationParser.
*/
private static void appendDeclarationLiteralForAnnotation(Declaration decl, StringBuilder sb) {
Scope container = decl.getContainer();
while (true) {
if (container instanceof Declaration) {
appendDeclarationLiteralForAnnotation((Declaration) container, sb);
sb.append(".");
break;
} else if (container instanceof Package) {
appendDeclarationLiteralForAnnotation((Package) container, sb);
sb.append(":");
break;
}
container = container.getContainer();
}
if (decl instanceof Class) {
sb.append("C").append(decl.getName());
} else if (decl instanceof Interface) {
sb.append("I").append(decl.getName());
} else if (decl instanceof TypeAlias) {
sb.append("A").append(decl.getName());
} else if (decl instanceof Value) {
sb.append("V").append(decl.getName());
} else if (decl instanceof Function) {
sb.append("F").append(decl.getName());
} else if (decl instanceof TypeParameter) {
sb.append("P").append(decl.getName());
} else if (decl instanceof Constructor) {
sb.append("c").append(decl.getName());
} else {
throw BugException.unhandledDeclarationCase(decl);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class ExpressionTransformer method transformMemberReference.
JCExpression transformMemberReference(Tree.QualifiedMemberOrTypeExpression expr, Tree.MemberOrTypeExpression primary) {
Declaration member = expr.getDeclaration();
Type qualifyingType = primary.getTypeModel();
Tree.TypeArguments typeArguments = expr.getTypeArguments();
Type expectedTypeIfCoerced = coerced ? expectedType : null;
boolean prevSyntheticClassBody = withinSyntheticClassBody(true);
try {
if (member.isStatic()) {
if (member instanceof Function) {
Function method = (Function) member;
// method.appliedReference(qualifyingType, typeArguments.getTypeModels());
Reference producedReference = expr.getTarget();
return CallableBuilder.javaStaticMethodReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced).build();
} else if (member instanceof FieldValue) {
return naming.makeName((TypedDeclaration) member, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED);
} else if (member instanceof Value) {
CallBuilder callBuilder = CallBuilder.instance(this);
JCExpression qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) member.getContainer(), DeclNameFlag.QUALIFIED);
Type primType = primary.getTarget().getType();
if (ModelUtil.isCeylonDeclaration(member) && !primType.getTypeArgumentList().isEmpty()) {
for (Type pt : primType.getTypeArgumentList()) {
callBuilder.typeArgument(makeJavaType(pt, JT_TYPE_ARGUMENT));
callBuilder.argument(makeReifiedTypeArgument(pt));
}
}
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
return callBuilder.build();
} else if (member instanceof Class) {
Reference producedReference = expr.getTarget();
return CallableBuilder.javaStaticMethodReference(gen(), expr, expr.getTypeModel(), (Class) member, producedReference, expectedTypeIfCoerced).build();
}
}
if (member instanceof Value) {
if (expr.getStaticMethodReference() && ModelUtil.isEnumeratedConstructor((Value) member)) {
CallBuilder callBuilder = CallBuilder.instance(this);
JCExpression qualExpr;
Class class1 = (Class) member.getContainer();
if (class1.isToplevel() || class1.isStatic()) {
qualExpr = naming.makeTypeDeclarationExpression(null, class1.isStatic() ? (TypeDeclaration) class1.getContainer() : class1, DeclNameFlag.QUALIFIED);
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
} else if (class1.isMember()) {
// creates a Callable<Outer.Inner,[Outer]> that returns the enumeratedConstructor given an outer instance
if (primary instanceof Tree.QualifiedMemberOrTypeExpression && (((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary() instanceof Tree.BaseTypeExpression || ((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary() instanceof Tree.QualifiedTypeExpression))
return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member), expectedTypeIfCoerced).build();
else {
qualExpr = primary instanceof Tree.QualifiedMemberOrTypeExpression ? transformExpression(((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary()) : null;
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
}
} else {
// Local enumerated constructor values are boxed
qualExpr = naming.makeQualifiedName(null, (TypedDeclaration) member, Naming.NA_Q_LOCAL_INSTANCE);
qualExpr = gen().makeSelect(qualExpr, naming.selector((TypedDeclaration) member));
callBuilder.fieldRead(qualExpr);
}
return callBuilder.build();
} else {
return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member), expectedTypeIfCoerced).build();
}
} else if (Decl.isConstructor(member)) {
Reference producedReference = expr.getTarget();
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), ModelUtil.getConstructor(member), producedReference, expectedTypeIfCoerced);
} else if (member instanceof Function) {
Function method = (Function) member;
if (!method.isParameter()) {
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced);
} else {
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced);
}
} else if (member instanceof Class) {
Reference producedReference = expr.getTarget();
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), (Class) member, producedReference, expectedTypeIfCoerced);
} else {
return makeErroneous(expr, "compiler bug: member reference of " + expr + " not supported yet");
}
} finally {
withinSyntheticClassBody(prevSyntheticClassBody);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Value in project ceylon by eclipse.
the class ExpressionTransformer method transformJavaStaticOrInterfaceMember.
private JCExpression transformJavaStaticOrInterfaceMember(Tree.QualifiedMemberOrTypeExpression qmte, Type staticType) {
Declaration decl = qmte.getDeclaration();
if (decl instanceof FieldValue) {
Value member = (Value) decl;
return naming.makeName(member, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED);
} else if (decl instanceof Value) {
Value member = (Value) decl;
CallBuilder callBuilder = CallBuilder.instance(this);
Type qualifyingType = ((TypeDeclaration) member.getContainer()).getType();
callBuilder.invoke(naming.makeQualifiedName(makeJavaType(qualifyingType, JT_RAW | JT_NO_PRIMITIVES), member, Naming.NA_GETTER | Naming.NA_MEMBER));
return utilInvocation().checkNull(callBuilder.build());
} else if (decl instanceof Function) {
Function method = (Function) decl;
final ParameterList parameterList = method.getFirstParameterList();
Type qualifyingType = qmte.getPrimary().getTypeModel();
Tree.TypeArguments typeArguments = qmte.getTypeArguments();
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return utilInvocation().checkNull(makeJavaStaticInvocation(gen(), method, producedReference, parameterList));
} else if (decl instanceof Class) {
Class class_ = (Class) decl;
if (class_.isStatic()) {
return naming.makeTypeDeclarationExpression(null, class_, Naming.DeclNameFlag.QUALIFIED);
} else {
final ParameterList parameterList = class_.getFirstParameterList();
Reference producedReference = qmte.getTarget();
return utilInvocation().checkNull(makeJavaStaticInvocation(gen(), class_, producedReference, parameterList));
}
} else if (decl instanceof Interface) {
return naming.makeTypeDeclarationExpression(null, (Interface) decl, Naming.DeclNameFlag.QUALIFIED);
} else {
return makeErroneous(qmte, "compiler bug: unsupported static");
}
}
Aggregations