Search in sources :

Example 1 with Comprehension

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);
    }
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCSwitch(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCSwitch) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Comprehension(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCCase(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCCase)

Example 2 with Comprehension

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);
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Comprehension(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension) FunctionArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionArgument)

Example 3 with Comprehension

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;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Comprehension(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension)

Aggregations

Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)3 Comprehension (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension)3 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)3 PositionalArgument (org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)2 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)2 Type (org.eclipse.ceylon.model.typechecker.model.Type)2 Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)1 FunctionArgument (org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionArgument)1 JCCase (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCCase)1 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)1 JCSwitch (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCSwitch)1 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)1 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)1