use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension in project ceylon by eclipse.
the class AbstractTransformer method makeLazyIterable.
/**
* Makes a lazy iterable literal, for a sequenced argument to a named invocation
* (<code>f{foo=""; expr1, expr2, *expr3}</code>) or
* for an iterable instantiation (<code>{expr1, expr2, *expr3}</code>)
*/
JCExpression makeLazyIterable(Tree.SequencedArgument sequencedArgument, Type seqElemType, Type absentType, int flags) {
java.util.List<PositionalArgument> list = sequencedArgument.getPositionalArguments();
int i = 0;
ListBuffer<JCStatement> returns = new ListBuffer<JCStatement>();
boolean spread = false;
boolean old = expressionGen().withinSyntheticClassBody(true);
try {
for (Tree.PositionalArgument arg : list) {
at(arg);
JCExpression jcExpression;
// last expression can be an Iterable<seqElemType>
if (arg instanceof Tree.SpreadArgument || arg instanceof Tree.Comprehension) {
// make sure we only have spread/comprehension as last
if (i != list.size() - 1) {
jcExpression = makeErroneous(arg, "compiler bug: spread or comprehension argument is not last in sequence literal");
} else {
spread = true;
jcExpression = transformSpreadOrComprehension(arg, seqElemType);
}
} else if (arg instanceof Tree.ListedArgument) {
Tree.Expression expr = ((Tree.ListedArgument) arg).getExpression();
// always boxed since we stuff them into a sequence
jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, seqElemType);
} else {
jcExpression = makeErroneous(arg, "compiler bug: " + arg.getNodeType() + " is not a supported sequenced argument");
}
at(arg);
// the last iterable goes first if spread
returns.add(make().Return(jcExpression));
i++;
}
at(sequencedArgument);
if (Strategy.preferLazySwitchingIterable(sequencedArgument.getPositionalArguments())) {
// use a LazySwitchingIterable
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$evaluate$.toString());
mdb.isOverride(true);
mdb.modifiers(PROTECTED | FINAL);
mdb.resultType(new TransformedType(make().Type(syms().objectType)));
mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, Unfix.$index$.toString()).type(new TransformedType(make().Type(syms().intType))));
JCSwitch swtch;
try (SavedPosition sp = noPosition()) {
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
i = 0;
for (JCStatement e : returns) {
cases.add(make().Case(make().Literal(i++), List.<JCStatement>of(e)));
}
cases.add(make().Case(null, List.<JCStatement>of(make().Return(makeNull()))));
swtch = make().Switch(naming.makeUnquotedIdent(Unfix.$index$), cases.toList());
}
mdb.body(swtch);
return at(sequencedArgument).NewClass(null, // of(makeJavaType(seqElemType), makeJavaType(absentType)),
List.<JCExpression>nil(), make().TypeApply(make().QualIdent(syms.ceylonLazyIterableType.tsym), List.<JCExpression>of(makeJavaType(seqElemType, JT_TYPE_ARGUMENT), makeJavaType(absentType, JT_TYPE_ARGUMENT))), // td,
List.of(// td,
makeReifiedTypeArgument(seqElemType), // td
makeReifiedTypeArgument(absentType), // numMethods
make().Literal(list.size()), // spread),
make().Literal(spread)), make().AnonymousClassDef(make().Modifiers(FINAL), List.<JCTree>of(mdb.build())));
} else {
ListBuffer<JCTree> methods = new ListBuffer<JCTree>();
// generate a method for each expression in the iterable
MethodDefinitionBuilder mdb;
i = 0;
for (JCStatement expr : returns) {
mdb = MethodDefinitionBuilder.systemMethod(this, "$" + i);
i++;
mdb.modifiers(PRIVATE | FINAL);
mdb.resultType(new TransformedType(make().Type(syms().objectType)));
mdb.body(expr);
methods.add(mdb.build());
}
// the $evaluate method switches between them
mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$evaluate$.toString());
mdb.isOverride(true);
mdb.modifiers(PROTECTED | FINAL);
mdb.resultType(new TransformedType(make().Type(syms().objectType)));
mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, Unfix.$index$.toString()).type(new TransformedType(make().Type(syms().intType))));
JCSwitch swtch;
try (SavedPosition sp = noPosition()) {
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
for (i = 0; i < returns.size(); i++) {
cases.add(make().Case(make().Literal(i), List.<JCStatement>of(make().Return(make().Apply(null, naming.makeUnquotedIdent("$" + i), List.<JCExpression>nil())))));
}
cases.add(make().Case(null, List.<JCStatement>of(make().Return(makeNull()))));
swtch = make().Switch(naming.makeUnquotedIdent(Unfix.$index$), cases.toList());
}
mdb.body(swtch);
return at(sequencedArgument).NewClass(null, // of(makeJavaType(seqElemType), makeJavaType(absentType)),
List.<JCExpression>nil(), make().TypeApply(make().QualIdent(syms.ceylonLazyIterableType.tsym), List.<JCExpression>of(makeJavaType(seqElemType, JT_TYPE_ARGUMENT), makeJavaType(absentType, JT_TYPE_ARGUMENT))), // td,
List.of(// td,
makeReifiedTypeArgument(seqElemType), // td
makeReifiedTypeArgument(absentType), // numMethods
make().Literal(list.size()), // spread),
make().Literal(spread)), make().AnonymousClassDef(make().Modifiers(FINAL), methods.toList().prepend(mdb.build())));
}
} finally {
expressionGen().withinSyntheticClassBody(old);
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension in project ceylon by eclipse.
the class NamedArgumentInvocation method getTransformedArgumentExpression.
@Override
protected JCExpression getTransformedArgumentExpression(int argIndex) {
PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
// FIXME: I don't like much this weird special case here
if (arg instanceof Tree.ListedArgument) {
Tree.Expression expr = ((Tree.ListedArgument) arg).getExpression();
if (expr.getTerm() instanceof FunctionArgument) {
FunctionArgument farg = (FunctionArgument) expr.getTerm();
Type parameterType = getParameterType(argIndex);
if (isParameterJavaVariadic(argIndex) && parameterType.isSequential()) {
parameterType = gen.typeFact().getSequentialElementType(parameterType);
}
return gen.expressionGen().transform(farg, parameterType);
}
}
// special case for comprehensions which are not expressions
if (arg instanceof Tree.Comprehension) {
Type type = getParameterType(argIndex);
return gen.expressionGen().comprehensionAsSequential((Comprehension) arg, type);
}
return gen.expressionGen().transformArg(this, argIndex);
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension in project ceylon by eclipse.
the class AbstractTransformer method transformSpreadOrComprehension.
protected JCExpression transformSpreadOrComprehension(Tree.PositionalArgument arg, Type seqElemType) {
Type type = typeFact().getIterableType(seqElemType);
JCExpression jcExpression;
if (arg instanceof Tree.SpreadArgument) {
Tree.Expression expr = ((Tree.SpreadArgument) arg).getExpression();
if (typeFact().isIterableType(expr.getTypeModel())) {
// always boxed since it is a sequence
jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, type);
} else if (typeFact().isJavaIterableType(expr.getTypeModel())) {
// need to convert j.l.Iterable to a c.l.Iterable
jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, expr.getTypeModel());
if (willEraseToObject(expr.getTypeModel())) {
jcExpression = make().TypeCast(make().Type(syms().iterableType), jcExpression);
}
Type iteratedType = typeFact().getJavaIteratedType(expr.getTypeModel());
jcExpression = utilInvocation().toIterable(makeJavaType(iteratedType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(iteratedType), jcExpression);
} else if (typeFact().isJavaArrayType(expr.getTypeModel())) {
jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, type);
Type iteratedType = typeFact().getJavaArrayElementType(expr.getTypeModel());
if (typeFact().isJavaObjectArrayType(expr.getTypeModel())) {
jcExpression = utilInvocation().toIterable(makeJavaType(iteratedType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(iteratedType), jcExpression);
} else {
// primitive
jcExpression = utilInvocation().toIterable(jcExpression);
}
} else {
throw BugException.unhandledTypeCase(expr.getTypeModel());
}
} else {
jcExpression = expressionGen().transformComprehension((Comprehension) arg, type);
}
return jcExpression;
}
Aggregations