use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class BoxingDeclarationVisitor method boxMethod.
private void boxMethod(Function method, Node that) {
// deal with invalid input
if (method == null)
return;
Declaration refined = CodegenUtil.getTopmostRefinedDeclaration(method, optimisedMethodSpecifiersToMethods);
// deal with invalid input
if (refined == null || (!(refined instanceof Function)))
return;
TypedDeclaration refinedMethod = (TypedDeclaration) refined;
if (method.getName() != null) {
// A Callable, which never have primitive parameters
setBoxingState(method, refinedMethod, that);
} else {
// Anonymous methods are always boxed
method.setUnboxed(false);
}
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
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, DelegateType delegateType, 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 = 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(null, make().Type(syms().intType));
returnType = typedMember.getType();
} else if (typedMember instanceof TypedReference) {
TypedReference typedRef = (TypedReference) typedMember;
if (delegateType == DelegateType.OTHER) {
// 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 {
// for default value
NonWideningParam nonWideningParam = concreteWrapper.getNonWideningParam(typedRef, currentType.getDeclaration() instanceof Class ? WideningRules.FOR_MIXIN : WideningRules.NONE);
returnType = nonWideningParam.nonWideningType;
if (member instanceof Function)
returnType = typeFact().getCallableType(returnType);
concreteWrapper.resultType(null, makeJavaType(returnType, nonWideningParam.flags));
}
} else {
concreteWrapper.resultType(null, makeJavaType((Type) typedMember));
returnType = (Type) typedMember;
}
}
ListBuffer<JCExpression> arguments = ListBuffer.<JCExpression>lb();
if (typeParameters != null) {
for (TypeParameter tp : typeParameters) {
arguments.add(naming.makeUnquotedIdent(naming.getTypeArgumentDescriptorName(tp)));
}
}
if (typedMember.getDeclaration() instanceof Constructor && !Decl.isDefaultConstructor((Constructor) typedMember.getDeclaration())) {
concreteWrapper.parameter(makeConstructorNameParameter((Constructor) typedMember.getDeclaration()));
arguments.add(naming.makeUnquotedIdent(Unfix.$name$));
}
for (Parameter param : parameters) {
final TypedReference typedParameter = typedMember.getTypedParameter(param);
concreteWrapper.parameter(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 '" + typedMember.getDeclaration().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;
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationGet.
private void serializationGet(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$get$.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);
mdb.resultType(null, make().Type(syms().objectType));
/*
* public void $set$(Object reference, Object instance) {
* switch((String)reference) {
* case ("attr1")
* return ...;
* // ... other fields of this class
* case ("lateAttr1")
* if (!$init$lateAttr1) {
* return ceylon.language.serialization.uninitializedLateValue.get_();
* }
* return ...;
* case (null):
* return Outer.this;
* default:
* return super.get(reference);
*/
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()) {
// TODO this should be encapsulated so the ADB and this
// code can just call something common
JCExpression test;
if (CodegenUtil.needsLateInitField((Value) member, typeFact())) {
test = make().Unary(JCTree.NOT, naming.makeUnquotedIdent(Naming.getInitializationFieldName(member.getName())));
} else {
test = make().Binary(JCTree.EQ, naming.makeQualifiedName(naming.makeThis(), (Value) member, Naming.NA_IDENT), makeNull());
}
caseStmts.add(make().If(test, make().Return(makeLanguageSerializationValue("uninitializedLateValue")), null));
}
caseStmts.add(make().Return(makeSerializationGetter((Value) member)));
cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
}
}
SyntheticName reference = naming.synthetic(Unfix.reference);
ListBuffer<JCStatement> defaultCase = ListBuffer.lb();
if (extendsSerializable(model)) {
// super.get(reference);
defaultCase.add(make().Return(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$get$.toString()), List.<JCExpression>of(reference.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());
if (model.isMember() && !model.getExtendedType().getDeclaration().isMember()) {
stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonOuterType)), make().Return(expressionGen().makeOuterExpr(((TypeDeclaration) model.getContainer()).getType())), swtch));
} else {
stmts.add(swtch);
}
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method transformMethod.
private List<MethodDefinitionBuilder> transformMethod(final Function methodModel, Tree.TypeParameterList typeParameterList, Tree.AnyMethod node, java.util.List<Tree.ParameterList> parameterLists, Tree.Declaration annotated, boolean transformMethod, boolean actual, boolean includeAnnotations, List<JCStatement> body, DaoBody daoTransformation, boolean defaultValuesBody) {
ListBuffer<MethodDefinitionBuilder> lb = ListBuffer.<MethodDefinitionBuilder>lb();
Declaration refinedDeclaration = methodModel.getRefinedDeclaration();
final MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.method(this, methodModel);
// do the reified type param arguments
if (gen().supportsReified(methodModel)) {
methodBuilder.reifiedTypeParameters(methodModel.getTypeParameters());
}
if (methodModel.getParameterLists().size() > 1) {
methodBuilder.mpl(methodModel.getParameterLists());
}
boolean hasOverloads = false;
Tree.ParameterList parameterList = parameterLists.get(0);
int flags = 0;
if (rawParameters(methodModel)) {
flags |= JT_RAW;
}
for (final Tree.Parameter parameter : parameterList.getParameters()) {
Parameter parameterModel = parameter.getParameterModel();
List<JCAnnotation> annotations = null;
if (includeAnnotations) {
Tree.TypedDeclaration typedDeclaration = Decl.getMemberDeclaration(annotated, parameter);
// f = function(Integer param) => 2;
if (typedDeclaration != null)
annotations = expressionGen().transformAnnotations(OutputElement.PARAMETER, typedDeclaration);
}
methodBuilder.parameter(parameterModel, annotations, flags, WideningRules.CAN_WIDEN);
if (Strategy.hasDefaultParameterValueMethod(parameterModel) || Strategy.hasDefaultParameterOverload(parameterModel)) {
if (Decl.equal(refinedDeclaration, methodModel) || (!Decl.withinInterface(methodModel) && body != null) || Decl.withinInterface(methodModel) && daoTransformation instanceof DaoCompanion == false) {
if (daoTransformation != null && (daoTransformation instanceof DaoCompanion == false || body != null)) {
DaoBody daoTrans = (body == null) ? daoAbstract : new DaoThis(node, parameterList);
MethodDefinitionBuilder overloadedMethod = new DefaultedArgumentMethod(daoTrans, MethodDefinitionBuilder.method(this, methodModel), methodModel).makeOverload(parameterList.getModel(), parameter.getParameterModel(), methodModel.getTypeParameters());
overloadedMethod.location(null);
lb.append(overloadedMethod);
}
if (Decl.equal(refinedDeclaration, methodModel) && Strategy.hasDefaultParameterValueMethod(parameterModel)) {
lb.append(makeParamDefaultValueMethod(defaultValuesBody, methodModel, parameterList, parameter));
}
}
hasOverloads = true;
}
}
// Determine if we need to generate a "canonical" method
boolean createCanonical = hasOverloads && Decl.withinClassOrInterface(methodModel) && body != null;
if (createCanonical) {
// Creates the private "canonical" method containing the actual body
MethodDefinitionBuilder canonicalMethod = new CanonicalMethod(daoTransformation, methodModel, body).makeOverload(parameterList.getModel(), null, methodModel.getTypeParameters());
lb.append(canonicalMethod);
}
if (transformMethod) {
methodBuilder.modifiers(transformMethodDeclFlags(methodModel));
if (actual) {
methodBuilder.isOverride(methodModel.isActual());
}
if (includeAnnotations) {
methodBuilder.userAnnotations(expressionGen().transformAnnotations(OutputElement.METHOD, annotated));
methodBuilder.modelAnnotations(methodModel.getAnnotations());
} else {
methodBuilder.ignoreModelAnnotations();
}
methodBuilder.resultType(methodModel, 0);
copyTypeParameters(methodModel, methodBuilder);
if (createCanonical) {
// Creates method that redirects to the "canonical" method containing the actual body
MethodDefinitionBuilder overloadedMethod = new CanonicalMethod(new DaoThis(node, parameterList), methodBuilder, methodModel).makeOverload(parameterList.getModel(), null, methodModel.getTypeParameters());
lb.append(overloadedMethod);
} else {
if (body != null) {
// Construct the outermost method using the body we've built so far
methodBuilder.body(body);
} else {
methodBuilder.noBody();
}
lb.append(methodBuilder);
}
}
return lb.toList();
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method concreteMembersFromSuperinterfaces.
/**
* Generates companion fields ($Foo$impl) and methods
*/
private void concreteMembersFromSuperinterfaces(final Class model, ClassDefinitionBuilder classBuilder, Type satisfiedType, Set<Interface> satisfiedInterfaces) {
satisfiedType = satisfiedType.resolveAliases();
Interface iface = (Interface) satisfiedType.getDeclaration();
if (satisfiedInterfaces.contains(iface) || iface.getType().isExactly(typeFact().getIdentifiableDeclaration().getType())) {
return;
}
// then don't instantiate it...
if (hasImpl(iface)) {
// ... otherwise for each satisfied interface,
// instantiate an instance of the
// companion class in the constructor and assign it to a
// $Interface$impl field
transformInstantiateCompanions(classBuilder, model, iface, satisfiedType);
}
if (!Decl.isCeylon(iface)) {
// let's not try to implement CMI for Java interfaces
return;
}
// For each super interface
for (Declaration member : iface.getMembers()) {
if (member instanceof Class) {
Class klass = (Class) member;
final Type typedMember = satisfiedType.getTypeMember(klass, Collections.<Type>emptyList());
if (Strategy.generateInstantiator(member) && !klass.hasConstructors() && !model.isFormal() && needsCompanionDelegate(model, typedMember) && model.getDirectMember(member.getName(), null, false) == null) {
// instantiator method implementation
generateInstantiatorDelegate(classBuilder, satisfiedType, iface, klass, null, model.getType(), !member.isFormal());
}
if (klass.hasConstructors()) {
for (Declaration m : klass.getMembers()) {
if (m instanceof Constructor && Strategy.generateInstantiator(m)) {
Constructor ctor = (Constructor) m;
generateInstantiatorDelegate(classBuilder, satisfiedType, iface, klass, ctor, model.getType(), true);
}
}
}
}
// type aliases are on the $impl class
if (member instanceof TypeAlias)
continue;
if (Strategy.onlyOnCompanion(member)) {
// (they're just private methods on the $impl)
continue;
}
if (member instanceof Function) {
Function method = (Function) member;
final TypedReference typedMember = satisfiedType.getTypedMember(method, Collections.<Type>emptyList());
Declaration sub = (Declaration) model.getMember(method.getName(), getSignatureIfRequired(typedMember), false, true);
if (sub instanceof Function) /* && !sub.isAbstraction()*/
{
Function subMethod = (Function) sub;
if (subMethod.getParameterLists().isEmpty()) {
continue;
}
java.util.List<java.util.List<Type>> producedTypeParameterBounds = producedTypeParameterBounds(typedMember, subMethod);
// final TypedReference refinedTypedMember = model.getType().getTypedMember(subMethod, Collections.<Type>emptyList());
final java.util.List<TypeParameter> typeParameters = subMethod.getTypeParameters();
final java.util.List<Parameter> parameters = subMethod.getFirstParameterList().getParameters();
boolean hasOverloads = false;
if (!satisfiedInterfaces.contains((Interface) method.getContainer())) {
for (Parameter param : parameters) {
if (Strategy.hasDefaultParameterValueMethod(param) && CodegenUtil.getTopmostRefinedDeclaration(param.getModel()).getContainer().equals(member)) {
final TypedReference typedParameter = typedMember.getTypedParameter(param);
// If that method has a defaulted parameter,
// we need to generate a default value method
// which also delegates to the $impl
final MethodDefinitionBuilder defaultValueDelegate = makeDelegateToCompanion(iface, typedParameter, model.getType(), PUBLIC | FINAL, typeParameters, producedTypeParameterBounds, typedParameter.getFullType(), Naming.getDefaultedParamMethodName(method, param), parameters.subList(0, parameters.indexOf(param)), param.getModel().getTypeErased(), null, DelegateType.FOR_DEFAULT_VALUE);
classBuilder.method(defaultValueDelegate);
}
if (Strategy.hasDefaultParameterOverload(param)) {
if ((method.isDefault() || method.isShared() && !method.isFormal()) && Decl.equal(method, subMethod)) {
MethodDefinitionBuilder overload = new DefaultedArgumentMethodTyped(new DaoThis((Tree.AnyMethod) null, null), MethodDefinitionBuilder.method(this, subMethod), typedMember, true).makeOverload(subMethod.getFirstParameterList(), param, typeParameters);
classBuilder.method(overload);
}
hasOverloads = true;
}
}
}
// delegating to the $impl instance
if (needsCompanionDelegate(model, typedMember)) {
final MethodDefinitionBuilder concreteMemberDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), PUBLIC | (method.isDefault() ? 0 : FINAL), typeParameters, producedTypeParameterBounds, typedMember.getType(), naming.selector(method), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), null, DelegateType.OTHER);
classBuilder.method(concreteMemberDelegate);
}
if (hasOverloads && (method.isDefault() || method.isShared() && !method.isFormal()) && Decl.equal(method, subMethod)) {
final MethodDefinitionBuilder canonicalMethod = makeDelegateToCompanion(iface, typedMember, model.getType(), PRIVATE, subMethod.getTypeParameters(), producedTypeParameterBounds, typedMember.getType(), Naming.selector(method, Naming.NA_CANONICAL_METHOD), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), naming.selector(method), DelegateType.OTHER);
classBuilder.method(canonicalMethod);
}
}
} else if (member instanceof Value || member instanceof Setter) {
TypedDeclaration attr = (TypedDeclaration) member;
final TypedReference typedMember = satisfiedType.getTypedMember(attr, null);
if (needsCompanionDelegate(model, typedMember)) {
Setter setter = (member instanceof Setter) ? (Setter) member : null;
if (member instanceof Value) {
if (member instanceof JavaBeanValue) {
setter = ((Value) member).getSetter();
}
final MethodDefinitionBuilder getterDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), PUBLIC | (attr.isDefault() ? 0 : FINAL), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typedMember.getType(), Naming.getGetterName(attr), Collections.<Parameter>emptyList(), attr.getTypeErased(), null, DelegateType.OTHER);
classBuilder.method(getterDelegate);
}
if (setter != null) {
final MethodDefinitionBuilder setterDelegate = makeDelegateToCompanion(iface, satisfiedType.getTypedMember(setter, null), model.getType(), PUBLIC | (setter.getGetter().isDefault() ? 0 : FINAL), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typeFact().getAnythingType(), Naming.getSetterName(attr), Collections.<Parameter>singletonList(setter.getParameter()), setter.getTypeErased(), null, DelegateType.OTHER);
classBuilder.method(setterDelegate);
}
if (Decl.isValue(member) && ((Value) attr).isVariable()) {
// $impl to delegate to
throw new BugException("assertion failed: " + member.getQualifiedNameString() + " was unexpectedly a variable value");
}
}
} else {
Reference typedMember = member instanceof TypeDeclaration ? satisfiedType.getTypeMember((TypeDeclaration) member, Collections.<Type>emptyList()) : satisfiedType.getTypedMember((TypedDeclaration) member, Collections.<Type>emptyList());
if (needsCompanionDelegate(model, typedMember)) {
throw new BugException("unhandled concrete interface member " + member.getQualifiedNameString() + " " + member.getClass());
}
}
}
// Add $impl instances for the whole interface hierarchy
satisfiedInterfaces.add(iface);
for (Type sat : iface.getSatisfiedTypes()) {
sat = model.getType().getSupertype(sat.getDeclaration());
concreteMembersFromSuperinterfaces(model, classBuilder, sat, satisfiedInterfaces);
}
}
Aggregations