use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.
the class MsgFuncGenerator method pyFuncForPluralMsg.
private PyStringExpr pyFuncForPluralMsg() {
SoyMsgPluralPart pluralPart = (SoyMsgPluralPart) msgParts.get(0);
MsgPluralNode pluralNode = msgNode.getRepPluralNode(pluralPart.getPluralVarName());
Map<PyExpr, PyExpr> nodePyVarToPyExprMap = collectVarNameListAndToPyExprMap();
Map<PyExpr, PyExpr> caseSpecStrToMsgTexts = new LinkedHashMap<>();
for (Case<SoyMsgPluralCaseSpec> pluralCase : pluralPart.getCases()) {
caseSpecStrToMsgTexts.put(new PyStringExpr("'" + pluralCase.spec() + "'"), new PyStringExpr("'" + processMsgPartsHelper(pluralCase.parts(), escaperForIcuSection) + "'"));
}
prepareFunc.addArg(msgId).addArg(PyExprUtils.convertMapToPyExpr(caseSpecStrToMsgTexts)).addArg(PyExprUtils.convertIterableToPyTupleExpr(nodePyVarToPyExprMap.keySet()));
// Translates {@link MsgPluralNode#pluralExpr} into a Python lookup expression.
// Note that pluralExpr represent the Soy expression inside the attributes of a plural tag.
PyExpr pluralPyExpr = translateToPyExprVisitor.exec(pluralNode.getExpr());
return renderFunc.addArg(prepareFunc.asPyExpr()).addArg(pluralPyExpr).addArg(PyExprUtils.convertMapToPyExpr(nodePyVarToPyExprMap)).asPyStringExpr();
}
use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.
the class GenPyCallExprVisitor method genObjToPass.
/**
* Generates the Python expression for the object to pass in a given call. This expression will be
* a combination of passed data and additional content params. If both are passed, they'll be
* combined into one dictionary.
*
* @param callNode The call to generate code for.
* @return The Python expression for the object to pass in the call.
*/
public String genObjToPass(CallNode callNode) {
TranslateToPyExprVisitor translator = new TranslateToPyExprVisitor(localVarStack, errorReporter);
// Generate the expression for the original data to pass.
String dataToPass;
if (callNode.isPassingAllData()) {
dataToPass = "data";
} else if (callNode.isPassingData()) {
dataToPass = translator.exec(callNode.getDataExpr()).getText();
} else {
dataToPass = "{}";
}
// Case 1: No additional params.
if (callNode.numChildren() == 0) {
return dataToPass;
}
// Build an object literal containing the additional params.
Map<PyExpr, PyExpr> additionalParams = new LinkedHashMap<>();
for (CallParamNode child : callNode.getChildren()) {
PyExpr key = new PyStringExpr("'" + child.getKey().identifier() + "'");
if (child instanceof CallParamValueNode) {
CallParamValueNode cpvn = (CallParamValueNode) child;
additionalParams.put(key, translator.exec(cpvn.getExpr()));
} else {
CallParamContentNode cpcn = (CallParamContentNode) child;
PyExpr valuePyExpr;
if (isComputableAsPyExprVisitor.exec(cpcn)) {
valuePyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitorFactory.create(localVarStack, errorReporter).exec(cpcn));
} else {
// This is a param with content that cannot be represented as Python expressions, so we
// assume that code has been generated to define the temporary variable 'param<n>'.
String paramExpr = "param" + cpcn.getId();
// The param can be assumed to be a list at this point since it was created as an output
// variable.
valuePyExpr = new PyListExpr(paramExpr, Integer.MAX_VALUE);
}
// Param content nodes require a content kind in strict autoescaping, so the content must be
// wrapped as SanitizedContent.
valuePyExpr = InternalPyExprUtils.wrapAsSanitizedContent(cpcn.getContentKind(), valuePyExpr.toPyString());
additionalParams.put(key, valuePyExpr);
}
}
PyExpr additionalParamsExpr = PyExprUtils.convertMapToPyExpr(additionalParams);
// Cases 2 and 3: Additional params with and without original data to pass.
if (callNode.isPassingData()) {
// make a shallow copy so we don't accidentally modify the param
dataToPass = "dict(" + dataToPass + ")";
return "runtime.merge_into_dict(" + dataToPass + ", " + additionalParamsExpr.getText() + ")";
} else {
return additionalParamsExpr.getText();
}
}
use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.
the class GenPyCallExprVisitor method escapeCall.
/**
* Escaping directives might apply to the output of the call node, so wrap the output with all
* required directives.
*
* @param callExpr The expression text of the call itself.
* @param directives The list of the directives to be applied to the call.
* @return A PyExpr containing the call expression with all directives applied.
*/
private PyExpr escapeCall(String callExpr, ImmutableList<SoyPrintDirective> directives) {
PyExpr escapedExpr = new PyExpr(callExpr, Integer.MAX_VALUE);
if (directives.isEmpty()) {
return escapedExpr;
}
// Successively wrap each escapedExpr in various directives.
for (SoyPrintDirective directive : directives) {
Preconditions.checkState(directive instanceof SoyPySrcPrintDirective, "Autoescaping produced a bogus directive: %s", directive.getName());
escapedExpr = ((SoyPySrcPrintDirective) directive).applyForPySrc(escapedExpr, ImmutableList.<PyExpr>of());
}
return escapedExpr;
}
use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.
the class GenPyExprsVisitor method visitMsgFallbackGroupNode.
@Override
protected void visitMsgFallbackGroupNode(MsgFallbackGroupNode node) {
PyExpr msg = generateMsgFunc(node.getMsg());
// MsgFallbackGroupNode could only have one child or two children. See MsgFallbackGroupNode.
if (node.hasFallbackMsg()) {
StringBuilder pyExprTextSb = new StringBuilder();
PyExpr fallbackMsg = generateMsgFunc(node.getFallbackMsg());
// Build Python ternary expression: a if cond else c
pyExprTextSb.append(msg.getText()).append(" if ");
// The fallback message is only used if the first message is not available, but the fallback
// is. So availability of both messages must be tested.
long firstId = MsgUtils.computeMsgIdForDualFormat(node.getMsg());
long secondId = MsgUtils.computeMsgIdForDualFormat(node.getFallbackMsg());
pyExprTextSb.append(PyExprUtils.TRANSLATOR_NAME).append(".is_msg_available(").append(firstId).append(")").append(" or not ").append(PyExprUtils.TRANSLATOR_NAME).append(".is_msg_available(").append(secondId).append(")");
pyExprTextSb.append(" else ").append(fallbackMsg.getText());
msg = new PyStringExpr(pyExprTextSb.toString(), PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL));
}
// Escaping directives apply to messages, especially in attribute context.
for (SoyPrintDirective directive : node.getEscapingDirectives()) {
Preconditions.checkState(directive instanceof SoyPySrcPrintDirective, "Contextual autoescaping produced a bogus directive: %s", directive.getName());
msg = ((SoyPySrcPrintDirective) directive).applyForPySrc(msg, ImmutableList.<PyExpr>of());
}
pyExprs.add(msg);
}
use of com.google.template.soy.pysrc.restricted.PyExpr 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)));
}
Aggregations