use of org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy in project ceylon by eclipse.
the class NamedArgumentInvocation method bindAttributeArgument.
private void bindAttributeArgument(Tree.AttributeArgument attrArg, Parameter declaredParam, Naming.SyntheticName argName) {
ListBuffer<JCStatement> statements;
final Value model = attrArg.getDeclarationModel();
final String name = model.getName();
String className = Naming.getAttrClassName(model, 0);
final List<JCTree> attrClass = gen.gen().transformAttribute(model, name, className, null, attrArg.getBlock(), attrArg.getSpecifierExpression(), null, null);
TypedReference typedRef = gen.getTypedReference(model);
TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
Type nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef);
Type type = parameterType(declaredParam, model.getType(), 0);
final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam);
JCExpression initValue = gen.make().Apply(null, gen.makeSelect(gen.makeUnquotedIdent(className), Naming.getGetterName(model)), List.<JCExpression>nil());
initValue = gen.expressionGen().applyErasureAndBoxing(initValue, nonWideningType, !CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration()), boxType, type);
JCTree.JCVariableDecl var = gen.make().VarDef(gen.make().Modifiers(FINAL, List.<JCAnnotation>nil()), argName.asName(), gen.makeJavaType(type, boxType == BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), initValue);
statements = toStmts(attrArg, attrClass).append(var);
bind(declaredParam, argName, gen.makeJavaType(type, boxType == BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), statements.toList());
}
use of org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy in project ceylon by eclipse.
the class NamedArgumentInvocation method bindMethodArgument.
private void bindMethodArgument(Tree.MethodArgument methodArg, Parameter declaredParam, Naming.SyntheticName argName) {
ListBuffer<JCStatement> statements;
Function model = methodArg.getDeclarationModel();
List<JCStatement> body;
boolean prevNoExpressionlessReturn = gen.statementGen().noExpressionlessReturn;
boolean prevSyntheticClassBody = gen.expressionGen().withinSyntheticClassBody(Decl.isMpl(model) || gen.expressionGen().isWithinSyntheticClassBody());
try {
gen.expressionGen().withinSyntheticClassBody(true);
gen.statementGen().noExpressionlessReturn = AbstractTransformer.isAnything(model.getType());
if (methodArg.getBlock() != null) {
body = gen.statementGen().transformBlock(methodArg.getBlock());
if (!methodArg.getBlock().getDefinitelyReturns()) {
if (AbstractTransformer.isAnything(model.getType())) {
body = body.append(gen.make().Return(gen.makeNull()));
} else {
body = body.append(gen.make().Return(gen.makeErroneous(methodArg.getBlock(), "compiler bug: non-void method does not definitely return")));
}
}
} else {
Expression expr = methodArg.getSpecifierExpression().getExpression();
BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(model);
Type type = model.getType();
JCExpression transExpr = gen.expressionGen().transformExpression(expr, boxing, type);
JCReturn returnStat = gen.make().Return(transExpr);
body = List.<JCStatement>of(returnStat);
}
} finally {
gen.expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
gen.statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
}
Type callableType = model.appliedReference(null, Collections.<Type>emptyList()).getFullType();
CallableBuilder callableBuilder = CallableBuilder.methodArgument(gen.gen(), methodArg, model, callableType, Collections.singletonList(methodArg.getParameterLists().get(0)), gen.classGen().transformMplBody(methodArg.getParameterLists(), model, body));
JCExpression callable = callableBuilder.build();
gen.at(methodArg);
JCExpression typeExpr = gen.makeJavaType(callableType, JT_RAW);
JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, callable);
statements = ListBuffer.<JCStatement>of(varDecl);
bind(declaredParam, argName, gen.makeJavaType(callableType), statements.toList());
}
use of org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy in project ceylon by eclipse.
the class NamedArgumentInvocation method bindSpecifiedArgument.
private void bindSpecifiedArgument(Tree.SpecifiedArgument specifiedArg, Parameter declaredParam, Naming.SyntheticName argName) {
ListBuffer<JCStatement> statements;
Tree.Expression expr = specifiedArg.getSpecifierExpression().getExpression();
Type type = parameterType(declaredParam, expr.getTypeModel(), AbstractTransformer.TP_TO_BOUND);
final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam);
int jtFlags = 0;
int exprFlags = 0;
if (boxType == BoxingStrategy.BOXED)
jtFlags |= JT_TYPE_ARGUMENT;
if (!isParameterRaw(declaredParam)) {
exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_NOT_RAW;
}
if (isParameterWithConstrainedTypeParameters(declaredParam)) {
exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS;
// 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
jtFlags |= JT_RAW;
}
if (isParameterWithDependentCovariantTypeParameters(declaredParam)) {
exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS;
}
if (erasedArgument(TreeUtil.unwrapExpressionUntilTerm(expr))) {
exprFlags |= ExpressionTransformer.EXPR_DOWN_CAST;
}
if (CodegenUtil.downcastForSmall(expr, specifiedArg.getParameter().getModel())) {
exprFlags |= ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK;
}
JCExpression typeExpr = gen.makeJavaType(type, jtFlags);
gen.at(specifiedArg);
JCExpression argExpr = gen.expressionGen().transformExpression(expr, boxType, type, exprFlags);
gen.at(specifiedArg);
JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, argExpr);
statements = ListBuffer.<JCStatement>of(varDecl);
bind(declaredParam, argName, gen.makeJavaType(type, jtFlags), statements.toList());
}
use of org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy in project ceylon by eclipse.
the class CallableBuilder method makeFunctionalInterfaceMethod.
public MethodDefinitionBuilder makeFunctionalInterfaceMethod() {
FunctionOrValue methodOrValue = (FunctionOrValue) functionalInterfaceMethod.getDeclaration();
MethodDefinitionBuilder callMethod = MethodDefinitionBuilder.method(gen, methodOrValue, 0);
callMethod.isOverride(true);
callMethod.modifiers(Flags.PUBLIC);
Type returnType = functionalInterfaceMethod.getType();
if (methodOrValue instanceof Value || !((Function) methodOrValue).isDeclaredVoid()) {
int flags = CodegenUtil.isUnBoxed(methodOrValue) ? 0 : JT_NO_PRIMITIVES;
callMethod.resultType(gen.makeJavaType(returnType, flags), null);
}
ListBuffer<JCExpression> args = new ListBuffer<>();
// this depends on how we're declared to Java
boolean turnedToRaw = gen.rawSupertype(functionalInterface, JT_EXTENDS | JT_CLASS_NEW);
boolean variadic = false;
if (methodOrValue instanceof Function) {
int index = 0;
java.util.List<Parameter> parameters = ((Function) methodOrValue).getFirstParameterList().getParameters();
for (int i = 0; i < parameters.size(); i++) {
Parameter param = parameters.get(i);
Parameter targetParam = paramLists.getParameters().get(i);
TypedReference typedParameter = functionalInterfaceMethod.getTypedParameter(param);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(gen, param.getName());
Type paramType = typedParameter.getType();
if (param.isSequenced()) {
paramType = gen.typeFact().getSequentialElementType(paramType);
variadic = true;
}
// This is very special-casey, but is required and I haven't found more subtle
if (turnedToRaw && gen.simplifyType(param.getType()).isTypeParameter()) {
paramType = gen.typeFact().getObjectType();
}
long flags = Flags.FINAL;
// that looks fishy, perhaps we need to call non-widening rules instead
JCExpression javaType = gen.makeJavaType(paramType, paramType.isRaw() ? AbstractTransformer.JT_RAW : 0);
if (param.isSequenced()) {
flags |= Flags.VARARGS;
javaType = gen.make().TypeArray(javaType);
}
pdb.type(new TransformedType(javaType));
pdb.modifiers(flags);
callMethod.parameter(pdb);
JCExpression arg;
if (param.isSequenced()) {
arg = gen.javaVariadicToSequential(paramType, param);
} else {
arg = gen.makeUnquotedIdent(param.getName());
Type argumentType = parameterTypes.get(index);
if (gen.isOptional(paramType) && argumentType.isSubtypeOf(gen.typeFact().getObjectType()) && !targetParam.getModel().hasUncheckedNullType()) {
arg = gen.utilInvocation().checkNull(arg);
}
Type simpleParamType = gen.simplifyType(paramType);
// make unboxed java strings pass for ceylon strings so we can box them
boolean unboxedString = gen.isJavaStringExactly(simpleParamType);
if (unboxedString)
simpleParamType = gen.typeFact().getStringType();
BoxingStrategy boxingStrategy = BoxingStrategy.BOXED;
// in rare cases we don't want boxes
if (unboxedString && gen.isJavaStringExactly(argumentType))
boxingStrategy = BoxingStrategy.UNBOXED;
arg = gen.expressionGen().applyErasureAndBoxing(arg, simpleParamType, !(CodegenUtil.isUnBoxed(param.getModel()) || unboxedString), boxingStrategy, argumentType);
}
args.append(arg);
index++;
}
} else {
// no-arg getter
}
String callMethodName;
if (variadic)
callMethodName = Naming.getCallableVariadicMethodName();
else
callMethodName = Naming.getCallableMethodName();
JCExpression call = gen.make().Apply(null, gen.makeUnquotedIdent(callMethodName), args.toList());
JCStatement body;
if (methodOrValue instanceof Function && ((Function) methodOrValue).isDeclaredVoid())
body = gen.make().Exec(call);
else {
Type callableReturnType = gen.getReturnTypeOfCallable(typeModel);
Type simpleReturnType = gen.simplifyType(returnType);
boolean unboxed = CodegenUtil.isUnBoxed(methodOrValue) || gen.isJavaStringExactly(simpleReturnType);
if (unboxed) {
call = gen.expressionGen().applyErasureAndBoxing(call, callableReturnType, true, BoxingStrategy.UNBOXED, returnType);
} else if (callableReturnType.isNull()) {
// if the callable returns null and the SAM does not, we need a cast
call = gen.expressionGen().applyErasureAndBoxing(call, callableReturnType, true, BoxingStrategy.INDIFFERENT, returnType);
}
body = gen.make().Return(call);
}
callMethod.body(body);
return callMethod;
}
Aggregations