Search in sources :

Example 16 with JCStatement

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

the class ClassTransformer method addRefinedThrowerAttribute.

/**
 * Adds a getter (and possibly a setter) to {@code classBuilder}
 * which throws
 * @param classBuilder The class builder to add the method to
 * @param error The message
 * @param classModel The class which doesn't refine {@code formalAttribute}
 * @param formalAttribute The formal attribute that hasn't been refined in {@code classModel}
 */
private void addRefinedThrowerAttribute(ClassDefinitionBuilder classBuilder, String error, Node node, ClassOrInterface classModel, Value formalAttribute) {
    Value refined = refineValue(formalAttribute, formalAttribute.appliedTypedReference(null, null), classModel, classModel.getUnit());
    AttributeDefinitionBuilder getterBuilder = AttributeDefinitionBuilder.getter(this, refined.getName(), refined);
    getterBuilder.skipField();
    getterBuilder.modifiers(modifierTransformation().getterSetter(refined, false));
    getterBuilder.getterBlock(make().Block(0, List.<JCStatement>of(makeThrowUnresolvedCompilationError(error))));
    classBuilder.attribute(getterBuilder);
    if (formalAttribute.isVariable()) {
        AttributeDefinitionBuilder setterBuilder = AttributeDefinitionBuilder.setter(this, node, refined.getName(), refined);
        setterBuilder.skipField();
        setterBuilder.modifiers(modifierTransformation().getterSetter(refined, false));
        setterBuilder.setterBlock(make().Block(0, List.<JCStatement>of(makeThrowUnresolvedCompilationError(error))));
        classBuilder.attribute(setterBuilder);
    }
}
Also used : Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)

Example 17 with JCStatement

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement 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)

Example 18 with JCStatement

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

the class ClassTransformer method generateIndirectGetterBlock.

private JCTree.JCBlock generateIndirectGetterBlock(Value v) {
    JCTree.JCExpression returnExpr;
    returnExpr = naming.makeQualIdent(naming.makeName(v, Naming.NA_WRAPPER), "get_");
    returnExpr = make().Apply(null, returnExpr, List.<JCExpression>nil());
    JCReturn returnValue = make().Return(returnExpr);
    List<JCStatement> stmts = List.<JCTree.JCStatement>of(returnValue);
    JCTree.JCBlock block = make().Block(0L, stmts);
    return block;
}
Also used : JCReturn(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCReturn) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCBlock(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)

Example 19 with JCStatement

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

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() && (ModelUtil.isCaptured(klass) || model.isCaptured())) {
            addWriteReplace(klass, objectClassBuilder);
        }
    }
    makeReadResolve(def, 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;
        naming.closeScopedSubstitutions(def.getScope());
    }
    addMissingUnrefinedMembers(def, klass, objectClassBuilder);
    satisfaction(satisfiesTypes, klass, objectClassBuilder);
    serialization(klass, objectClassBuilder);
    if (model != null && model.isToplevel() && def instanceof Tree.ObjectDefinition) {
        // generate a field and getter
        AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.wrapped(this, model.getName(), model, true, null).userAnnotations(makeAtIgnore()).userAnnotationsSetter(makeAtIgnore()).immutable().initialValue(makeNewClass(naming.makeName(model, Naming.NA_FQ | Naming.NA_WRAPPER)), BoxingStrategy.BOXED).is(PUBLIC, klass.isShared()).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(childDefs);
    objectClassBuilder.getInitBuilder().modifiers(PRIVATE);
    objectClassBuilder.addGetTypeMethod(klass.getType());
    if (model != null)
        objectClassBuilder.modelAnnotations(model.getAnnotations()).modifiers(modifierTransformation().object(model));
    at(def);
    List<JCTree> result = objectClassBuilder.build();
    if (makeLocalInstance && !model.isStatic()) {
        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 && model.isClassOrInterfaceMember()) {
        boolean generateGetter = ModelUtil.isCaptured(model);
        JCExpression type = makeJavaType(klass.getType());
        if (generateGetter) {
            int modifiers = TRANSIENT | PRIVATE | (model.isStatic() ? STATIC : 0);
            JCExpression initialValue = makeNull();
            containingClassBuilder.field(modifiers, name, type, initialValue, false);
            AttributeDefinitionBuilder getter = AttributeDefinitionBuilder.getter(this, name, model).modifiers(modifierTransformation().getterSetter(model, false));
            if (def instanceof Tree.ObjectDefinition) {
                getter.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, ((Tree.ObjectDefinition) def)));
            }
            ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
            stmts.add(make().If(make().Binary(JCTree.Tag.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 | (model.isStatic() ? STATIC : 0);
            JCExpression initialValue = makeNewClass(makeJavaType(klass.getType()), null);
            containingClassBuilder.field(modifiers, name, type, initialValue, true);
        }
    }
    return result;
}
Also used : JCFieldAccess(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCFieldAccess) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) 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) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)

Example 20 with JCStatement

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

the class ClassTransformer method serializationGet.

private void serializationGet(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$get$.toString());
    mdb.isOverride(true);
    mdb.ignoreModelAnnotations();
    mdb.modifiers(PUBLIC);
    ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
    pdb.modifiers(FINAL);
    pdb.type(new TransformedType(make().Type(syms().ceylonReachableReferenceType), null, makeAtNonNull()));
    mdb.parameter(pdb);
    mdb.resultType(new TransformedType(make().Type(syms().objectType), null, makeAtNonNull()));
    /*
         * public void $get$(Object reference, Object instance) {
         *     switch((String)reference) {
         *     case ("attr1")
         *           return ...;
         *     // ... other fields of this class
         *     case ("lateAttr1")
         *           if (!$init$lateAttr1) {
         *               return ceylon.language.serialization.uninitializedLateValue.get_();
         *           }
         *           return ...;
         *     case (null):
         *           return Outer.this;
         *     default:
         *           return super.get(reference);
         */
    ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
    boolean[] needsLookup = new boolean[] { false };
    for (Declaration member : model.getMembers()) {
        if (hasField(member)) {
            if (member instanceof Function)
                // TODO: This class is not serializable
                continue;
            ListBuffer<JCStatement> caseStmts = new ListBuffer<JCStatement>();
            if (member instanceof Value && ((Value) member).isLate()) {
                // TODO this should be encapsulated so the ADB and this
                // code can just call something common
                JCExpression test = AttributeDefinitionBuilder.field(this, null, member.getName(), (Value) member, false).buildUninitTest();
                if (test != null) {
                    caseStmts.add(make().If(test, make().Return(makeLanguageSerializationValue("uninitializedLateValue")), null));
                }
            }
            caseStmts.add(make().Return(makeSerializationGetter((Value) member)));
            cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
        }
    }
    SyntheticName reference = naming.synthetic(Unfix.reference);
    ListBuffer<JCStatement> defaultCase = new ListBuffer<JCStatement>();
    if (extendsSerializable(model)) {
        // super.get(reference);
        defaultCase.add(make().Return(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$get$.toString()), List.<JCExpression>of(reference.makeIdent()))));
    } else {
        // throw (or pass to something else to throw, based on policy)
        defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
    }
    cases.add(make().Case(null, defaultCase.toList()));
    ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
    if (needsLookup[0]) {
        // if we needed to use a lookup object to reset final fields,
        // prepend that variable
        stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
    }
    JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
    if (model.isMember() && !model.getExtendedType().getDeclaration().isMember()) {
        stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonOuterType)), make().Return(expressionGen().makeOuterExpr(((TypeDeclaration) model.getContainer()).getType())), swtch));
    } else {
        stmts.add(swtch);
    }
    mdb.body(stmts.toList());
    classBuilder.method(mdb);
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Function(org.eclipse.ceylon.model.typechecker.model.Function) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCSwitch(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCSwitch) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) JCCase(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCCase)

Aggregations

JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)73 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)52 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)38 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)31 Type (org.eclipse.ceylon.model.typechecker.model.Type)29 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)25 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)21 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)18 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)16 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)15 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)13 Value (org.eclipse.ceylon.model.typechecker.model.Value)13 Function (org.eclipse.ceylon.model.typechecker.model.Function)12 HasErrorException (org.eclipse.ceylon.compiler.java.codegen.recovery.HasErrorException)11 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)11 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)10 Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)10 JCBlock (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock)10 JCPrimitiveTypeTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree)10 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)10