Search in sources :

Example 1 with IfBlock

use of com.google.template.soy.jbcsrc.ControlFlow.IfBlock 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 IfBlock

use of com.google.template.soy.jbcsrc.ControlFlow.IfBlock 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)

Example 3 with IfBlock

use of com.google.template.soy.jbcsrc.ControlFlow.IfBlock in project closure-templates by google.

the class SoyNodeCompiler method visitMsgFallbackGroupNode.

/**
 * MsgFallbackGroupNodes have either one or two children. In the 2 child case the second child is
 * the {@code {fallbackmsg}} entry. For this we generate code that looks like:
 *
 * <pre>{@code
 * if (renderContext.hasMsg(primaryId)) {
 *   <render primary msg>
 * } else {
 *   <render fallback msg>
 * }
 * }</pre>
 *
 * <p>All of the logic for actually rendering {@code msg} nodes is handled by the {@link
 * MsgCompiler}.
 */
@Override
protected Statement visitMsgFallbackGroupNode(MsgFallbackGroupNode node) {
    MsgNode msg = node.getMsg();
    MsgPartsAndIds idAndParts = MsgUtils.buildMsgPartsAndComputeMsgIdForDualFormat(msg);
    ImmutableList<SoyPrintDirective> escapingDirectives = node.getEscapingDirectives();
    Statement renderDefault = getMsgCompiler().compileMessage(idAndParts, msg, escapingDirectives);
    // need to check for presence.
    if (node.hasFallbackMsg()) {
        MsgNode fallback = node.getFallbackMsg();
        MsgPartsAndIds fallbackIdAndParts = MsgUtils.buildMsgPartsAndComputeMsgIdForDualFormat(fallback);
        // TODO(lukes): consider changing the control flow here by 'inlining' the usePrimaryMsg logic
        // it would save some lookups.  Right now we will do to 2- 3 calls to
        // SoyMsgBundle.getMsgParts (each of which requires a binary search).  We could reduce that
        // to 1-2 in the worse case by inlining and storing the lists in local variables.
        IfBlock ifAvailableRenderDefault = IfBlock.create(parameterLookup.getRenderContext().usePrimaryMsg(idAndParts.id, fallbackIdAndParts.id), renderDefault);
        return ControlFlow.ifElseChain(ImmutableList.of(ifAvailableRenderDefault), Optional.of(getMsgCompiler().compileMessage(fallbackIdAndParts, fallback, escapingDirectives)));
    } else {
        return renderDefault;
    }
}
Also used : SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) Statement(com.google.template.soy.jbcsrc.restricted.Statement) IfBlock(com.google.template.soy.jbcsrc.ControlFlow.IfBlock) MsgPartsAndIds(com.google.template.soy.msgs.internal.MsgUtils.MsgPartsAndIds) MsgNode(com.google.template.soy.soytree.MsgNode)

Aggregations

IfBlock (com.google.template.soy.jbcsrc.ControlFlow.IfBlock)3 Statement (com.google.template.soy.jbcsrc.restricted.Statement)3 SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)2 SoyNode (com.google.template.soy.soytree.SoyNode)2 ArrayList (java.util.ArrayList)2 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)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 MsgPartsAndIds (com.google.template.soy.msgs.internal.MsgUtils.MsgPartsAndIds)1 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)1 IfCondNode (com.google.template.soy.soytree.IfCondNode)1 IfElseNode (com.google.template.soy.soytree.IfElseNode)1 MsgNode (com.google.template.soy.soytree.MsgNode)1 BlockNode (com.google.template.soy.soytree.SoyNode.BlockNode)1 SwitchCaseNode (com.google.template.soy.soytree.SwitchCaseNode)1 SwitchDefaultNode (com.google.template.soy.soytree.SwitchDefaultNode)1 Label (org.objectweb.asm.Label)1