use of com.redhat.ceylon.model.typechecker.model.Interface 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.Interface in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformQualifiedInstantiation.
private JCExpression transformQualifiedInstantiation(Invocation invocation, CallBuilder callBuilder, TransformedInvocationPrimary transformedPrimary) {
Tree.QualifiedTypeExpression qte = (Tree.QualifiedTypeExpression) invocation.getPrimary();
Declaration declaration = qte.getDeclaration();
invocation.location(callBuilder);
if (Decl.isJavaStaticOrInterfacePrimary(invocation.getPrimary())) {
callBuilder.instantiate(transformedPrimary.expr);
} else if (!Strategy.generateInstantiator(declaration)) {
if (Decl.isConstructorPrimary(invocation.getPrimary())) {
if (Decl.getConstructedClass(invocation.getPrimaryDeclaration()).isMember()) /*&& invocation.getPrimary() instanceof Tree.QualifiedTypeExpression
&& !(((Tree.QualifiedTypeExpression)invocation.getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression)*/
{
callBuilder.instantiate(new ExpressionAndType(transformedPrimary.expr, null), makeJavaType(invocation.getReturnType(), JT_CLASS_NEW | (transformedPrimary.expr == null ? 0 : JT_NON_QUALIFIED)));
} else {
callBuilder.instantiate(makeJavaType(invocation.getReturnType(), JT_CLASS_NEW));
}
} else {
JCExpression qualifier;
JCExpression qualifierType;
if (declaration.getContainer() instanceof Interface) {
// When doing qualified invocation through an interface we need
// to get the companion.
Interface qualifyingInterface = (Interface) declaration.getContainer();
qualifier = transformedPrimary.expr;
qualifierType = makeJavaType(qualifyingInterface.getType(), JT_COMPANION);
} else {
qualifier = transformedPrimary.expr;
if (declaration.getContainer() instanceof TypeDeclaration) {
qualifierType = makeJavaType(((TypeDeclaration) declaration.getContainer()).getType());
} else {
qualifierType = null;
}
}
Type classType = (Type) qte.getTarget();
JCExpression type;
// special case for package-qualified things that are not really qualified
if (qualifier == null) {
type = makeJavaType(classType, AbstractTransformer.JT_CLASS_NEW);
} else {
// Note: here we're not fully qualifying the class name because the JLS says that if "new" is qualified the class name
// is qualified relative to it
type = makeJavaType(classType, AbstractTransformer.JT_CLASS_NEW | AbstractTransformer.JT_NON_QUALIFIED);
}
callBuilder.instantiate(new ExpressionAndType(qualifier, qualifierType), type);
}
} else {
// instantiator
callBuilder.typeArguments(List.<JCExpression>nil());
java.util.List<Type> typeModels = qte.getTypeArguments().getTypeModels();
if (typeModels != null) {
for (Type tm : typeModels) {
callBuilder.typeArgument(makeJavaType(tm, AbstractTransformer.JT_TYPE_ARGUMENT));
}
}
callBuilder.invoke(naming.makeInstantiatorMethodName(transformedPrimary.expr, Decl.getConstructedClass(declaration)));
}
JCExpression result = callBuilder.build();
if (Strategy.isInstantiatorUntyped(declaration)) {
result = make().TypeCast(makeJavaType(invocation.getReturnType()), result);
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeReifiedTypeArgumentResolved.
private JCExpression makeReifiedTypeArgumentResolved(Type pt, boolean qualified) {
if (pt.isUnion()) {
// FIXME: refactor this shite
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getCaseTypes();
if (typeParameters.size() == 2) {
Type alternative = null;
if (typeParameters.get(0).isEmpty())
alternative = typeParameters.get(1);
else if (typeParameters.get(1).isEmpty())
alternative = typeParameters.get(0);
if (alternative != null && alternative.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(alternative, true);
if (tupleType != null)
return tupleType;
}
}
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "union"), typeTestArguments);
} else if (pt.isIntersection()) {
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getSatisfiedTypes();
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "intersection"), typeTestArguments);
} else if (pt.isNothing()) {
return makeNothingTypeDescriptor();
}
TypeDeclaration declaration = pt.getDeclaration();
if (declaration instanceof Constructor) {
pt = pt.getExtendedType();
declaration = pt.getDeclaration();
}
if (pt.isClassOrInterface()) {
if (declaration.isJavaEnum()) {
pt = pt.getExtendedType();
declaration = pt.getDeclaration();
}
// see if we have an alias for it
if (supportsReifiedAlias((ClassOrInterface) declaration)) {
JCExpression qualifier = naming.makeDeclarationName(declaration, DeclNameFlag.QUALIFIED);
return makeSelect(qualifier, naming.getTypeDescriptorAliasName());
}
if (pt.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(pt, false);
if (tupleType != null)
return tupleType;
}
// no alias, must build it
List<JCExpression> typeTestArguments = makeReifiedTypeArgumentsResolved(pt.getTypeArgumentList(), qualified);
JCExpression thisType = makeUnerasedClassLiteral(declaration);
// do we have variance overrides?
Map<TypeParameter, SiteVariance> varianceOverrides = pt.getVarianceOverrides();
if (!varianceOverrides.isEmpty()) {
// we need to pass them as second argument then, in an array
ListBuffer<JCExpression> varianceElements = new ListBuffer<JCExpression>();
for (TypeParameter typeParameter : declaration.getTypeParameters()) {
SiteVariance useSiteVariance = varianceOverrides.get(typeParameter);
String selector;
if (useSiteVariance != null) {
switch(useSiteVariance) {
case IN:
selector = "IN";
break;
case OUT:
selector = "OUT";
break;
default:
selector = "NONE";
break;
}
} else {
selector = "NONE";
}
JCExpression varianceElement = make().Select(makeIdent(syms().ceylonVarianceType), names().fromString(selector));
varianceElements.append(varianceElement);
}
JCNewArray varianceArray = make().NewArray(makeIdent(syms().ceylonVarianceType), List.<JCExpression>nil(), varianceElements.toList());
typeTestArguments = typeTestArguments.prepend(varianceArray);
}
typeTestArguments = typeTestArguments.prepend(thisType);
JCExpression classDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), "klass"), typeTestArguments);
Type qualifyingType = pt.getQualifyingType();
JCExpression containerType = null;
if (qualifyingType == null && // ignore qualifying types of static java declarations
(Decl.isCeylon(declaration) || !declaration.isStaticallyImportable())) {
// it may be contained in a function or value, and we want its type
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration)
containerType = makeTypedDeclarationTypeDescriptorResolved((TypedDeclaration) enclosingDeclaration);
else if (enclosingDeclaration instanceof TypeDeclaration) {
qualifyingType = ((TypeDeclaration) enclosingDeclaration).getType();
}
}
if (qualifyingType != null && qualifyingType.getDeclaration() instanceof Constructor) {
qualifyingType = qualifyingType.getQualifyingType();
}
if (qualifyingType != null) {
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true);
}
if (containerType == null) {
return classDescriptor;
} else {
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "member"), List.of(containerType, classDescriptor));
}
} else if (pt.isTypeParameter()) {
TypeParameter tp = (TypeParameter) declaration;
String name = naming.getTypeArgumentDescriptorName(tp);
if (!qualified || isTypeParameterSubstituted(tp))
return makeUnquotedIdent(name);
Scope container = tp.getContainer();
JCExpression qualifier = null;
if (container instanceof Class) {
qualifier = naming.makeQualifiedThis(makeJavaType(((Class) container).getType(), JT_RAW));
} else if (container instanceof Interface) {
qualifier = naming.makeQualifiedThis(makeJavaType(((Interface) container).getType(), JT_COMPANION | JT_RAW));
} else if (container instanceof Function) {
// name must be a unique name, as returned by getTypeArgumentDescriptorName
return makeUnquotedIdent(name);
} else {
throw BugException.unhandledCase(container);
}
return makeSelect(qualifier, name);
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class BoxingVisitor method visit.
@Override
public void visit(QualifiedMemberExpression that) {
super.visit(that);
// handle errors gracefully
if (that.getDeclaration() == null)
return;
if (that.getMemberOperator() instanceof Tree.SafeMemberOp) {
TypedDeclaration decl = (TypedDeclaration) that.getDeclaration();
if (CodegenUtil.isRaw(decl))
CodegenUtil.markRaw(that);
if (CodegenUtil.hasTypeErased(decl))
CodegenUtil.markTypeErased(that);
if (CodegenUtil.hasUntrustedType(decl) || hasTypeParameterWithConstraintsOutsideScope(decl.getType(), that.getScope()))
CodegenUtil.markUntrustedType(that);
// we must be boxed, since safe member op "?." returns an optional type
// return;
} else if (that.getMemberOperator() instanceof Tree.MemberOp && Decl.isValueTypeDecl(that.getPrimary()) && CodegenUtil.isUnBoxed(that.getPrimary())) {
// it's unboxed if it's an unboxable type or it's declared void
if (Decl.isValueTypeDecl((TypedDeclaration) that.getDeclaration()) || (that.getDeclaration() instanceof Function && ((Function) that.getDeclaration()).isDeclaredVoid()))
CodegenUtil.markUnBoxed(that);
if (CodegenUtil.isRaw((TypedDeclaration) that.getDeclaration()))
CodegenUtil.markRaw(that);
if (CodegenUtil.hasTypeErased((TypedDeclaration) that.getDeclaration()))
CodegenUtil.markTypeErased(that);
} else {
propagateFromDeclaration(that, (TypedDeclaration) that.getDeclaration());
}
// be (ex: <String>), and in that case we will generate a proper Sequential<String> which is not raw at all
if (that.getMemberOperator() instanceof Tree.SpreadOp) {
// find the return element type
Type elementType = that.getTarget().getType();
CodegenUtil.markTypeErased(that, hasErasure(elementType));
}
if (ExpressionTransformer.isSuperOrSuperOf(that.getPrimary())) {
// if the target is an interface whose type arguments have been turned to raw, make this expression
// as erased
Reference target = that.getTarget();
if (target != null && target.getQualifyingType() != null && target.getQualifyingType().getDeclaration() instanceof Interface) {
if (isRaw(target.getQualifyingType())) {
CodegenUtil.markTypeErased(that);
} else // See note in ClassTransformer.makeDelegateToCompanion for a similar test
{
TypeDeclaration declaration = target.getQualifyingType().getDeclaration();
if (needsRawCastForMixinSuperCall(declaration, target.getType()))
CodegenUtil.markTypeErased(that);
}
}
}
Type primaryType;
if (that.getPrimary() instanceof Tree.Package || that.getTarget() == null) {
primaryType = that.getPrimary().getTypeModel();
} else {
primaryType = that.getTarget().getQualifyingType();
}
if (primaryType != null && (isRaw(primaryType) || willEraseToSequence(primaryType)) && that.getTarget() != null && that.getTarget().getDeclaration() instanceof TypedDeclaration && CodegenUtil.containsTypeParameter(((TypedDeclaration) that.getTarget().getDeclaration()).getType())) {
CodegenUtil.markTypeErased(that);
}
if (isRaw(primaryType) && !that.getTypeModel().getDeclaration().getTypeParameters().isEmpty()) {
CodegenUtil.markRaw(that);
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeParameterisedType.
public JCExpression makeParameterisedType(Type type, Type generalType, final int flags, JCExpression qualifyingExpression, java.util.List<Reference> qualifyingTypes, int firstQualifyingTypeWithTypeParameters, int index) {
JCExpression baseType;
TypeDeclaration tdecl = type.getDeclaration();
ListBuffer<JCExpression> typeArgs = null;
if (index >= firstQualifyingTypeWithTypeParameters) {
int taFlags = flags;
if (qualifyingTypes != null && index < qualifyingTypes.size()) {
// The qualifying types before the main one should
// have type parameters with proper variance
taFlags &= ~(JT_EXTENDS | JT_SATISFIES);
}
typeArgs = makeTypeArgs(type, taFlags);
}
if (isCeylonCallable(generalType) && (flags & JT_CLASS_NEW) != 0) {
baseType = makeIdent(syms().ceylonAbstractCallableType);
} else if (index == 0) {
// qualified type is static
if (tdecl instanceof Interface && qualifyingTypes != null && qualifyingTypes.size() > 1 && firstQualifyingTypeWithTypeParameters == 0 && (flags & JT_NON_QUALIFIED) == 0) {
baseType = naming.makeCompanionClassName(tdecl);
} else {
baseType = naming.makeDeclarationName(tdecl, jtFlagsToDeclNameOpts(flags));
}
} else {
baseType = naming.makeTypeDeclarationExpression(qualifyingExpression, tdecl, jtFlagsToDeclNameOpts(flags | JT_NON_QUALIFIED | (type.getDeclaration() instanceof Interface ? JT_COMPANION : 0)));
}
if (typeArgs != null && typeArgs.size() > 0) {
qualifyingExpression = make().TypeApply(baseType, typeArgs.toList());
} else {
qualifyingExpression = baseType;
}
return qualifyingExpression;
}
Aggregations