Search in sources :

Example 51 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class JvmBackendUtil method findParamForDecl.

public static Parameter findParamForDecl(String attrName, TypedDeclaration decl) {
    Parameter result = null;
    if (decl.getContainer() instanceof Functional) {
        Functional f = (Functional) decl.getContainer();
        result = f.getParameter(attrName);
    }
    return result;
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter)

Example 52 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class ExpressionTransformer method transformMemberExpression.

private JCExpression transformMemberExpression(Tree.StaticMemberOrTypeExpression expr, JCExpression primaryExpr, TermTransformer transformer) {
    JCExpression result = null;
    // do not throw, an error will already have been reported
    Declaration decl = expr.getDeclaration();
    if (decl == null) {
        return makeErroneous(expr, "compiler bug: expression with no declaration");
    }
    // creating a tmp variable (in which case we have a substitution for it)
    while (decl instanceof TypedDeclaration) {
        TypedDeclaration typedDecl = (TypedDeclaration) decl;
        if (!naming.isSubstituted(decl) && typedDecl.getOriginalDeclaration() != null) {
            decl = ((TypedDeclaration) decl).getOriginalDeclaration();
        } else {
            break;
        }
    }
    // (the header might look like a field while the implementation is a getter)
    if (decl.isNativeHeader()) {
        Declaration d = ModelUtil.getNativeDeclaration(decl, Backend.Java);
        if (d != null) {
            decl = d;
        }
    }
    // Explanation: primaryExpr and qualExpr both specify what is to come before the selector
    // but the important difference is that primaryExpr is used for those situations where
    // the result comes from the actual Ceylon code while qualExpr is used for those situations
    // where we need to refer to synthetic objects (like wrapper classes for toplevel methods)
    JCExpression qualExpr = null;
    String selector = null;
    // true for Java interop using fields, and for super constructor parameters, which must use
    // parameters rather than getter methods
    boolean mustUseField = false;
    // true for default parameter methods
    boolean mustUseParameter = false;
    if (decl instanceof Functional && (!(decl instanceof Class) || ((Class) decl).getParameterList() != null) && (!(decl instanceof Function) || !decl.isParameter() || functionalParameterRequiresCallable((Function) decl, expr)) && isFunctionalResult(expr.getTypeModel())) {
        result = transformFunctional(expr, (Functional) decl, expectedType);
    } else if (coerced && decl instanceof Value && isFunctionalResult(expr.getTypeModel()) && checkForFunctionalInterface(expectedType) != null) {
        result = transformFunctionalInterfaceBridge(expr, (Value) decl, expectedType);
    } else if (coerced && decl instanceof Functional && decl.isParameter() && isFunctionalResult(expr.getTypeModel()) && checkForFunctionalInterface(expectedType) != null) {
        result = transformFunctional(expr, (Functional) decl, expectedType);
    // } else if (coerced
    // && decl instanceof Value
    // && isJavaFunctionalInterfaceResult(expr.getTypeModel())
    // && expectedType != null
    // && isCeylonCallable(expectedType)) {
    // result = transformCallableBridge(expr, (Value)decl, expectedType);
    } else if (Decl.isGetter(decl)) {
        // invoke the getter
        if (decl.isToplevel()) {
            primaryExpr = null;
            qualExpr = naming.makeName((Value) decl, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER);
            selector = null;
        } else if (decl.isClassOrInterfaceMember() && !ModelUtil.isLocalToInitializer(decl)) {
            selector = naming.selector((Value) decl);
        } else {
            // method local attr
            if (!isRecursiveReference(expr)) {
                primaryExpr = naming.makeQualifiedName(primaryExpr, (Value) decl, Naming.NA_Q_LOCAL_INSTANCE);
            }
            selector = naming.selector((Value) decl);
        }
    } else if (Decl.isValueOrSharedOrCapturedParam(decl)) {
        if (decl.isToplevel()) {
            // ERASURE
            if (isNullValue(decl)) {
                result = makeNull();
            } else if (isBooleanTrue(decl)) {
                result = makeBoolean(true);
            } else if (isBooleanFalse(decl)) {
                result = makeBoolean(false);
            } else {
                // it's a toplevel attribute
                primaryExpr = naming.makeName((TypedDeclaration) decl, Naming.NA_FQ | Naming.NA_WRAPPER);
                selector = naming.selector((TypedDeclaration) decl);
            }
        } else if (Decl.isClassAttribute(decl) || Decl.isClassParameter(decl)) {
            mustUseField = Decl.isJavaField(decl) || (isWithinSuperInvocation() && primaryExpr == null && withinSuperInvocation == decl.getContainer());
            mustUseParameter = (primaryExpr == null && isWithinDefaultParameterExpression(decl.getContainer()));
            if (mustUseField || mustUseParameter) {
                if (decl instanceof FieldValue) {
                    selector = ((FieldValue) decl).getRealName();
                } else if (decl.isParameter()) {
                    selector = Naming.getAliasedParameterName(((Value) decl).getInitializerParameter());
                } else {
                    selector = decl.getName();
                }
            } else {
                // invoke the getter, using the Java interop form of Util.getGetterName because this is the only case
                // (Value inside a Class) where we might refer to JavaBean properties
                selector = naming.selector((TypedDeclaration) decl);
            }
        } else if (ModelUtil.isCaptured(decl)) {
            TypedDeclaration typedDecl = ((TypedDeclaration) decl);
            TypeDeclaration typeDecl = typedDecl.getType().getDeclaration();
            mustUseField = Decl.isBoxedVariable((TypedDeclaration) decl);
            if (ModelUtil.isLocalNotInitializer(typeDecl) && typeDecl.isAnonymous() && // we need the box if it's a captured object
            !typedDecl.isSelfCaptured()) {
            // accessing a local 'object' declaration, so don't need a getter
            } else if (decl.isCaptured() && !((TypedDeclaration) decl).isVariable() && // captured objects are never variable but need the box
            !typedDecl.isSelfCaptured()) {
            // accessing a local that is not getter wrapped
            } else {
                primaryExpr = naming.makeQualifiedName(primaryExpr, (TypedDeclaration) decl, Naming.NA_Q_LOCAL_INSTANCE);
                selector = naming.selector((TypedDeclaration) decl);
            }
        }
    } else if (Decl.isMethodOrSharedOrCapturedParam(decl)) {
        mustUseParameter = (primaryExpr == null && decl.isParameter() && isWithinDefaultParameterExpression(decl.getContainer()));
        if (!decl.isParameter() && (ModelUtil.isLocalNotInitializer(decl) || (ModelUtil.isLocalToInitializer(decl) && ((Function) decl).isDeferred()))) {
            primaryExpr = null;
            int flags = Naming.NA_MEMBER;
            if (!isRecursiveReference(expr)) {
                // Only want to quote the method name
                // e.g. enum.$enum()
                flags |= Naming.NA_WRAPPER_UNQUOTED;
            } else if (!isReferenceInSameScope(expr)) {
                // always qualify it with this
                flags |= Naming.NA_WRAPPER | Naming.NA_WRAPPER_WITH_THIS;
            }
            qualExpr = naming.makeName((Function) decl, flags);
            selector = null;
        } else if (decl.isToplevel()) {
            primaryExpr = null;
            qualExpr = naming.makeName((Function) decl, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER);
            selector = null;
        } else if (!isWithinInvocation()) {
            selector = null;
        } else if (decl.isClassOrInterfaceMember()) {
            selector = naming.selector((Function) decl);
        } else {
            selector = null;
        }
    }
    boolean isCtor = decl instanceof Function && ((Function) decl).getTypeDeclaration() instanceof Constructor;
    if (result == null) {
        boolean useGetter = !(decl instanceof Function || isCtor) && !mustUseField && !mustUseParameter;
        if (qualExpr == null && selector == null && !(isCtor)) {
            useGetter = Decl.isClassAttribute(decl) && CodegenUtil.isErasedAttribute(decl.getName());
            if (useGetter) {
                selector = naming.selector((TypedDeclaration) decl);
            } else {
                selector = naming.substitute(decl);
            }
        }
        if (qualExpr == null) {
            qualExpr = primaryExpr;
        }
        // cases
        if (!mustUseParameter) {
            qualExpr = addQualifierForObjectMembersOfInterface(expr, decl, qualExpr);
            qualExpr = addInterfaceImplAccessorIfRequired(qualExpr, expr, decl);
            qualExpr = addThisOrObjectQualifierIfRequired(qualExpr, expr, decl);
            if (qualExpr == null && expr instanceof Tree.BaseMemberExpression && needDollarThis(expr)) {
                qualExpr = makeQualifiedDollarThis((Tree.BaseMemberExpression) expr);
            }
        }
        boolean isEnumeratedConstructorGetter = false;
        if ((decl instanceof Value && ModelUtil.isEnumeratedConstructor((Value) decl))) {
            Class constructedClass = ModelUtil.getConstructedClass(decl);
            // See CeylonVisitor.transformSingletonConstructor for that logic
            if (constructedClass.isToplevel() || constructedClass.isClassMember())
                isEnumeratedConstructorGetter = true;
            else {
                // Local enumerated constructor values are boxed
                // local class will use a field
                useGetter = false;
                qualExpr = naming.makeQualifiedName(primaryExpr, (TypedDeclaration) decl, Naming.NA_Q_LOCAL_INSTANCE);
                selector = naming.selector((TypedDeclaration) decl);
            }
        }
        if (qualExpr == null && (decl.isStatic() || isEnumeratedConstructorGetter) && // and not classes
        decl.getContainer() instanceof TypeDeclaration) {
            qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) decl.getContainer(), DeclNameFlag.QUALIFIED);
        }
        if (Decl.isPrivateAccessRequiringUpcast(expr)) {
            qualExpr = makePrivateAccessUpcast(expr, qualExpr);
        }
        if (transformer != null) {
            if (decl instanceof TypedDeclaration && ((TypedDeclaration) decl).getType().isTypeConstructor()) {
                // This is a bit of a hack, but we're "invoking a type constructor"
                // so recurse to get the applied expression.
                qualExpr = transformMemberExpression(expr, qualExpr, null);
                selector = null;
            }
            result = transformer.transform(qualExpr, selector);
        } else {
            Tree.Primary qmePrimary = null;
            if (expr instanceof Tree.QualifiedMemberOrTypeExpression) {
                qmePrimary = ((Tree.QualifiedMemberOrTypeExpression) expr).getPrimary();
            }
            boolean safeMemberJavaArray = expr instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) expr).getMemberOperator() instanceof Tree.SafeMemberOp && isJavaArray(qmePrimary.getTypeModel());
            if ((safeMemberJavaArray || Decl.isValueTypeDecl(qmePrimary)) && // Safe operators always work on boxed things, so don't use value types
            (safeMemberJavaArray || (expr instanceof Tree.QualifiedMemberOrTypeExpression == false) || ((Tree.QualifiedMemberOrTypeExpression) expr).getMemberOperator() instanceof Tree.MemberOp) && // We never want to use value types on boxed things, unless they are java arrays
            (CodegenUtil.isUnBoxed(qmePrimary) || isJavaArray(qmePrimary.getTypeModel())) && // Java arrays length property does not go via value types
            (!isJavaArray(qmePrimary.getTypeModel()) || (!"length".equals(selector) && !"hashCode".equals(selector)))) {
                JCExpression primTypeExpr = makeJavaType(qmePrimary.getTypeModel(), JT_NO_PRIMITIVES | JT_VALUE_TYPE);
                result = makeQualIdent(primTypeExpr, selector);
                result = make().Apply(List.<JCTree.JCExpression>nil(), result, List.<JCTree.JCExpression>of(qualExpr));
            } else if (expr instanceof Tree.QualifiedMemberOrTypeExpression && isThrowableMessage((Tree.QualifiedMemberOrTypeExpression) expr)) {
                result = utilInvocation().throwableMessage(qualExpr);
            } else if (expr instanceof Tree.QualifiedMemberOrTypeExpression && isThrowableSuppressed((Tree.QualifiedMemberOrTypeExpression) expr)) {
                result = utilInvocation().suppressedExceptions(qualExpr);
            } else {
                result = makeQualIdent(qualExpr, selector);
                if (useGetter) {
                    result = make().Apply(List.<JCTree.JCExpression>nil(), result, List.<JCTree.JCExpression>nil());
                }
            }
        }
    }
    if (transformer == null && decl instanceof TypedDeclaration && ((TypedDeclaration) decl).getType().isTypeConstructor() && !expr.getTypeArguments().getTypeModels().isEmpty()) {
        // applying a type constructor
        ListBuffer<JCExpression> tds = new ListBuffer<JCExpression>();
        for (Type t : expr.getTypeArguments().getTypeModels()) {
            tds.add(makeReifiedTypeArgument(t));
        }
        result = make().Apply(null, makeQualIdent(result, Naming.Unfix.apply.toString()), List.<JCExpression>of(make().NewArray(make().Type(syms().ceylonTypeDescriptorType), List.<JCExpression>nil(), tds.toList())));
    }
    return result;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 53 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class NamedArgumentInvocation method getParameter.

@Override
protected Parameter getParameter(int argIndex) {
    int realIndex = argIndex >= parameters.size() ? parameters.size() - 1 : argIndex;
    Parameter param = parameters.get(realIndex);
    if (param.getModel().isCoercionPoint()) {
        Parameter realParameter = ((Functional) getPrimaryDeclaration()).getFirstParameterList().getParameters().get(realIndex);
        return realParameter;
    }
    return param;
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter)

Example 54 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class NamedArgumentInvocation method buildVars.

/**
 * Constructs the vars used in the Let expression
 */
private void buildVars() {
    if (getPrimaryDeclaration() == null) {
        return;
    }
    boolean prev = gen.expressionGen().withinInvocation(false);
    java.util.List<Tree.NamedArgument> namedArguments = namedArgumentList.getNamedArguments();
    SequencedArgument sequencedArgument = namedArgumentList.getSequencedArgument();
    java.util.List<ParameterList> paramLists = ((Functional) getPrimaryDeclaration()).getParameterLists();
    java.util.List<Parameter> declaredParams = paramLists.get(0).getParameters();
    appendVarsForNamedArguments(namedArguments, declaredParams);
    appendVarsForReifiedTypeArguments();
    if (sequencedArgument != null)
        appendVarsForSequencedArguments(sequencedArgument, declaredParams);
    boolean hasDefaulted = appendVarsForDefaulted(declaredParams);
    DefaultParameterMethodOwner owner = Strategy.defaultParameterMethodOwner(getPrimaryDeclaration());
    if (hasDefaulted && owner != DefaultParameterMethodOwner.STATIC && owner != DefaultParameterMethodOwner.OUTER && owner != DefaultParameterMethodOwner.OUTER_COMPANION) {
        vars.prepend(makeThis());
    }
    gen.expressionGen().withinInvocation(prev);
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) DefaultParameterMethodOwner(org.eclipse.ceylon.compiler.java.codegen.Strategy.DefaultParameterMethodOwner) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) SequencedArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SequencedArgument)

Example 55 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class ClassOrPackageDoc method writeParameters.

protected final void writeParameters(Declaration decl) throws IOException {
    if (decl instanceof Functional) {
        Map<Parameter, Map<Tree.Assertion, List<Tree.Condition>>> parametersAssertions = getParametersAssertions(decl);
        boolean first = true;
        List<ParameterList> parameterLists = ((Functional) decl).getParameterLists();
        for (ParameterList parameterList : parameterLists) {
            for (Parameter parameter : parameterList.getParameters()) {
                ParameterDocData parameterDocData = getParameterDocData(parameter, parametersAssertions);
                if (!parameterDocData.isEmpty()) {
                    if (first) {
                        first = false;
                        open("div class='parameters section'");
                        around("span class='title'", "Parameters: ");
                        open("ul");
                    }
                    open("li");
                    open("code");
                    around("span class='parameter' id='" + decl.getName() + "-" + parameter.getName() + "'", parameter.getName());
                    // if parameter is function, we need to produce links to its parameters
                    if (parameter.getModel() instanceof Function) {
                        writeParameterLinksIfRequired((Function) parameter.getModel(), false, decl.getName() + "-");
                    }
                    if (!isEmpty(parameterDocData.defaultValue)) {
                        around("span class='parameter-default-value' title='Parameter default value'", " = " + parameterDocData.defaultValue);
                    }
                    close("code");
                    if (!isEmpty(parameterDocData.doc)) {
                        around("div class='doc section'", parameterDocData.doc);
                    }
                    writeParameterAssertions(decl, parameterDocData.parameterAssertions);
                    close("li");
                }
            }
        }
        if (!first) {
            close("ul");
            close("div");
        }
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

Functional (org.eclipse.ceylon.model.typechecker.model.Functional)58 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)30 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)28 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)27 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)25 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)24 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)24 Type (org.eclipse.ceylon.model.typechecker.model.Type)22 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)13 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)13 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)12 Value (org.eclipse.ceylon.model.typechecker.model.Value)12 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)11 Class (org.eclipse.ceylon.model.typechecker.model.Class)11 Function (org.eclipse.ceylon.model.typechecker.model.Function)11 Reference (org.eclipse.ceylon.model.typechecker.model.Reference)11 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)10 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 AnalyzerUtil.checkCasesDisjoint (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint)8