Search in sources :

Example 41 with Value

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

the class StatementTransformer method transform.

JCStatement transform(Node node, Tree.SwitchClause switchClause, Tree.SwitchCaseList caseList, String tmpVar, Tree.Term outerExpression, Type expectedType) {
    at(switchClause);
    block();
    SwitchTransformation transformation = null;
    Type exprType = switchExpressionType(switchClause);
    Boolean switchUnboxed = switchExpressionUnboxed(switchClause);
    // Are we switching with just String literal or Character literal match cases?
    if (isJavaSwitchableType(exprType, switchUnboxed)) {
        boolean canUseSwitch = true;
        caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
            if (clause.getCaseItem() instanceof Tree.MatchCase) {
                Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
                if (!matchList.getTypes().isEmpty()) {
                    canUseSwitch = false;
                    break caseStmts;
                }
                java.util.List<Expression> caseExprs = matchList.getExpressions();
                caseExpr: for (Tree.Expression expr : caseExprs) {
                    Tree.Term e = ExpressionTransformer.eliminateParens(expr);
                    if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
                        continue caseExpr;
                    } else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
                        continue caseExpr;
                    } else {
                        canUseSwitch = false;
                        break caseStmts;
                    }
                }
            } else {
                canUseSwitch = false;
                break caseStmts;
            }
        }
        if (canUseSwitch) {
            // yes, so use a Java Switch
            transformation = new Switch();
        }
    }
    if (transformation == null && isOptional(exprType)) {
        // Are we switching with just String literal or Character literal plus null
        // match cases?
        Type definiteType = typeFact().getDefiniteType(exprType);
        if (isJavaSwitchableType(definiteType, switchUnboxed)) {
            boolean canUseIfElseSwitch = true;
            boolean hasSingletonNullCase = false;
            caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
                if (clause.getCaseItem() instanceof Tree.MatchCase) {
                    if (getSingletonNullCase(clause) != null) {
                        hasSingletonNullCase = true;
                    }
                    Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
                    if (!matchList.getTypes().isEmpty()) {
                        canUseIfElseSwitch = false;
                        break caseStmts;
                    }
                    java.util.List<Expression> caseExprs = matchList.getExpressions();
                    caseExpr: for (Tree.Expression expr : caseExprs) {
                        Tree.Term e = ExpressionTransformer.eliminateParens(expr);
                        if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
                            continue caseExpr;
                        } else if (e instanceof Tree.BaseMemberExpression && isNullValue(((Tree.BaseMemberExpression) e).getDeclaration()) && caseExprs.size() == 1) {
                            continue caseExpr;
                        } else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
                            continue caseExpr;
                        } else {
                            canUseIfElseSwitch = false;
                            break caseStmts;
                        }
                    }
                } else {
                    canUseIfElseSwitch = false;
                    break caseStmts;
                }
            }
            canUseIfElseSwitch &= hasSingletonNullCase;
            if (canUseIfElseSwitch) {
                // yes, so use a If
                transformation = new IfNullElseSwitch();
            }
        }
    }
    // The default transformation
    if (transformation == null) {
        transformation = new IfElseChain();
    }
    JCStatement result = transformation.transformSwitch(node, switchClause, caseList, tmpVar, outerExpression, expectedType);
    unblock();
    return result;
}
Also used : Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) CaseClause(org.eclipse.ceylon.compiler.typechecker.tree.Tree.CaseClause) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Type(org.eclipse.ceylon.model.typechecker.model.Type) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Value(org.eclipse.ceylon.model.typechecker.model.Value) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) List(org.eclipse.ceylon.langtools.tools.javac.util.List) ArrayList(java.util.ArrayList)

Example 42 with Value

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

the class StatementTransformer method transform.

public JCTree transform(CustomTree.GuardedVariable that) {
    BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(that.getDeclarationModel());
    Tree.Expression expr = that.getSpecifierExpression().getExpression();
    Type fromType = expr.getTypeModel();
    Value newValue = that.getDeclarationModel();
    Type toType = newValue.getType();
    Tree.ConditionList conditionList = that.getConditionList();
    Tree.Condition condition = conditionList.getConditions().get(0);
    JCExpression val = expressionGen().transformExpression(expr, newValue.hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0);
    at(that);
    if (condition instanceof Tree.IsCondition) {
        if (!willEraseToObject(toType)) {
            // Want raw type for instanceof since it can't be used with generic types
            JCExpression rawToTypeExpr = makeJavaType(toType, JT_NO_PRIMITIVES | JT_RAW);
            // Substitute variable with the correct type to use in the rest of the code block
            val = make().TypeCast(rawToTypeExpr, val);
            if (CodegenUtil.isUnBoxed(newValue) && canUnbox(toType)) {
                val = unboxType(val, toType);
            }
        }
    } else if (condition instanceof Tree.ExistsCondition) {
        Type exprType = fromType;
        if (isOptional(exprType)) {
            exprType = typeFact().getDefiniteType(exprType);
        }
        val = expressionGen().applyErasureAndBoxing(val, exprType, CodegenUtil.hasTypeErased(expr), true, CodegenUtil.hasUntrustedType(expr), boxingStrategy, toType, 0);
    } else if (condition instanceof Tree.NonemptyCondition) {
        Type exprType = fromType;
        if (isOptional(exprType)) {
            exprType = typeFact().getDefiniteType(exprType);
        }
        val = expressionGen().applyErasureAndBoxing(val, exprType, false, true, BoxingStrategy.BOXED, toType, ExpressionTransformer.EXPR_DOWN_CAST);
    }
    SyntheticName alias = naming.alias(that.getIdentifier().getText());
    Substitution subst = naming.addVariableSubst(newValue, alias.getName());
    // FIXME: this is rubbish, but the same rubbish from assert. it's most likely wrong there too
    Scope scope = that.getScope().getScope();
    while (scope instanceof ConditionScope) {
        scope = scope.getScope();
    }
    subst.scopeClose(scope);
    JCExpression varType = makeJavaType(toType);
    return make().VarDef(make().Modifiers(FINAL), alias.asName(), varType, val);
}
Also used : SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Substitution(org.eclipse.ceylon.compiler.java.codegen.Naming.Substitution) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) ConditionScope(org.eclipse.ceylon.model.typechecker.model.ConditionScope) ConditionScope(org.eclipse.ceylon.model.typechecker.model.ConditionScope) Condition(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Condition) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Value(org.eclipse.ceylon.model.typechecker.model.Value) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 43 with Value

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

the class CeylonVisitor method transformSingletonConstructor.

protected void transformSingletonConstructor(HashMap<Constructor, CtorDelegation> delegates, Tree.Enumerated ctor) {
    // generate a constructor
    transformConstructor(ctor, // ctor.getParameterList(),
    null, ctor.getDelegatedConstructor(), ctor.getBlock(), ctor.getEnumerated(), delegates);
    Class clz = ModelUtil.getConstructedClass(ctor.getEnumerated());
    Value singletonModel = ctor.getDeclarationModel();
    // generate a field
    AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.singleton(gen, singletonModel.getName(), singletonModel, false);
    adb.modelAnnotations(gen.makeAtEnumerated());
    adb.modelAnnotations(gen.makeAtIgnore());
    adb.userAnnotations(gen.expressionGen().transformAnnotations(OutputElement.GETTER, ctor));
    adb.fieldAnnotations(gen.expressionGen().transformAnnotations(OutputElement.FIELD, ctor));
    // not setter
    adb.immutable();
    SyntheticName field = gen.naming.getValueConstructorFieldName(singletonModel);
    if (clz.isToplevel()) {
        adb.modifiers((singletonModel.isShared() ? PUBLIC : PRIVATE) | STATIC | FINAL);
        adb.initialValue(gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null), BoxingStrategy.BOXED);
        classBuilder.defs(adb.build());
    } else if (clz.isClassMember()) {
        int mods = 0;
        if (!singletonModel.isShared()) {
            mods |= PRIVATE;
        }
        if (clz.isClassOrInterfaceMember() && clz.isStatic()) {
            mods |= STATIC;
        }
        adb.modifiers(mods);
        // lazy
        adb.initialValue(gen.makeNull(), BoxingStrategy.BOXED);
        List<JCStatement> l = List.<JCStatement>of(gen.make().If(gen.make().Binary(JCTree.Tag.EQ, field.makeIdent(), gen.makeNull()), gen.make().Exec(gen.make().Assign(field.makeIdent(), gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null))), null), gen.make().Return(field.makeIdent()));
        adb.getterBlock(gen.make().Block(0, l));
        long mods2 = PRIVATE | TRANSIENT;
        if (clz.isStatic()) {
            mods2 |= STATIC;
        }
        classBuilder.getContainingClassBuilder().defs(gen.makeVar(mods2, field, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), gen.makeNull()));
        classBuilder.getContainingClassBuilder().defs(adb.build());
    } else {
        // LOCAL
        // we have to first make an empty box
        JCNewClass initialValue = gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null);
        JCVariableDecl box = gen.makeVariableBoxDecl(gen.makeNull(), singletonModel);
        classBuilder.before(box);
        // then do the class, and after that, assign our instance to the box
        JCAssign assign = gen.make().Assign(gen.makeSelect(field.getName(), NamingBase.getGetterName(singletonModel)), initialValue);
        classBuilder.after(gen.make().Exec(assign));
    }
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCAssign(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAssign) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) List(org.eclipse.ceylon.langtools.tools.javac.util.List) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 44 with Value

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

the class MethodDefinitionBuilder method getNonWideningParam.

public NonWideningParam getNonWideningParam(TypedReference typedRef, WideningRules wideningRules) {
    TypedDeclaration nonWideningDecl = null;
    int flags = 0;
    long modifiers = 0;
    Type nonWideningType;
    FunctionOrValue mov = (FunctionOrValue) typedRef.getDeclaration();
    if (Decl.isValue(mov)) {
        TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
        nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef).resolveAliases();
        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().resolveAliases();
        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);
        if (refinedParameter != null && refinedParameter instanceof Value && ((Value) refinedParameter).getInitializerParameter() != null && gen.isJavaVariadic(((Value) refinedParameter).getInitializerParameter())) {
            modifiers |= Flags.VARARGS;
        }
        // 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;
            }
            if ((flags & AbstractTransformer.JT_RAW) == 0 && !Decl.equal(refinedParameter, mov) && implementsRawParameter(mov)) {
                flags |= AbstractTransformer.JT_RAW;
            }
        }
    }
    // 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, modifiers, nonWideningType, nonWideningDecl);
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 45 with Value

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

the class InterfaceVisitor method visit.

@Override
public void visit(Tree.AttributeGetterDefinition that) {
    Value model = that.getDeclarationModel();
    // locals and toplevels get a type generated for them
    if (!model.isMember() && !model.isToplevel()) {
        Set<String> old = localCompanionClasses;
        localCompanionClasses = new HashSet<String>();
        super.visit(that);
        localCompanionClasses = old;
    } else {
        super.visit(that);
    }
}
Also used : Value(org.eclipse.ceylon.model.typechecker.model.Value)

Aggregations

Value (org.eclipse.ceylon.model.typechecker.model.Value)190 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)135 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)77 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)74 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)70 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)69 Type (org.eclipse.ceylon.model.typechecker.model.Type)68 Function (org.eclipse.ceylon.model.typechecker.model.Function)50 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)47 Class (org.eclipse.ceylon.model.typechecker.model.Class)46 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)42 JavaBeanValue (org.eclipse.ceylon.model.loader.model.JavaBeanValue)30 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)30 ArrayList (java.util.ArrayList)29 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)29 FieldValue (org.eclipse.ceylon.model.loader.model.FieldValue)28 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)27 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)26 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)24 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)23