Search in sources :

Example 46 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class ClassTransformer method transformObject.

private List<JCTree> transformObject(Node def, Tree.Declaration annotated, Tree.SatisfiedTypes satisfiesTypes, Value model, Class klass, ClassDefinitionBuilder containingClassBuilder, boolean makeLocalInstance) {
    naming.clearSubstitutions(klass);
    String name = klass.getName();
    String javaClassName = Naming.quoteClassName(name);
    ClassDefinitionBuilder objectClassBuilder = ClassDefinitionBuilder.object(this, javaClassName, name, Decl.isLocal(klass)).forDefinition(klass);
    if (Strategy.introduceJavaIoSerializable(klass, typeFact().getJavaIoSerializable())) {
        objectClassBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
        if (def instanceof Tree.ObjectDefinition && klass.isMember() && (klass.isShared() || klass.isCaptured() || model.isCaptured())) {
            addWriteReplace(klass, objectClassBuilder);
        }
    }
    makeReadResolve(objectClassBuilder, klass, model);
    // Make sure top types satisfy reified type
    addReifiedTypeInterface(objectClassBuilder, klass);
    if (supportsReifiedAlias(klass))
        objectClassBuilder.reifiedAlias(klass.getType());
    CeylonVisitor visitor = gen().visitor;
    final ListBuffer<JCTree> prevDefs = visitor.defs;
    final boolean prevInInitializer = visitor.inInitializer;
    final ClassDefinitionBuilder prevClassBuilder = visitor.classBuilder;
    List<JCStatement> childDefs;
    try {
        visitor.defs = new ListBuffer<JCTree>();
        visitor.inInitializer = true;
        visitor.classBuilder = objectClassBuilder;
        def.visitChildren(visitor);
        childDefs = (List<JCStatement>) visitor.getResult().toList();
    } finally {
        visitor.classBuilder = prevClassBuilder;
        visitor.inInitializer = prevInInitializer;
        visitor.defs = prevDefs;
    }
    addMissingUnrefinedMembers(def, klass, objectClassBuilder);
    satisfaction(satisfiesTypes, klass, objectClassBuilder);
    serialization(klass, objectClassBuilder);
    if (model != null && Decl.isToplevel(model) && def instanceof Tree.ObjectDefinition) {
        // generate a field and getter
        AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.wrapped(this, null, objectClassBuilder, model.getName(), model, true).userAnnotations(makeAtIgnore()).userAnnotationsSetter(makeAtIgnore()).immutable().initialValue(makeNewClass(naming.makeName(model, Naming.NA_FQ | Naming.NA_WRAPPER))).is(PUBLIC, Decl.isShared(klass)).is(STATIC, true);
        if (annotated != null) {
            builder.fieldAnnotations(expressionGen().transformAnnotations(OutputElement.FIELD, annotated));
            builder.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, annotated));
        }
        objectClassBuilder.defs(builder.build());
    }
    if (annotated != null) {
        objectClassBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, annotated));
        objectClassBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, annotated));
    }
    // make sure we set the container in case we move it out
    addAtContainer(objectClassBuilder, klass);
    objectClassBuilder.annotations(makeAtObject()).satisfies(klass.getSatisfiedTypes()).defs((List) childDefs);
    objectClassBuilder.getInitBuilder().modifiers(PRIVATE);
    objectClassBuilder.addGetTypeMethod(klass.getType());
    if (model != null)
        objectClassBuilder.modelAnnotations(model.getAnnotations()).modifiers(transformObjectDeclFlags(model));
    List<JCTree> result = objectClassBuilder.build();
    if (makeLocalInstance) {
        if (model.isSelfCaptured()) {
            // if it's captured we need to box it and define the var before the class, so it can access it
            JCNewClass newInstance = makeNewClass(objectClassBuilder.getClassName(), false, null);
            JCFieldAccess setter = naming.makeSelect(Naming.getLocalValueName(model), Naming.getSetterName(model));
            JCStatement assign = make().Exec(make().Assign(setter, newInstance));
            result = result.prepend(assign);
            JCVariableDecl localDecl = makeVariableBoxDecl(null, model);
            result = result.prepend(localDecl);
        } else {
            // not captured, we can define the var after the class
            JCVariableDecl localDecl = makeLocalIdentityInstance(name, objectClassBuilder.getClassName(), false);
            result = result.append(localDecl);
        }
    } else if (model != null && Decl.withinClassOrInterface(model)) {
        boolean generateGetter = Decl.isCaptured(model);
        JCExpression type = makeJavaType(klass.getType());
        if (generateGetter) {
            int modifiers = TRANSIENT | PRIVATE;
            JCExpression initialValue = makeNull();
            containingClassBuilder.field(modifiers, name, type, initialValue, false);
            AttributeDefinitionBuilder getter = AttributeDefinitionBuilder.getter(this, name, model).modifiers(transformAttributeGetSetDeclFlags(model, false));
            if (def instanceof Tree.ObjectDefinition) {
                getter.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, ((Tree.ObjectDefinition) def)));
            }
            ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
            stmts.add(make().If(make().Binary(JCTree.EQ, naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNull()), make().Exec(make().Assign(naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNewClass(makeJavaType(klass.getType()), null))), null));
            stmts.add(make().Return(naming.makeUnquotedIdent(Naming.quoteFieldName(name))));
            getter.getterBlock(make().Block(0, stmts.toList()));
            result = result.appendList(getter.build());
        } else {
            int modifiers = FINAL;
            JCExpression initialValue = makeNewClass(makeJavaType(klass.getType()), null);
            containingClassBuilder.field(modifiers, name, type, initialValue, true);
        }
    }
    return result;
}
Also used : JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCTree(com.sun.tools.javac.tree.JCTree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass)

Example 47 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class ClassTransformer method serializationConstructor.

/** 
     * <p>Generates the serialization constructor 
     * with signature {@code ($Serialization$)} which:</p>
     * <ul>
     * <li>invokes {@code super()}, if the super class is also 
     *     serializable,</li>
     * <li>initializes all companion instance fields to a 
     *     newly instantiated companion instance,</li>
     * <li>initializes all reified type argument fields to null,</li>
     * <li>initializes all reference attribute fields to null,</li>
     * <li>initializesall primitive attribute fields to a default 
     *     value (basically some kind of 0)</li>
     * </ul>
     */
private void serializationConstructor(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder ctor = classBuilder.addConstructor();
    ctor.ignoreModelAnnotations();
    ctor.modifiers(PUBLIC);
    ParameterDefinitionBuilder serializationPdb = ParameterDefinitionBuilder.systemParameter(this, "ignored");
    serializationPdb.modifiers(FINAL);
    serializationPdb.type(make().Type(syms().ceylonSerializationType), null);
    ctor.parameter(serializationPdb);
    for (TypeParameter tp : model.getTypeParameters()) {
        ctor.reifiedTypeParameter(tp);
    }
    final ListBuffer<JCStatement> stmts = ListBuffer.lb();
    if (extendsSerializable(model)) {
        // invoke super
        ListBuffer<JCExpression> superArgs = ListBuffer.<JCExpression>lb();
        superArgs.add(naming.makeUnquotedIdent("ignored"));
        for (JCExpression ta : makeReifiedTypeArguments(model.getExtendedType())) {
            superArgs.add(ta);
        }
        stmts.add(make().Exec(make().Apply(null, naming.makeSuper(), superArgs.toList())));
    }
    buildFieldInits(model, classBuilder, stmts);
    ctor.body(stmts.toList());
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 48 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class ClassTransformer method serializationReferences.

/**
     * <p>Generates the {@code $deserialize$()} method to deserialize 
     * the classes state, which:</p>
     * <ul>
     * <li>invokes {@code super.$deserialize$()}, if the super class is also 
     *     serializable,</li>
     * <li>assigns each reified type argument in the 
     *     class by invoking {@code dted.getTypeArgument()},</li>
     * <li>assigns each field in the 
     *     class by invoking {@code dted.getValue()}.</li>
     * </ul>
     */
private void serializationReferences(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$references$.toString());
    mdb.isOverride(true);
    mdb.ignoreModelAnnotations();
    mdb.modifiers(PUBLIC);
    mdb.resultType(null, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))));
    ListBuffer<JCStatement> stmts = ListBuffer.lb();
    // TODO this is all static information, but the method itself needs to be 
    // callable virtually, so we should cache it somehow.
    SyntheticName r = naming.synthetic(Unfix.reference);
    if (extendsSerializable(model)) {
        // prepend the invocation of super.$serialize$()
        stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$references$.toString()), List.<JCExpression>nil())));
    } else {
        stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().NewClass(null, null, make().TypeApply(naming.makeQuotedFQIdent("java.util.ArrayList"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), List.<JCExpression>nil(), null)));
    }
    if (model.isMember()) {
        JCExpressionStatement outer = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.<JCExpression>of(make().Apply(null, naming.makeQualIdent(make().Type(syms().ceylonOuterImplType), "get_"), List.<JCExpression>nil()))));
        stmts.add(outer);
    }
    for (Declaration member : model.getMembers()) {
        if (hasField(member)) {
            // Obtain a ValueDeclaration
            JCExpression valueDeclaration = expressionGen().makeMemberValueOrFunctionDeclarationLiteral(null, member, false);
            // Create a MemberImpl
            JCExpression mi = make().NewClass(null, null, make().QualIdent(syms().ceylonMemberImplType.tsym), List.of(valueDeclaration), null);
            JCExpressionStatement attribute = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.of(mi)));
            stmts.add(attribute);
        }
    }
    stmts.add(make().Return(r.makeIdent()));
    mdb.body(stmts.toList());
    classBuilder.method(mdb);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement)

Example 49 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class ClassTransformer method transformMethodBlock.

private List<JCStatement> transformMethodBlock(final Tree.MethodDefinition def) {
    final Function model = def.getDeclarationModel();
    final Tree.Block block = def.getBlock();
    List<JCStatement> body;
    boolean prevNoExpressionlessReturn = statementGen().noExpressionlessReturn;
    try {
        statementGen().noExpressionlessReturn = Decl.isMpl(model) || Strategy.useBoxedVoid(model);
        body = statementGen().transformBlock(block);
    } finally {
        statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
    }
    // We void methods need to have their Callables return null
    // so adjust here.
    HasErrorException error = errors().getFirstErrorBlock(block);
    if ((Decl.isMpl(model) || Strategy.useBoxedVoid(model)) && !block.getDefinitelyReturns() && error == null) {
        if (Decl.isUnboxedVoid(model)) {
            body = body.append(make().Return(makeNull()));
        } else {
            body = body.append(make().Return(makeErroneous(block, "compiler bug: non-void method doesn't definitely return")));
        }
    }
    return body;
}
Also used : Function(com.redhat.ceylon.model.typechecker.model.Function) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 50 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class ClassDefinitionBuilder method addAnnotationTypeMethod.

public ClassDefinitionBuilder addAnnotationTypeMethod(Type type) {
    MethodDefinitionBuilder method = MethodDefinitionBuilder.systemMethod(gen, "annotationType");
    method.modifiers(PUBLIC);
    method.resultType(List.<JCAnnotation>nil(), gen.make().TypeApply(gen.make().QualIdent(gen.syms().classType.tsym), List.<JCTree.JCExpression>of(gen.make().Wildcard(gen.make().TypeBoundKind(BoundKind.EXTENDS), gen.make().Type(gen.syms().annotationType)))));
    method.isOverride(true);
    List<JCStatement> body = List.<JCStatement>of(gen.make().Return(gen.makeClassLiteral(type, AbstractTransformer.JT_ANNOTATION)));
    method.body(body);
    JCMethodDecl build = method.build();
    defs(build);
    return this;
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Aggregations

JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)112 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)82 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)37 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)33 JCTree (com.sun.tools.javac.tree.JCTree)32 Name (com.sun.tools.javac.util.Name)32 Type (com.redhat.ceylon.model.typechecker.model.Type)26 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)26 ListBuffer (com.sun.tools.javac.util.ListBuffer)25 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)23 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)18 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)16 JavacTreeMaker (lombok.javac.JavacTreeMaker)16 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)14 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)14 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)12 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)12 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)12 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)11 HasErrorException (com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException)10