use of com.google.template.soy.jbcsrc.restricted.Statement in project closure-templates by google.
the class SoyNodeCompiler method visitChildrenInNewScope.
private Statement visitChildrenInNewScope(BlockNode node) {
Scope prev = currentScope;
currentScope = variables.enterScope();
List<Statement> children = visitChildren(node);
Statement leave = currentScope.exitScope();
children.add(leave);
currentScope = prev;
return Statement.concat(children);
}
use of com.google.template.soy.jbcsrc.restricted.Statement 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;
}
}
use of com.google.template.soy.jbcsrc.restricted.Statement in project closure-templates by google.
the class SoyNodeCompiler method calculateRangeArgs.
/**
* Interprets the given expressions as the arguments of a {@code range(...)} expression in a
* {@code foreach} loop.
*/
private CompiledForeachRangeArgs calculateRangeArgs(ForNode forNode, Scope scope) {
RangeArgs rangeArgs = RangeArgs.createFromNode(forNode).get();
ForNonemptyNode nonEmptyNode = (ForNonemptyNode) forNode.getChild(0);
ImmutableList.Builder<Statement> initStatements = ImmutableList.builder();
Expression startExpression = computeRangeValue(SyntheticVarName.foreachLoopRangeStart(nonEmptyNode), rangeArgs.start(), 0, scope, initStatements);
Expression stepExpression = computeRangeValue(SyntheticVarName.foreachLoopRangeStep(nonEmptyNode), rangeArgs.increment(), 1, scope, initStatements);
Expression endExpression = computeRangeValue(SyntheticVarName.foreachLoopRangeEnd(nonEmptyNode), Optional.of(rangeArgs.limit()), Integer.MAX_VALUE, scope, initStatements);
return new AutoValue_SoyNodeCompiler_CompiledForeachRangeArgs(startExpression, endExpression, stepExpression, initStatements.build());
}
use of com.google.template.soy.jbcsrc.restricted.Statement in project closure-templates by google.
the class TemplateCompiler method generateConstructor.
/**
* Generate a public constructor that assigns our final field and checks for missing required
* params.
*
* <p>This constructor is called by the generate factory classes.
*
* @param fieldInitializers additional statements to initialize fields (other than params)
*/
private void generateConstructor(Statement fieldInitializers) {
final Label start = new Label();
final Label end = new Label();
final LocalVariable thisVar = createThisVar(template.typeInfo(), start, end);
final LocalVariable paramsVar = createLocal("params", 1, SOY_RECORD_TYPE, start, end);
final LocalVariable ijVar = createLocal("ij", 2, SOY_RECORD_TYPE, start, end);
final List<Statement> assignments = new ArrayList<>();
// for other fields needed by the compiler.
assignments.add(fieldInitializers);
assignments.add(paramsField.putInstanceField(thisVar, paramsVar));
assignments.add(ijField.putInstanceField(thisVar, ijVar));
for (TemplateParam param : template.node().getAllParams()) {
Expression paramProvider = getParam(paramsVar, ijVar, param);
assignments.add(paramFields.get(param.name()).putInstanceField(thisVar, paramProvider));
}
Statement constructorBody = new Statement() {
@Override
protected void doGen(CodeBuilder ga) {
ga.mark(start);
// call super()
thisVar.gen(ga);
ga.invokeConstructor(OBJECT.type(), NULLARY_INIT);
for (Statement assignment : assignments) {
assignment.gen(ga);
}
ga.visitInsn(Opcodes.RETURN);
ga.visitLabel(end);
thisVar.tableEntry(ga);
paramsVar.tableEntry(ga);
ijVar.tableEntry(ga);
}
};
constructorBody.writeMethod(Opcodes.ACC_PUBLIC, template.constructor().method(), writer);
}
use of com.google.template.soy.jbcsrc.restricted.Statement in project closure-templates by google.
the class TemplateCompiler method compile.
/**
* Returns the list of classes needed to implement this template.
*
* <p>For each template, we generate:
*
* <ul>
* <li>A {@link com.google.template.soy.jbcsrc.shared.CompiledTemplate.Factory}
* <li>A {@link CompiledTemplate}
* <li>A DetachableSoyValueProvider subclass for each {@link LetValueNode} and {@link
* CallParamValueNode}
* <li>A DetachableContentProvider subclass for each {@link LetContentNode} and {@link
* CallParamContentNode}
* <p>Note: This will <em>not</em> generate classes for other templates, only the template
* configured in the constructor. But it will generate classes that <em>reference</em> the
* classes that are generated for other templates. It is the callers responsibility to
* ensure that all referenced templates are generated and available in the classloader that
* ultimately loads the returned classes.
*/
Iterable<ClassData> compile() {
List<ClassData> classes = new ArrayList<>();
// first generate the factory
if (template.node().getVisibility() != Visibility.PRIVATE) {
// Don't generate factory if the template is private. The factories are only
// useful to instantiate templates for calls from java. Soy->Soy calls should invoke
// constructors directly.
new TemplateFactoryCompiler(template, innerClasses).compile();
}
writer = SoyClassWriter.builder(template.typeInfo()).setAccess(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + Opcodes.ACC_FINAL).implementing(TEMPLATE_TYPE).sourceFileName(template.node().getSourceLocation().getFileName()).build();
generateTemplateMetadata();
generateKindMethod();
stateField.defineField(writer);
paramsField.defineField(writer);
ijField.defineField(writer);
for (FieldRef field : paramFields.values()) {
field.defineField(writer);
}
Statement fieldInitializers = generateRenderMethod();
generateConstructor(fieldInitializers);
innerClasses.registerAllInnerClasses(writer);
writer.visitEnd();
classes.add(writer.toClassData());
classes.addAll(innerClasses.getInnerClassData());
writer = null;
return classes;
}
Aggregations