Search in sources :

Example 1 with SwitchCaseNode

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

the class SoyNodeCompiler method visitSwitchNode.

@Override
protected Statement visitSwitchNode(SwitchNode node) {
    // A few special cases:
    // 1. only a {default} block.  In this case we can skip all the switch logic and temporaries
    // 2. no children.  Just return the empty statement
    // Note that in both of these cases we do not evalutate (or generate code) for the switch
    // expression.
    List<BlockNode> children = node.getChildren();
    if (children.isEmpty()) {
        return Statement.NULL_STATEMENT;
    }
    if (children.size() == 1 && children.get(0) instanceof SwitchDefaultNode) {
        return visitChildrenInNewScope(children.get(0));
    }
    // otherwise we need to evaluate the switch variable and generate dispatching logic.
    SoyExpression switchVar = exprCompiler.compile(node.getExpr());
    Scope scope = variables.enterScope();
    Variable variable = scope.createSynthetic(SyntheticVarName.forSwitch(node), switchVar, STORE);
    Statement initializer = variable.initializer();
    switchVar = switchVar.withSource(variable.local());
    List<IfBlock> cases = new ArrayList<>();
    Optional<Statement> defaultBlock = Optional.absent();
    for (SoyNode child : children) {
        if (child instanceof SwitchCaseNode) {
            SwitchCaseNode caseNode = (SwitchCaseNode) child;
            Label reattachPoint = new Label();
            List<Expression> comparisons = new ArrayList<>();
            for (ExprRootNode caseExpr : caseNode.getExprList()) {
                comparisons.add(compareSoyEquals(switchVar, exprCompiler.compile(caseExpr, reattachPoint)));
            }
            Expression condition = BytecodeUtils.logicalOr(comparisons).labelStart(reattachPoint);
            Statement block = visitChildrenInNewScope(caseNode);
            cases.add(IfBlock.create(condition, block));
        } else {
            SwitchDefaultNode defaultNode = (SwitchDefaultNode) child;
            defaultBlock = Optional.of(visitChildrenInNewScope(defaultNode));
        }
    }
    Statement exitScope = scope.exitScope();
    // generation that we could maybe use
    return Statement.concat(initializer, ControlFlow.ifElseChain(cases, defaultBlock), exitScope);
}
Also used : BlockNode(com.google.template.soy.soytree.SoyNode.BlockNode) SoyNode(com.google.template.soy.soytree.SoyNode) Variable(com.google.template.soy.jbcsrc.TemplateVariableManager.Variable) Statement(com.google.template.soy.jbcsrc.restricted.Statement) ArrayList(java.util.ArrayList) Label(org.objectweb.asm.Label) ExprRootNode(com.google.template.soy.exprtree.ExprRootNode) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Scope(com.google.template.soy.jbcsrc.TemplateVariableManager.Scope) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Expression(com.google.template.soy.jbcsrc.restricted.Expression) SwitchCaseNode(com.google.template.soy.soytree.SwitchCaseNode) IfBlock(com.google.template.soy.jbcsrc.ControlFlow.IfBlock) SwitchDefaultNode(com.google.template.soy.soytree.SwitchDefaultNode)

Example 2 with SwitchCaseNode

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

the class GenJsCodeVisitor method visitSwitchNode.

/**
 * Example:
 *
 * <pre>
 *   {switch $boo}
 *     {case 0}
 *       ...
 *     {case 1, 2}
 *       ...
 *     {default}
 *       ...
 *   {/switch}
 * </pre>
 *
 * might generate
 *
 * <pre>
 *   switch (opt_data.boo) {
 *     case 0:
 *       ...
 *       break;
 *     case 1:
 *     case 2:
 *       ...
 *       break;
 *     default:
 *       ...
 *   }
 * </pre>
 */
@Override
protected void visitSwitchNode(SwitchNode node) {
    CodeChunk.WithValue switchOn = coerceTypeForSwitchComparison(node.getExpr());
    SwitchBuilder switchBuilder = switch_(switchOn);
    for (SoyNode child : node.getChildren()) {
        if (child instanceof SwitchCaseNode) {
            SwitchCaseNode scn = (SwitchCaseNode) child;
            ImmutableList.Builder<CodeChunk.WithValue> caseChunks = ImmutableList.builder();
            for (ExprNode caseExpr : scn.getExprList()) {
                CodeChunk.WithValue caseChunk = translateExpr(caseExpr);
                caseChunks.add(caseChunk);
            }
            CodeChunk body = visitChildrenReturningCodeChunk(scn);
            switchBuilder.case_(caseChunks.build(), body);
        } else if (child instanceof SwitchDefaultNode) {
            CodeChunk body = visitChildrenReturningCodeChunk((SwitchDefaultNode) child);
            switchBuilder.default_(body);
        } else {
            throw new AssertionError();
        }
    }
    jsCodeBuilder.append(switchBuilder.build());
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) SoyNode(com.google.template.soy.soytree.SoyNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SwitchBuilder(com.google.template.soy.jssrc.dsl.SwitchBuilder) ImmutableList(com.google.common.collect.ImmutableList) SwitchCaseNode(com.google.template.soy.soytree.SwitchCaseNode) SwitchDefaultNode(com.google.template.soy.soytree.SwitchDefaultNode)

Example 3 with SwitchCaseNode

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

the class TemplateParserTest method testParseSwitchStmt.

@Test
public void testParseSwitchStmt() throws Exception {
    String templateBody = "{@param boo: ?}{@param foo : ?}{@param moo : ?}\n" + "  {switch $boo} {case 0}Blah\n" + "    {case $foo.goo}\n" + "      Bleh\n" + "    {case -1, 1, $moo}\n" + "      Bluh\n" + "    {default}\n" + "      Bloh\n" + "  {/switch}\n";
    List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
    assertEquals(1, nodes.size());
    SwitchNode sn = (SwitchNode) nodes.get(0);
    assertEquals("$boo", sn.getExpr().toSourceString());
    assertTrue(sn.getExpr().getRoot() instanceof VarRefNode);
    assertEquals(4, sn.numChildren());
    SwitchCaseNode scn0 = (SwitchCaseNode) sn.getChild(0);
    assertEquals(1, scn0.getExprList().size());
    assertTrue(scn0.getExprList().get(0).getRoot() instanceof IntegerNode);
    assertEquals(0, ((IntegerNode) scn0.getExprList().get(0).getRoot()).getValue());
    SwitchCaseNode scn1 = (SwitchCaseNode) sn.getChild(1);
    assertEquals(1, scn1.getExprList().size());
    assertTrue(scn1.getExprList().get(0).getRoot() instanceof FieldAccessNode);
    assertEquals("$foo.goo", scn1.getExprList().get(0).getRoot().toSourceString());
    SwitchCaseNode scn2 = (SwitchCaseNode) sn.getChild(2);
    assertEquals(3, scn2.getExprList().size());
    assertTrue(scn2.getExprList().get(0).getRoot() instanceof IntegerNode);
    assertTrue(scn2.getExprList().get(1).getRoot() instanceof IntegerNode);
    assertTrue(scn2.getExprList().get(2).getRoot() instanceof VarRefNode);
    assertEquals("-1", scn2.getExprList().get(0).getRoot().toSourceString());
    assertEquals("1", scn2.getExprList().get(1).getRoot().toSourceString());
    assertEquals("$moo", scn2.getExprList().get(2).getRoot().toSourceString());
    assertEquals("Bluh", ((RawTextNode) scn2.getChild(0)).getRawText());
    assertEquals("Bloh", ((RawTextNode) ((SwitchDefaultNode) sn.getChild(3)).getChild(0)).getRawText());
    assertEquals("{switch $boo}{case 0}Blah{case $foo.goo}Bleh{case -1, 1, $moo}Bluh{default}Bloh{/switch}", sn.toSourceString());
}
Also used : StandaloneNode(com.google.template.soy.soytree.SoyNode.StandaloneNode) VarRefNode(com.google.template.soy.exprtree.VarRefNode) IntegerNode(com.google.template.soy.exprtree.IntegerNode) SwitchCaseNode(com.google.template.soy.soytree.SwitchCaseNode) SwitchNode(com.google.template.soy.soytree.SwitchNode) FieldAccessNode(com.google.template.soy.exprtree.FieldAccessNode) SwitchDefaultNode(com.google.template.soy.soytree.SwitchDefaultNode) Test(org.junit.Test)

Aggregations

SwitchCaseNode (com.google.template.soy.soytree.SwitchCaseNode)3 SwitchDefaultNode (com.google.template.soy.soytree.SwitchDefaultNode)3 SoyNode (com.google.template.soy.soytree.SoyNode)2 ImmutableList (com.google.common.collect.ImmutableList)1 ExprNode (com.google.template.soy.exprtree.ExprNode)1 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)1 FieldAccessNode (com.google.template.soy.exprtree.FieldAccessNode)1 IntegerNode (com.google.template.soy.exprtree.IntegerNode)1 VarRefNode (com.google.template.soy.exprtree.VarRefNode)1 IfBlock (com.google.template.soy.jbcsrc.ControlFlow.IfBlock)1 Scope (com.google.template.soy.jbcsrc.TemplateVariableManager.Scope)1 Variable (com.google.template.soy.jbcsrc.TemplateVariableManager.Variable)1 Expression (com.google.template.soy.jbcsrc.restricted.Expression)1 SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)1 Statement (com.google.template.soy.jbcsrc.restricted.Statement)1 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)1 SwitchBuilder (com.google.template.soy.jssrc.dsl.SwitchBuilder)1 BlockNode (com.google.template.soy.soytree.SoyNode.BlockNode)1 ParentSoyNode (com.google.template.soy.soytree.SoyNode.ParentSoyNode)1 StandaloneNode (com.google.template.soy.soytree.SoyNode.StandaloneNode)1