Search in sources :

Example 1 with TypeCache

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);
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AbstractTransformer.isPinnedType(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.isPinnedType) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypeCache(org.eclipse.ceylon.model.typechecker.context.TypeCache) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) FunctionalParameterDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 2 with TypeCache

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;
}
Also used : ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) TypeCache(org.eclipse.ceylon.model.typechecker.context.TypeCache)

Aggregations

TypeCache (org.eclipse.ceylon.model.typechecker.context.TypeCache)2 AbstractTransformer.isPinnedType (org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.isPinnedType)1 AttributeDeclaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)1 FunctionalParameterDeclaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration)1 Class (org.eclipse.ceylon.model.typechecker.model.Class)1 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)1 Function (org.eclipse.ceylon.model.typechecker.model.Function)1 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)1 Functional (org.eclipse.ceylon.model.typechecker.model.Functional)1 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)1 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)1 Type (org.eclipse.ceylon.model.typechecker.model.Type)1 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)1 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)1 Value (org.eclipse.ceylon.model.typechecker.model.Value)1