Search in sources :

Example 1 with RangeOp

use of com.redhat.ceylon.compiler.typechecker.tree.Tree.RangeOp in project ceylon-compiler by ceylon.

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)'");
    }
    com.sun.tools.javac.code.Type type;
    Type integerType = typeFact().getIntegerType();
    Type characterType = typeFact().getCharacterType();
    if (isSpanOf(range, integerType)) {
        type = syms().longType;
    } else if (isSpanOf(range, characterType)) {
        type = syms().intType;
    } else {
        return optimizationFailed(stmt, Optimization.SpanOpIteration, "The RangeOp doesn't produce a Range<Integer>/Range<Character>");
    }
    return increment == null ? new SpanOpIterationOptimization(stmt, range, increment, type) : new SpanOpWithStepIterationOptimization(stmt, range, increment, type);
}
Also used : Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) CustomTree(com.redhat.ceylon.compiler.typechecker.tree.CustomTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) RangeOp(com.redhat.ceylon.compiler.typechecker.tree.Tree.RangeOp) Term(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) SpecifierOrInitializerExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) RangeOp(com.redhat.ceylon.compiler.typechecker.tree.Tree.RangeOp)

Aggregations

CustomTree (com.redhat.ceylon.compiler.typechecker.tree.CustomTree)1 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)1 Expression (com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression)1 RangeOp (com.redhat.ceylon.compiler.typechecker.tree.Tree.RangeOp)1 SpecifierOrInitializerExpression (com.redhat.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression)1 Term (com.redhat.ceylon.compiler.typechecker.tree.Tree.Term)1 Type (com.redhat.ceylon.model.typechecker.model.Type)1 JCTree (com.sun.tools.javac.tree.JCTree)1 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)1