Search in sources :

Example 51 with JCVariableDecl

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

the class ClassTransformer method transformConstructorName.

protected void transformConstructorName(ClassDefinitionBuilder classBuilder, ListBuffer<JCTree> result, Constructor ctor, Class clz, int classMods, String ctorName, DeclNameFlag... declFlags) {
    ClassDefinitionBuilder constructorNameClass = ClassDefinitionBuilder.klass(this, ctorName, null, true);
    JCVariableDecl constructorNameConst;
    if (Decl.isEnumeratedConstructor(ctor)) {
        if (clz.isToplevel()) {
            classMods &= ~(PRIVATE | PROTECTED | PUBLIC);
            classMods |= PRIVATE | STATIC | FINAL;
        } else if (clz.isMember() && Decl.isToplevel((Declaration) clz.getContainer())) {
            classMods &= ~(PRIVATE | PROTECTED | PUBLIC);
            classMods |= FINAL;
            if (!Decl.isAncestorLocal(ctor)) {
                classMods |= STATIC;
            }
            if (!ctor.isShared()) {
                classMods |= PRIVATE;
            }
        } else {
            classMods &= ~(PRIVATE | PROTECTED | PUBLIC);
            classMods |= FINAL;
        }
        constructorNameConst = null;
    } else {
        if (clz.isToplevel() || (clz.isMember() && Decl.isToplevel((Declaration) clz.getContainer()))) {
            classMods |= STATIC | FINAL;
            constructorNameConst = make().VarDef(make().Modifiers(classMods, makeAtIgnore()), names().fromString(ctorName), naming.makeTypeDeclarationExpression(null, ctor, declFlags), makeNull());
        } else {
            classMods &= ~(PRIVATE | PROTECTED | PUBLIC);
            constructorNameConst = null;
        }
    }
    constructorNameClass.modifiers(classMods);
    constructorNameClass.annotations(makeAtIgnore());
    constructorNameClass.annotations(makeAtConstructorName(ctor.getName(), contains(declFlags, DeclNameFlag.DELEGATION)));
    constructorNameClass.getInitBuilder().modifiers(PRIVATE);
    List<JCTree> ctorNameClassDecl = constructorNameClass.build();
    if (clz.isToplevel()) {
        result.addAll(ctorNameClassDecl);
        classBuilder.defs(constructorNameConst);
    } else if (clz.isClassMember()) {
        classBuilder.getContainingClassBuilder().defs(ctorNameClassDecl);
        classBuilder.getContainingClassBuilder().defs(constructorNameConst);
    } else if (clz.isInterfaceMember()) {
        classBuilder.getContainingClassBuilder().getCompanionBuilder(clz).defs(ctorNameClassDecl);
        classBuilder.getContainingClassBuilder().getCompanionBuilder(clz).defs(constructorNameConst);
    } else {
        classBuilder.defs(ctorNameClassDecl);
    }
}
Also used : JCTree(com.sun.tools.javac.tree.JCTree) 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) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 52 with JCVariableDecl

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

the class ClassDefinitionBuilder method reifiedAlias.

public void reifiedAlias(Type type) {
    try (AbstractTransformer.SavedPosition savedPos = gen.noPosition()) {
        JCExpression klass = gen.makeUnerasedClassLiteral(type.getDeclaration());
        JCExpression classDescriptor = gen.make().Apply(null, gen.makeSelect(gen.makeTypeDescriptorType(), "klass"), List.of(klass));
        JCVariableDecl varDef = gen.make().VarDef(gen.make().Modifiers(PUBLIC | FINAL | STATIC, gen.makeAtIgnore()), gen.names().fromString(gen.naming.getTypeDescriptorAliasName()), gen.makeTypeDescriptorType(), classDescriptor);
        defs(varDef);
    }
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 53 with JCVariableDecl

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

the class ExpressionTransformer method transformSpreadOperator.

private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
    at(expr);
    boolean spreadMethodReferenceOuter = !expr.equals(this.spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
    boolean spreadMethodReferenceInner = expr.equals(this.spreading) && isWithinInvocation();
    Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
    if (spreadMethodReferenceOuter) {
        spreading = expr;
    }
    try {
        Naming.SyntheticName varBaseName = naming.alias("spread");
        ListBuffer<JCStatement> letStmts = ListBuffer.<JCStatement>lb();
        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 srcIterableTypeExpr = makeJavaType(typeFact().getIterableType(srcElementType), JT_NO_PRIMITIVES);
        JCExpression srcIterableExpr;
        boolean isSuperOrSuperOf = false;
        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, typeFact().getIterableType(srcElementType));
            }
        }
        // do not capture the iterable for super invocations: see above
        if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
            JCVariableDecl srcIterable = null;
            srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
            letStmts.prepend(srcIterable);
        }
        Type resultElementType = expr.getTarget().getType();
        Type resultAbsentType = typeFact().getIteratedAbsentType(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()));
        Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
        /* 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 {
            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);
            }
            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(null, make().Type(syms().objectType));
            nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.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())));
            JCMethodDecl nextMethod = nextMdb.build();
            // 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), List.of(srcIterator, nextMethod)));
            MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
            iteratorMdb.isOverride(true);
            iteratorMdb.annotationFlags(Annotations.IGNORE);
            iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            iteratorMdb.resultType(null, makeJavaType(typeFact().getIteratorType(resultElementType)));
            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(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 54 with JCVariableDecl

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

the class ExpressionTransformer method transformAssignAndReturnOperation.

private JCExpression transformAssignAndReturnOperation(Node operator, Tree.Term term, boolean boxResult, Type valueType, Type returnType, AssignAndReturnOperationFactory factory) {
    List<JCVariableDecl> decls = List.nil();
    List<JCStatement> stats = List.nil();
    JCExpression result = null;
    // (let $tmp = OP(attr); attr = $tmp; $tmp)
    if (term instanceof Tree.BaseMemberExpression || // special case for java statics Foo.attr where Foo does not need to be evaluated
    (term instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) term).getStaticMethodReference())) {
        JCExpression getter;
        if (term instanceof Tree.BaseMemberExpression)
            getter = transform((Tree.BaseMemberExpression) term, null);
        else
            getter = transformMemberExpression((Tree.QualifiedMemberExpression) term, null, null);
        at(operator);
        // Type $tmp = OP(attr);
        JCExpression exprType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
        Name varName = naming.tempName("op");
        // make sure we box the results if necessary
        getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, valueType);
        JCExpression newValue = factory.getNewValue(getter);
        // no need to box/unbox here since newValue and $tmpV share the same boxing type
        JCVariableDecl tmpVar = make().VarDef(make().Modifiers(0), varName, exprType, newValue);
        decls = decls.prepend(tmpVar);
        // attr = $tmp
        // make sure the result is unboxed if necessary, $tmp may be boxed
        JCExpression value = make().Ident(varName);
        BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(term);
        value = applyErasureAndBoxing(value, returnType, boxResult, boxingStrategy, valueType);
        JCExpression assignment = transformAssignment(operator, term, value);
        stats = stats.prepend(at(operator).Exec(assignment));
        // $tmp
        // return, with the box type we asked for
        result = make().Ident(varName);
    } else if (term instanceof Tree.QualifiedMemberExpression) {
        // e.attr
        // (let $tmpE = e, $tmpV = OP($tmpE.attr); $tmpE.attr = $tmpV; $tmpV;)
        Tree.QualifiedMemberExpression qualified = (Tree.QualifiedMemberExpression) term;
        boolean isSuper = isSuperOrSuperOf(qualified.getPrimary());
        // transform the primary, this will get us a boxed primary 
        JCExpression e = transformQualifiedMemberPrimary(qualified);
        at(operator);
        // Type $tmpE = e
        JCExpression exprType = makeJavaType(qualified.getTarget().getQualifyingType(), JT_NO_PRIMITIVES);
        Name varEName = naming.tempName("opE");
        JCVariableDecl tmpEVar = make().VarDef(make().Modifiers(0), varEName, exprType, e);
        // Type $tmpV = OP($tmpE.attr)
        JCExpression attrType = makeJavaType(returnType, boxResult ? JT_NO_PRIMITIVES : 0);
        Name varVName = naming.tempName("opV");
        JCExpression getter = transformMemberExpression(qualified, isSuper ? transformSuper(qualified) : make().Ident(varEName), null);
        // make sure we box the results if necessary
        getter = applyErasureAndBoxing(getter, term, boxResult ? BoxingStrategy.BOXED : BoxingStrategy.UNBOXED, valueType);
        JCExpression newValue = factory.getNewValue(getter);
        // no need to box/unbox here since newValue and $tmpV share the same boxing type
        JCVariableDecl tmpVVar = make().VarDef(make().Modifiers(0), varVName, attrType, newValue);
        // define all the variables
        decls = decls.prepend(tmpVVar);
        if (!isSuper) {
            decls = decls.prepend(tmpEVar);
        }
        // $tmpE.attr = $tmpV
        // make sure $tmpV is unboxed if necessary
        JCExpression value = make().Ident(varVName);
        BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(term);
        value = applyErasureAndBoxing(value, returnType, boxResult, boxingStrategy, valueType);
        JCExpression assignment = transformAssignment(operator, term, isSuper ? transformSuper(qualified) : make().Ident(varEName), value);
        stats = stats.prepend(at(operator).Exec(assignment));
        // $tmpV
        // return, with the box type we asked for
        result = make().Ident(varVName);
    } else {
        return makeErroneous(operator, "compiler bug: " + term.getNodeType() + " is not a supported assign and return operator");
    }
    return make().LetExpr(decls, stats, result);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) Name(com.sun.tools.javac.util.Name)

Example 55 with JCVariableDecl

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

the class StatementTransformer method transformIterableIteration.

/**
     * The transformation of a ceylon {@code for} loop:
     * 
     * <pre>
     *     java.lang.Object ITERATION_VAR_NAME;
     *     Iterator<ITERATOR_ELEMENT_TYPE> ITERATOR_VAR_NAME = ITERABLE.getIterator();
     *     while (
     *             !((ITERATION_VAR_NAME = ITERATOR_VAR_NAME.getNext()) instanceof ceylon.language.Finished;
     *         ) {
     *         ITEM_DECLS;
     *         BODY_STMTS;
     *     }
     * </pre>
     * @param label 
     * 
     * @param iterationVarName The iteration variable (which recieves the value of {@code Iterator.next()})
     * @param iteratorVarName The name of the {@code Iterator} variable
     * @param iteratorElementType The type argument of the {@code Iterator}
     * @param iterableExpr The {@code Iterable} expression
     * @param itemDecls variable declarations for the iteration variables which 
     * begin the loop body (these depend on {@code iterationVarName} and may 
     * typecast or destructure it). May be null.
     * @param bodyStmts Other statements in the loop body
     * @return
     */
List<JCStatement> transformIterableIteration(Node node, Name label, Naming.SyntheticName iterationVarName, Naming.SyntheticName iteratorVarName, Type iterableType, Type iteratedType, JCExpression iterableExpr, List<JCStatement> itemDecls, List<JCStatement> bodyStmts, boolean allowArrayOpt, boolean allowArraySeqOpt) {
    Type iteratorElementType = iteratedType;
    ListBuffer<JCStatement> result = ListBuffer.<JCStatement>lb();
    // TODO Only when the iterable *could be* an array (e.g. if static type is Iterable, but not if static type is Sequence)
    // TODO Need to use naming.Infix for the hidden members of Array
    boolean optForArray = allowArrayOpt && typeFact().getArrayType(iteratedType).isSubtypeOf(iterableType);
    boolean optForTuple = allowArraySeqOpt && typeFact().getTupleType(Collections.singletonList(iteratedType), true, false, -1).isSubtypeOf(iterableType);
    SyntheticName iterableName = optForArray || optForTuple ? naming.alias("iterable") : null;
    SyntheticName isArrayName = optForArray ? naming.alias("isArray") : null;
    SyntheticName isTupleName = optForTuple ? naming.alias("isTuple") : null;
    SyntheticName arrayName = optForArray || optForTuple ? naming.alias("array") : null;
    SyntheticName arrayIndex = optForArray || optForTuple ? naming.alias("i") : null;
    SyntheticName arrayLength = optForArray || optForTuple ? naming.alias("length") : null;
    if (optForArray || optForTuple) {
        result.append(makeVar(FINAL, iterableName, makeJavaType(typeFact().getIterableType(iteratorElementType)), iterableExpr));
    }
    if (optForArray) {
        result.append(makeVar(FINAL, isArrayName, make().Type(syms().booleanType), make().TypeTest(iterableName.makeIdent(), makeJavaType(typeFact().getArrayType(iteratorElementType), JT_RAW))));
    }
    if (optForTuple) {
        result.append(makeVar(FINAL, isTupleName, make().Type(syms().booleanType), make().Binary(JCTree.AND, make().TypeTest(iterableName.makeIdent(), make().QualIdent(syms().ceylonTupleType.tsym)), make().Binary(JCTree.NE, make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getArray$.toString()), List.<JCExpression>nil()), makeNull()))));
    }
    // java.lang.Object ELEM_NAME;
    JCVariableDecl elemDecl = makeVar(iterationVarName, make().Type(syms().objectType), optForArray || optForTuple ? makeNull() : null);
    result.append(elemDecl);
    SyntheticName iterName = iteratorVarName;
    Type iteratorType = typeFact().getIteratorType(iteratorElementType);
    JCExpression iteratorTypeExpr = makeJavaType(iteratorType, CeylonTransformer.JT_TYPE_ARGUMENT);
    // ceylon.language.Iterator<T> LOOP_VAR_NAME$iter$X = ITERABLE.getIterator();
    // We don't need to unerase here as anything remotely a sequence will be erased to Iterable, which has getIterator()
    JCExpression getIter;
    if (optForArray || optForTuple) {
        at(node);
        result.append(makeVar(FINAL, arrayName, make().Type(syms().objectType), null));
        result.append(makeVar(arrayIndex, make().Type(syms().intType), make().Literal(0)));
        result.append(makeVar(FINAL, arrayLength, make().Type(syms().intType), null));
        ListBuffer<JCStatement> whenTuple = ListBuffer.<JCTree.JCStatement>lb();
        whenTuple.append(make().Exec(make().Assign(arrayName.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getArray$.toString()), List.<JCExpression>nil()))));
        whenTuple.append(make().Exec(make().Assign(arrayIndex.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getFirst$.toString()), List.<JCExpression>nil()))));
        whenTuple.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Binary(JCTree.PLUS, arrayIndex.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(make().QualIdent(syms().ceylonTupleType.tsym), iterableName.makeIdent()), Unfix.$getLength$.toString()), List.<JCExpression>nil())))));
        ListBuffer<JCStatement> whenArray = ListBuffer.<JCTree.JCStatement>lb();
        whenArray.append(make().Exec(make().Assign(arrayName.makeIdent(), make().Apply(null, naming.makeQualIdent(make().TypeCast(makeJavaType(typeFact().getArrayType(typeFact().getAnythingType()), JT_RAW), iterableName.makeIdent()), "toArray"), List.<JCExpression>nil()))));
        whenArray.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Apply(null, naming.makeQuotedFQIdent("com.redhat.ceylon.compiler.java.Util.arrayLength"), List.<JCExpression>of(arrayName.makeIdent())))));
        ListBuffer<JCStatement> whenIterable = ListBuffer.<JCTree.JCStatement>lb();
        whenIterable.append(make().Exec(make().Assign(arrayName.makeIdent(), makeNull())));
        whenIterable.append(make().Exec(make().Assign(arrayLength.makeIdent(), make().Literal(0))));
        if (optForArray && optForTuple) {
            result.append(make().If(isTupleName.makeIdent(), make().Block(0, whenTuple.toList()), make().If(isArrayName.makeIdent(), make().Block(0, whenArray.toList()), make().Block(0, whenIterable.toList()))));
        } else {
            result.append(make().If((optForArray ? isArrayName : isTupleName).makeIdent(), make().Block(0, (optForArray ? whenArray : whenTuple).toList()), make().Block(0, whenIterable.toList())));
        }
        getIter = make().Conditional(optForArray && optForTuple ? make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent()) : optForArray ? isArrayName.makeIdent() : isTupleName.makeIdent(), makeNull(), make().Apply(null, makeSelect(iterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
    } else {
        getIter = at(node).Apply(null, makeSelect(iterableExpr, "iterator"), List.<JCExpression>nil());
    }
    getIter = gen().expressionGen().applyErasureAndBoxing(getIter, iteratorType, true, BoxingStrategy.BOXED, iteratorType);
    JCVariableDecl iteratorDecl = at(node).VarDef(make().Modifiers(0), iterName.asName(), iteratorTypeExpr, getIter);
    // .ceylon.language.Iterator<T> LOOP_VAR_NAME$iter$X = ITERABLE.getIterator();
    result.append(iteratorDecl);
    ListBuffer<JCStatement> loopBody = ListBuffer.<JCStatement>lb();
    if (optForArray || optForTuple) {
        JCExpression cond;
        if (optForArray && optForTuple) {
            cond = make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent());
        } else if (optForArray) {
            cond = isArrayName.makeIdent();
        } else {
            cond = isTupleName.makeIdent();
        }
        loopBody.append(make().If(cond, make().Exec(make().Assign(iterationVarName.makeIdent(), make().Apply(null, naming.makeQuotedFQIdent("com.redhat.ceylon.compiler.java.Util.getObjectArray"), List.<JCExpression>of(arrayName.makeIdent(), make().Unary(JCTree.POSTINC, arrayIndex.makeIdent()))))), null));
    }
    if (itemDecls != null) {
        loopBody.appendList(itemDecls);
    }
    // The user-supplied contents of the loop
    loopBody.appendList(bodyStmts);
    // ELEM_NAME = LOOP_VAR_NAME$iter$X.next()
    JCExpression iter_elem = make().Apply(null, makeSelect(iterName.makeIdent(), "next"), List.<JCExpression>nil());
    JCExpression elem_assign = make().Assign(iterationVarName.makeIdent(), iter_elem);
    // !((ELEM_NAME = LOOP_VAR_NAME$iter$X.next()) instanceof Finished)
    JCExpression instof = make().TypeTest(elem_assign, makeIdent(syms().ceylonFinishedType));
    JCExpression loopCond = make().Unary(JCTree.NOT, instof);
    if (optForArray || optForTuple) {
        JCExpression cond;
        if (optForArray && optForTuple) {
            cond = make().Binary(JCTree.OR, isTupleName.makeIdent(), isArrayName.makeIdent());
        } else if (optForArray) {
            cond = isArrayName.makeIdent();
        } else {
            cond = isTupleName.makeIdent();
        }
        loopCond = make().Conditional(cond, make().Binary(JCTree.LT, arrayIndex.makeIdent(), arrayLength.makeIdent()), make().Unary(JCTree.NOT, instof));
    }
    // while (!(($elem$X = $V$iter$X.next()) instanceof Finished); ) {
    JCStatement whileLoop = at(node).WhileLoop(loopCond, at(node).Block(0, loopBody.toList()));
    if (label != null) {
        whileLoop = make().Labelled(label, whileLoop);
    }
    return result.append(whileLoop).toList();
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) 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) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Aggregations

JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)98 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)56 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)36 JCTree (com.sun.tools.javac.tree.JCTree)31 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)31 Name (com.sun.tools.javac.util.Name)31 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)27 JavacNode (lombok.javac.JavacNode)27 ListBuffer (com.sun.tools.javac.util.ListBuffer)25 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)24 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)22 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)18 JavacTreeMaker (lombok.javac.JavacTreeMaker)18 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)13 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)12 Type (com.redhat.ceylon.model.typechecker.model.Type)11 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)9 JCMethodInvocation (com.sun.tools.javac.tree.JCTree.JCMethodInvocation)9 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)8 Type (com.sun.tools.javac.code.Type)7