Search in sources :

Example 31 with JCStatement

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

the class StatementTransformer method transform.

/**
 * Transforms a Ceylon destructuring assignment to Java code.
 * @param stmt The Ceylon destructure
 * @return The Java tree
 */
List<JCStatement> transform(Tree.Destructure stmt) {
    List<JCStatement> result = List.nil();
    // Create temp var to hold result of expression
    Tree.Pattern pat = stmt.getPattern();
    Naming.SyntheticName tmpVarName = naming.synthetic(pat);
    Expression destExpr = stmt.getSpecifierExpression().getExpression();
    JCExpression typeExpr = makeJavaType(destExpr.getTypeModel());
    JCExpression expr = expressionGen().transformExpression(destExpr);
    at(stmt);
    JCVariableDecl tmpVar = makeVar(Flags.FINAL, tmpVarName, typeExpr, expr);
    result = result.append(tmpVar);
    // Now add the destructured variables
    List<VarDefBuilder> destructured = transformPattern(pat, tmpVarName.makeIdent());
    for (VarDefBuilder vdb : destructured) {
        Value v = vdb.var.getDeclarationModel();
        at(vdb.var);
        if (v.isClassMember() && v.isCaptured()) {
            AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.getter(this, v.getName(), v);
            adb.immutable();
            classGen().current().attribute(adb);
            classGen().current().defs(vdb.buildDefOnly());
            result = result.append(make().Exec(make().Assign(vdb.name().makeIdentWithThis(), vdb.expr())));
        } else {
            result = result.append(vdb.build());
        }
    }
    return result;
}
Also used : 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) SpecifierOrInitializerExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Value(org.eclipse.ceylon.model.typechecker.model.Value) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 32 with JCStatement

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

the class StatementTransformer method transform.

// FIXME There is a similar implementation in ClassGen!
public List<JCStatement> transform(Tree.AttributeDeclaration decl) {
    ListBuffer<JCStatement> result = new ListBuffer<JCStatement>();
    // If the attribute is really from a parameter then don't generate a local variable
    Parameter parameter = CodegenUtil.findParamForDecl(decl);
    if (parameter == null) {
        final Name attrName = names().fromString(naming.substitute(decl.getDeclarationModel()));
        Type t = decl.getDeclarationModel().getType();
        JCExpression initialValue = null;
        SpecifierOrInitializerExpression initOrSpec = decl.getSpecifierOrInitializerExpression();
        if (initOrSpec != null) {
            HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(initOrSpec.getExpression().getTerm());
            if (error != null) {
                return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
            }
            int flags = CodegenUtil.downcastForSmall(initOrSpec.getExpression(), decl.getDeclarationModel()) ? ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK : 0;
            flags |= decl.getDeclarationModel().hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0;
            initialValue = expressionGen().transformExpression(initOrSpec.getExpression(), CodegenUtil.getBoxingStrategy(decl.getDeclarationModel()), decl.getDeclarationModel().getType(), flags);
        } else if (decl.getDeclarationModel().isVariable()) {
            // Java's definite initialization doesn't always work
            // so give variable attribute declarations without
            // initializers a default value. See #1153.
            initialValue = makeDefaultExprForType(t);
            if (CodegenUtil.getBoxingStrategy(decl.getDeclarationModel()) == BoxingStrategy.BOXED && canUnbox(t)) {
                initialValue = boxType(initialValue, t);
            }
        }
        List<JCAnnotation> annots = List.<JCAnnotation>nil();
        int modifiers = transformLocalFieldDeclFlags(decl);
        JCExpression typeExpr = makeJavaType(decl.getDeclarationModel(), t, modifiers);
        result.append(at(decl.getIdentifier()).VarDef(at(decl.getIdentifier()).Modifiers(modifiers, annots), attrName, typeExpr, initialValue));
        JCStatement outerSubs = openOuterSubstitutionIfNeeded(decl.getDeclarationModel(), t, modifiers);
        if (outerSubs != null) {
            result.append(outerSubs);
        }
    }
    return result.toList();
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) HasErrorException(org.eclipse.ceylon.compiler.java.codegen.recovery.HasErrorException) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) SpecifierOrInitializerExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation) Name(org.eclipse.ceylon.langtools.tools.javac.util.Name) CName(org.eclipse.ceylon.compiler.java.codegen.Naming.CName) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 33 with JCStatement

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

the class StatementTransformer method transform.

JCStatement transform(Node node, Tree.SwitchClause switchClause, Tree.SwitchCaseList caseList, String tmpVar, Tree.Term outerExpression, Type expectedType) {
    at(switchClause);
    block();
    SwitchTransformation transformation = null;
    Type exprType = switchExpressionType(switchClause);
    Boolean switchUnboxed = switchExpressionUnboxed(switchClause);
    // Are we switching with just String literal or Character literal match cases?
    if (isJavaSwitchableType(exprType, switchUnboxed)) {
        boolean canUseSwitch = true;
        caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
            if (clause.getCaseItem() instanceof Tree.MatchCase) {
                Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
                if (!matchList.getTypes().isEmpty()) {
                    canUseSwitch = false;
                    break caseStmts;
                }
                java.util.List<Expression> caseExprs = matchList.getExpressions();
                caseExpr: for (Tree.Expression expr : caseExprs) {
                    Tree.Term e = ExpressionTransformer.eliminateParens(expr);
                    if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
                        continue caseExpr;
                    } else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
                        continue caseExpr;
                    } else {
                        canUseSwitch = false;
                        break caseStmts;
                    }
                }
            } else {
                canUseSwitch = false;
                break caseStmts;
            }
        }
        if (canUseSwitch) {
            // yes, so use a Java Switch
            transformation = new Switch();
        }
    }
    if (transformation == null && isOptional(exprType)) {
        // Are we switching with just String literal or Character literal plus null
        // match cases?
        Type definiteType = typeFact().getDefiniteType(exprType);
        if (isJavaSwitchableType(definiteType, switchUnboxed)) {
            boolean canUseIfElseSwitch = true;
            boolean hasSingletonNullCase = false;
            caseStmts: for (Tree.CaseClause clause : caseList.getCaseClauses()) {
                if (clause.getCaseItem() instanceof Tree.MatchCase) {
                    if (getSingletonNullCase(clause) != null) {
                        hasSingletonNullCase = true;
                    }
                    Tree.MatchList matchList = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList();
                    if (!matchList.getTypes().isEmpty()) {
                        canUseIfElseSwitch = false;
                        break caseStmts;
                    }
                    java.util.List<Expression> caseExprs = matchList.getExpressions();
                    caseExpr: for (Tree.Expression expr : caseExprs) {
                        Tree.Term e = ExpressionTransformer.eliminateParens(expr);
                        if (e instanceof Tree.StringLiteral || e instanceof Tree.CharLiteral) {
                            continue caseExpr;
                        } else if (e instanceof Tree.BaseMemberExpression && isNullValue(((Tree.BaseMemberExpression) e).getDeclaration()) && caseExprs.size() == 1) {
                            continue caseExpr;
                        } else if (e instanceof Tree.BaseMemberExpression && ((Tree.BaseMemberExpression) e).getDeclaration() instanceof Value && ((Value) ((Tree.BaseMemberExpression) e).getDeclaration()).isEnumValue()) {
                            continue caseExpr;
                        } else {
                            canUseIfElseSwitch = false;
                            break caseStmts;
                        }
                    }
                } else {
                    canUseIfElseSwitch = false;
                    break caseStmts;
                }
            }
            canUseIfElseSwitch &= hasSingletonNullCase;
            if (canUseIfElseSwitch) {
                // yes, so use a If
                transformation = new IfNullElseSwitch();
            }
        }
    }
    // The default transformation
    if (transformation == null) {
        transformation = new IfElseChain();
    }
    JCStatement result = transformation.transformSwitch(node, switchClause, caseList, tmpVar, outerExpression, expectedType);
    unblock();
    return result;
}
Also used : Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) CaseClause(org.eclipse.ceylon.compiler.typechecker.tree.Tree.CaseClause) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Type(org.eclipse.ceylon.model.typechecker.model.Type) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Value(org.eclipse.ceylon.model.typechecker.model.Value) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) List(org.eclipse.ceylon.langtools.tools.javac.util.List) ArrayList(java.util.ArrayList)

Example 34 with JCStatement

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

the class CeylonVisitor method transformConstructor.

private void transformConstructor(Tree.Declaration ctor, Tree.ParameterList parameterList, Tree.DelegatedConstructor delegatedCtor, Tree.Block block, Constructor ctorModel, Map<Constructor, CtorDelegation> delegates) {
    TransformationPlan plan = gen.errors().hasDeclarationAndMarkBrokenness(ctor);
    if (plan instanceof Drop) {
        return;
    }
    if (parameterList != null) {
        for (Parameter param : parameterList.getModel().getParameters()) {
            FunctionOrValue model = param.getModel();
            if (Naming.aliasConstructorParameterName(model)) {
                gen.naming.addVariableSubst(model, Naming.suffixName(Suffix.$param$, param.getName()));
            }
        }
    }
    final CtorDelegation delegation = delegates.get(ctorModel);
    ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
    boolean delegatedTo = CtorDelegation.isDelegatedTo(delegates, ctorModel);
    if (delegatedTo && !ctorModel.isAbstract()) {
        Tree.InvocationExpression chainedCtorInvocation;
        if (delegatedCtor != null) {
            chainedCtorInvocation = delegatedCtor.getInvocationExpression();
        } else {
            chainedCtorInvocation = null;
        }
        // We need to generate $delegation$ delegation constructor
        makeDelegationConstructor(ctor, parameterList, delegatedCtor, block, ctorModel, delegation, chainedCtorInvocation);
        JCStatement delegateExpr;
        if (chainedCtorInvocation != null) {
            delegateExpr = gen.expressionGen().transformConstructorDelegation(chainedCtorInvocation, delegation.isSelfDelegation() ? delegation : new CtorDelegation(ctorModel, ctorModel), chainedCtorInvocation, classBuilder, !delegation.isSelfDelegation());
        } else {
            // In this case there is no extends clause in the source code
            // so we have to construct the argument list "by hand".
            ListBuffer<JCExpression> arguments = new ListBuffer<JCExpression>();
            for (TypeParameter tp : ((Class) delegation.getConstructor().getContainer()).getTypeParameters()) {
                arguments.add(gen.makeReifiedTypeArgument(tp.getType()));
            }
            arguments.add(gen.naming.makeNamedConstructorName(delegation.getConstructor(), true));
            for (Parameter p : delegation.getConstructor().getFirstParameterList().getParameters()) {
                arguments.add(gen.naming.makeName(p.getModel(), Naming.NA_IDENT));
            }
            delegateExpr = gen.make().Exec(gen.make().Apply(null, gen.naming.makeThis(), arguments.toList()));
        }
        stmts.add(delegateExpr);
    } else if (delegatedCtor != null) {
        stmts.add(gen.expressionGen().transformConstructorDelegation(delegatedCtor, delegation, delegatedCtor.getInvocationExpression(), classBuilder, false));
    } else {
    // no explicit extends clause
    }
    final boolean addBody;
    if (delegatedTo && (delegation.isAbstractSelfOrSuperDelegation())) {
        if (delegation.getConstructor().isAbstract()) {
            stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(null, ctorModel));
            addBody = true;
        } else if (delegation.getExtendingConstructor() != null && delegation.getExtendingConstructor().isAbstract()) {
            stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
            addBody = true;
        } else {
            addBody = false;
        }
    } else if (delegation.isAbstractSelfDelegation()) {
        // delegating to abstract
        stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
        addBody = true;
    } else if (delegation.isConcreteSelfDelegation()) {
        stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
        addBody = true;
    } else {
        // super delegation
        stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(null, ctorModel));
        addBody = true;
    }
    if (ctorModel.isAbstract() && !delegatedTo) {
        stmts.add(gen.make().Throw(gen.make().NewClass(null, List.<JCExpression>nil(), gen.make().QualIdent(gen.syms().ceylonUninvokableErrorType.tsym), List.<JCExpression>nil(), null)));
    }
    List<JCStatement> following = ctorModel.isAbstract() ? List.<JCStatement>nil() : classBuilder.getInitBuilder().copyStatementsBetween(ctorModel, null);
    if (addBody) {
        if (following.isEmpty()) {
            stmts.addAll(gen.statementGen().transformBlock(block));
        } else {
            Name label = gen.naming.aliasName(Naming.Unfix.$return$.toString());
            Transformer<JCStatement, Return> prev = gen.statementGen().returnTransformer(gen.statementGen().new ConstructorReturnTransformer(label));
            try {
                stmts.add(gen.make().Labelled(label, gen.make().DoLoop(gen.make().Block(0, gen.statementGen().transformBlock(block, true)), gen.make().Literal(false))));
            } finally {
                gen.statementGen().returnTransformer(prev);
            }
        }
    }
    ThrowVisitor visitor = new ThrowVisitor();
    block.visit(visitor);
    if (!visitor.getDefinitelyReturnsViaThrow()) {
        stmts.addAll(following);
    }
    String ctorName = !Decl.isDefaultConstructor(ctorModel) ? gen.naming.makeTypeDeclarationName(ctorModel) : null;
    classBuilder.defs(gen.classGen().makeNamedConstructor(ctor, parameterList, ctorModel, classBuilder, Strategy.generateInstantiator(ctorModel), gen.classGen().modifierTransformation().constructor(ctorModel), false, ctorName, stmts.toList(), DeclNameFlag.QUALIFIED));
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Return(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Return) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Drop(org.eclipse.ceylon.compiler.java.codegen.recovery.Drop) Name(org.eclipse.ceylon.langtools.tools.javac.util.Name) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Class(org.eclipse.ceylon.model.typechecker.model.Class) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) TransformationPlan(org.eclipse.ceylon.compiler.java.codegen.recovery.TransformationPlan) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 35 with JCStatement

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

the class ClassDefinitionBuilder method addRefineReifiedTypeParametersMethod.

public ClassDefinitionBuilder addRefineReifiedTypeParametersMethod(java.util.List<TypeParameter> typeParameterList) {
    MethodDefinitionBuilder method = MethodDefinitionBuilder.systemMethod(gen, gen.naming.getRefineTypeParametersMethodName());
    method.modifiers(PUBLIC);
    method.ignoreModelAnnotations();
    List<JCStatement> body = List.nil();
    for (TypeParameter tp : typeParameterList) {
        String descriptorName = gen.naming.getTypeArgumentDescriptorName(tp);
        method.parameter(makeReifiedParameter(descriptorName));
        body = body.prepend(gen.makeReifiedTypeParameterAssignment(tp));
    }
    method.body(body);
    defs(method.build());
    return this;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)

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