Search in sources :

Example 1 with PositionalArgument

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

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 {
                    Type type = typeFact().getIterableType(seqElemType);
                    spread = true;
                    if (arg instanceof Tree.SpreadArgument) {
                        Tree.Expression expr = ((Tree.SpreadArgument) arg).getExpression();
                        // always boxed since it is a sequence
                        jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, type);
                    } else {
                        jcExpression = expressionGen().transformComprehension((Comprehension) arg, type);
                    }
                }
            } 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(null, make().Type(syms().objectType));
            mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, Unfix.$index$.toString()).type(make().Type(syms().intType), null));
            JCSwitch swtch;
            try (SavedPosition sp = noPosition()) {
                ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
                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 make().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 {
            // use a LazyInvokingIterable
            ListBuffer<JCTree> methods = new ListBuffer<JCTree>();
            MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$lookup$.toString());
            mdb.isOverride(true);
            mdb.modifiers(PROTECTED | FINAL);
            mdb.resultType(null, naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"));
            mdb.body(make().Return(make().Apply(List.<JCExpression>nil(), naming.makeQualIdent(make().Type(syms().methodHandlesType), "lookup"), List.<JCExpression>nil())));
            methods.add(mdb.build());
            mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$invoke$.toString());
            mdb.isOverride(true);
            mdb.modifiers(PROTECTED | FINAL);
            mdb.resultType(null, make().Type(syms().objectType));
            mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, "handle").type(make().Type(syms().methodHandleType), null));
            mdb.body(make().Return(make().Apply(List.<JCExpression>nil(), naming.makeQualIdent(naming.makeUnquotedIdent("handle"), "invokeExact"), List.<JCExpression>of(naming.makeThis()))));
            methods.add(mdb.build());
            i = 0;
            for (JCStatement expr : returns) {
                mdb = MethodDefinitionBuilder.systemMethod(this, "$" + i);
                i++;
                mdb.modifiers(PRIVATE | FINAL);
                mdb.resultType(null, make().Type(syms().objectType));
                mdb.body(expr);
                methods.add(mdb.build());
            }
            return make().NewClass(null, //of(makeJavaType(seqElemType), makeJavaType(absentType)),
            List.<JCExpression>nil(), make().TypeApply(make().QualIdent(syms.ceylonLazyInvokingIterableType.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()));
        }
    } finally {
        expressionGen().withinSyntheticClassBody(old);
    }
}
Also used : ListBuffer(com.sun.tools.javac.util.ListBuffer) PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCCase(com.sun.tools.javac.tree.JCTree.JCCase) JCTree(com.sun.tools.javac.tree.JCTree) Comprehension(com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Comprehension(com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension) PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)

Example 2 with PositionalArgument

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

the class NamedArgumentInvocation method isSpread.

@Override
protected boolean isSpread() {
    java.util.List<PositionalArgument> args = getPositional().getPositionalArguments();
    if (args.isEmpty())
        return false;
    PositionalArgument last = args.get(args.size() - 1);
    return last instanceof Tree.SpreadArgument || last instanceof Tree.Comprehension;
}
Also used : Comprehension(com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension) PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree)

Example 3 with PositionalArgument

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

the class ExpressionTransformer method checkForByteLiterals.

private JCExpression checkForByteLiterals(Tree.InvocationExpression ce) {
    // same test as in BoxingVisitor.isByteLiteral()
    if (ce.getPrimary() instanceof Tree.BaseTypeExpression && ce.getPositionalArgumentList() != null) {
        java.util.List<Tree.PositionalArgument> positionalArguments = ce.getPositionalArgumentList().getPositionalArguments();
        if (positionalArguments.size() == 1) {
            PositionalArgument argument = positionalArguments.get(0);
            if (argument instanceof Tree.ListedArgument && ((Tree.ListedArgument) argument).getExpression() != null) {
                Term term = ((Tree.ListedArgument) argument).getExpression().getTerm();
                boolean negative = false;
                if (term instanceof Tree.NegativeOp) {
                    negative = true;
                    term = ((Tree.NegativeOp) term).getTerm();
                }
                if (term instanceof Tree.NaturalLiteral) {
                    Declaration decl = ((Tree.BaseTypeExpression) ce.getPrimary()).getDeclaration();
                    if (decl instanceof Class) {
                        String name = decl.getQualifiedNameString();
                        if (name.equals("ceylon.language::Byte")) {
                            at(ce);
                            try {
                                long value = literalValue((Tree.NaturalLiteral) term);
                                if (negative)
                                    value = -value;
                                // assignment, not for method calls, so it's simpler to always cast
                                return make().TypeCast(syms().byteType, make().Literal(value));
                            } catch (ErroneousException e) {
                                // replaced with a throw.
                                return e.makeErroneous(this);
                            }
                        }
                    }
                }
            }
        }
    }
    return null;
}
Also used : PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) TreeUtil.unwrapExpressionUntilTerm(com.redhat.ceylon.compiler.typechecker.tree.TreeUtil.unwrapExpressionUntilTerm) Term(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)3 PositionalArgument (com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)3 JCTree (com.sun.tools.javac.tree.JCTree)3 Comprehension (com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension)2 Term (com.redhat.ceylon.compiler.typechecker.tree.Tree.Term)1 TreeUtil.unwrapExpressionUntilTerm (com.redhat.ceylon.compiler.typechecker.tree.TreeUtil.unwrapExpressionUntilTerm)1 Class (com.redhat.ceylon.model.typechecker.model.Class)1 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)1 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)1 Type (com.redhat.ceylon.model.typechecker.model.Type)1 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)1 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)1 JCCase (com.sun.tools.javac.tree.JCTree.JCCase)1 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)1 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)1 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)1 JCSwitch (com.sun.tools.javac.tree.JCTree.JCSwitch)1 ListBuffer (com.sun.tools.javac.util.ListBuffer)1