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