Search in sources :

Example 1 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class BoxingVisitor method visit.

@Override
public void visit(Tree.IfExpression that) {
    super.visit(that);
    if (that.getIfClause() == null || that.getElseClause() == null)
        return;
    Tree.Expression ifExpr = that.getIfClause().getExpression();
    Tree.Expression elseExpr = that.getElseClause().getExpression();
    if (ifExpr == null || elseExpr == null)
        return;
    if (CodegenUtil.isUnBoxed(ifExpr) && CodegenUtil.isUnBoxed(elseExpr) && !willEraseToObject(that.getUnit().denotableType(that.getTypeModel())))
        CodegenUtil.markUnBoxed(that);
    if (that.getTypeModel().isExactly(that.getUnit().getNullValueType())) {
        CodegenUtil.markTypeErased(that);
    }
// An If expression can never be raw, type erased or untrusted because
// it uses a Let with a new variable declaration, so the rawness,
// erasedness and untrustedness of its branches cannot propagate further
// up the tree.
}
Also used : Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 2 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class StatementTransformer method spanOpIteration.

/**
 * Returns a {@link SpanOpIterationOptimization} if that optimization applies
 * to the given {@code for} statement, otherwise null.
 * @param stmt The for statement
 * @return a {@link SpanOpIterationOptimization} or null.
 */
private ForStatementTransformation spanOpIteration(Tree.ForStatement stmt) {
    if (isOptimizationDisabled(stmt, Optimization.SpanOpIteration)) {
        return optimizationFailed(stmt, Optimization.SpanOpIteration, "optimization explicitly disabled by @disableOptimization");
    }
    Tree.ForIterator iterator = stmt.getForClause().getForIterator();
    if (!(iterator instanceof Tree.ValueIterator)) {
        return optimizationFailed(stmt, Optimization.SpanOpIteration, "optimization applies only to ValueIterators");
    }
    Tree.ValueIterator vi = (Tree.ValueIterator) iterator;
    Tree.SpecifierExpression specifier = vi.getSpecifierExpression();
    Tree.Term term = specifier.getExpression().getTerm();
    final Tree.Term increment;
    final Tree.RangeOp range;
    if (term instanceof Tree.RangeOp) {
        // So it's a for (i in (lhs..rhs)) { ... }
        increment = null;
        range = (Tree.RangeOp) term;
    } else if (term instanceof Tree.InvocationExpression) {
        Tree.InvocationExpression inv = (Tree.InvocationExpression) term;
        if (inv.getPrimary() instanceof Tree.QualifiedMemberExpression) {
            Tree.QualifiedMemberExpression prim = (Tree.QualifiedMemberExpression) inv.getPrimary();
            if ("by".equals(prim.getIdentifier().getText()) && prim.getPrimary() instanceof Tree.Expression && (((Tree.Expression) (prim.getPrimary())).getTerm() instanceof Tree.RangeOp)) {
                // So it's a for (i in (lhs..rhs).by(increment)) { ... }
                range = (Tree.RangeOp) ((Tree.Expression) (prim.getPrimary())).getTerm();
                if (inv.getPositionalArgumentList() != null) {
                    Tree.PositionalArgument a = inv.getPositionalArgumentList().getPositionalArguments().get(0);
                    if (a instanceof Tree.ListedArgument)
                        increment = ((Tree.ListedArgument) a).getExpression().getTerm();
                    else
                        return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to determine expression for argument to by(): appears spread or comprehension");
                } else if (inv.getNamedArgumentList() != null) {
                    Tree.SpecifiedArgument sarg = null;
                    for (Tree.NamedArgument arg : inv.getNamedArgumentList().getNamedArguments()) {
                        if ("step".equals(arg.getIdentifier().getText())) {
                            if (arg instanceof Tree.SpecifiedArgument) {
                                sarg = ((Tree.SpecifiedArgument) arg);
                                break;
                            }
                        // TODO In theory we could support Tree.AttributeArgument too
                        }
                    }
                    if (sarg != null) {
                        increment = sarg.getSpecifierExpression().getExpression().getTerm();
                    } else {
                        return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to determine expression for argument to by{}");
                    }
                } else {
                    return optimizationFailed(stmt, Optimization.SpanOpIteration, "Unable to get arguments to by()");
                }
            } else {
                return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
            }
        } else {
            return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
        }
    } else {
        return optimizationFailed(stmt, Optimization.SpanOpIteration, "Only applies to Iterables of the form 'lhs..rhs' or '(lhs..rhs).by(step)'");
    }
    if (!isSpanOf(range, typeFact().getCharacterType()) && !isSpanOf(range, typeFact().getIntegerType())) {
        return optimizationFailed(stmt, Optimization.SpanOpIteration, "The RangeOp doesn't produce a Range<Integer>/Range<Character>");
    }
    return increment == null ? new SpanOpIterationOptimization(stmt, range, increment) : new SpanOpWithStepIterationOptimization(stmt, range, increment);
}
Also used : Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) SpecifierOrInitializerExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) 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) RangeOp(org.eclipse.ceylon.compiler.typechecker.tree.Tree.RangeOp) RangeOp(org.eclipse.ceylon.compiler.typechecker.tree.Tree.RangeOp)

Example 3 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class StatementTransformer method transform.

/**
 * Transforms a Ceylon destructuring assignment to Java code.
 * @param stmt The Ceylon destructure
 * @return The Java tree
 */
List<JCStatement> transform(Tree.Destructure stmt) {
    List<JCStatement> result = List.nil();
    // Create temp var to hold result of expression
    Tree.Pattern pat = stmt.getPattern();
    Naming.SyntheticName tmpVarName = naming.synthetic(pat);
    Expression destExpr = stmt.getSpecifierExpression().getExpression();
    JCExpression typeExpr = makeJavaType(destExpr.getTypeModel());
    JCExpression expr = expressionGen().transformExpression(destExpr);
    at(stmt);
    JCVariableDecl tmpVar = makeVar(Flags.FINAL, tmpVarName, typeExpr, expr);
    result = result.append(tmpVar);
    // Now add the destructured variables
    List<VarDefBuilder> destructured = transformPattern(pat, tmpVarName.makeIdent());
    for (VarDefBuilder vdb : destructured) {
        Value v = vdb.var.getDeclarationModel();
        at(vdb.var);
        if (v.isClassMember() && v.isCaptured()) {
            AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.getter(this, v.getName(), v);
            adb.immutable();
            classGen().current().attribute(adb);
            classGen().current().defs(vdb.buildDefOnly());
            result = result.append(make().Exec(make().Assign(vdb.name().makeIdentWithThis(), vdb.expr())));
        } else {
            result = result.append(vdb.build());
        }
    }
    return result;
}
Also used : JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) SpecifierOrInitializerExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) 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) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 4 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression 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 5 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class NamedArgumentInvocation method bindMethodArgument.

private void bindMethodArgument(Tree.MethodArgument methodArg, Parameter declaredParam, Naming.SyntheticName argName) {
    ListBuffer<JCStatement> statements;
    Function model = methodArg.getDeclarationModel();
    List<JCStatement> body;
    boolean prevNoExpressionlessReturn = gen.statementGen().noExpressionlessReturn;
    boolean prevSyntheticClassBody = gen.expressionGen().withinSyntheticClassBody(Decl.isMpl(model) || gen.expressionGen().isWithinSyntheticClassBody());
    try {
        gen.expressionGen().withinSyntheticClassBody(true);
        gen.statementGen().noExpressionlessReturn = AbstractTransformer.isAnything(model.getType());
        if (methodArg.getBlock() != null) {
            body = gen.statementGen().transformBlock(methodArg.getBlock());
            if (!methodArg.getBlock().getDefinitelyReturns()) {
                if (AbstractTransformer.isAnything(model.getType())) {
                    body = body.append(gen.make().Return(gen.makeNull()));
                } else {
                    body = body.append(gen.make().Return(gen.makeErroneous(methodArg.getBlock(), "compiler bug: non-void method does not definitely return")));
                }
            }
        } else {
            Expression expr = methodArg.getSpecifierExpression().getExpression();
            BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(model);
            Type type = model.getType();
            JCExpression transExpr = gen.expressionGen().transformExpression(expr, boxing, type);
            JCReturn returnStat = gen.make().Return(transExpr);
            body = List.<JCStatement>of(returnStat);
        }
    } finally {
        gen.expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
        gen.statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
    }
    Type callableType = model.appliedReference(null, Collections.<Type>emptyList()).getFullType();
    CallableBuilder callableBuilder = CallableBuilder.methodArgument(gen.gen(), methodArg, model, callableType, Collections.singletonList(methodArg.getParameterLists().get(0)), gen.classGen().transformMplBody(methodArg.getParameterLists(), model, body));
    JCExpression callable = callableBuilder.build();
    gen.at(methodArg);
    JCExpression typeExpr = gen.makeJavaType(callableType, JT_RAW);
    JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, callable);
    statements = ListBuffer.<JCStatement>of(varDecl);
    bind(declaredParam, argName, gen.makeJavaType(callableType), statements.toList());
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCReturn(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCReturn) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) QualifiedTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) StaticMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Aggregations

Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)19 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)17 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)9 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)8 Type (org.eclipse.ceylon.model.typechecker.model.Type)8 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)7 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)7 SpecifierOrInitializerExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression)6 Term (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term)5 ArrayList (java.util.ArrayList)4 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)4 Value (org.eclipse.ceylon.model.typechecker.model.Value)4 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)3 LazySpecifierExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)3 StaticMemberOrTypeExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression)3 JCBlock (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock)3 CName (org.eclipse.ceylon.compiler.java.codegen.Naming.CName)2 BaseMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression)2 LetExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.LetExpression)2 QualifiedMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression)2