Search in sources :

Example 66 with JCStatement

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

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) {
                java.util.List<Expression> caseExprs = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList().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;
                    }
                    java.util.List<Expression> caseExprs = ((Tree.MatchCase) clause.getCaseItem()).getExpressionList().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(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) CaseClause(com.redhat.ceylon.compiler.typechecker.tree.Tree.CaseClause) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Type(com.redhat.ceylon.model.typechecker.model.Type) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) Value(com.redhat.ceylon.model.typechecker.model.Value) CustomTree(com.redhat.ceylon.compiler.typechecker.tree.CustomTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) ConditionList(com.redhat.ceylon.compiler.typechecker.tree.Tree.ConditionList) List(com.sun.tools.javac.util.List) ArrayList(java.util.ArrayList)

Example 67 with JCStatement

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

the class StatementTransformer method transformCatchesIfElseIf.

/**
     * Transforms a list of {@code CatchClause}s to a single {@code JCCatch} 
     * containing and if/else if chain for finding the appropriate catch block.
     * @see #transformCatchesPolymorphic(java.util.List)
     */
private List<JCCatch> transformCatchesIfElseIf(java.util.List<Tree.CatchClause> catchClauses) {
    Type supertype = intersectionOfCatchClauseTypes(catchClauses);
    JCExpression exceptionType = makeJavaType(supertype, JT_CATCH | JT_RAW);
    SyntheticName exceptionVar = naming.alias("exception");
    JCVariableDecl param = make().VarDef(make().Modifiers(Flags.FINAL), exceptionVar.asName(), exceptionType, null);
    ArrayList<Tree.CatchClause> reversed = new ArrayList<Tree.CatchClause>(catchClauses);
    Collections.reverse(reversed);
    JCStatement elsePart = make().Throw(exceptionVar.makeIdent());
    for (Tree.CatchClause catchClause : reversed) {
        Tree.Variable caughtVar = catchClause.getCatchVariable().getVariable();
        Type caughtType = caughtVar.getType().getTypeModel();
        List<JCStatement> catchBlock = transformBlock(catchClause.getBlock());
        catchBlock = catchBlock.prepend(makeVar(FINAL, caughtVar.getIdentifier().getText(), makeJavaType(caughtType), expressionGen().applyErasureAndBoxing(exceptionVar.makeIdent(), supertype, true, true, BoxingStrategy.BOXED, caughtType, 0)));
        elsePart = make().If(makeOptimizedTypeTest(null, exceptionVar, caughtType, supertype), make().Block(0, catchBlock), elsePart);
    }
    return List.of(make().Catch(param, make().Block(0, List.<JCStatement>of(elsePart))));
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Variable(com.redhat.ceylon.compiler.typechecker.tree.Tree.Variable) ArrayList(java.util.ArrayList) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) CustomTree(com.redhat.ceylon.compiler.typechecker.tree.CustomTree) 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)

Example 68 with JCStatement

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

the class NamedArgumentInvocation method bindSpecifiedArgument.

private void bindSpecifiedArgument(Tree.SpecifiedArgument specifiedArg, Parameter declaredParam, Naming.SyntheticName argName) {
    ListBuffer<JCStatement> statements;
    Tree.Expression expr = specifiedArg.getSpecifierExpression().getExpression();
    Type type = parameterType(declaredParam, expr.getTypeModel(), gen.TP_TO_BOUND);
    final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam);
    int jtFlags = 0;
    int exprFlags = 0;
    if (boxType == BoxingStrategy.BOXED)
        jtFlags |= JT_TYPE_ARGUMENT;
    if (!isParameterRaw(declaredParam)) {
        exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_NOT_RAW;
    }
    if (isParameterWithConstrainedTypeParameters(declaredParam)) {
        exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS;
        // we can't just generate types like Foo<?> if the target type param is not raw because the bounds will
        // not match, so we go raw
        jtFlags |= JT_RAW;
    }
    if (isParameterWithDependentCovariantTypeParameters(declaredParam)) {
        exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS;
    }
    if (erasedArgument(TreeUtil.unwrapExpressionUntilTerm(expr))) {
        exprFlags |= ExpressionTransformer.EXPR_DOWN_CAST;
    }
    JCExpression typeExpr = gen.makeJavaType(type, jtFlags);
    JCExpression argExpr = gen.expressionGen().transformExpression(expr, boxType, type, exprFlags);
    JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, argExpr);
    statements = ListBuffer.<JCStatement>of(varDecl);
    bind(declaredParam, argName, gen.makeJavaType(type, jtFlags), statements.toList());
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 69 with JCStatement

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

the class NamedArgumentInvocation method bindAttributeArgument.

private void bindAttributeArgument(Tree.AttributeArgument attrArg, Parameter declaredParam, Naming.SyntheticName argName) {
    ListBuffer<JCStatement> statements;
    final Value model = attrArg.getDeclarationModel();
    final String name = model.getName();
    String className = Naming.getAttrClassName(model, 0);
    final List<JCTree> attrClass = gen.gen().transformAttribute(model, name, className, null, attrArg.getBlock(), attrArg.getSpecifierExpression(), null, null);
    TypedReference typedRef = gen.getTypedReference(model);
    TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
    Type nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef);
    Type type = parameterType(declaredParam, model.getType(), 0);
    final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam);
    JCExpression initValue = gen.make().Apply(null, gen.makeSelect(gen.makeUnquotedIdent(className), Naming.getGetterName(model)), List.<JCExpression>nil());
    initValue = gen.expressionGen().applyErasureAndBoxing(initValue, nonWideningType, !CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration()), boxType, type);
    JCTree.JCVariableDecl var = gen.make().VarDef(gen.make().Modifiers(FINAL, List.<JCAnnotation>nil()), argName.asName(), gen.makeJavaType(type, boxType == BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), initValue);
    statements = toStmts(attrArg, attrClass).append(var);
    bind(declaredParam, argName, gen.makeJavaType(type, boxType == BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), statements.toList());
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) Value(com.redhat.ceylon.model.typechecker.model.Value) JCTree(com.sun.tools.javac.tree.JCTree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) BoxingStrategy(com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Example 70 with JCStatement

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

the class StatementTransformer method transformCaseIs.

/**
     * Transform a "case(is ...)"
     * @param selectorAlias
     * @param caseClause
     * @param isCase
     * @param last
     * @return
     */
private JCStatement transformCaseIs(Naming.SyntheticName selectorAlias, Tree.CaseClause caseClause, String tmpVar, Tree.Term outerExpression, Type expectedType, Tree.IsCase isCase, JCStatement last, Type expressionType) {
    at(isCase);
    // Use the type of the variable, which is more precise than the type we test for.
    Type varType = isCase.getVariable().getDeclarationModel().getType();
    Type caseType = isCase.getType().getTypeModel();
    // note: There's no point using makeOptimizedTypeTest() because cases are disjoint
    // anyway and the cheap cases get evaluated first.
    JCExpression cond = makeTypeTest(null, selectorAlias, caseType, expressionType);
    String name = isCase.getVariable().getIdentifier().getText();
    TypedDeclaration varDecl = isCase.getVariable().getDeclarationModel();
    Naming.SyntheticName tmpVarName = selectorAlias;
    Name substVarName = naming.aliasName(name);
    // Want raw type for instanceof since it can't be used with generic types
    JCExpression rawToTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES | JT_RAW);
    // Substitute variable with the correct type to use in the rest of the code block
    JCExpression tmpVarExpr = at(isCase).TypeCast(rawToTypeExpr, tmpVarName.makeIdent());
    JCExpression toTypeExpr;
    if (isCeylonBasicType(varType) && varDecl.getUnboxed() == true) {
        toTypeExpr = makeJavaType(varType);
        tmpVarExpr = unboxType(tmpVarExpr, varType);
    } else {
        toTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES);
    }
    // The variable holding the result for the code inside the code block
    JCVariableDecl decl2 = at(isCase).VarDef(make().Modifiers(FINAL), substVarName, toTypeExpr, tmpVarExpr);
    // Prepare for variable substitution in the following code block
    Substitution prevSubst = naming.addVariableSubst(varDecl, substVarName.toString());
    List<JCStatement> stats = List.<JCStatement>of(decl2);
    stats = stats.appendList(transformCaseClause(caseClause, tmpVar, outerExpression, expectedType));
    JCBlock block = at(isCase).Block(0, stats);
    // Deactivate the above variable substitution
    prevSubst.close();
    last = make().If(cond, block, last);
    return last;
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) 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) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) CName(com.redhat.ceylon.compiler.java.codegen.Naming.CName) Name(com.sun.tools.javac.util.Name) OptionName(com.sun.tools.javac.main.OptionName)

Aggregations

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