Search in sources :

Example 1 with TypedDeclaration

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

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);
    } 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.withinClassOrInterface(decl) && !Decl.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 (isWithinSuperInvocation() && ((Value) decl).isVariable() && ((Value) decl).isCaptured()) {
                    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 (decl.isCaptured() || decl.isShared()) {
            TypedDeclaration typedDecl = ((TypedDeclaration) decl);
            TypeDeclaration typeDecl = typedDecl.getType().getDeclaration();
            mustUseField = Decl.isBoxedVariable((TypedDeclaration) decl);
            if (Decl.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() && (Decl.isLocalNotInitializer(decl) || (Decl.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 {
            // not toplevel, not within method, must be a class member
            selector = naming.selector((Function) decl);
        }
    }
    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 && needDollarThis(expr)) {
                qualExpr = makeQualifiedDollarThis((Tree.BaseMemberExpression) expr);
            }
        }
        if (qualExpr == null && (decl.isStaticallyImportable() || (decl instanceof Value && Decl.isEnumeratedConstructor((Value) decl))) && // 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 = ListBuffer.lb();
        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(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Functional(com.redhat.ceylon.model.typechecker.model.Functional) 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) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) Value(com.redhat.ceylon.model.typechecker.model.Value) 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) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 2 with TypedDeclaration

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

the class ExpressionTransformer method transformSpreadOperator.

private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
    at(expr);
    boolean spreadMethodReferenceOuter = !expr.equals(this.spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
    boolean spreadMethodReferenceInner = expr.equals(this.spreading) && isWithinInvocation();
    Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
    if (spreadMethodReferenceOuter) {
        spreading = expr;
    }
    try {
        Naming.SyntheticName varBaseName = naming.alias("spread");
        ListBuffer<JCStatement> letStmts = ListBuffer.<JCStatement>lb();
        final Naming.SyntheticName srcIterableName;
        if (spreadMethodReferenceInner) {
            // use the var we initialized in the outer
            srcIterableName = this.memberPrimary;
        } else {
            srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
        }
        if (spreadMethodReferenceOuter) {
            // if we're in the outer, note then name of the var for use in the inner.
            this.memberPrimary = srcIterableName;
        }
        Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
        Type srcElementType = expr.getTarget().getQualifyingType();
        JCExpression srcIterableTypeExpr = makeJavaType(typeFact().getIterableType(srcElementType), JT_NO_PRIMITIVES);
        JCExpression srcIterableExpr;
        boolean isSuperOrSuperOf = false;
        if (spreadMethodReferenceInner) {
            srcIterableExpr = srcIterableName.makeIdent();
        } else {
            boolean isSuper = isSuper(expr.getPrimary());
            isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
            if (isSuperOrSuperOf) {
                // so we just refer to it later
                if (isSuper) {
                    Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
                    srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
                } else
                    srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
            } else {
                srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, typeFact().getIterableType(srcElementType));
            }
        }
        // do not capture the iterable for super invocations: see above
        if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
            JCVariableDecl srcIterable = null;
            srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
            letStmts.prepend(srcIterable);
        }
        Type resultElementType = expr.getTarget().getType();
        Type resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
        // private Iterator<srcElementType> iterator = srcIterableName.iterator();
        JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
        naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
        Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
        /* public Object next() {
             *     Object result;
             *     if (!((result = iterator.next()) instanceof Finished)) {
             *         result = transformedMember(result);
             *     }
             *     return result;
             */
        /* Any arguments in the member of the spread would get re-evaluated on each iteration
             * so we need to shift them to the scope of the Let to ensure they're evaluated once. 
             */
        boolean aliasArguments = (transformer instanceof InvocationTermTransformer) && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
        if (aliasArguments) {
            ((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
        }
        JCNewClass iterableClass;
        boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
        try {
            JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
            transformedElement = transformMemberExpression(expr, transformedElement, transformer);
            // be handled by the previous recursion
            if (spreadMethodReferenceOuter) {
                return make().LetExpr(letStmts.toList(), transformedElement);
            }
            transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
            expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
            MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
            nextMdb.isOverride(true);
            nextMdb.annotationFlags(Annotations.IGNORE);
            nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            nextMdb.resultType(null, make().Type(syms().objectType));
            nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
            JCMethodDecl nextMethod = nextMdb.build();
            // new AbstractIterator()
            JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), List.of(srcIterator, nextMethod)));
            MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
            iteratorMdb.isOverride(true);
            iteratorMdb.annotationFlags(Annotations.IGNORE);
            iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            iteratorMdb.resultType(null, makeJavaType(typeFact().getIteratorType(resultElementType)));
            iteratorMdb.body(make().Return(iteratorClass));
            // new AbstractIterable()
            iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
        } finally {
            expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
        }
        if (aliasArguments) {
            letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
        }
        JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
        JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
        // Do we *statically* know the result must be a Sequence
        final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
        Type returnElementType = expr.getTarget().getType();
        if (primaryIsSequence) {
            int flags = EXPR_DOWN_CAST;
            spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
        }
        return spread;
    } finally {
        spreading = oldSpreading;
    }
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 3 with TypedDeclaration

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

the class MethodDefinitionBuilder method getNonWideningParam.

public NonWideningParam getNonWideningParam(TypedReference typedRef, WideningRules wideningRules) {
    TypedDeclaration nonWideningDecl = null;
    int flags = 0;
    Type nonWideningType;
    FunctionOrValue mov = (FunctionOrValue) typedRef.getDeclaration();
    if (Decl.isValue(mov)) {
        TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
        nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef);
        nonWideningDecl = nonWideningTypedRef.getDeclaration();
    } else {
        // Stef: So here's the thing. I know this is wrong for Function where we should do getFullType(), BUT
        // lots of methods call this and then feed the output into AT.makeJavaType(TypedDeclaration typeDecl, Type type, int flags)
        // which adds the Callable type, so if we fix it here we have to remove it from there and there's lots of callers of that
        // function which rely on its behaviour and frankly I've had enough of this refactoring, so a few callers of this function
        // have to add the Callable back. It sucks, yeah, but so far it works, which is amazing enough that I don't want to touch it
        // any more. More ambitious/courageous people are welcome to fix this properly.
        nonWideningType = typedRef.getType();
        nonWideningDecl = mov;
    }
    if (!CodegenUtil.isUnBoxed(nonWideningDecl))
        flags |= AbstractTransformer.JT_NO_PRIMITIVES;
    // make sure we don't accidentally narrow value parameters that would be erased in the topmost declaration
    if (wideningRules != WideningRules.NONE && mov instanceof Value) {
        TypedDeclaration refinedParameter = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(mov);
        // mixin bridge methods have the same rules as when refining stuff except they are their own refined decl
        if (wideningRules == WideningRules.FOR_MIXIN || !Decl.equal(refinedParameter, mov)) {
            Type refinedParameterType;
            // in the refined parameter type
            if (refinedParameter instanceof Function)
                refinedParameterType = refinedParameter.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType();
            else
                refinedParameterType = refinedParameter.getType();
            // if the supertype method itself got erased to Object, we can't do better than this
            if (gen.willEraseToObject(refinedParameterType) && !gen.willEraseToBestBounds(mov))
                nonWideningType = gen.typeFact().getObjectType();
            else if (CodegenUtil.isRaw(refinedParameter)) {
                flags |= AbstractTransformer.JT_RAW;
            } else {
                flags |= AbstractTransformer.JT_NARROWED;
            }
        }
    }
    // keep in sync with gen.willEraseToBestBounds()
    if (wideningRules != WideningRules.NONE && (gen.typeFact().isUnion(nonWideningType) || gen.typeFact().isIntersection(nonWideningType))) {
        final Type refinedType = ((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(nonWideningDecl)).getType();
        if (refinedType.isTypeParameter() && !refinedType.getSatisfiedTypes().isEmpty()) {
            nonWideningType = refinedType.getSatisfiedTypes().get(0);
            // Could be parameterized, and type param won't be in scope, so have to go raw
            flags |= AbstractTransformer.JT_RAW;
        }
    }
    // this is to be done on the parameter's containing method, to see if that method must have raw parameters
    if (mov.isParameter() && mov.getContainer() instanceof Declaration && gen.rawParameters((Declaration) mov.getContainer())) {
        flags |= AbstractTransformer.JT_RAW;
    }
    return new NonWideningParam(flags, nonWideningType, nonWideningDecl);
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) Value(com.redhat.ceylon.model.typechecker.model.Value) 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 4 with TypedDeclaration

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

the class Naming method appendTypeDeclaration.

private void appendTypeDeclaration(final TypeDeclaration decl, EnumSet<DeclNameFlag> flags, TypeDeclarationBuilder<?> typeDeclarationBuilder, Scope scope, final boolean last) {
    if (scope instanceof Class || scope instanceof TypeAlias || (scope instanceof Constructor && (scope.equals(decl) || !Decl.isLocalNotInitializerScope(scope)))) {
        TypeDeclaration klass = (TypeDeclaration) scope;
        if (klass.isAnonymous() && !klass.isNamed())
            typeDeclarationBuilder.clear();
        typeDeclarationBuilder.append(escapeClassName(klass.getName() != null ? klass.getName() : ""));
        if (Decl.isCeylon(klass)) {
            if (flags.contains(DeclNameFlag.COMPANION) && Decl.isLocalNotInitializer(klass) && last) {
                typeDeclarationBuilder.append(IMPL_POSTFIX);
            } else if (flags.contains(DeclNameFlag.ANNOTATION) && last) {
                typeDeclarationBuilder.append(ANNO_POSTFIX);
            } else if (flags.contains(DeclNameFlag.ANNOTATIONS) && last) {
                typeDeclarationBuilder.append(ANNOS_POSTFIX);
            } else if (flags.contains(DeclNameFlag.DELEGATION) && last) {
                typeDeclarationBuilder.append(DELEGATION_POSTFIX);
            }
        }
    } else if (scope instanceof Interface) {
        Interface iface = (Interface) scope;
        typeDeclarationBuilder.append(iface.getName());
        if (Decl.isCeylon(iface) && ((decl instanceof Class || decl instanceof Constructor || decl instanceof TypeAlias || scope instanceof Constructor) || flags.contains(DeclNameFlag.COMPANION))) {
            typeDeclarationBuilder.append(IMPL_POSTFIX);
        }
    } else if (Decl.isLocalNotInitializerScope(scope)) {
        if (flags.contains(DeclNameFlag.COMPANION) || !(decl instanceof Interface)) {
            typeDeclarationBuilder.clear();
        } else if (flags.contains(DeclNameFlag.QUALIFIED) || (decl instanceof Interface)) {
            Scope nonLocal = scope;
            while (!(nonLocal instanceof Declaration)) {
                nonLocal = nonLocal.getContainer();
            }
            typeDeclarationBuilder.append(((Declaration) nonLocal).getPrefixedName());
            if (!Decl.equalScopes(scope, nonLocal)) {
                typeDeclarationBuilder.append('$');
                typeDeclarationBuilder.append(getLocalId(scope));
            }
            if (decl instanceof Interface) {
                typeDeclarationBuilder.append('$');
            } else {
                if (flags.contains(DeclNameFlag.QUALIFIED)) {
                    typeDeclarationBuilder.selectAppended();
                } else {
                    typeDeclarationBuilder.clear();
                }
            }
        }
        return;
    } else if (scope instanceof TypedDeclaration && ((Declaration) scope).isToplevel()) {
    // nothing? that's just weird
    }
    if (!last) {
        if (decl instanceof Interface && Decl.isCeylon((TypeDeclaration) decl) && !flags.contains(DeclNameFlag.COMPANION)) {
            typeDeclarationBuilder.append('$');
        } else if (decl instanceof Constructor && ((Class) decl.getContainer()).isMember() && decl.getContainer().equals(scope)) {
            typeDeclarationBuilder.append('$');
        } else {
            if (flags.contains(DeclNameFlag.QUALIFIED)) {
                typeDeclarationBuilder.selectAppended();
            } else {
                typeDeclarationBuilder.clear();
            }
        }
    } else {
        typeDeclarationBuilder.selectAppended();
    }
    return;
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Scope(com.redhat.ceylon.model.typechecker.model.Scope) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Class(com.redhat.ceylon.model.typechecker.model.Class) LazyClass(com.redhat.ceylon.model.loader.model.LazyClass) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 5 with TypedDeclaration

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

the class Naming method addNamesForWrapperClass.

private <R> void addNamesForWrapperClass(TypeDeclarationBuilder<R> builder, TypedDeclaration decl, int namingOptions) {
    if ((namingOptions & NA_FQ) != 0) {
        if ((namingOptions & NA_WRAPPER) == 0 && (namingOptions & NA_WRAPPER_UNQUOTED) == 0) {
            throw new BugException("If you pass FQ you must pass WRAPPER or WRAPPER_UNQUOTED too, or there's no class name to qualify!");
        }
        List<String> outerNames = null;
        Scope s = decl.getContainer();
        while (s != null) {
            if (s instanceof Package) {
                final List<String> packageName = ((Package) s).getName();
                for (int ii = 0; ii < packageName.size(); ii++) {
                    if (ii == 0 && packageName.get(ii).isEmpty()) {
                        continue;
                    }
                    builder.select(quoteIfJavaKeyword(packageName.get(ii)));
                }
                break;
            } else if (s instanceof ClassOrInterface) {
                if (outerNames == null) {
                    outerNames = new ArrayList<String>(2);
                }
                outerNames.add(getQuotedClassName((ClassOrInterface) s, 0));
            } else if (s instanceof TypedDeclaration) {
                if (outerNames == null) {
                    outerNames = new ArrayList<String>(2);
                }
                outerNames.add(quoteIfJavaKeyword(((TypedDeclaration) s).getName()));
            }
            s = s.getContainer();
        }
        if (outerNames != null) {
            for (int ii = outerNames.size() - 1; ii >= 0; ii--) {
                String outerName = outerNames.get(ii);
                builder.select(outerName);
            }
        }
    }
    if ((namingOptions & NA_WRAPPER) != 0) {
        builder.select(getQuotedClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
    } else if ((namingOptions & NA_WRAPPER_UNQUOTED) != 0) {
        builder.select(getRealName(decl, namingOptions & (NA_GETTER | NA_SETTER | NA_WRAPPER_UNQUOTED)));
    } else if ((namingOptions & NA_Q_LOCAL_INSTANCE) != 0) {
        if (Decl.isBoxedVariable(decl)) {
            builder.select(getVariableBoxName(decl));
        } else {
            builder.select(getAttrClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
        }
    }
    if ((namingOptions & NA_WRAPPER_WITH_THIS) != 0) {
        builder.select("this");
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Scope(com.redhat.ceylon.model.typechecker.model.Scope) ArrayList(java.util.ArrayList) Package(com.redhat.ceylon.model.typechecker.model.Package)

Aggregations

TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)52 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)28 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)26 Type (com.redhat.ceylon.model.typechecker.model.Type)26 Function (com.redhat.ceylon.model.typechecker.model.Function)23 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)17 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)17 Class (com.redhat.ceylon.model.typechecker.model.Class)15 Value (com.redhat.ceylon.model.typechecker.model.Value)14 JCTree (com.sun.tools.javac.tree.JCTree)14 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)13 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)12 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)11 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)10 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)10 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)9 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)9 Interface (com.redhat.ceylon.model.typechecker.model.Interface)8 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)8 AttributeDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)7