Search in sources :

Example 11 with Functional

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

the class MethodOrValueReferenceVisitor method isCapturableMplParameter.

/**
 * Because methods with MPL use nested anonymous AbstractCallables
 * if the declaration is a parameter in all but the last parameter list
 * it should be captured.
 */
private boolean isCapturableMplParameter(Declaration d) {
    if (!(d instanceof FunctionOrValue)) {
        return false;
    }
    com.redhat.ceylon.model.typechecker.model.Parameter param = ((FunctionOrValue) d).getInitializerParameter();
    if (param == null) {
        return false;
    }
    Declaration paramDecl = param.getDeclaration();
    if (paramDecl instanceof Functional) {
        List<com.redhat.ceylon.model.typechecker.model.ParameterList> parameterLists = ((Functional) paramDecl).getParameterLists();
        for (int i = 0; i < parameterLists.size() - 1; i++) {
            if (parameterLists.get(i).getParameters().contains(param)) {
                return true;
            }
        }
    }
    return false;
}
Also used : Functional(com.redhat.ceylon.model.typechecker.model.Functional) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue)

Example 12 with Functional

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

the class ExpressionTransformer method transformConstructorDelegation.

/**
 * Transform a delegated constructor call ({@code extends XXX()})
 * which may be either a superclass initializer/constructor or a
 * same-class constructor.
 * @param extendedType
 * @param delegation The kind of delegation
 * @param invocation
 * @param classBuilder
 * @return
 */
JCStatement transformConstructorDelegation(Node extendedType, CtorDelegation delegation, Tree.InvocationExpression invocation, ClassDefinitionBuilder classBuilder, boolean forDelegationConstructor) {
    if (delegation != null && delegation.isError()) {
        return delegation.makeThrow(this);
    }
    Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) invocation.getPrimary()).getDeclaration();
    java.util.List<ParameterList> paramLists = ((Functional) primaryDeclaration).getParameterLists();
    if (paramLists.isEmpty()) {
        classBuilder.getInitBuilder().delegateCall(at(extendedType).Exec(makeErroneous(extendedType, "compiler bug: super class " + primaryDeclaration.getName() + " is missing parameter list")));
        return null;
    }
    SuperInvocation builder = new SuperInvocation(this, classBuilder.getForDefinition(), delegation, invocation, paramLists.get(0), forDelegationConstructor);
    CallBuilder callBuilder = CallBuilder.instance(this);
    boolean prevFnCall = withinInvocation(true);
    try {
        if (invocation.getPrimary() instanceof Tree.StaticMemberOrTypeExpression) {
            transformTypeArguments(callBuilder, (Tree.StaticMemberOrTypeExpression) invocation.getPrimary());
        }
        at(builder.getNode());
        JCExpression expr = null;
        Scope outerDeclaration;
        if (Decl.isConstructor(primaryDeclaration)) {
            outerDeclaration = builder.getPrimaryDeclaration().getContainer().getContainer();
        } else {
            outerDeclaration = builder.getPrimaryDeclaration().getContainer();
        }
        if ((Strategy.generateInstantiator(builder.getPrimaryDeclaration()) || builder.getPrimaryDeclaration() instanceof Class) && outerDeclaration instanceof Interface) {
            // If the subclass is inner to an interface then it will be
            // generated inner to the companion and we need to qualify the
            // super(), *unless* the subclass is nested within the same
            // interface as it's superclass.
            Scope outer = builder.getSub().getContainer();
            while (!(outer instanceof Package)) {
                if (outer == outerDeclaration) {
                    expr = naming.makeSuper();
                    break;
                }
                outer = outer.getContainer();
            }
            if (expr == null) {
                if (delegation.isSelfDelegation()) {
                    throw new BugException();
                }
                Interface iface = (Interface) outerDeclaration;
                JCExpression superQual;
                if (Decl.getClassOrInterfaceContainer(classBuilder.getForDefinition(), false) instanceof Interface) {
                    superQual = naming.makeCompanionAccessorCall(naming.makeQuotedThis(), iface);
                } else {
                    superQual = naming.makeCompanionFieldName(iface);
                }
                expr = naming.makeQualifiedSuper(superQual);
            }
        } else {
            expr = delegation.isSelfDelegation() ? naming.makeThis() : naming.makeSuper();
        }
        final List<JCExpression> superArguments = transformSuperInvocationArguments(classBuilder, builder, callBuilder);
        JCExpression superExpr = callBuilder.invoke(expr).arguments(superArguments).build();
        return at(extendedType).Exec(superExpr);
    // classBuilder.getInitBuilder().superCall(at(extendedType).Exec(superExpr));
    } finally {
        withinInvocation(prevFnCall);
    }
}
Also used : Functional(com.redhat.ceylon.model.typechecker.model.Functional) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Scope(com.redhat.ceylon.model.typechecker.model.Scope) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) 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) Package(com.redhat.ceylon.model.typechecker.model.Package) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 13 with Functional

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

the class ClassTransformer method transformSpecifiedMethodBody.

List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
    final Function model = def.getDeclarationModel();
    List<JCStatement> body;
    Tree.MethodDeclaration methodDecl = def;
    boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
    boolean returnNull = false;
    JCExpression bodyExpr;
    Tree.Term term = null;
    if (specifierExpression != null && specifierExpression.getExpression() != null) {
        term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
        if (error != null) {
            return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
        }
    }
    if (!isLazy && term instanceof Tree.FunctionArgument) {
        // Function specified with lambda: Don't bother generating a
        // Callable, just transform the expr to use as the method body.
        Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
        Type resultType = model.getType();
        returnNull = isAnything(resultType) && fa.getExpression().getUnboxed();
        final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
        final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
        List<Substitution> substitutions = List.nil();
        for (int ii = 0; ii < lambdaParams.size(); ii++) {
            substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
        }
        bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
        for (Substitution subs : substitutions) {
            subs.close();
        }
    } else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
        returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
        Function method = methodDecl.getDeclarationModel();
        boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
        boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
        Invocation invocation;
        if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
            Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
            Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
            invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
        } else if (!lazy && !inlined) {
            // must be a callable we stored
            String name = naming.getMethodSpecifierAttributeName(method);
            invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
        } else if (isCeylonCallableSubtype(term.getTypeModel())) {
            invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
        } else {
            throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
        }
        invocation.handleBoxing(true);
        invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
        bodyExpr = expressionGen().transformInvocation(invocation);
    } else {
        bodyExpr = expressionGen().transformExpression(model, term);
        // The innermost of an MPL method declared void needs to return null
        returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
    }
    if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
        if (returnNull) {
            body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
        } else {
            body = List.<JCStatement>of(make().Return(bodyExpr));
        }
    } else {
        body = List.<JCStatement>of(make().Exec(bodyExpr));
    }
    return body;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) 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) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Type(com.redhat.ceylon.model.typechecker.model.Type) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter)

Example 14 with Functional

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

the class ParameterAnnotationTerm method encode.

@Override
public int encode(AbstractTransformer gen, ListBuffer<JCExpression> instantiations) {
    Parameter parameter = getSourceParameter();
    int index = ((Functional) parameter.getDeclaration()).getFirstParameterList().getParameters().indexOf(parameter);
    if (isSpread()) {
        index += 256;
    }
    return index;
}
Also used : Functional(com.redhat.ceylon.model.typechecker.model.Functional) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter)

Example 15 with Functional

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

the class ExpressionTransformer method isNaturalTarget.

/**
 * Whether an annotation (with the given {@code annotationCtorDecl}
 * annotation constructor) used on the given declaration ({@code useSite})
 * should be added to the Java annotations of the given generated program
 * elements ({@code target})
 * @param annotationCtorDecl
 * @param useSite
 * @param target
 * @return
 */
private boolean isNaturalTarget(// use site is either a Declaration, or a Package, or a Module,
Function annotationCtorDecl, // module imports
Object useSite, OutputElement target) {
    EnumSet<AnnotationTarget> interopTargets;
    if (annotationCtorDecl instanceof AnnotationProxyMethod) {
        AnnotationProxyMethod annotationProxyMethod = (AnnotationProxyMethod) annotationCtorDecl;
        if (annotationProxyMethod.getAnnotationTarget() == target) {
            // Foo__WHATEVER, so honour the WHATEVER
            return true;
        }
        interopTargets = annotationProxyMethod.getProxyClass().getAnnotationTarget();
    } else {
        interopTargets = null;
    }
    if (useSite instanceof Declaration) {
        if (ModelUtil.isConstructor((Declaration) useSite)) {
            if (useSite instanceof Functional) {
                return target == OutputElement.CONSTRUCTOR;
            } else if (useSite instanceof Value) {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Class) {
            if (((Class) useSite).getParameterList() != null && interopTargets != null && interopTargets.contains(AnnotationTarget.CONSTRUCTOR) && !interopTargets.contains(AnnotationTarget.TYPE)) {
                return target == OutputElement.CONSTRUCTOR;
            }
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Interface) {
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Value) {
            Value value = (Value) useSite;
            TypeDeclaration decltype = typeFact().getValueDeclarationType().getDeclaration();
            if (value.isParameter() && !value.isShared() && !(value.isCaptured() && value.isMember())) {
                return target == OutputElement.PARAMETER;
            } else if (annotationCtorDecl instanceof AnnotationProxyMethod) {
                if (value.isLate() || value.isVariable()) {
                    return target == OutputElement.SETTER;
                } else if (!value.isTransient()) {
                    return target == OutputElement.FIELD;
                } else {
                    return target == OutputElement.GETTER;
                }
            } else {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Setter) {
            return target == OutputElement.SETTER;
        } else if (useSite instanceof Function) {
            return target == OutputElement.METHOD;
        } else if (useSite instanceof Constructor) {
            return target == OutputElement.CONSTRUCTOR;
        } else if (useSite instanceof TypeAlias) {
            return target == OutputElement.TYPE;
        }
    } else if (useSite instanceof Package) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Module) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Tree.ImportModule) {
        return target == OutputElement.FIELD;
    }
    throw new RuntimeException("" + useSite);
}
Also used : AnnotationTarget(com.redhat.ceylon.model.loader.model.AnnotationTarget) AnnotationProxyMethod(com.redhat.ceylon.model.loader.model.AnnotationProxyMethod) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Setter(com.redhat.ceylon.model.typechecker.model.Setter) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) 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) Package(com.redhat.ceylon.model.typechecker.model.Package) Module(com.redhat.ceylon.model.typechecker.model.Module) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Aggregations

Functional (com.redhat.ceylon.model.typechecker.model.Functional)17 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)9 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)9 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)8 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)7 Function (com.redhat.ceylon.model.typechecker.model.Function)7 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)7 ParameterList (com.redhat.ceylon.model.typechecker.model.ParameterList)6 Type (com.redhat.ceylon.model.typechecker.model.Type)6 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)5 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)5 Value (com.redhat.ceylon.model.typechecker.model.Value)5 Class (com.redhat.ceylon.model.typechecker.model.Class)4 JCTree (com.sun.tools.javac.tree.JCTree)4 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)3 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)3 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)3 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)3 HasErrorException (com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException)2 AttributeDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)2