use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformSpreadArgument.
private ExpressionAndType transformSpreadArgument(SimpleInvocation invocation, int numArguments, int argIndex, BoxingStrategy boxingStrategy, Type parameterType) {
ExpressionAndType exprAndType;
final Type iteratedType = typeFact().getIteratedType(parameterType);
final JCExpression expr;
final JCExpression type;
// optimise "*javaArray.iterable" into "javaArray" for java variadic parameters, since we can pass them just along
if (invocation.isJavaMethod() && numArguments == argIndex + 1 && !invocation.isArgumentComprehension(argIndex)) {
Expression argumentExpression = invocation.getArgumentExpression(argIndex);
Term argument = Decl.unwrapExpressionsUntilTerm(argumentExpression);
if (argument instanceof Tree.QualifiedMemberExpression) {
Tree.QualifiedMemberExpression qualifiedMemberArgument = (Tree.QualifiedMemberExpression) argument;
if ("iterable".equals(qualifiedMemberArgument.getIdentifier().getText()) && isJavaArray(qualifiedMemberArgument.getPrimary().getTypeModel())) {
// just pass the array as-is
// we don't care at all about unboxing or casting since we can't be dealing with boxing
// and we generate our own cast, at least for non-primitive arrays where it may be ambiguous,
// we could avoid the cast for non-type-parameter and non-Object arrays, but that's more expensive
// to check for
JCExpression primary = transformExpression(qualifiedMemberArgument.getPrimary());
type = makeJavaType(typeFact().getSequenceType(iteratedType).getType());
if (isJavaObjectArray(qualifiedMemberArgument.getPrimary().getTypeModel())) {
expr = make().TypeCast(makeJavaType(qualifiedMemberArgument.getPrimary().getTypeModel()), primary);
} else {
expr = primary;
}
return new ExpressionAndType(expr, type);
}
}
}
// invoking f(a, *b), where declared f(A a, B* b)
// we can have several remaining arguments and the last one is spread
List<JCExpression> x = List.<JCExpression>nil();
for (int ii = argIndex; ii < numArguments; ii++) {
JCExpression argExpr = invocation.getTransformedArgumentExpression(ii);
// the last parameter is spread and must be put first
if (ii < numArguments - 1) {
x = x.append(argExpr);
} else {
// convert to a Sequential if required
Type argType = invocation.getArgumentType(ii);
if (!typeFact().isSequentialType(argType))
argExpr = iterableToSequential(argExpr);
x = x.prepend(argExpr);
}
}
if (invocation.isJavaMethod()) {
// collect all the initial arguments and wrap into a Java array
// first arg is the spread part
JCExpression last = x.head;
// remove it from x
x = x.tail;
Type lastType = invocation.getArgumentType(numArguments - 1);
// must translate it into a Util call
expr = sequenceToJavaArray(invocation, last, parameterType, boxingStrategy, lastType, x);
} else {
JCExpression typeExpr = makeJavaType(iteratedType, JT_TYPE_ARGUMENT);
JCExpression sequentialExpr = utilInvocation().sequentialInstance(typeExpr, makeReifiedTypeArgument(iteratedType), x.head, x.tail);
if (invocation.isParameterVariadicPlus(argIndex)) {
expr = utilInvocation().castSequentialToSequence(sequentialExpr, iteratedType);
} else {
expr = sequentialExpr;
}
}
type = makeJavaType(typeFact().getSequenceType(iteratedType).getType());
exprAndType = new ExpressionAndType(expr, type);
return exprAndType;
}
use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformArg.
protected final JCExpression transformArg(SimpleInvocation invocation, int argIndex) {
final Tree.Term expr = invocation.getArgumentExpression(argIndex);
if (invocation.hasParameter(argIndex)) {
Type type = invocation.getParameterType(argIndex);
if (invocation.isParameterSequenced(argIndex) && // Java methods need their underlying type preserved
!invocation.isJavaMethod()) {
if (!invocation.isArgumentSpread(argIndex)) {
// If the parameter is sequenced and the argument is not ...
// then the expected type of the *argument* is the type arg to Iterator
type = typeFact().getIteratedType(type);
} else if (invocation.getArgumentType(argIndex).getSupertype(typeFact().getSequentialDeclaration()) == null) {
// On the other hand, if the parameter is sequenced and the argument is spread,
// but not sequential, then transformArguments() will use getSequence(),
// so we only need to expect an Iterable type
type = com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType(typeFact().getIterableDeclaration(), typeFact().getIteratedType(type), typeFact().getIteratedAbsentType(type));
}
}
BoxingStrategy boxingStrategy = invocation.getParameterBoxingStrategy(argIndex);
int flags = 0;
if (!invocation.isParameterRaw(argIndex))
flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_NOT_RAW;
if (invocation.isParameterWithConstrainedTypeParameters(argIndex))
flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS;
if (invocation.isParameterWithDependentCovariantTypeParameters(argIndex))
flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS;
if (invocation.erasedArgument(unwrapExpressionUntilTerm(expr))) {
flags |= EXPR_DOWN_CAST;
}
JCExpression ret = transformExpression(expr, boxingStrategy, type, flags);
return ret;
} else {
// Overloaded methods don't have a reference to a parameter
// so we have to treat them differently. Also knowing it's
// overloaded we know we're dealing with Java code so we unbox
Type type = expr.getTypeModel();
return expressionGen().transformExpression(expr, BoxingStrategy.UNBOXED, type);
}
}
use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method appendVarsForReifiedTypeArguments.
private void appendVarsForReifiedTypeArguments() {
java.util.List<JCExpression> reifiedTypeArgs = gen.makeReifiedTypeArguments(producedReference);
int index = 0;
for (JCExpression reifiedTypeArg : reifiedTypeArgs) {
Naming.SyntheticName argName = reifiedTypeArgName(index);
JCVariableDecl varDecl = gen.makeVar(argName, gen.makeTypeDescriptorType(), reifiedTypeArg);
this.vars.append(varDecl);
index++;
}
}
use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method appendDefaulted.
private final void appendDefaulted(Parameter param, JCExpression argExpr) {
// we can't just generate types like Foo<?> if the target type param is not raw because the bounds will
// not match, so we go raw
int flags = JT_RAW;
if (getNamedParameterBoxingStrategy(param) == BoxingStrategy.BOXED) {
flags |= JT_TYPE_ARGUMENT;
}
Type type = gen.getTypeForParameter(param, producedReference, gen.TP_TO_BOUND);
Naming.SyntheticName argName = argName(param);
JCExpression typeExpr = gen.makeJavaType(type, flags);
JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, argExpr);
bind(param, argName, gen.makeJavaType(type, flags), List.<JCStatement>of(varDecl));
}
use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class ImportScanner method visitClassDef.
@Override
public void visitClassDef(JCClassDecl that) {
// we have to do field types, method signatures, type parameters and extends/implements, that's all
visit(that.defs);
visitType(that.extending);
for (JCExpression impl : that.implementing) {
visitType(impl);
}
visitTypeParameters(that.typarams);
}
Aggregations