Search in sources :

Example 1 with PositionalArgument

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument 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 PositionalArgument

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument in project ceylon by eclipse.

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) {
                        if (((Class) decl).isByte()) {
                            at(ce);
                            try {
                                long value = literalValue((Tree.NaturalLiteral) term).longValue();
                                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(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) TreeUtil.unwrapExpressionUntilTerm(org.eclipse.ceylon.compiler.typechecker.tree.TreeUtil.unwrapExpressionUntilTerm) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 3 with PositionalArgument

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument in project ceylon by eclipse.

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(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension) 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)

Example 4 with PositionalArgument

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument in project ceylon by eclipse.

the class TypeArgumentInference method getInferredTypeArgsForStaticReference.

/**
 * Infer type arguments for the qualifying type in a
 * static method reference that is directly invoked.
 * This method does not correctly handle stuff like
 * constructors or Java static methods.
 *
 * @param that the invocation
 * @param type the type whose type arguments we're
 *             inferring (the qualifying type)
 * @param receiverType
 */
List<Type> getInferredTypeArgsForStaticReference(Tree.InvocationExpression that, TypeDeclaration type, Type receiverType, Tree.MemberOrTypeExpression primary) {
    Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
    Declaration invoked = primary.getDeclaration();
    if (pal == null) {
        return null;
    } else {
        if (invoked instanceof Functional) {
            List<PositionalArgument> args = pal.getPositionalArguments();
            Functional fun = (Functional) invoked;
            List<ParameterList> parameterLists = fun.getParameterLists();
            if (args.isEmpty() || parameterLists.isEmpty()) {
                return null;
            } else {
                // a static method ref invocation has exactly
                // one meaningful argument (the instance of
                // the receiving type)
                Tree.PositionalArgument arg = args.get(0);
                if (arg == null) {
                    return null;
                } else {
                    Type at = arg.getTypeModel();
                    Type tt = type.getType();
                    List<TypeParameter> typeParams = type.getTypeParameters();
                    List<Type> typeArgs = new ArrayList<Type>(typeParams.size());
                    for (TypeParameter tp : typeParams) {
                        Type it = inferTypeArg(tp, tt, at, // TODO: is this 100% correct?
                        false, arg);
                        if (it == null || it.containsUnknowns()) {
                            that.addError("could not infer type argument from given arguments: type parameter '" + tp.getName() + "' could not be inferred");
                        }
                        typeArgs.add(it);
                    }
                    return constrainInferredTypes(typeParams, typeArgs, receiverType, invoked);
                }
            }
        } else {
            return null;
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 5 with PositionalArgument

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument in project ceylon by eclipse.

the class ExpressionVisitor method visit.

/**
 * Typecheck an invocation expression. Note that this
 * is a tricky process involving type argument inference,
 * anonymous function parameter type inference, function
 * reference type argument inference, Java overload
 * resolution, and argument type checking, and it all
 * has to happen in exactly the right order, which is
 * not at all the natural order for walking the tree.
 */
@Override
public void visit(Tree.InvocationExpression that) {
    // assign some provisional argument types
    // that will help with overload resolution
    visitInvocationPositionalArgs(that);
    // make a first attempt at resolving the
    // invoked reference (but we don't have
    // all the needed types yet)
    Tree.Primary p = that.getPrimary();
    p.visit(this);
    // set up the parameter lists of all
    // argument anonymous functions with
    // inferred (missing) parameter lists
    createAnonymousFunctionParameters(that);
    // named argument lists are the easy
    // case because they don't support
    // anonymous functions with inferred
    // parameter lists
    Tree.NamedArgumentList nal = that.getNamedArgumentList();
    if (nal != null) {
        inferParameterTypes(p, nal);
        nal.visit(this);
    }
    Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
    int argCount = 0;
    boolean[] delayed = null;
    if (pal != null) {
        List<PositionalArgument> args = pal.getPositionalArguments();
        argCount = args.size();
        // infer parameter types as far as we
        // can without having the inferred type
        // parameters of the primary
        delayed = inferParameterTypes(p, pal, false);
        // which parameter type inference failed
        for (int j = 0; j < argCount; j++) {
            if (!delayed[j]) {
                Tree.PositionalArgument pa = args.get(j);
                if (pa != null) {
                    pa.visit(this);
                }
            }
        }
    }
    // assign some additional types that
    // we will use for overload resolution
    visitInvocationPositionalArgs(that);
    // now here's where overloading is
    // finally resolved and then type
    // argments are inferred
    visitInvocationPrimary(that);
    if (pal != null) {
        List<PositionalArgument> args = pal.getPositionalArguments();
        // now infer the remaining parameter
        // types
        inferParameterTypes(p, pal, true);
        // missed the first time round
        for (int j = 0; j < argCount; j++) {
            if (delayed[j]) {
                Tree.PositionalArgument pa = args.get(j);
                if (pa != null) {
                    pa.visit(this);
                }
            }
        }
    }
    // assignable to parameters)
    if (isIndirectInvocation(that)) {
        visitIndirectInvocation(that);
    } else {
        visitDirectInvocation(that);
    }
}
Also used : CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) AnalyzerUtil.checkCasesDisjoint(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint) ModelUtil.argumentSatisfiesEnumeratedConstraint(org.eclipse.ceylon.model.typechecker.model.ModelUtil.argumentSatisfiesEnumeratedConstraint)

Aggregations

PositionalArgument (org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)7 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)6 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)4 Comprehension (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Comprehension)3 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)2 Type (org.eclipse.ceylon.model.typechecker.model.Type)2 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)2 ArrayList (java.util.ArrayList)1 AnalyzerUtil.checkCasesDisjoint (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint)1 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)1 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)1 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)1 Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)1 FunctionArgument (org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionArgument)1 SequencedArgument (org.eclipse.ceylon.compiler.typechecker.tree.Tree.SequencedArgument)1 Term (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term)1 TreeUtil.unwrapExpressionUntilTerm (org.eclipse.ceylon.compiler.typechecker.tree.TreeUtil.unwrapExpressionUntilTerm)1 JCCase (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCCase)1 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)1 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)1