use of org.eclipse.ceylon.model.typechecker.context.TypeCache in project ceylon by eclipse.
the class BoxingDeclarationVisitor method setBoxingState.
private void setBoxingState(TypedDeclaration declaration, TypedDeclaration refinedDeclaration, Node that) {
Type type = declaration.getType();
if (type == null) {
// an error must have already been reported
return;
}
// fetch the real refined declaration if required
if (Decl.equal(declaration, refinedDeclaration) && declaration instanceof FunctionOrValue && ((FunctionOrValue) declaration).isParameter() && declaration.getContainer() instanceof Class) {
// maybe it is really inherited from a field?
FunctionOrValue methodOrValueForParam = (FunctionOrValue) declaration;
if (methodOrValueForParam != null) {
// make sure we get the refined version of that member
refinedDeclaration = (TypedDeclaration) methodOrValueForParam.getRefinedDeclaration();
}
}
// inherit underlying type constraints
if (!Decl.equal(refinedDeclaration, declaration)) {
// simple case
if (type.getUnderlyingType() == null && refinedDeclaration.getType() != null) {
if (type.isCached()) {
type = type.clone();
}
type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
declaration.setType(type);
}
// special case for variadics
if (Decl.isValueParameter(refinedDeclaration)) {
Parameter parameter = ((FunctionOrValue) refinedDeclaration).getInitializerParameter();
if (parameter.isSequenced()) {
// inherit the underlying type of the iterated type
Type refinedIteratedType = refinedDeclaration.getType().getTypeArgumentList().get(0);
if (refinedIteratedType.getUnderlyingType() != null) {
Type ourIteratedType = type.getTypeArgumentList().get(0);
if (ourIteratedType.getUnderlyingType() == null) {
if (ourIteratedType.isCached()) {
ourIteratedType = ourIteratedType.clone();
}
ourIteratedType.setUnderlyingType(refinedIteratedType.getUnderlyingType());
type.getTypeArgumentList().set(0, ourIteratedType);
// make sure we remove those types from the cache otherwise UGLY things happen
TypeCache cache = type.getDeclaration().getUnit().getCache();
if (cache != null) {
cache.remove(ourIteratedType);
cache.remove(type);
}
}
}
}
}
}
// abort if our boxing state has already been set
if (declaration.getUnboxed() != null)
return;
// functional parameter return values are always boxed if we're not creating a method for them
if (declaration instanceof Function && ((Function) declaration).isParameter() && !JvmBackendUtil.createMethod((Function) declaration)) {
declaration.setUnboxed(false);
return;
}
if (!Decl.equal(refinedDeclaration, declaration)) {
// make sure refined declarations have already been set
if (refinedDeclaration.getUnboxed() == null)
setBoxingState(refinedDeclaration, refinedDeclaration, that);
// inherit
declaration.setUnboxed(refinedDeclaration.getUnboxed());
} else if (declaration instanceof Function && Strategy.useBoxedVoid((Function) declaration) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
declaration.setUnboxed(false);
} else if ((isCeylonBasicType(type) || Decl.isUnboxedVoid(declaration)) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && (refinedDeclaration.getContainer() instanceof Declaration == false || !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration)) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
boolean unbox = !forceBoxedLocals || !(declaration instanceof Value) || !Decl.isLocal(declaration) || Decl.isParameter(declaration) || Decl.isTransient(declaration);
// until it's used later by user code
if (declaration.getOriginalDeclaration() != null && declaration.hasUncheckedNullType())
unbox = false;
declaration.setUnboxed(unbox);
} else if (Decl.isValueParameter(declaration) && CodegenUtil.isContainerFunctionalParameter(declaration) && JvmBackendUtil.createMethod((FunctionOrValue) declaration.getContainer())) {
Function functionalParameter = (Function) declaration.getContainer();
TypedDeclaration refinedFrom = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(functionalParameter, optimisedMethodSpecifiersToMethods);
if (Decl.equal(refinedFrom, functionalParameter)) {
// not a method return type (where void would be considered unboxed).
if (declaration.getUnit().getAnythingType().isExactly(declaration.getType()) || declaration.getUnit().isOptionalType(declaration.getType())) {
declaration.setUnboxed(false);
} else {
declaration.setUnboxed(true);
}
} else {
// make sure refined declarations have already been set
if (refinedFrom.getUnboxed() == null)
setBoxingState(refinedFrom, refinedFrom, that);
// inherit
declaration.setUnboxed(refinedFrom.getUnboxed());
}
} else {
declaration.setUnboxed(false);
}
// Any "@boxed" or "@unboxed" compiler annotation overrides
boxFromAnnotation(declaration, that);
}
use of org.eclipse.ceylon.model.typechecker.context.TypeCache in project ceylon by eclipse.
the class Type method getSupertype.
/**
* Given a type declaration, return a produced type of
* which this type is an invariant subtype.
*
* If this type is Nothing, always return null.
*
* @param dec a type declaration
*
* @return a produced type of the given type declaration
* which is a supertype of this type, or null if
* there is no such supertype
*/
public Type getSupertype(TypeDeclaration dec) {
if (dec == null) {
return null;
}
if (isNothing()) {
// this is what the backend expects, apparently
return null;
}
boolean canCache = canCacheSupertype(dec);
if (canCache) {
TypeCache cache = dec.getUnit().getCache();
Type ret = cache.get(this, dec);
if (ret != null) {
return ret == NULL_VALUE ? null : ret;
}
}
while (dec.isAlias()) {
Type et = dec.getExtendedType();
if (et == null) {
return null;
} else {
dec = et.getDeclaration();
if (dec == null) {
return null;
}
}
}
Type superType;
if (isSimpleSupertypeLookup(dec)) {
// fast!
if (getDeclaration().inherits(dec)) {
superType = dec.getType();
} else {
superType = null;
}
} else {
// slow:
superType = getSupertype(new SupertypeCriteria(dec));
}
if (canCache) {
TypeCache cache = dec.getUnit().getCache();
cache.put(this, dec, superType == null ? NULL_VALUE : superType);
}
return superType;
}
Aggregations