Search in sources :

Example 1 with BoxingStrategy

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());
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) Value(org.eclipse.ceylon.model.typechecker.model.Value) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)

Example 2 with BoxingStrategy

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());
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCReturn(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCReturn) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) QualifiedTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) StaticMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 3 with BoxingStrategy

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());
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 4 with BoxingStrategy

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;
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) BoxingStrategy(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

BoxingStrategy (org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy)4 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)4 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)4 Type (org.eclipse.ceylon.model.typechecker.model.Type)4 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)3 Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)2 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)2 Function (org.eclipse.ceylon.model.typechecker.model.Function)2 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)2 Value (org.eclipse.ceylon.model.typechecker.model.Value)2 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)1 QualifiedTypeExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression)1 StaticMemberOrTypeExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression)1 JCAnnotation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)1 JCReturn (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCReturn)1 JCTypeParameter (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter)1 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)1 FieldValue (org.eclipse.ceylon.model.loader.model.FieldValue)1 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)1 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)1