use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.RangeOp 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);
}
Aggregations