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);
}
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);
}
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;
}
}
Aggregations