Search in sources :

Example 51 with Function

use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.

the class BoxingDeclarationVisitor method visit.

@Override
public void visit(SpecifierStatement that) {
    TypedDeclaration declaration = that.getDeclaration();
    Function optimisedDeclaration = null;
    // make sure we detect the shortcut refinement inlining cases
    if (declaration instanceof Function) {
        if (that.getSpecifierExpression() != null && that.getSpecifierExpression() instanceof LazySpecifierExpression == false) {
            Tree.Term term = Decl.unwrapExpressionsUntilTerm(that.getSpecifierExpression().getExpression());
            if (term != null && term instanceof Tree.FunctionArgument) {
                optimisedDeclaration = ((Tree.FunctionArgument) term).getDeclarationModel();
                this.optimisedMethodSpecifiersToMethods.put(optimisedDeclaration, (Function) declaration);
            }
        }
    }
    try {
        super.visit(that);
    } finally {
        if (optimisedDeclaration != null)
            this.optimisedMethodSpecifiersToMethods.remove(optimisedDeclaration);
    }
    if (declaration == null)
        return;
    if (declaration instanceof Function) {
        visitMethod((Function) declaration, that);
    } else if (declaration instanceof Value)
        visitAttributeOrParameter(declaration, that);
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)

Example 52 with Function

use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.

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) && type.getUnderlyingType() == null && refinedDeclaration.getType() != null)
        type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
    // 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 && CodegenUtil.isVoid(declaration.getType()) && 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);
        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(com.redhat.ceylon.model.typechecker.model.Functional) Function(com.redhat.ceylon.model.typechecker.model.Function) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Class(com.redhat.ceylon.model.typechecker.model.Class) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) FunctionalParameterDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue)

Example 53 with Function

use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.

the class BoxingDeclarationVisitor method boxMethod.

private void boxMethod(Function method, Node that) {
    // deal with invalid input
    if (method == null)
        return;
    Declaration refined = CodegenUtil.getTopmostRefinedDeclaration(method, optimisedMethodSpecifiersToMethods);
    // deal with invalid input
    if (refined == null || (!(refined instanceof Function)))
        return;
    TypedDeclaration refinedMethod = (TypedDeclaration) refined;
    if (method.getName() != null) {
        // A Callable, which never have primitive parameters
        setBoxingState(method, refinedMethod, that);
    } else {
        // Anonymous methods are always boxed
        method.setUnboxed(false);
    }
}
Also used : Function(com.redhat.ceylon.model.typechecker.model.Function) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) FunctionalParameterDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)

Example 54 with Function

use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.

the class AbstractTransformer method supportsReified.

public static boolean supportsReified(Declaration declaration) {
    if (declaration instanceof ClassOrInterface) {
        // Java constructors don't support reified type arguments
        return Decl.isCeylon((TypeDeclaration) declaration);
    } else if (Decl.isConstructor(declaration)) {
        // Java constructors don't support reified type arguments
        return Decl.isCeylon(Decl.getConstructor(declaration));
    } else if (declaration instanceof Function) {
        if (((Function) declaration).isParameter()) {
            // those can never be parameterised
            return false;
        }
        if (Decl.isToplevel(declaration))
            return true;
        // Java methods don't support reified type arguments
        Function m = (Function) CodegenUtil.getTopmostRefinedDeclaration(declaration);
        // See what its container is
        ClassOrInterface container = Decl.getClassOrInterfaceContainer(m);
        // that must be Ceylon so it supports it
        if (container == null)
            return true;
        return supportsReified(container);
    } else {
        throw BugException.unhandledDeclarationCase(declaration);
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Function(com.redhat.ceylon.model.typechecker.model.Function)

Example 55 with Function

use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.

the class ClassTransformer method makeDelegateToCompanion.

/**
     * Generates a method which delegates to the companion instance $Foo$impl
     */
private MethodDefinitionBuilder makeDelegateToCompanion(Interface iface, Reference typedMember, Type currentType, final long mods, final java.util.List<TypeParameter> typeParameters, final java.util.List<java.util.List<Type>> producedTypeParameterBounds, final Type methodType, final String methodName, final java.util.List<Parameter> parameters, boolean typeErased, final String targetMethodName, DelegateType delegateType, boolean includeBody) {
    final MethodDefinitionBuilder concreteWrapper = MethodDefinitionBuilder.systemMethod(gen(), methodName);
    concreteWrapper.modifiers(mods);
    concreteWrapper.ignoreModelAnnotations();
    if ((mods & PRIVATE) == 0) {
        concreteWrapper.isOverride(true);
    }
    if (typeParameters != null) {
        concreteWrapper.reifiedTypeParametersFromModel(typeParameters);
    }
    Iterator<java.util.List<Type>> iterator = producedTypeParameterBounds.iterator();
    if (typeParameters != null) {
        for (TypeParameter tp : typeParameters) {
            concreteWrapper.typeParameter(tp, iterator.next());
        }
    }
    boolean explicitReturn = false;
    Declaration member = typedMember.getDeclaration();
    Type returnType = null;
    if (!isAnything(methodType) || ((member instanceof Function || member instanceof Value) && !Decl.isUnboxedVoid(member)) || (member instanceof Function && Strategy.useBoxedVoid((Function) member))) {
        explicitReturn = true;
        if (CodegenUtil.isHashAttribute(member)) {
            // delegates for hash attributes are int
            concreteWrapper.resultType(null, make().Type(syms().intType));
            returnType = typedMember.getType();
        } else if (typedMember instanceof TypedReference) {
            TypedReference typedRef = (TypedReference) typedMember;
            if (delegateType == DelegateType.OTHER) {
                // This is very much like for method refinement: if the supertype is erased -> go raw.
                // Except for some reason we only need to do it with multiple inheritance with different type
                // arguments, so let's not go overboard
                int flags = 0;
                if (CodegenUtil.hasTypeErased((TypedDeclaration) member.getRefinedDeclaration()) || CodegenUtil.hasTypeErased((TypedDeclaration) member) && isInheritedTwiceWithDifferentTypeArguments(currentType, iface)) {
                    flags |= AbstractTransformer.JT_RAW;
                }
                concreteWrapper.resultTypeNonWidening(currentType, typedRef, typedMember.getType(), flags);
                // FIXME: this is redundant with what we computed in the previous line in concreteWrapper.resultTypeNonWidening
                TypedReference nonWideningTypedRef = gen().nonWideningTypeDecl(typedRef, currentType);
                returnType = gen().nonWideningType(typedRef, nonWideningTypedRef);
            } else {
                // for default value
                NonWideningParam nonWideningParam = concreteWrapper.getNonWideningParam(typedRef, currentType.getDeclaration() instanceof Class ? WideningRules.FOR_MIXIN : WideningRules.NONE);
                returnType = nonWideningParam.nonWideningType;
                if (member instanceof Function)
                    returnType = typeFact().getCallableType(returnType);
                concreteWrapper.resultType(null, makeJavaType(returnType, nonWideningParam.flags));
            }
        } else {
            concreteWrapper.resultType(null, makeJavaType((Type) typedMember));
            returnType = (Type) typedMember;
        }
    }
    ListBuffer<JCExpression> arguments = ListBuffer.<JCExpression>lb();
    if (typeParameters != null) {
        for (TypeParameter tp : typeParameters) {
            arguments.add(naming.makeUnquotedIdent(naming.getTypeArgumentDescriptorName(tp)));
        }
    }
    if (typedMember.getDeclaration() instanceof Constructor && !Decl.isDefaultConstructor((Constructor) typedMember.getDeclaration())) {
        concreteWrapper.parameter(makeConstructorNameParameter((Constructor) typedMember.getDeclaration()));
        arguments.add(naming.makeUnquotedIdent(Unfix.$name$));
    }
    for (Parameter param : parameters) {
        final TypedReference typedParameter = typedMember.getTypedParameter(param);
        concreteWrapper.parameter(param, typedParameter, null, FINAL, WideningRules.FOR_MIXIN);
        arguments.add(naming.makeName(param.getModel(), Naming.NA_MEMBER | Naming.NA_ALIASED));
    }
    if (includeBody) {
        JCExpression qualifierThis = makeUnquotedIdent(getCompanionFieldName(iface));
        // our impl accessor to get the expected bounds of the qualifying type
        if (explicitReturn) {
            Type javaType = getBestSatisfiedType(currentType, iface);
            Type ceylonType = typedMember.getQualifyingType();
            // don't even bother if the impl accessor is turned to raw because casting it to raw doesn't help
            if (!isTurnedToRaw(ceylonType) && // if it's exactly the same we don't need any cast
            !javaType.isExactly(ceylonType))
                // this will add the proper cast to the impl accessor
                qualifierThis = expressionGen().applyErasureAndBoxing(qualifierThis, currentType, false, true, BoxingStrategy.BOXED, ceylonType, ExpressionTransformer.EXPR_WANTS_COMPANION);
        }
        JCExpression expr = make().Apply(// TODO Type args
        null, makeSelect(qualifierThis, (targetMethodName != null) ? targetMethodName : methodName), arguments.toList());
        if (isUnimplementedMemberClass(currentType, typedMember)) {
            concreteWrapper.body(makeThrowUnresolvedCompilationError(// TODO encapsulate the error message
            "formal member '" + typedMember.getDeclaration().getName() + "' of '" + iface.getName() + "' not implemented in class hierarchy"));
            current().broken();
        } else if (!explicitReturn) {
            concreteWrapper.body(gen().make().Exec(expr));
        } else {
            // deal with erasure and stuff
            BoxingStrategy boxingStrategy;
            boolean exprBoxed;
            if (member instanceof TypedDeclaration) {
                TypedDeclaration typedDecl = (TypedDeclaration) member;
                exprBoxed = !CodegenUtil.isUnBoxed(typedDecl);
                boxingStrategy = CodegenUtil.getBoxingStrategy(typedDecl);
            } else {
                // must be a class or interface
                exprBoxed = true;
                boxingStrategy = BoxingStrategy.UNBOXED;
            }
            // to force an additional cast
            if (isTurnedToRaw(typedMember.getQualifyingType()) || // in invariant locations
            needsRawCastForMixinSuperCall(iface, methodType) || needsCastForErasedInstantiator(iface, methodName, member))
                typeErased = true;
            expr = gen().expressionGen().applyErasureAndBoxing(expr, methodType, typeErased, exprBoxed, boxingStrategy, returnType, 0);
            concreteWrapper.body(gen().make().Return(expr));
        }
    }
    return concreteWrapper;
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) NonWideningParam(com.redhat.ceylon.compiler.java.codegen.MethodDefinitionBuilder.NonWideningParam) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(com.redhat.ceylon.model.loader.model.JavaBeanValue) Value(com.redhat.ceylon.model.typechecker.model.Value) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) ArrayList(java.util.ArrayList) AnnotationList(com.redhat.ceylon.compiler.typechecker.tree.Tree.AnnotationList) List(com.sun.tools.javac.util.List) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)

Aggregations

Function (com.redhat.ceylon.model.typechecker.model.Function)74 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)35 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)35 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)33 Type (com.redhat.ceylon.model.typechecker.model.Type)33 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)26 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)26 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)25 Value (com.redhat.ceylon.model.typechecker.model.Value)25 Class (com.redhat.ceylon.model.typechecker.model.Class)23 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)22 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)20 JCTree (com.sun.tools.javac.tree.JCTree)18 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)17 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)17 ArrayList (java.util.ArrayList)14 ParameterList (com.redhat.ceylon.model.typechecker.model.ParameterList)13 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)12 MethodDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)11 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)11