use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformConstructorDelegation.
/**
* Transform a delegated constructor call ({@code extends XXX()})
* which may be either a superclass initializer/constructor or a
* same-class constructor.
* @param extendedType
* @param delegation The kind of delegation
* @param invocation
* @param classBuilder
* @return
*/
JCStatement transformConstructorDelegation(Node extendedType, CtorDelegation delegation, Tree.InvocationExpression invocation, ClassDefinitionBuilder classBuilder, boolean forDelegationConstructor) {
if (delegation != null && delegation.isError()) {
return delegation.makeThrow(this);
}
Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) invocation.getPrimary()).getDeclaration();
java.util.List<ParameterList> paramLists = ((Functional) primaryDeclaration).getParameterLists();
if (paramLists.isEmpty()) {
classBuilder.getInitBuilder().delegateCall(at(extendedType).Exec(makeErroneous(extendedType, "compiler bug: super class " + primaryDeclaration.getName() + " is missing parameter list")));
return null;
}
SuperInvocation builder = new SuperInvocation(this, classBuilder.getForDefinition(), delegation, invocation, paramLists.get(0), forDelegationConstructor);
CallBuilder callBuilder = CallBuilder.instance(this);
boolean prevFnCall = withinInvocation(true);
try {
if (invocation.getPrimary() instanceof Tree.StaticMemberOrTypeExpression) {
transformTypeArguments(callBuilder, (Tree.StaticMemberOrTypeExpression) invocation.getPrimary());
}
at(builder.getNode());
JCExpression expr = null;
Scope outerDeclaration;
if (Decl.isConstructor(primaryDeclaration)) {
outerDeclaration = builder.getPrimaryDeclaration().getContainer().getContainer();
} else {
outerDeclaration = builder.getPrimaryDeclaration().getContainer();
}
if ((Strategy.generateInstantiator(builder.getPrimaryDeclaration()) || builder.getPrimaryDeclaration() instanceof Class) && outerDeclaration instanceof Interface) {
// If the subclass is inner to an interface then it will be
// generated inner to the companion and we need to qualify the
// super(), *unless* the subclass is nested within the same
// interface as it's superclass.
Scope outer = builder.getSub().getContainer();
while (!(outer instanceof Package)) {
if (outer == outerDeclaration) {
expr = naming.makeSuper();
break;
}
outer = outer.getContainer();
}
if (expr == null) {
if (delegation.isSelfDelegation()) {
throw new BugException();
}
Interface iface = (Interface) outerDeclaration;
JCExpression superQual;
if (Decl.getClassOrInterfaceContainer(classBuilder.getForDefinition(), false) instanceof Interface) {
superQual = naming.makeCompanionAccessorCall(naming.makeQuotedThis(), iface);
} else {
superQual = naming.makeCompanionFieldName(iface);
}
expr = naming.makeQualifiedSuper(superQual);
}
} else {
expr = delegation.isSelfDelegation() ? naming.makeThis() : naming.makeSuper();
}
final List<JCExpression> superArguments = transformSuperInvocationArguments(classBuilder, builder, callBuilder);
JCExpression superExpr = callBuilder.invoke(expr).arguments(superArguments).build();
return at(extendedType).Exec(superExpr);
// classBuilder.getInitBuilder().superCall(at(extendedType).Exec(superExpr));
} finally {
withinInvocation(prevFnCall);
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transform.
// Prefix operator
public JCExpression transform(final Tree.PrefixOperatorExpression expr) {
final OperatorTranslation operator = Operators.getOperator(expr.getClass());
if (operator == null) {
return makeErroneous(expr, "compiler bug: " + expr.getNodeType() + " is not supported yet");
}
OptimisationStrategy optimisationStrategy = operator.getUnOpOptimisationStrategy(expr, expr.getTerm(), this);
final boolean canOptimise = optimisationStrategy.useJavaOperator();
Tree.Term term = expr.getTerm();
// only fully optimise if we don't have to access the getter/setter
if (canOptimise && CodegenUtil.isDirectAccessVariable(term)) {
JCExpression jcTerm = transformExpression(term, BoxingStrategy.UNBOXED, expr.getTypeModel(), EXPR_WIDEN_PRIM);
return at(expr).Unary(operator.javacOperator, jcTerm);
}
Interface compoundType = expr.getUnit().getOrdinalDeclaration();
Type valueType = getSupertype(term, compoundType);
final Type returnType = getMostPreciseType(term, getTypeArgument(valueType, 0));
// we work on boxed types unless we could have optimised
return transformAssignAndReturnOperation(expr, term, !canOptimise, valueType, returnType, new AssignAndReturnOperationFactory() {
@Override
public JCExpression getNewValue(JCExpression previousValue) {
// use +1/-1 if we can optimise a bit
if (canOptimise) {
JCExpression ret = make().Binary(operator == OperatorTranslation.UNARY_PREFIX_INCREMENT ? JCTree.PLUS : JCTree.MINUS, previousValue, makeInteger(1));
ret = unAutoPromote(ret, returnType);
return ret;
}
// make this call: previousValue.getSuccessor() or previousValue.getPredecessor()
return make().Apply(null, makeSelect(previousValue, operator.ceylonMethod), List.<JCExpression>nil());
}
});
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
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_.isStaticallyImportable()) {
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");
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
public List<JCTree> transform(final Tree.ClassOrInterface def) {
final ClassOrInterface model = def.getDeclarationModel();
// in that case
if (model.isAlias() && Decl.isAncestorLocal(def))
return List.nil();
naming.clearSubstitutions(model);
final String javaClassName;
String ceylonClassName = def.getIdentifier().getText();
if (def instanceof Tree.AnyInterface) {
javaClassName = naming.makeTypeDeclarationName(model, QUALIFIED).replaceFirst(".*\\.", "");
} else {
javaClassName = Naming.quoteClassName(ceylonClassName);
}
ClassDefinitionBuilder instantiatorImplCb;
ClassDefinitionBuilder instantiatorDeclCb;
if (Decl.withinInterface(model)) {
instantiatorImplCb = gen().current().getCompanionBuilder((Interface) model.getContainer());
instantiatorDeclCb = gen().current();
} else {
instantiatorImplCb = gen().current();
instantiatorDeclCb = null;
}
ClassDefinitionBuilder classBuilder = ClassDefinitionBuilder.klass(this, javaClassName, ceylonClassName, Decl.isLocal(model)).forDefinition(model).hasDelegatingConstructors(CodegenUtil.hasDelegatingConstructors(def));
// Very special case for Anything
if ("ceylon.language::Anything".equals(model.getQualifiedNameString())) {
classBuilder.extending(model.getType(), null);
}
if (def instanceof Tree.AnyClass) {
classBuilder.getInitBuilder().modifiers(transformConstructorDeclFlags(model));
Tree.AnyClass classDef = (Tree.AnyClass) def;
Class cls = classDef.getDeclarationModel();
// Member classes need a instantiator method
boolean generateInstantiator = Strategy.generateInstantiator(cls);
if (!cls.hasConstructors()) {
classBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, def));
}
if (generateInstantiator && !cls.hasConstructors() && !cls.hasEnumerated()) {
classBuilder.getInitBuilder().modifiers(PROTECTED);
generateInstantiators(classBuilder, cls, null, instantiatorDeclCb, instantiatorImplCb, classDef, classDef.getParameterList());
}
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.ClassDefinition) {
transformClass((Tree.ClassDefinition) def, cls, classBuilder, classDef.getParameterList(), generateInstantiator, instantiatorDeclCb, instantiatorImplCb);
} else {
// class alias
classBuilder.getInitBuilder().modifiers(PRIVATE);
transformClassAlias((Tree.ClassDeclaration) def, classBuilder);
}
addMissingUnrefinedMembers(def, cls, classBuilder);
}
if (def instanceof Tree.AnyInterface) {
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.InterfaceDefinition) {
transformInterface(def, (Interface) model, classBuilder);
} else {
// interface alias
classBuilder.annotations(makeAtAlias(model.getExtendedType(), null));
classBuilder.isAlias(true);
}
classBuilder.isDynamic(model.isDynamic());
}
// make sure we set the container in case we move it out
addAtContainer(classBuilder, model);
// Transform the class/interface members
List<JCStatement> childDefs = visitClassOrInterfaceDefinition(def, classBuilder);
// everything else is synthetic
at(null);
TransformationPlan plan = errors().hasDeclarationError(def);
if (plan instanceof ThrowerCatchallConstructor) {
MethodDefinitionBuilder initBuilder = classBuilder.addConstructor();
initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
// Although we have the class pl which we could use we don't know
// that it won't collide with the default named constructor's pl
// which would cause a javac error about two constructors with the same sig
// so we generate a Object... here. There's still a risk of collision though
// when the default constructor has pl (ObjectArray).
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.implicitParameter(this, "ignored");
pdb.modifiers(VARARGS);
pdb.type(make().TypeArray(make().Type(syms().objectType)), null);
initBuilder.parameter(pdb);
}
// If it's a Class without initializer parameters...
if (Strategy.generateMain(def)) {
// ... then add a main() method
classBuilder.method(makeMainForClass(model));
}
classBuilder.modelAnnotations(model.getAnnotations()).modifiers(transformClassDeclFlags(model)).satisfies(model.getSatisfiedTypes()).caseTypes(model.getCaseTypes(), model.getSelfType()).defs((List) childDefs);
// aliases and native headers don't need a $getType method
if (!model.isAlias()) {
// only classes get a $getType method
if (model instanceof Class)
classBuilder.addGetTypeMethod(model.getType());
if (supportsReifiedAlias(model))
classBuilder.reifiedAlias(model.getType());
}
// we can add things which depend on knowing all the fields
if (Strategy.generateJpaCtor(def)) {
buildJpaConstructor((Class) def.getDeclarationModel(), classBuilder);
}
if (model instanceof Class && !(model instanceof ClassAlias)) {
Class c = (Class) model;
if (Strategy.introduceJavaIoSerializable(c, typeFact().getJavaIoSerializable())) {
classBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
if (Strategy.useSerializationProxy(c) && noValueConstructorErrors((Tree.ClassDefinition) def)) {
addWriteReplace(c, classBuilder);
}
}
serialization(c, classBuilder);
}
// reset position before initializer constructor is generated.
at(def);
List<JCTree> result;
if (Decl.isAnnotationClass(def)) {
ListBuffer<JCTree> trees = ListBuffer.lb();
trees.addAll(transformAnnotationClass((Tree.AnyClass) def));
transformAnnotationClassConstructor((Tree.AnyClass) def, classBuilder);
// you only need that method if you satisfy Annotation which is erased to j.l.a.Annotation
if (model.inherits(typeFact().getAnnotationDeclaration()))
classBuilder.addAnnotationTypeMethod(model.getType());
trees.addAll(classBuilder.build());
result = trees.toList();
} else {
result = classBuilder.build();
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassDefinitionBuilder method refineReifiedType.
public ClassDefinitionBuilder refineReifiedType(Type thisType) {
// init: $type$impl.$refine(tp1, tp2...)
Interface iface = (Interface) thisType.getDeclaration();
String companion = gen.naming.getCompanionFieldName(iface);
ListBuffer<JCExpression> typeParameters = new ListBuffer<JCExpression>();
for (Type tp : thisType.getTypeArgumentList()) {
typeParameters.add(gen.makeReifiedTypeArgument(tp));
}
JCExpression refine = gen.make().Apply(null, gen.makeSelect(companion, gen.naming.getRefineTypeParametersMethodName()), typeParameters.toList());
initBuilder.init(gen.make().Exec(refine));
return this;
}
Aggregations