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);
}
}
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;
}
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;
}
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;
}
}
}
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);
}
}
Aggregations