use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface 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.ClassOrInterface 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.ClassOrInterface in project ceylon by eclipse.
the class AbstractTransformer method canUseFastFailTypeTest.
private boolean canUseFastFailTypeTest(Type type) {
if (type.getDeclaration() instanceof ClassOrInterface == false)
return false;
boolean isRaw = type.getDeclaration().isParameterized();
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();
boolean local = false;
do {
// getDeclarationContainer will skip some containers we don't want to consider, so it's not good
// for checking locality, rely on isLocal for that.
local |= Decl.isLocal(declaration);
// it may be contained in a function or value, and we want its type
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration) {
local = true;
// look up the containers
declaration = enclosingDeclaration;
} else if (enclosingDeclaration instanceof TypeDeclaration) {
// contain type parameters, unless the local is raw
if (enclosingDeclaration.isParameterized() && local && !isRaw)
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 fast-fail!
return true;
} else if (qualifyingType != null) {
// we can only fast-fail if the qualifying type can also be fast-failed
return canUseFastFailTypeTest(qualifyingType);
} else {
// we can fast-fail!
return true;
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class AbstractTransformer method supportsReified.
public static boolean supportsReified(Declaration declaration) {
if (declaration instanceof ClassOrInterface) {
// Java constructors don't support reified type arguments
return ModelUtil.isCeylonDeclaration((TypeDeclaration) declaration);
} else if (Decl.isConstructor(declaration)) {
// Java constructors don't support reified type arguments
return ModelUtil.isCeylonDeclaration(ModelUtil.getConstructor(declaration));
} else if (declaration instanceof Function) {
if (((Function) declaration).isParameter()) {
// those can never be parameterised
return false;
}
if (declaration.isToplevel())
return true;
// Java methods don't support reified type arguments
Function m = (Function) CodegenUtil.getTopmostRefinedDeclaration(declaration);
// See what its container is
ClassOrInterface container = ModelUtil.getClassOrInterfaceContainer(m);
// that must be Ceylon so it supports it
if (container == null)
return true;
return supportsReified(container);
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class AbstractTransformer method collectQualifyingTypeArguments.
/**
* Collects all the type parameters and arguments required for an interface that's been pulled up to the
* toplevel, including its containing type and method type parameters.
*/
private void collectQualifyingTypeArguments(java.util.List<TypeParameter> qualifyingTypeParameters, Map<TypeParameter, Type> qualifyingTypeArguments, java.util.List<Reference> qualifyingTypes) {
// make sure we only add type parameters with the same name once, as duplicates are erased from the target interface
// since they cannot be accessed
Set<String> names = new HashSet<String>();
// walk the qualifying types backwards to make sure we only add a TP with the same name once and the outer one wins
for (int i = qualifyingTypes.size() - 1; i >= 0; i--) {
Reference qualifiedType = qualifyingTypes.get(i);
Map<TypeParameter, Type> tas = qualifiedType.getTypeArguments();
java.util.List<TypeParameter> tps = qualifiedType.getDeclaration().getTypeParameters();
// add any type params for this type
if (tps != null) {
int index = 0;
for (TypeParameter tp : tps) {
// add it only once
if (names.add(tp.getName())) {
// start putting all these type parameters at 0 and then in order
// so that outer type params end up before inner type params but
// order is preserved within each type
qualifyingTypeParameters.add(index++, tp);
qualifyingTypeArguments.put(tp, tas.get(tp));
}
}
}
// add any container method TP
Declaration declaration = qualifiedType.getDeclaration();
if (Decl.isLocal(declaration)) {
Scope scope = declaration.getContainer();
// collect every container method until the next type or package
java.util.List<Function> methods = new LinkedList<Function>();
while (scope != null && scope instanceof ClassOrInterface == false && scope instanceof Package == false) {
if (scope instanceof Function) {
methods.add((Function) scope);
}
scope = scope.getContainer();
}
// methods are sorted inner to outer, which is the order we're following here for types
for (Function method : methods) {
java.util.List<TypeParameter> methodTypeParameters = method.getTypeParameters();
if (methodTypeParameters != null) {
int index = 0;
for (TypeParameter tp : methodTypeParameters) {
// add it only once
if (names.add(tp.getName())) {
// start putting all these type parameters at 0 and then in order
// so that outer type params end up before inner type params but
// order is preserved within each type
qualifyingTypeParameters.add(index++, tp);
qualifyingTypeArguments.put(tp, tp.getType());
}
}
}
}
}
}
}
Aggregations