use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class AbstractTransformer method canOptimiseReifiedTypeTest.
/**
* Determine whether we can use a plain {@code instanceof} instead of
* a full {@code Util.isReified()} for a {@code is} test
*/
private boolean canOptimiseReifiedTypeTest(Type type) {
if (isJavaArray(type)) {
if (isJavaObjectArray(type)) {
MultidimensionalArray multiArray = getMultiDimensionalArrayInfo(type);
// we can test, even if not fully reified in Java
return multiArray.type.getDeclaration() instanceof ClassOrInterface;
} else {
// primitive array we can test
return true;
}
}
// we can optimise it if we've got a ClassOrInterface with only Anything type parameters
TypeDeclaration typeDeclaration = type.getDeclaration();
if (typeDeclaration instanceof ClassOrInterface == false)
return false;
for (Entry<TypeParameter, Type> entry : type.getTypeArguments().entrySet()) {
TypeParameter tp = entry.getKey();
// skip type params for qualifying types
if (!tp.getDeclaration().equals(typeDeclaration))
continue;
if (!type.isCovariant(tp)) {
return false;
}
java.util.List<Type> bounds = tp.getSatisfiedTypes();
Type ta = entry.getValue();
if ((bounds == null || bounds.isEmpty()) && !isAnything(ta)) {
return false;
}
for (Type bound : bounds) {
if (!ta.isSupertypeOf(bound)) {
return false;
}
}
}
// they're all Anything (or supertypes of their upper bound) we can optimise, unless we have a container with type arguments
Type qualifyingType = type.getQualifyingType();
if (qualifyingType == null && // ignore qualifying types of static java declarations
(ModelUtil.isCeylonDeclaration(type.getDeclaration()) || !type.getDeclaration().isStatic())) {
Declaration declaration = type.getDeclaration();
do {
// it may be contained in a function or value, and we want its type
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration) {
// must be in scope
if (enclosingDeclaration.isParameterized())
return false;
// look up the containers
declaration = enclosingDeclaration;
} else if (enclosingDeclaration instanceof TypeDeclaration) {
// we can't optimise if that container has type arguments as they are not provided
if (enclosingDeclaration.isParameterized())
return false;
// look up the containers
declaration = enclosingDeclaration;
} else {
// that's fucked up
break;
}
// go up every containing typed declaration
} while (declaration != null);
// we can optimise!
return true;
} else if (qualifyingType != null) {
// we can only optimise if the qualifying type can also be optimised
return canOptimiseReifiedTypeTest(qualifyingType);
} else {
// we can optimise!
return true;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class AbstractTransformer method getFirstRefinedDeclaration.
private TypedDeclaration getFirstRefinedDeclaration(TypedDeclaration decl) {
if (decl.getContainer() instanceof ClassOrInterface == false)
return decl;
java.util.List<Type> signature = org.eclipse.ceylon.model.typechecker.model.ModelUtil.getSignature(decl);
boolean variadic = org.eclipse.ceylon.model.typechecker.model.ModelUtil.isVariadic(decl);
boolean overloaded = decl.isOverloaded() || decl.isAbstraction();
Declaration refinedDeclaration = decl.getRefinedDeclaration();
if (refinedDeclaration != null) {
overloaded |= refinedDeclaration.isOverloaded() || refinedDeclaration.isAbstraction();
}
ClassOrInterface container = (ClassOrInterface) decl.getContainer();
HashSet<TypeDeclaration> visited = new HashSet<TypeDeclaration>();
// start looking for it, but skip this type, only lookup upwards of it
TypedDeclaration firstRefinedDeclaration = getFirstRefinedDeclaration(container, decl, signature, variadic, visited, true, overloaded);
// only keep the first refined decl if its type can be trusted: if it is not itself widening
if (firstRefinedDeclaration != null) {
if (CodegenUtil.hasUntrustedType(firstRefinedDeclaration))
firstRefinedDeclaration = getFirstRefinedDeclaration(firstRefinedDeclaration);
}
return firstRefinedDeclaration != null ? firstRefinedDeclaration : decl;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class AbstractTransformer method makeTypeParameter.
JCTypeParameter makeTypeParameter(TypeParameter declarationModel, java.util.List<Type> satisfiedTypesForBounds) {
TypeParameter typeParameterForBounds = declarationModel;
if (satisfiedTypesForBounds == null) {
satisfiedTypesForBounds = declarationModel.getSatisfiedTypes();
}
// special case for method refinenement where Java doesn't let us refine the parameter bounds
if (declarationModel.getContainer() instanceof Function) {
Function method = (Function) declarationModel.getContainer();
Function refinedMethod = (Function) method.getRefinedDeclaration();
if (!Decl.equal(method, refinedMethod)) {
// find the param index
int index = method.getTypeParameters().indexOf(declarationModel);
if (index == -1) {
log.error("Failed to find type parameter index: " + declarationModel.getName());
} else if (refinedMethod.getTypeParameters().size() > index) {
// ignore smaller index than size since the typechecker would have found the error
TypeParameter refinedTP = refinedMethod.getTypeParameters().get(index);
if (!haveSameBounds(declarationModel, refinedTP)) {
// find the right instantiation of that type parameter
TypeDeclaration methodContainer = (TypeDeclaration) method.getContainer();
TypeDeclaration refinedMethodContainer = (TypeDeclaration) refinedMethod.getContainer();
// find the supertype that gave us that method and its type arguments
Type supertype = methodContainer.getType().getSupertype(refinedMethodContainer);
satisfiedTypesForBounds = new ArrayList<Type>(refinedTP.getSatisfiedTypes().size());
for (Type satisfiedType : refinedTP.getSatisfiedTypes()) {
// substitute the refined type parameter bounds with the right type arguments
satisfiedTypesForBounds.add(satisfiedType.substitute(supertype));
}
typeParameterForBounds = refinedTP;
}
}
}
}
return makeTypeParameter(declarationModel.getName(), satisfiedTypesForBounds, typeParameterForBounds.isCovariant(), typeParameterForBounds.isContravariant());
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class AbstractTransformer method getRefinedTypedReference.
private TypedReference getRefinedTypedReference(TypedReference typedReference, TypedDeclaration refinedDeclaration) {
TypeDeclaration refinedContainer = (TypeDeclaration) refinedDeclaration.getContainer();
Type refinedContainerType = typedReference.getQualifyingType().getSupertype(refinedContainer);
ArrayList<Type> typeArgs = new ArrayList<Type>();
for (TypeParameter tp : typedReference.getDeclaration().getTypeParameters()) {
typeArgs.add(typedReference.getTypeArguments().get(tp));
}
return refinedDeclaration.appliedTypedReference(refinedContainerType, typeArgs);
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class AbstractTransformer method makeReifiedTypeArgumentResolved.
private JCExpression makeReifiedTypeArgumentResolved(Type pt, boolean qualified, TypeArgumentAccessor typeArgumentAccessor, boolean wantsRaw) {
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()) {
// 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;
JCExpression thisType = makeUnerasedClassLiteral(declaration);
if (!wantsRaw) {
typeTestArguments = makeReifiedTypeArgumentsResolved(pt.getTypeArgumentList(), qualified, typeArgumentAccessor);
// 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);
}
} else {
typeTestArguments = List.nil();
}
typeTestArguments = typeTestArguments.prepend(thisType);
JCExpression classDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), "klass"), typeTestArguments);
Type qualifyingType = pt.getQualifyingType();
JCExpression containerType = null;
if (qualifyingType == null) {
// it may be contained in a function or value, and we want its type
// or static class members may have no qualifying type but we want the TDs to treat
// them as members anyway
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration)
containerType = makeTypedDeclarationTypeDescriptorResolved((TypedDeclaration) enclosingDeclaration, typeArgumentAccessor);
else if (enclosingDeclaration instanceof TypeDeclaration) {
qualifyingType = ((TypeDeclaration) enclosingDeclaration).getType();
}
}
if (qualifyingType != null && qualifyingType.isConstructor()) {
qualifyingType = qualifyingType.getQualifyingType();
}
if (qualifyingType != null) {
if (declaration.isStatic() && supportsReified(declaration)) {
// There is no outer instance with a $reified$T field
final Type t = pt;
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true, new TypeArgumentAccessor() {
public JCExpression getTypeDescriptor(TypeParameter tp, boolean qualified) {
return makeSelect(naming.makeQualifiedThis(makeJavaType(t, JT_RAW)), naming.getTypeArgumentDescriptorName(tp));
}
}, false);
} else {
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true, typeArgumentAccessor, // we want raw containers, since we can't capture their TPs
declaration.isStatic());
}
}
if (containerType == null) {
return classDescriptor;
} else {
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "member"), List.of(containerType, classDescriptor));
}
} else if (pt.isTypeParameter()) {
return typeArgumentAccessor.getTypeDescriptor((TypeParameter) declaration, qualified);
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
}
Aggregations