Search in sources :

Example 26 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class CallableBuilder method build.

public JCExpression build() {
    // Generate a subclass of Callable
    ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
    gen.at(node);
    if (parameterDefaultValueMethods != null) {
        for (MethodDefinitionBuilder mdb : parameterDefaultValueMethods) {
            classBody.append(mdb.build());
        }
    }
    transformation.appendMethods(classBody);
    gen.at(node);
    JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0, annotations != null ? annotations : List.<JCAnnotation>nil()), classBody.toList());
    int variadicIndex = isVariadic ? numParams - 1 : -1;
    Type callableType;
    if (typeModel.isTypeConstructor()) {
        callableType = typeModel.getDeclaration().getExtendedType();
    } else {
        callableType = typeModel;
    }
    JCNewClass callableInstance;
    if (functionalInterface == null) {
        callableInstance = gen.at(node).NewClass(null, null, gen.makeJavaType(callableType, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(0)), gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(1)), gen.make().Literal(callableType.asString(true)), gen.make().TypeCast(gen.syms().shortType, gen.makeInteger(variadicIndex))), classDef);
    } else {
        callableInstance = gen.make().NewClass(null, null, gen.makeJavaType(functionalInterface, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>nil(), classDef);
    }
    JCExpression result;
    if (typeModel.isTypeConstructor()) {
        result = buildTypeConstructor(callableType, callableInstance);
    } else {
        result = callableInstance;
    }
    gen.at(null);
    if (instanceSubstitution != null) {
        instanceSubstitution.close();
    }
    return result;
}
Also used : JCClassDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCClassDecl) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)

Example 27 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class CallableBuilder method makeCallableCallParam.

private ParameterDefinitionBuilder makeCallableCallParam(long flags, int ii) {
    JCExpression type = gen.makeIdent(gen.syms().objectType);
    if ((flags & Flags.VARARGS) != 0) {
        type = gen.make().TypeArray(type);
    }
    ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(gen, getParamName(ii));
    pdb.modifiers(Flags.FINAL | flags);
    pdb.type(new TransformedType(type));
    return pdb;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)

Example 28 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class CallableBuilder method methodReference.

/**
 * Constructs an {@code AbstractCallable} suitable for wrapping a
 * method reference. For example:
 * <pre>
 *   void someMethod() { ... }
 *   Anything() ref = someMethod;
 * </pre>
 */
public static JCExpression methodReference(CeylonTransformer gen, final Tree.StaticMemberOrTypeExpression forwardCallTo, ParameterList parameterList, Type expectedType, Type callableType, boolean useParameterTypesFromCallableModel) {
    ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
    CallableBuilder cb = new CallableBuilder(gen, forwardCallTo, callableType, parameterList);
    cb.parameterTypes = useParameterTypesFromCallableModel ? cb.getParameterTypesFromCallableModel() : cb.getParameterTypesFromParameterModels();
    Naming.SyntheticName instanceFieldName;
    boolean instanceFieldIsBoxed = false;
    if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression && !ExpressionTransformer.isSuperOrSuperOf(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary()) && !ExpressionTransformer.isPackageQualified((Tree.QualifiedMemberOrTypeExpression) forwardCallTo)) {
        if ((((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SpreadOp)) {
            instanceFieldIsBoxed = true;
            instanceFieldName = null;
        } else {
            Tree.QualifiedMemberOrTypeExpression qmte = (Tree.QualifiedMemberOrTypeExpression) forwardCallTo;
            boolean prevCallableInv = gen.expressionGen().withinSyntheticClassBody(true);
            try {
                instanceFieldName = gen.naming.synthetic(Unfix.$instance$);
                int varTypeFlags = Decl.isPrivateAccessRequiringCompanion(qmte) ? JT_COMPANION : 0;
                Type primaryType;
                if (Decl.isValueTypeDecl(qmte.getPrimary().getTypeModel())) {
                    primaryType = qmte.getPrimary().getTypeModel();
                } else {
                    primaryType = qmte.getTarget().getQualifyingType();
                }
                if (((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SafeMemberOp) {
                    primaryType = gen.typeFact().getOptionalType(primaryType);
                }
                JCExpression primaryExpr = gen.expressionGen().transformQualifiedMemberPrimary(qmte);
                Declaration dec = qmte.getDeclaration();
                if (Decl.isPrivateAccessRequiringCompanion(qmte)) {
                    primaryExpr = gen.naming.makeCompanionAccessorCall(primaryExpr, (Interface) dec.getContainer());
                }
                Type varType = dec.isShared() ? primaryType : Decl.getPrivateAccessType(qmte);
                if (qmte.getPrimary().getUnboxed() == false) {
                    varTypeFlags |= JT_NO_PRIMITIVES;
                    instanceFieldIsBoxed = true;
                }
                letStmts.add(gen.makeVar(Flags.FINAL, instanceFieldName, gen.makeJavaType(varType, varTypeFlags), primaryExpr));
                if (qmte.getPrimary() instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration() instanceof TypedDeclaration) {
                    cb.instanceSubstitution = gen.naming.addVariableSubst((TypedDeclaration) ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration(), instanceFieldName.getName());
                }
            } finally {
                gen.expressionGen().withinSyntheticClassBody(prevCallableInv);
            }
        }
    } else {
        instanceFieldName = null;
    }
    CallableTransformation tx;
    cb.defaultValueCall = new DefaultValueMethodTransformation() {

        @Override
        public JCExpression makeDefaultValueMethod(AbstractTransformer gen, Parameter defaultedParam, List<JCExpression> defaultMethodArgs) {
            JCExpression fn = null;
            if (forwardCallTo instanceof Tree.BaseMemberOrTypeExpression) {
                fn = gen.naming.makeDefaultedParamMethod(null, defaultedParam);
            } else if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression) {
                JCExpression qualifier = gen.expressionGen().transformTermForInvocation(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary(), null);
                fn = gen.naming.makeDefaultedParamMethod(qualifier, defaultedParam);
            }
            return gen.make().Apply(null, fn, defaultMethodArgs);
        }
    };
    if (cb.isVariadic) {
        tx = cb.new VariadicCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, false, callableType));
    } else {
        tx = cb.new FixedArityCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, true, callableType), null);
    }
    cb.useTransformation(tx);
    cb.checkForFunctionalInterface(expectedType);
    return letStmts.isEmpty() ? cb.build() : gen.make().LetExpr(letStmts.toList(), cb.build());
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) 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) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Example 29 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class CallableBuilder method makeCallTypedMethod.

/**
 * Makes the {@code call$typed()} method, using the given body.
 */
private MethodDefinitionBuilder makeCallTypedMethod(List<JCStatement> body) {
    // make the method
    MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.systemMethod(gen, Naming.getCallableTypedMethodName());
    methodBuilder.noAnnotations();
    methodBuilder.modifiers(Flags.PRIVATE);
    Type returnType = gen.getReturnTypeOfCallable(typeModel);
    methodBuilder.resultType(gen.makeJavaType(returnType, JT_NO_PRIMITIVES), null);
    // add all parameters
    int i = 0;
    for (Parameter param : paramLists.getParameters()) {
        ParameterDefinitionBuilder parameterBuilder = ParameterDefinitionBuilder.systemParameter(gen, Naming.getAliasedParameterName(param));
        JCExpression paramType = gen.makeJavaType(parameterTypes.get(i));
        parameterBuilder.modifiers(Flags.FINAL);
        parameterBuilder.type(new TransformedType(paramType));
        methodBuilder.parameter(parameterBuilder);
        i++;
    }
    // Return the call result, or null if a void method
    methodBuilder.body(body);
    return methodBuilder;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) 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)

Example 30 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class CallableBuilder method javaStaticMethodReference.

public static CallableBuilder javaStaticMethodReference(CeylonTransformer gen, Node node, Type typeModel, final Functional methodOrClass, Reference producedReference, Type expectedType) {
    final ParameterList parameterList = methodOrClass.getFirstParameterList();
    CallableBuilder inner = new CallableBuilder(gen, node, typeModel, parameterList);
    ArrayList<Type> pt = new ArrayList<>();
    for (Parameter p : methodOrClass.getFirstParameterList().getParameters()) {
        pt.add(((Tree.MemberOrTypeExpression) node).getTarget().getTypedParameter(p).getType());
    }
    inner.parameterTypes = pt;
    inner.defaultValueCall = inner.new MemberReferenceDefaultValueCall(methodOrClass);
    JCExpression innerInvocation = gen.expressionGen().makeJavaStaticInvocation(gen, methodOrClass, producedReference, parameterList);
    // Need to worry about boxing for Function and FunctionalParameter
    if (methodOrClass instanceof TypedDeclaration) {
        innerInvocation = gen.expressionGen().applyErasureAndBoxing(innerInvocation, methodOrClass.getType(), !CodegenUtil.isUnBoxed((TypedDeclaration) methodOrClass), BoxingStrategy.BOXED, methodOrClass.getType());
    } else if (Strategy.isInstantiatorUntyped((Class) methodOrClass)) {
        // $new method declared to return Object, so needs typecast
        innerInvocation = gen.make().TypeCast(gen.makeJavaType(((Class) methodOrClass).getType()), innerInvocation);
    }
    List<JCStatement> innerBody = List.<JCStatement>of(gen.make().Return(innerInvocation));
    inner.useDefaultTransformation(innerBody);
    if (expectedType != null)
        inner.checkForFunctionalInterface(expectedType);
    return inner;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) ArrayList(java.util.ArrayList) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) 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) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Class(org.eclipse.ceylon.model.typechecker.model.Class) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)

Aggregations

JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)224 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)95 Type (org.eclipse.ceylon.model.typechecker.model.Type)95 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)74 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)53 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)53 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)45 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)41 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)39 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)38 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)33 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)32 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)30 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)28 Function (org.eclipse.ceylon.model.typechecker.model.Function)26 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)22 Value (org.eclipse.ceylon.model.typechecker.model.Value)22 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)21 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)21 Class (org.eclipse.ceylon.model.typechecker.model.Class)17