use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ExpressionTransformer method lostTypeParameterInInheritance.
private boolean lostTypeParameterInInheritance(ClassOrInterface exprDecl, ClassOrInterface commonDecl, boolean searchInterfaces, boolean lostTypeParameter) {
// stop if we found the common decl
if (Decl.equal(exprDecl, commonDecl))
return lostTypeParameter;
if (searchInterfaces) {
// find a match in interfaces
for (Type pt : exprDecl.getSatisfiedTypes()) {
// FIXME: this is very heavy-handed because we consider that once we've lost a type parameter we've lost them all
// but we could optimise this by checking:
// 1/ which type parameter we've really lost
// 2/ if the type parameters we're passing to our super type actually depend in any way from type parameters we've lost
boolean lostTypeParameter2 = lostTypeParameter || isTurnedToRaw(pt);
pt = simplifyType(pt);
// skip unknown types
if (pt.isUnknown())
continue;
// it has to be an interface
Interface interf = (Interface) pt.getDeclaration();
if (lostTypeParameterInInheritance(interf, commonDecl, searchInterfaces, lostTypeParameter2))
return true;
}
}
// search for super classes
Type extendedType = exprDecl.getExtendedType();
if (extendedType != null) {
// FIXME: see above
boolean lostTypeParameter2 = lostTypeParameter || isTurnedToRaw(extendedType);
extendedType = simplifyType(extendedType);
// it has to be a Class
Class extendedTypeDeclaration = (Class) extendedType.getDeclaration();
// looks like Object's superclass is Object, so stop right there
if (extendedTypeDeclaration != typeFact().getObjectDeclaration())
return lostTypeParameterInInheritance(extendedTypeDeclaration, commonDecl, searchInterfaces, lostTypeParameter2);
}
// didn't find it
return false;
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
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 (ModelUtil.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, ModelUtil.getConstructedClass(declaration)));
}
JCExpression result = callBuilder.build();
if (Strategy.isInstantiatorUntyped(declaration)) {
result = make().TypeCast(makeJavaType(invocation.getReturnType()), result);
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ExpressionTransformer method transform.
//
// Operator-Assignment expressions
public JCExpression transform(final Tree.ArithmeticAssignmentOp op) {
final AssignmentOperatorTranslation operator = Operators.getAssignmentOperator(op.getClass());
if (operator == null) {
return makeErroneous(op, "compiler bug: " + op.getNodeType() + " is not a supported arithmetic assignment operator");
}
// see if we can optimise it
if (op.getUnboxed() && CodegenUtil.isDirectAccessVariable(op.getLeftTerm())) {
return optimiseAssignmentOperator(op, operator);
}
// we can use unboxed types if both operands are unboxed
final boolean boxResult = !op.getUnboxed();
// find the proper type
Interface compoundType = op.getUnit().getNumericDeclaration();
if (op instanceof Tree.AddAssignOp) {
compoundType = op.getUnit().getSummableDeclaration();
} else if (op instanceof Tree.SubtractAssignOp) {
compoundType = op.getUnit().getInvertableDeclaration();
} else if (op instanceof Tree.RemainderAssignOp) {
compoundType = op.getUnit().getIntegralDeclaration();
}
final Type leftType = getSupertype(op.getLeftTerm(), compoundType);
// Normally we don't look at the RHS type because it can lead to unknown types, but if we want to extract its
// underlying type we have to, and we deal with any eventual unknown type. Presumably unknown types will not have
// any useful underlying type anyways.
// Note that looking at the RHS allows us to not have the issue of using the LHS type wrongly for the RHS type when
// the LHS type is Float and the RHS type is Integer with implicit Float coercion
Type rightSupertype = getSupertype(op.getRightTerm(), compoundType);
if (rightSupertype == null || rightSupertype.isUnknown()) {
// supertype could be null if, e.g. right type is Nothing
rightSupertype = leftType;
}
Type rightTypeArgument = getTypeArgument(rightSupertype);
if (rightTypeArgument == null || rightTypeArgument.isUnknown())
rightTypeArgument = getTypeArgument(leftType);
final Type rightType = getMostPreciseType(op.getLeftTerm(), rightTypeArgument);
final Type resultType = getLeastPreciseType(op.getLeftTerm(), op.getRightTerm());
// we work on boxed types
return transformAssignAndReturnOperation(op, op.getLeftTerm(), boxResult, op.getLeftTerm().getTypeModel(), resultType, new AssignAndReturnOperationFactory() {
@Override
public JCExpression getNewValue(JCExpression previousValue) {
// make this call: previousValue OP RHS
JCExpression ret = transformOverridableBinaryOperator(op, op.getLeftTerm(), op.getRightTerm(), rightType, operator.binaryOperator, boxResult ? OptimisationStrategy.NONE : OptimisationStrategy.OPTIMISE, previousValue, op.getTypeModel());
return ret;
}
});
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ClassTransformer method walkSatisfiedInterfacesInternal.
private void walkSatisfiedInterfacesInternal(final Class model, Type type, Class via, SatisfactionVisitor visitor, Set<Interface> satisfiedInterfaces) {
type = type.resolveAliases();
Type ext = type.getExtendedType();
if (ext != null) {
// recurse up this extended class
walkSatisfiedInterfacesInternal(model, ext, (Class) ext.getDeclaration(), visitor, satisfiedInterfaces);
}
for (Type sat : type.getSatisfiedTypes()) {
if (sat.isIdentifiable()) {
return;
}
Interface iface = (Interface) sat.getDeclaration();
// recurse up this satisfies interface
walkSatisfiedInterfacesInternal(model, sat, via, visitor, satisfiedInterfaces);
boolean alreadySatisfied = !satisfiedInterfaces.add((Interface) model.getType().getSupertype(iface).getDeclaration());
if (via != null) {
visitor.satisfiesIndirectlyViaClass(model, iface, via, alreadySatisfied);
} else if (model.getType().equals(type)) {
visitor.satisfiesDirectly(model, iface, alreadySatisfied);
} else {
visitor.satisfiesIndirectly(model, iface, alreadySatisfied);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ClassTransformer method addAtMembers.
private void addAtMembers(ClassDefinitionBuilder classBuilder, ClassOrInterface model, Tree.ClassOrInterface def) {
List<JCExpression> members = List.nil();
for (Declaration member : model.getMembers()) {
if (member instanceof ClassOrInterface == false && member instanceof TypeAlias == false) {
continue;
}
TypeDeclaration innerType = (TypeDeclaration) member;
Tree.Declaration innerTypeTree = findInnerType(def, innerType.getName());
if (innerTypeTree != null) {
TransformationPlan plan = errors().hasDeclarationAndMarkBrokenness(innerTypeTree);
if (plan instanceof Drop) {
continue;
}
}
if (innerType.isAlias() && innerTypeTree != null && Decl.isAncestorLocal(innerTypeTree.getDeclarationModel()))
// for the same reason we do not generate aliases in transform(ClassOrInterface def) let's not list them
continue;
JCAnnotation atMember;
// interfaces are moved to toplevel so they can lose visibility of member types if they are local
if (Decl.isLocal(model) && model instanceof Interface)
atMember = makeAtMember(innerType.getName());
else
atMember = makeAtMember(innerType.getType());
members = members.prepend(atMember);
}
classBuilder.annotations(makeAtMembers(members));
}
Aggregations