Search in sources :

Example 41 with JCExpression

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

the class ClassTransformer method transform.

public void transform(Tree.AttributeDeclaration decl, ClassDefinitionBuilder classBuilder) {
    final Value model = decl.getDeclarationModel();
    boolean withinInterface = model.isInterfaceMember();
    Tree.SpecifierOrInitializerExpression initializer = decl.getSpecifierOrInitializerExpression();
    final boolean lazy = initializer instanceof Tree.LazySpecifierExpression;
    String attrName = decl.getIdentifier().getText();
    boolean memoized = Decl.isMemoized(decl);
    boolean isStatic = model.isStatic();
    // Only a non-formal or a concrete-non-lazy attribute has a corresponding field
    // and if a captured class parameter exists with the same name we skip this part as well
    Parameter parameter = CodegenUtil.findParamForDecl(decl);
    boolean useField = !lazy && Strategy.useField(model);
    boolean createField = !lazy && !model.isFormal() && Strategy.createField(parameter, model) && !model.isJavaNative();
    boolean createCompanionField = !lazy && withinInterface && initializer != null;
    JCThrow err = null;
    JCExpression memoizedInitialValue = null;
    if (createCompanionField || createField) {
        TypedReference typedRef = getTypedReference(model);
        TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
        Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
        if (Decl.isIndirect(decl)) {
            attrName = Naming.getAttrClassName(model, 0);
            nonWideningType = getGetterInterfaceType(model);
        }
        JCExpression initialValue = null;
        BoxingStrategy boxingStrategy = null;
        if (initializer != null) {
            Tree.Expression expression = initializer.getExpression();
            HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getTerm());
            int flags = CodegenUtil.downcastForSmall(expression, model) ? ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK : 0;
            flags |= model.hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0;
            if (error != null) {
                initialValue = null;
                err = makeThrowUnresolvedCompilationError(error.getErrorMessage().getMessage());
            } else {
                boxingStrategy = useJavaBox(model, nonWideningType) && javaBoxExpression(expression.getTypeModel(), nonWideningType) ? BoxingStrategy.JAVA : CodegenUtil.getBoxingStrategy(model);
                initialValue = expressionGen().transformExpression(expression, boxingStrategy, isStatic && nonWideningType.isTypeParameter() ? typeFact().getAnythingType() : nonWideningType, flags);
            }
        }
        if (memoized) {
            memoizedInitialValue = initialValue;
            initialValue = makeDefaultExprForType(nonWideningType);
        }
        int flags = 0;
        if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
            flags |= JT_NO_PRIMITIVES;
        }
        long modifiers = useField ? modifierTransformation().field(decl) : modifierTransformation().localVar(decl);
        // does it in those cases)
        if (parameter == null || parameter.isHidden()) {
            JCExpression type;
            if (isStatic && nonWideningType.isTypeParameter()) {
                type = make().Type(syms().objectType);
            } else {
                type = makeJavaType(nonWideningType, flags);
            }
            if (createCompanionField) {
                classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).field(modifiers, attrName, type, initialValue, !useField);
            } else {
                List<JCAnnotation> annos = makeAtIgnore().prependList(expressionGen().transformAnnotations(OutputElement.FIELD, decl));
                if (classBuilder.hasDelegatingConstructors()) {
                    annos = annos.prependList(makeAtNoInitCheck());
                }
                // fields should be ignored, they are accessed by the getters
                if (err == null) {
                    // TODO This should really be using AttributeDefinitionBuilder somehow
                    if (useField) {
                        AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.field(this, null, attrName, model, Decl.isIndirect(decl)).fieldAnnotations(annos).fieldNullability(makeNullabilityAnnotations(model)).initialValue(initialValue, boxingStrategy).fieldVisibilityModifiers(modifiers).modifiers(modifiers);
                        classBuilder.defs(adb.buildFields());
                        List<JCStatement> buildInit = adb.buildInit(false);
                        if (!buildInit.isEmpty()) {
                            if (isStatic) {
                                classBuilder.defs(make().Block(STATIC, buildInit));
                            } else {
                                classBuilder.getInitBuilder().init(buildInit);
                            }
                        }
                    } else if (!memoized) {
                        classBuilder.field(modifiers, attrName, type, initialValue, !useField, annos);
                        if (!isEe(model) && model.isLate() && CodegenUtil.needsLateInitField(model, typeFact())) {
                            classBuilder.field(PRIVATE | Flags.VOLATILE | Flags.TRANSIENT, Naming.getInitializationFieldName(attrName), make().Type(syms().booleanType), make().Literal(false), false, makeAtIgnore());
                        }
                    }
                }
            }
        }
        // A shared attribute might be initialized in a for statement, so
        // we might need a def-assignment subst for it
        JCStatement outerSubs = statementGen().openOuterSubstitutionIfNeeded(model, model.getType(), 0);
        if (outerSubs != null) {
            classBuilder.getInitBuilder().init(outerSubs);
        }
    }
    if (useField || withinInterface || lazy) {
        boolean generateInClassOrInterface = !withinInterface || model.isShared() || isStatic;
        boolean generateInCompanionClass = withinInterface && lazy && !isStatic;
        if (generateInClassOrInterface) {
            // Generate getter in main class or interface (when shared)
            at(decl.getType());
            AttributeDefinitionBuilder getter = makeGetter(decl, false, memoizedInitialValue);
            if (err != null) {
                getter.getterBlock(make().Block(0, List.<JCStatement>of(err)));
            }
            classBuilder.attribute(getter);
        }
        if (generateInCompanionClass) {
            Interface container = (Interface) model.getContainer();
            // Generate getter in companion class
            classBuilder.getCompanionBuilder(container).attribute(makeGetter(decl, true, null));
        }
        if (Decl.isVariable(model) || model.isLate()) {
            if (generateInClassOrInterface) {
                // Generate setter in main class or interface (when shared)
                classBuilder.attribute(makeSetter(decl, false, memoizedInitialValue));
            }
            if (generateInCompanionClass) {
                Interface container = (Interface) model.getContainer();
                // Generate setter in companion class
                classBuilder.getCompanionBuilder(container).attribute(makeSetter(decl, true, null));
            }
        }
    }
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) 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) HasErrorException(org.eclipse.ceylon.compiler.java.codegen.recovery.HasErrorException) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface) JCThrow(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCThrow)

Example 42 with JCExpression

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

the class ClassTransformer method makeSerializationGetter.

private JCExpression makeSerializationGetter(Value value) {
    JCExpression result;
    if (value.isToplevel() || value.isLate()) {
        // XXX duplicates logic in AttributeDefinitionBuilder
        // We use the setter for late values, since that will allocate
        // the array if needed.
        result = make().Apply(null, naming.makeQualifiedName(naming.makeThis(), value, Naming.NA_MEMBER | Naming.NA_GETTER), List.<JCExpression>nil());
    } else {
        // We bypass the setter
        // if (value.isVariable()) {
        result = naming.makeQualifiedName(naming.makeThis(), value, Naming.NA_IDENT);
    /*} else {
                // The field will have final modifier, so we need some 
                // jiggery pokery to reset it.
                requiredLookup[0] = true;
                String fieldName = value.getName();
                JCExpression fieldType = makeJavaType(value.getType());//TODO probably wrong
                result = makeReassignFinalField(fieldType, fieldName, newValue);
            }*/
    }
    BoxingStrategy boxingStrategy = useJavaBox(value, value.getType()) ? BoxingStrategy.JAVA : BoxingStrategy.BOXED;
    if (boxingStrategy == BoxingStrategy.JAVA && !isJavaString(value.getType())) {
        result = make().Conditional(make().Binary(JCTree.Tag.EQ, result, makeNull()), makeNull(), // FIXME!!!
        boxType(unboxJavaType(result, value.getType()), simplifyType(value.getType())));
    } else {
        result = expressionGen().applyErasureAndBoxing(result, value.getType(), !CodegenUtil.isUnBoxed(value), boxingStrategy, value.getType());
    }
    return result;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)

Example 43 with JCExpression

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

the class ClassTransformer method appendDefaultFieldInits.

protected void appendDefaultFieldInits(ClassDefinitionBuilder model, final ListBuffer<JCStatement> stmts, Collection<String> excludeFields) {
    for (JCVariableDecl field : model.getFields()) {
        String fieldName = field.name.toString();
        if (excludeFields != null && excludeFields.contains(fieldName)) {
            continue;
        }
        if (field.mods != null && (field.mods.flags & STATIC) != 0) {
            continue;
        }
        // initialize all reference fields to null and all primitive
        // fields to a default value.
        JCExpression nullOrZero;
        if (field.vartype instanceof JCPrimitiveTypeTree) {
            switch(((JCPrimitiveTypeTree) field.vartype).typetag) {
                case BYTE:
                case SHORT:
                case INT:
                    nullOrZero = make().Literal(0);
                    break;
                case LONG:
                    nullOrZero = make().Literal(0L);
                    break;
                case FLOAT:
                    nullOrZero = make().Literal(0.0f);
                    break;
                case DOUBLE:
                    nullOrZero = make().Literal(0.0);
                    break;
                case BOOLEAN:
                    nullOrZero = make().Literal(false);
                    break;
                case CHAR:
                    nullOrZero = make().Literal(TypeTag.CHAR, 0);
                    break;
                default:
                    throw new RuntimeException();
            }
        } else {
            nullOrZero = makeNull();
        }
        stmts.add(make().Exec(make().Assign(naming.makeQualIdent(naming.makeThis(), fieldName), nullOrZero)));
    }
}
Also used : JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 44 with JCExpression

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

the class ClassTransformer method makeArrayInitializer.

/**
 * Makes a new Array expression suitable for use in initializing a Java array
 * using as elements the positional arguments
 * of the given {@link Tree.SequencedArgument} (which must
 * be {@link Tree.ListedArgument}s).
 *
 * <pre>
 *     Whatever[] w = <strong>{ listedArg1, listedArg2, ... }</strong>
 *     //             ^---------- this bit ---------^
 * </pre>
 *
 * @param sequencedArgument
 * @return The array initializer expression
 */
JCExpression makeArrayInitializer(Tree.SequencedArgument sequencedArgument) {
    JCExpression defaultLiteral;
    ListBuffer<JCExpression> elements = new ListBuffer<JCExpression>();
    if (sequencedArgument != null) {
        for (Tree.PositionalArgument arg : sequencedArgument.getPositionalArguments()) {
            if (arg instanceof Tree.ListedArgument) {
                Tree.ListedArgument la = (Tree.ListedArgument) arg;
                elements.append(expressionGen().transformExpression(la.getExpression().getTerm(), BoxingStrategy.UNBOXED, la.getExpression().getTypeModel()));
            } else {
                elements = null;
                break;
            }
        }
    }
    defaultLiteral = elements == null ? null : make().NewArray(null, List.<JCExpression>nil(), elements.toList());
    return defaultLiteral;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 45 with JCExpression

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

the class ClassTransformer method makeMethodForFunctionalParameter.

// private JCExpression makeValueDeclaration(Value value) {
// return expressionGen().makeMemberValueOrFunctionDeclarationLiteral(null, value, false);
// }
/**
 * Generate a method for a shared FunctionalParameter which delegates to the Callable
 * @param klass
 * @param annotations
 */
private void makeMethodForFunctionalParameter(ClassDefinitionBuilder classBuilder, Tree.Parameter paramTree, Tree.TypedDeclaration memberDecl) {
    Parameter paramModel = paramTree.getParameterModel();
    if (Strategy.createMethod(paramModel)) {
        Tree.MethodDeclaration methodDecl = (Tree.MethodDeclaration) memberDecl;
        makeFieldForParameter(classBuilder, paramModel, memberDecl);
        Function method = (Function) paramModel.getModel();
        java.util.List<Parameter> parameters = method.getFirstParameterList().getParameters();
        JCExpression fieldRef;
        if (method.getMemberOrParameter(typeFact(), method.getName(), null, false) != method) {
            fieldRef = naming.makeQualifiedName(naming.makeThis(), method, Naming.NA_IDENT);
        } else {
            fieldRef = naming.makeName(method, Naming.NA_IDENT);
        }
        CallBuilder callBuilder = CallBuilder.instance(this).invoke(naming.makeQualIdent(fieldRef, Naming.getCallableMethodName(method)));
        for (Parameter parameter : parameters) {
            JCExpression parameterExpr = naming.makeName(parameter.getModel(), Naming.NA_IDENT);
            parameterExpr = expressionGen().applyErasureAndBoxing(parameterExpr, parameter.getType(), !CodegenUtil.isUnBoxed(parameter.getModel()), BoxingStrategy.BOXED, parameter.getType());
            callBuilder.argument(parameterExpr);
        }
        JCExpression expr = callBuilder.build();
        JCStatement body;
        if (isVoid(memberDecl) && Decl.isUnboxedVoid(method) && !Strategy.useBoxedVoid(method)) {
            body = make().Exec(expr);
        } else {
            expr = expressionGen().applyErasureAndBoxing(expr, paramModel.getType(), true, CodegenUtil.getBoxingStrategy(method), paramModel.getType());
            body = make().Return(expr);
        }
        classBuilder.methods(transformMethod(method, null, methodDecl, methodDecl.getParameterLists(), methodDecl, true, method.isActual(), true, List.of(body), new DaoThis(methodDecl, methodDecl.getParameterLists().get(0)), false));
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) 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) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)

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