use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term in project ceylon by eclipse.
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.isJavaVariadicMethod() && 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().isJavaArrayType(argType)) {
String methodName;
if (typeFact().getJavaIntArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.IntArray.getIterable";
} else if (typeFact().getJavaShortArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.ShortArray.getIterable";
} else if (typeFact().getJavaLongArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.LongArray.getIterable";
} else if (typeFact().getJavaByteArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.ByteArray.getIterable";
} else if (typeFact().getJavaBooleanArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.BooleanArray.getIterable";
} else if (typeFact().getJavaCharArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.CharArray.getIterable";
} else if (typeFact().getJavaFloatArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.FloatArray.getIterable";
} else if (typeFact().getJavaDoubleArrayDeclaration().equals(argType.getDeclaration())) {
methodName = "org.eclipse.ceylon.compiler.java.language.DoubleArray.getIterable";
} else {
methodName = "org.eclipse.ceylon.compiler.java.language.ObjectArray.getIterable";
}
argExpr = make().Apply(null, naming.makeQuotedQualIdentFromString(methodName), List.<JCExpression>of(argExpr));
argExpr = iterableToSequential(argExpr);
} else if (typeFact().isSequentialType(argType)) {
// we're good
} else if (typeFact().isIterableType(argType)) {
argExpr = iterableToSequential(argExpr);
} else if (typeFact().isJavaIterableType(argType)) {
argExpr = utilInvocation().toIterable(makeJavaType(iteratedType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(iteratedType), argExpr);
argExpr = iterableToSequential(argExpr);
}
x = x.prepend(argExpr);
}
}
if (invocation.isJavaVariadicMethod()) {
// 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 org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term in project ceylon by eclipse.
the class ExpressionTransformer method transformLet.
// this one trusts the expected type
private JCExpression transformLet(LetExpression op, Type expectedType) {
ListBuffer<JCStatement> defs = new ListBuffer<JCStatement>();
for (Tree.Statement stmt : op.getLetClause().getVariables()) {
defs.addAll(statementGen().transformVariableOrDestructure(stmt));
}
Tree.Term term = op.getLetClause().getExpression().getTerm();
BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(term);
JCExpression expr = transformExpression(term, boxingStrategy, expectedType);
at(op);
if (isAnything(op.getTypeModel()) && CodegenUtil.isUnBoxed(term)) {
defs.add(make().Exec(expr));
expr = makeNull();
}
return make().LetExpr(defs.toList(), expr);
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term in project ceylon by eclipse.
the class BoxingDeclarationVisitor method visit.
@Override
public void visit(SpecifierStatement that) {
TypedDeclaration declaration = that.getDeclaration();
Function optimisedDeclaration = null;
// make sure we detect the shortcut refinement inlining cases
if (declaration instanceof Function) {
if (that.getSpecifierExpression() != null && that.getSpecifierExpression() instanceof LazySpecifierExpression == false) {
Tree.Term term = Decl.unwrapExpressionsUntilTerm(that.getSpecifierExpression().getExpression());
if (term != null && term instanceof Tree.FunctionArgument) {
optimisedDeclaration = ((Tree.FunctionArgument) term).getDeclarationModel();
this.optimisedMethodSpecifiersToMethods.put(optimisedDeclaration, (Function) declaration);
}
}
}
try {
super.visit(that);
} finally {
if (optimisedDeclaration != null)
this.optimisedMethodSpecifiersToMethods.remove(optimisedDeclaration);
}
if (declaration == null)
return;
if (declaration instanceof Function) {
visitMethod((Function) declaration, that);
} else if (declaration instanceof Value)
visitAttributeOrParameter(declaration, that);
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term in project ceylon by eclipse.
the class BoxingDeclarationVisitor method visit.
@Override
public void visit(Tree.MethodDeclaration that) {
super.visit(that);
Function model = that.getDeclarationModel();
visitMethod(that.getDeclarationModel(), that);
SpecifierExpression specifierExpression = that.getSpecifierExpression();
// See ClassTransformer.transformSpecifiedMethodBody for this logic
if (model != null && model.isMember() && specifierExpression != null && specifierExpression.getExpression() != null) {
boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
Term term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
if (!isLazy && term instanceof Tree.FunctionArgument) {
// this is inlined for member methods, so the term should inherit our boxing specs
Function specifierModel = ((Tree.FunctionArgument) term).getDeclarationModel();
if (specifierModel != null) {
specifierModel.setUnboxed(model.getUnboxed());
}
}
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term in project ceylon by eclipse.
the class BoxingVisitor method visit.
@Override
public void visit(Expression that) {
Stack<Boolean> npebs = setPEB();
super.visit(that);
resetPEB(npebs);
Term term = that.getTerm();
propagateFromTerm(that, term);
// which will need to be marked boxed
if (term instanceof MemberOrTypeExpression) {
Tree.MemberOrTypeExpression expr = (Tree.MemberOrTypeExpression) term;
if (expr.getDeclaration() instanceof Function) {
that.setUnboxed(false);
}
}
}
Aggregations