Search in sources :

Example 1 with JCNewClass

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass 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 2 with JCNewClass

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass 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 3 with JCNewClass

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

the class ClassTransformer method makeMainForClass.

/**
 * Makes a {@code main()} method which calls the given top-level method
 * @param def
 */
private MethodDefinitionBuilder makeMainForClass(ClassOrInterface model) {
    at(null);
    List<JCExpression> arguments = List.nil();
    if (model.isAlias()) {
        TypeDeclaration constr = ((ClassAlias) model).getConstructor();
        if (constr instanceof Constructor) {
            // must pass the constructor name arg
            arguments = List.of(naming.makeNamedConstructorName((Constructor) constr, false));
        }
        model = (ClassOrInterface) model.getExtendedType().getDeclaration();
    }
    JCExpression nameId = makeJavaType(model.getType(), JT_RAW);
    arguments = makeBottomReifiedTypeParameters(model.getTypeParameters(), arguments);
    JCNewClass expr = make().NewClass(null, null, nameId, arguments, null);
    return makeMainMethod(model, expr);
}
Also used : ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ThrowerCatchallConstructor(org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 4 with JCNewClass

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

the class CeylonVisitor method transformSingletonConstructor.

protected void transformSingletonConstructor(HashMap<Constructor, CtorDelegation> delegates, Tree.Enumerated ctor) {
    // generate a constructor
    transformConstructor(ctor, // ctor.getParameterList(),
    null, ctor.getDelegatedConstructor(), ctor.getBlock(), ctor.getEnumerated(), delegates);
    Class clz = ModelUtil.getConstructedClass(ctor.getEnumerated());
    Value singletonModel = ctor.getDeclarationModel();
    // generate a field
    AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.singleton(gen, singletonModel.getName(), singletonModel, false);
    adb.modelAnnotations(gen.makeAtEnumerated());
    adb.modelAnnotations(gen.makeAtIgnore());
    adb.userAnnotations(gen.expressionGen().transformAnnotations(OutputElement.GETTER, ctor));
    adb.fieldAnnotations(gen.expressionGen().transformAnnotations(OutputElement.FIELD, ctor));
    // not setter
    adb.immutable();
    SyntheticName field = gen.naming.getValueConstructorFieldName(singletonModel);
    if (clz.isToplevel()) {
        adb.modifiers((singletonModel.isShared() ? PUBLIC : PRIVATE) | STATIC | FINAL);
        adb.initialValue(gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null), BoxingStrategy.BOXED);
        classBuilder.defs(adb.build());
    } else if (clz.isClassMember()) {
        int mods = 0;
        if (!singletonModel.isShared()) {
            mods |= PRIVATE;
        }
        if (clz.isClassOrInterfaceMember() && clz.isStatic()) {
            mods |= STATIC;
        }
        adb.modifiers(mods);
        // lazy
        adb.initialValue(gen.makeNull(), BoxingStrategy.BOXED);
        List<JCStatement> l = List.<JCStatement>of(gen.make().If(gen.make().Binary(JCTree.Tag.EQ, field.makeIdent(), gen.makeNull()), gen.make().Exec(gen.make().Assign(field.makeIdent(), gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null))), null), gen.make().Return(field.makeIdent()));
        adb.getterBlock(gen.make().Block(0, l));
        long mods2 = PRIVATE | TRANSIENT;
        if (clz.isStatic()) {
            mods2 |= STATIC;
        }
        classBuilder.getContainingClassBuilder().defs(gen.makeVar(mods2, field, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), gen.makeNull()));
        classBuilder.getContainingClassBuilder().defs(adb.build());
    } else {
        // LOCAL
        // we have to first make an empty box
        JCNewClass initialValue = gen.make().NewClass(null, null, gen.naming.makeTypeDeclarationExpression(null, ModelUtil.getConstructedClass(ctor.getEnumerated())), List.<JCExpression>of(gen.make().TypeCast(gen.naming.makeNamedConstructorType(ctor.getEnumerated(), false), gen.makeNull())), null);
        JCVariableDecl box = gen.makeVariableBoxDecl(gen.makeNull(), singletonModel);
        classBuilder.before(box);
        // then do the class, and after that, assign our instance to the box
        JCAssign assign = gen.make().Assign(gen.makeSelect(field.getName(), NamingBase.getGetterName(singletonModel)), initialValue);
        classBuilder.after(gen.make().Exec(assign));
    }
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCAssign(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAssign) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) List(org.eclipse.ceylon.langtools.tools.javac.util.List) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 5 with JCNewClass

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

the class ExpressionTransformer method transformSpreadOperator.

private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
    at(expr);
    boolean spreadMethodReferenceOuter = !expr.equals(spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
    boolean spreadMethodReferenceInner = expr.equals(spreading) && isWithinInvocation();
    Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
    if (spreadMethodReferenceOuter) {
        spreading = expr;
    }
    try {
        Naming.SyntheticName varBaseName = naming.alias("spread");
        ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
        final Naming.SyntheticName srcIterableName;
        if (spreadMethodReferenceInner) {
            // use the var we initialized in the outer
            srcIterableName = this.memberPrimary;
        } else {
            srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
        }
        if (spreadMethodReferenceOuter) {
            // if we're in the outer, note then name of the var for use in the inner.
            this.memberPrimary = srcIterableName;
        }
        Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
        Type srcElementType = expr.getTarget().getQualifyingType();
        JCExpression srcIterableExpr;
        boolean isSuperOrSuperOf = false;
        Type srcIterableType;
        if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
            srcIterableType = typeFact().getIterableType(srcElementType);
        } else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
            srcIterableType = typeFact().getJavaIterableDeclaration().appliedType(null, Collections.singletonList(srcElementType));
        } else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
            srcIterableType = expr.getPrimary().getTypeModel();
            srcElementType = typeFact().getJavaArrayElementType(srcIterableType);
        } else {
            return makeErroneous(expr, "unhandled iterable type");
        }
        if (spreadMethodReferenceInner) {
            srcIterableExpr = srcIterableName.makeIdent();
        } else {
            boolean isSuper = isSuper(expr.getPrimary());
            isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
            if (isSuperOrSuperOf) {
                // so we just refer to it later
                if (isSuper) {
                    Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
                    srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
                } else
                    srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
            } else {
                srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, srcIterableType);
            }
        }
        // do not capture the iterable for super invocations: see above
        if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
            JCVariableDecl srcIterable = null;
            JCExpression srcIterableTypeExpr = makeJavaType(srcIterableType, JT_NO_PRIMITIVES);
            srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
            letStmts.prepend(srcIterable);
        }
        /* public Object next() {
             *     Object result;
             *     if (!((result = iterator.next()) instanceof Finished)) {
             *         result = transformedMember(result);
             *     }
             *     return result;
             */
        /* Any arguments in the member of the spread would get re-evaluated on each iteration
             * so we need to shift them to the scope of the Let to ensure they're evaluated once. 
             */
        boolean aliasArguments = transformer instanceof InvocationTermTransformer && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
        if (aliasArguments) {
            ((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
        }
        JCNewClass iterableClass;
        boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
        try {
            Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
            JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
            transformedElement = transformMemberExpression(expr, transformedElement, transformer);
            // be handled by the previous recursion
            if (spreadMethodReferenceOuter) {
                return make().LetExpr(letStmts.toList(), transformedElement);
            }
            Type resultElementType = expr.getTarget().getType();
            final Type resultAbsentType;
            transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
            expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
            MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
            nextMdb.isOverride(true);
            nextMdb.annotationFlags(Annotations.IGNORE);
            nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            nextMdb.resultType(new TransformedType(make().Type(syms().objectType)));
            final List<JCTree> l;
            if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
                // private Iterator<srcElementType> iterator = srcIterableName.iterator();
                JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
                naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
                resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
                nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.Tag.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
                l = List.of(srcIterator, nextMdb.build());
            } else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
                // private Iterator<srcElementType> iterator = srcIterableName.iterator();
                JCVariableDecl srcIterator = makeVar(Flags.PRIVATE | Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getJavaIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
                naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
                resultAbsentType = typeFact().getNullType();
                nextMdb.body(List.<JCStatement>of(make().If(make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "hasNext"), List.<JCExpression>nil()), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Return(transformedElement))), make().Return(makeFinished()))));
                l = List.of(srcIterator, nextMdb.build());
            } else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
                resultAbsentType = typeFact().getNullType();
                JCVariableDecl srcIndex = makeVar(Flags.PRIVATE, srcIteratorName, make().Type(syms().intType), make().Literal(0));
                JCExpression indexed = make().Indexed(srcIterableName.makeIdent(), make().Unary(Tag.POSTINC, srcIteratorName.makeIdent()));
                if (typeFact().isJavaPrimitiveArrayType(expr.getPrimary().getTypeModel())) {
                    indexed = applyErasureAndBoxing(indexed, srcElementType, false, BoxingStrategy.BOXED, srcElementType);
                }
                nextMdb.body(List.<JCStatement>of(make().If(make().Binary(Tag.LT, srcIteratorName.makeIdent(), // for super we do not capture it because we can't and it's constant anyways
                naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "length")), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), indexed), make().Return(transformedElement))), make().Return(makeFinished()))));
                l = List.of(srcIndex, nextMdb.build());
            } else {
                return makeErroneous(expr, "unhandled iterable type");
            }
            // new AbstractIterator()
            JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), l));
            MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
            iteratorMdb.isOverride(true);
            iteratorMdb.annotationFlags(Annotations.IGNORE);
            iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            iteratorMdb.resultType(new TransformedType(makeJavaType(typeFact().getIteratorType(resultElementType)), makeAtNonNull()));
            iteratorMdb.body(make().Return(iteratorClass));
            // new AbstractIterable()
            iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
        } finally {
            expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
        }
        if (aliasArguments) {
            letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
        }
        JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
        JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
        // Do we *statically* know the result must be a Sequence
        final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
        Type returnElementType = expr.getTarget().getType();
        if (primaryIsSequence) {
            int flags = EXPR_DOWN_CAST;
            spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
        }
        return spread;
    } finally {
        spreading = oldSpreading;
    }
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) 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) JCMethodInvocation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCMethodInvocation) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) 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) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)7 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)6 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)5 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)4 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)3 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)2 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)2 JCAssign (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAssign)2 JCBlock (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock)2 JCClassDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCClassDecl)2 JCFieldAccess (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCFieldAccess)2 JCMethodInvocation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCMethodInvocation)2 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)2 CharArrayWriter (java.io.CharArrayWriter)1 IOException (java.io.IOException)1 ThrowerCatchallConstructor (org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor)1 JCAnnotation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)1 JCArrayAccess (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCArrayAccess)1 JCArrayTypeTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCArrayTypeTree)1 JCAssert (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAssert)1