Search in sources :

Example 1 with IfElseNode

use of com.google.template.soy.soytree.IfElseNode in project closure-templates by google.

the class GenJsCodeVisitor method generateNonExpressionIfNode.

/**
 * Generates the JavaScript code for an {if} block that cannot be done as an expression.
 *
 * <p>TODO(user): Instead of interleaving JsCodeBuilders like this, consider refactoring
 * GenJsCodeVisitor to return CodeChunks for each sub-Template level SoyNode.
 */
protected void generateNonExpressionIfNode(IfNode node) {
    ConditionalBuilder conditional = null;
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode condNode = (IfCondNode) child;
            // Convert predicate.
            CodeChunk.WithValue predicate = translateExpr(condNode.getExpr());
            // Convert body.
            CodeChunk consequent = visitChildrenReturningCodeChunk(condNode);
            // Add if-block to conditional.
            if (conditional == null) {
                conditional = ifStatement(predicate, consequent);
            } else {
                conditional.elseif_(predicate, consequent);
            }
        } else if (child instanceof IfElseNode) {
            // Convert body.
            CodeChunk trailingElse = visitChildrenReturningCodeChunk((IfElseNode) child);
            // Add else-block to conditional.
            conditional.else_(trailingElse);
        } else {
            throw new AssertionError();
        }
    }
    jsCodeBuilder.append(conditional.build());
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) SoyNode(com.google.template.soy.soytree.SoyNode) IfCondNode(com.google.template.soy.soytree.IfCondNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) ConditionalBuilder(com.google.template.soy.jssrc.dsl.ConditionalBuilder)

Example 2 with IfElseNode

use of com.google.template.soy.soytree.IfElseNode in project closure-templates by google.

the class GenJsExprsVisitor method visitIfNode.

/**
 * Example:
 * <pre>
 *   {if $boo}
 *     AAA
 *   {elseif $foo}
 *     BBB
 *   {else}
 *     CCC
 *   {/if}
 * </pre>
 * might generate
 * <pre>
 *   (opt_data.boo) ? AAA : (opt_data.foo) ? BBB : CCC
 * </pre>
 */
@Override
protected void visitIfNode(IfNode node) {
    // Create another instance of this visitor class for generating JS expressions from children.
    GenJsExprsVisitor genJsExprsVisitor = genJsExprsVisitorFactory.create(translationContext, templateAliases, errorReporter);
    CodeChunk.Generator generator = translationContext.codeGenerator();
    List<CodeChunk.WithValue> ifs = new ArrayList<>();
    List<CodeChunk.WithValue> thens = new ArrayList<>();
    CodeChunk.WithValue trailingElse = null;
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode ifCond = (IfCondNode) child;
            ifs.add(translateExpr(ifCond.getExpr()));
            thens.add(CodeChunkUtils.concatChunks(genJsExprsVisitor.exec(ifCond)));
        } else if (child instanceof IfElseNode) {
            trailingElse = CodeChunkUtils.concatChunks(genJsExprsVisitor.exec(child));
        } else {
            throw new AssertionError();
        }
    }
    Preconditions.checkState(ifs.size() == thens.size());
    ConditionalExpressionBuilder builder = CodeChunk.ifExpression(ifs.get(0), thens.get(0));
    for (int i = 1; i < ifs.size(); i++) {
        builder.elseif_(ifs.get(i), thens.get(i));
    }
    CodeChunk.WithValue ifChunk = trailingElse != null ? builder.else_(trailingElse).build(generator) : builder.else_(LITERAL_EMPTY_STRING).build(generator);
    chunks.add(ifChunk);
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) SoyNode(com.google.template.soy.soytree.SoyNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) ConditionalExpressionBuilder(com.google.template.soy.jssrc.dsl.ConditionalExpressionBuilder) ArrayList(java.util.ArrayList) IfCondNode(com.google.template.soy.soytree.IfCondNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)

Example 3 with IfElseNode

use of com.google.template.soy.soytree.IfElseNode in project closure-templates by google.

the class ResolveExpressionTypesVisitor method visitIfNode.

@Override
protected void visitIfNode(IfNode node) {
    // TODO(user): Also support switch / case.
    TypeSubstitution savedSubstitutionState = substitutions;
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode icn = (IfCondNode) child;
            visitExpressions(icn);
            // Visit the conditional expression to compute which types can be narrowed.
            TypeNarrowingConditionVisitor visitor = new TypeNarrowingConditionVisitor();
            visitor.exec(icn.getExpr());
            // Save the state of substitutions from the previous if block.
            TypeSubstitution previousSubstitutionState = substitutions;
            // Modify the current set of type substitutions for the 'true' branch
            // of the if statement.
            addTypeSubstitutions(visitor.positiveTypeConstraints);
            visitChildren(icn);
            // Rewind the substitutions back to the state before the if-condition.
            // Add in the negative substitutions, which will affect subsequent blocks
            // of the if statement.
            // So for example if we have a variable whose type is (A|B|C) and the
            // first if-block tests whether that variable is type A, then in the
            // 'else' block it must be of type (B|C); If a subsequent 'elseif'
            // statement tests whether it's type B, then in the following else block
            // it can only be of type C.
            substitutions = previousSubstitutionState;
            addTypeSubstitutions(visitor.negativeTypeConstraints);
        } else if (child instanceof IfElseNode) {
            // For the else node, we simply inherit the previous set of subsitutions.
            IfElseNode ien = (IfElseNode) child;
            visitChildren(ien);
        }
    }
    substitutions = savedSubstitutionState;
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) SoyNode(com.google.template.soy.soytree.SoyNode) IfCondNode(com.google.template.soy.soytree.IfCondNode)

Example 4 with IfElseNode

use of com.google.template.soy.soytree.IfElseNode in project closure-templates by google.

the class GenPyExprsVisitor method visitIfNode.

/**
 * If all the children are computable as expressions, the IfNode can be written as a ternary
 * conditional expression.
 */
@Override
protected void visitIfNode(IfNode node) {
    // Create another instance of this visitor for generating Python expressions from children.
    GenPyExprsVisitor genPyExprsVisitor = genPyExprsVisitorFactory.create(localVarExprs, errorReporter);
    TranslateToPyExprVisitor translator = new TranslateToPyExprVisitor(localVarExprs, errorReporter);
    StringBuilder pyExprTextSb = new StringBuilder();
    boolean hasElse = false;
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode icn = (IfCondNode) child;
            // Python ternary conditional expressions modify the order of the conditional from
            // <conditional> ? <true> : <false> to
            // <true> if <conditional> else <false>
            PyExpr condBlock = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(icn)).toPyString();
            condBlock = PyExprUtils.maybeProtect(condBlock, PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL));
            pyExprTextSb.append(condBlock.getText());
            // Append the conditional and if/else syntax.
            PyExpr condPyExpr = translator.exec(icn.getExpr());
            pyExprTextSb.append(" if ").append(condPyExpr.getText()).append(" else ");
        } else if (child instanceof IfElseNode) {
            hasElse = true;
            IfElseNode ien = (IfElseNode) child;
            PyExpr elseBlock = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(ien)).toPyString();
            pyExprTextSb.append(elseBlock.getText());
        } else {
            throw new AssertionError("Unexpected if child node type. Child: " + child);
        }
    }
    if (!hasElse) {
        pyExprTextSb.append("''");
    }
    // By their nature, inline'd conditionals can only contain output strings, so they can be
    // treated as a string type with a conditional precedence.
    pyExprs.add(new PyStringExpr(pyExprTextSb.toString(), PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL)));
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) SoyNode(com.google.template.soy.soytree.SoyNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) IfCondNode(com.google.template.soy.soytree.IfCondNode) PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) PyStringExpr(com.google.template.soy.pysrc.restricted.PyStringExpr)

Example 5 with IfElseNode

use of com.google.template.soy.soytree.IfElseNode in project closure-templates by google.

the class SoyNodeCompiler method visitIfNode.

@Override
protected Statement visitIfNode(IfNode node) {
    List<IfBlock> ifs = new ArrayList<>();
    Optional<Statement> elseBlock = Optional.absent();
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode icn = (IfCondNode) child;
            SoyExpression cond = exprCompiler.compile(icn.getExpr()).coerceToBoolean();
            Statement block = visitChildrenInNewScope(icn);
            ifs.add(IfBlock.create(cond, block));
        } else {
            IfElseNode ien = (IfElseNode) child;
            elseBlock = Optional.of(visitChildrenInNewScope(ien));
        }
    }
    return ControlFlow.ifElseChain(ifs, elseBlock);
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) SoyNode(com.google.template.soy.soytree.SoyNode) IfCondNode(com.google.template.soy.soytree.IfCondNode) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Statement(com.google.template.soy.jbcsrc.restricted.Statement) ArrayList(java.util.ArrayList) IfBlock(com.google.template.soy.jbcsrc.ControlFlow.IfBlock)

Aggregations

IfCondNode (com.google.template.soy.soytree.IfCondNode)5 IfElseNode (com.google.template.soy.soytree.IfElseNode)5 SoyNode (com.google.template.soy.soytree.SoyNode)5 ParentSoyNode (com.google.template.soy.soytree.SoyNode.ParentSoyNode)4 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)2 ArrayList (java.util.ArrayList)2 IfBlock (com.google.template.soy.jbcsrc.ControlFlow.IfBlock)1 SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)1 Statement (com.google.template.soy.jbcsrc.restricted.Statement)1 WithValue (com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)1 ConditionalBuilder (com.google.template.soy.jssrc.dsl.ConditionalBuilder)1 ConditionalExpressionBuilder (com.google.template.soy.jssrc.dsl.ConditionalExpressionBuilder)1 PyExpr (com.google.template.soy.pysrc.restricted.PyExpr)1 PyStringExpr (com.google.template.soy.pysrc.restricted.PyStringExpr)1