use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method applyJavaCoercions.
private JCExpression applyJavaCoercions(JCExpression ret, Type exprType, Type expectedType) {
if (expectedType == null)
return ret;
Type nonSimpleExprType = exprType;
exprType = simplifyType(exprType);
expectedType = simplifyType(expectedType);
if (isCeylonString(exprType) && isJavaCharSequence(expectedType)) {
// FIXME: only do this if boxed, or rather, do not box in the first place
if (isOptional(nonSimpleExprType)) {
Naming.SyntheticName varName = naming.temp();
JCExpression test = make().Binary(JCTree.Tag.NE, varName.makeIdent(), makeNull());
JCExpression convert = make().Apply(null, makeQualIdent(varName.makeIdent(), "toString"), List.<JCTree.JCExpression>nil());
JCExpression cond = make().Conditional(test, convert, makeNull());
JCExpression typeExpr = makeJavaType(typeFact().getObjectType());
return makeLetExpr(varName, null, typeExpr, ret, cond);
} else {
return make().Apply(null, makeQualIdent(ret, "toString"), List.<JCTree.JCExpression>nil());
}
}
// TODO: obsolete code?
if (isJavaCharSequence(exprType) && expectedType.isExactly(typeFact().getStringDeclaration().getType())) {
return make().Apply(null, makeQualIdent(ret, "toString"), List.<JCTree.JCExpression>nil());
}
// end of obsolete code
if (isCeylonArray(exprType) && isJavaArray(expectedType)) {
JCExpression result;
if (isOptional(nonSimpleExprType)) {
Naming.SyntheticName varName = naming.temp();
JCExpression test = make().Binary(JCTree.Tag.NE, varName.makeIdent(), makeNull());
JCExpression convert = make().Apply(null, makeQualIdent(varName.makeIdent(), "toArray"), List.<JCTree.JCExpression>nil());
JCExpression cond = make().Conditional(test, convert, makeNull());
JCExpression typeExpr = makeJavaType(typeFact().getObjectType());
result = makeLetExpr(varName, null, typeExpr, ret, cond);
} else {
result = make().Apply(null, makeQualIdent(ret, "toArray"), List.<JCTree.JCExpression>nil());
}
JCExpression targetType = makeJavaType(expectedType, JT_NO_PRIMITIVES);
return make().TypeCast(targetType, result);
}
if (isCeylonClassOrInterfaceModel(exprType) && isJavaClass(expectedType) && !(ret instanceof JCTree.JCFieldAccess && ret.toString().endsWith(".class"))) {
// FIXME: perhaps cast as RAW?
JCTree arg = ret;
// into Util.classErasure(.org.eclipse.ceylon.compiler.java.test.interop.LambdasJava.class)
while (arg instanceof JCTree.JCTypeCast) arg = ((JCTree.JCTypeCast) arg).getExpression();
if (arg instanceof JCTree.JCMethodInvocation) {
JCExpression methodSelect = ((JCTree.JCMethodInvocation) arg).getMethodSelect();
if (methodSelect instanceof JCTree.JCFieldAccess) {
JCTree.JCFieldAccess methodField = (JCTree.JCFieldAccess) methodSelect;
if (methodField.getIdentifier().toString().equals("typeLiteral") && methodField.getExpression() instanceof JCTree.JCFieldAccess && ((JCTree.JCFieldAccess) methodField.getExpression()).toString().equals(".ceylon.language.meta.typeLiteral_")) {
JCExpression classLiteral = extractClassLiteralFromTypeDescriptor(((JCTree.JCMethodInvocation) arg).getArguments().get(0));
if (classLiteral != null)
// FIXME: pass type arg explicitly?
return utilInvocation().classErasure(classLiteral);
}
}
}
// make sure erasure doesn't get in the way of calling this method
if (willEraseToObject(exprType))
ret = make().TypeCast(makeJavaType(typeFact().getClassOrInterfaceModelType(typeFact().getObjectType())), ret);
// FIXME: pass type arg explicitly?
return utilInvocation().javaClassForModel(ret);
}
return ret;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transform.
//
// Unary and Binary operators that can be overridden
//
// Unary operators
public JCExpression transform(Tree.NotOp op) {
// No need for an erasure cast since Term must be Boolean and we never need to erase that
JCExpression term = transformExpression(op.getTerm(), CodegenUtil.getBoxingStrategy(op), op.getTypeModel());
JCUnary jcu = at(op).Unary(JCTree.Tag.NOT, term);
return jcu;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
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.isJavaVariadicMethod()) {
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 = org.eclipse.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;
}
if (!expr.getSmall() && invocation.getParameterSmall(argIndex)) {
flags |= ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK;
}
boolean coerced = invocation.isParameterCoerced(argIndex);
if (coerced) {
flags |= ExpressionTransformer.EXPR_IS_COERCED;
if (invocation.isParameterJavaVariadic(argIndex) && type.isSequential()) {
type = typeFact().getSequentialElementType(type);
}
}
JCExpression ret = transformExpression(expr, boxingStrategy, type, flags);
// We can coerce most SAMs in transformExpression, EXCEPT invocation
// calls which we do here.
Term term = Decl.unwrapExpressionsUntilTerm(expr);
if (coerced && term instanceof Tree.InvocationExpression && isFunctionalResult(term.getTypeModel()) && checkForFunctionalInterface(type) != null) {
return transformFunctionalInterfaceBridge((Tree.InvocationExpression) term, ret, type);
}
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 org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method makeTopLevelValueOrFunctionLiteral.
private JCTree makeTopLevelValueOrFunctionLiteral(Tree.MemberLiteral expr) {
Declaration declaration = expr.getDeclaration();
JCExpression toplevelCall = makeTopLevelValueOrFunctionDeclarationLiteral(declaration);
if (!expr.getWantsDeclaration()) {
ListBuffer<JCExpression> closedTypeArgs = new ListBuffer<JCExpression>();
// expr is of type Function<Type,Arguments> or Value<Get,Set> so we can get its type like that
JCExpression reifiedType = makeReifiedTypeArgument(expr.getTypeModel().getTypeArgumentList().get(0));
closedTypeArgs.append(reifiedType);
if (Decl.isMethod(declaration)) {
// expr is of type Function<Type,Arguments> so we can get its arguments type like that
Type argumentsType = typeFact().getCallableTuple(expr.getTypeModel());
JCExpression reifiedArguments = makeReifiedTypeArgument(argumentsType);
closedTypeArgs.append(reifiedArguments);
if (expr.getTypeArgumentList() != null) {
java.util.List<Type> typeModels = expr.getTypeArgumentList().getTypeModels();
if (typeModels != null) {
JCExpression closedTypesExpr = getClosedTypesSequential(typeModels);
// must apply it
closedTypeArgs.append(closedTypesExpr);
}
}
} else {
JCExpression reifiedSet;
Type ptype;
if (!((Value) declaration).isVariable())
ptype = typeFact().getNothingType();
else
ptype = expr.getTypeModel().getTypeArgumentList().get(0);
reifiedSet = makeReifiedTypeArgument(ptype);
closedTypeArgs.append(reifiedSet);
}
toplevelCall = make().Apply(null, makeSelect(toplevelCall, "apply"), closedTypeArgs.toList());
// add cast
Type exprType = expr.getTypeModel().resolveAliases();
JCExpression typeClass = makeJavaType(exprType, JT_NO_PRIMITIVES);
JCExpression rawTypeClass = makeJavaType(exprType, JT_NO_PRIMITIVES | JT_RAW);
return make().TypeCast(typeClass, make().TypeCast(rawTypeClass, toplevelCall));
}
return toplevelCall;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.
the class ExpressionTransformer method transform.
public JCExpression transform(Tree.ScaleOp op) {
OperatorTranslation operator = Operators.getOperator(Tree.ScaleOp.class);
Tree.Term scalableTerm = op.getRightTerm();
Type scalableTermType = getSupertype(scalableTerm, typeFact().getScalableDeclaration());
SyntheticName scaleableName = naming.alias("scalable");
JCVariableDecl scaleable = makeVar(scaleableName, makeJavaType(scalableTermType, JT_NO_PRIMITIVES), transformExpression(scalableTerm, BoxingStrategy.BOXED, scalableTermType));
Tree.Term scaleTerm = op.getLeftTerm();
SyntheticName scaleName = naming.alias("scale");
Type scaleType = getTypeArgument(scalableTermType, 0);
JCExpression scaleValue;
if (isCeylonInteger(scaleTerm.getTypeModel()) && isCeylonFloat(scaleType)) {
// Disgusting coercion
scaleValue = transformExpression(scaleTerm, BoxingStrategy.UNBOXED, scalableTerm.getTypeModel());
scaleValue = boxType(scaleValue, typeFact().getFloatType());
} else {
scaleValue = transformExpression(scaleTerm, BoxingStrategy.BOXED, scaleType);
}
JCVariableDecl scale = makeVar(scaleName, makeJavaType(scaleType, JT_NO_PRIMITIVES), scaleValue);
at(op);
return make().LetExpr(List.<JCStatement>of(scale, scaleable), transformOverridableBinaryOperator(op, operator, OptimisationStrategy.NONE, scaleableName.makeIdent(), scaleName.makeIdent(), null, null, op.getTypeModel()).build());
}
Aggregations