Search in sources :

Example 1 with SoyExpression

use of com.google.template.soy.jbcsrc.restricted.SoyExpression in project closure-templates by google.

the class SoyNodeCompiler method visitPrintNode.

@Override
protected Statement visitPrintNode(PrintNode node) {
    if (node.getExpr().getRoot() instanceof FunctionNode) {
        FunctionNode fn = (FunctionNode) node.getExpr().getRoot();
        if (fn.getSoyFunction() instanceof LoggingFunction) {
            return visitLoggingFunction(node, fn, (LoggingFunction) fn.getSoyFunction());
        }
    }
    // evaluates to a SoyValueProvider.  This will allow us to render incrementally.
    if (areAllPrintDirectivesStreamable(node)) {
        Label reattachPoint = new Label();
        ExprRootNode expr = node.getExpr();
        Optional<Expression> asSoyValueProvider = expressionToSoyValueProviderCompiler.compileAvoidingBoxing(expr, reattachPoint);
        if (asSoyValueProvider.isPresent()) {
            return renderIncrementally(asSoyValueProvider.get(), node.getChildren(), reattachPoint);
        }
    }
    // otherwise we need to apply some non-streaming print directives, or the expression would
    // require boxing to be a print directive (which usually means it is quite trivial).
    Label reattachPoint = new Label();
    SoyExpression value = compilePrintNodeAsExpression(node, reattachPoint);
    // TODO(lukes): call value.render?
    AppendableExpression renderSoyValue = appendableExpression.appendString(value.coerceToString()).labelStart(reattachPoint);
    Statement stmt;
    if (shouldCheckBuffer(node)) {
        stmt = detachState.detachLimited(renderSoyValue);
    } else {
        stmt = renderSoyValue.toStatement();
    }
    return stmt;
}
Also used : SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Expression(com.google.template.soy.jbcsrc.restricted.Expression) Statement(com.google.template.soy.jbcsrc.restricted.Statement) FunctionNode(com.google.template.soy.exprtree.FunctionNode) Label(org.objectweb.asm.Label) LoggingFunction(com.google.template.soy.logging.LoggingFunction) ExprRootNode(com.google.template.soy.exprtree.ExprRootNode)

Example 2 with SoyExpression

use of com.google.template.soy.jbcsrc.restricted.SoyExpression in project closure-templates by google.

the class SoyNodeCompiler method visitForNode.

@Override
protected Statement visitForNode(ForNode node) {
    ForNonemptyNode nonEmptyNode = (ForNonemptyNode) node.getChild(0);
    Optional<RangeArgs> exprAsRangeArgs = RangeArgs.createFromNode(node);
    Scope scope = variables.enterScope();
    final Variable indexVar;
    final List<Statement> initializers = new ArrayList<>();
    final Variable sizeVar;
    final Variable itemVar;
    if (exprAsRangeArgs.isPresent()) {
        final CompiledForeachRangeArgs compiledArgs = calculateRangeArgs(node, scope);
        initializers.addAll(compiledArgs.initStatements());
        // The size is just the number of items in the range.  The logic is a little tricky so we
        // implement it in a runtime function: JbcsrcRuntime.rangeLoopLength
        sizeVar = scope.createSynthetic(SyntheticVarName.foreachLoopLength(nonEmptyNode), MethodRef.RUNTIME_RANGE_LOOP_LENGTH.invoke(compiledArgs.start(), compiledArgs.end(), compiledArgs.step()), DERIVED);
        indexVar = scope.createSynthetic(SyntheticVarName.foreachLoopIndex(nonEmptyNode), constant(0), STORE);
        itemVar = scope.create(nonEmptyNode.getVarName(), new Expression(Type.LONG_TYPE, Feature.CHEAP) {

            @Override
            protected void doGen(CodeBuilder adapter) {
                // executes ((long) start + index * step)
                compiledArgs.start().gen(adapter);
                compiledArgs.step().gen(adapter);
                indexVar.local().gen(adapter);
                adapter.visitInsn(Opcodes.IMUL);
                adapter.visitInsn(Opcodes.IADD);
                adapter.cast(Type.INT_TYPE, Type.LONG_TYPE);
            }
        }, DERIVED);
    } else {
        SoyExpression expr = exprCompiler.compile(node.getExpr()).unboxAs(List.class);
        Variable listVar = scope.createSynthetic(SyntheticVarName.foreachLoopList(nonEmptyNode), expr, STORE);
        initializers.add(listVar.initializer());
        sizeVar = scope.createSynthetic(SyntheticVarName.foreachLoopLength(nonEmptyNode), MethodRef.LIST_SIZE.invoke(listVar.local()), DERIVED);
        indexVar = scope.createSynthetic(SyntheticVarName.foreachLoopIndex(nonEmptyNode), constant(0), STORE);
        itemVar = scope.create(nonEmptyNode.getVarName(), MethodRef.LIST_GET.invoke(listVar.local(), indexVar.local()).checkedCast(SOY_VALUE_PROVIDER_TYPE), DERIVED);
    }
    initializers.add(sizeVar.initializer());
    final Statement loopBody = visitChildrenInNewScope(nonEmptyNode);
    final Statement exitScope = scope.exitScope();
    // it important for this to be generated after exitScope is called (or before enterScope)
    final Statement emptyBlock = node.numChildren() == 2 ? visitChildrenInNewScope(node.getChild(1)) : null;
    return new Statement() {

        @Override
        protected void doGen(CodeBuilder adapter) {
            for (Statement initializer : initializers) {
                initializer.gen(adapter);
            }
            sizeVar.local().gen(adapter);
            Label emptyListLabel = new Label();
            adapter.ifZCmp(Opcodes.IFEQ, emptyListLabel);
            indexVar.initializer().gen(adapter);
            Label loopStart = adapter.mark();
            itemVar.initializer().gen(adapter);
            loopBody.gen(adapter);
            // index++
            adapter.iinc(indexVar.local().index(), 1);
            indexVar.local().gen(adapter);
            sizeVar.local().gen(adapter);
            // if index < list.size(), goto loopstart
            adapter.ifICmp(Opcodes.IFLT, loopStart);
            // exit the loop
            exitScope.gen(adapter);
            if (emptyBlock != null) {
                Label skipIfEmptyBlock = new Label();
                adapter.goTo(skipIfEmptyBlock);
                adapter.mark(emptyListLabel);
                emptyBlock.gen(adapter);
                adapter.mark(skipIfEmptyBlock);
            } else {
                adapter.mark(emptyListLabel);
            }
        }
    };
}
Also used : Variable(com.google.template.soy.jbcsrc.TemplateVariableManager.Variable) RangeArgs(com.google.template.soy.shared.RangeArgs) Statement(com.google.template.soy.jbcsrc.restricted.Statement) ArrayList(java.util.ArrayList) Label(org.objectweb.asm.Label) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder) 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) ForNonemptyNode(com.google.template.soy.soytree.ForNonemptyNode)

Example 3 with SoyExpression

use of com.google.template.soy.jbcsrc.restricted.SoyExpression 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 4 with SoyExpression

use of com.google.template.soy.jbcsrc.restricted.SoyExpression in project closure-templates by google.

the class SoyNodeCompiler method compilePrintNodeAsExpression.

private SoyExpression compilePrintNodeAsExpression(PrintNode node, Label reattachPoint) {
    BasicExpressionCompiler basic = exprCompiler.asBasicCompiler(reattachPoint);
    SoyExpression value = basic.compile(node.getExpr());
    // because instead of wrapping the soy value, we would just wrap the appendable.
    for (PrintDirectiveNode printDirective : node.getChildren()) {
        value = parameterLookup.getRenderContext().applyPrintDirective(printDirective.getPrintDirective(), value, basic.compileToList(printDirective.getArgs()));
    }
    return value;
}
Also used : SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) PrintDirectiveNode(com.google.template.soy.soytree.PrintDirectiveNode) BasicExpressionCompiler(com.google.template.soy.jbcsrc.ExpressionCompiler.BasicExpressionCompiler)

Example 5 with SoyExpression

use of com.google.template.soy.jbcsrc.restricted.SoyExpression in project closure-templates by google.

the class MapKeysFunction method computeForJbcSrc.

@Override
public SoyExpression computeForJbcSrc(JbcSrcPluginContext context, List<SoyExpression> args) {
    SoyExpression soyExpression = args.get(0);
    SoyType argType = soyExpression.soyType();
    SoyType keyType = ((MapType) argType).getKeyType();
    return SoyExpression.forList(keyType == null ? ListType.EMPTY_LIST : ListType.of(keyType), JbcSrcMethods.MAP_KEYS_FN.invoke(soyExpression.box().checkedCast(SoyMap.class)));
}
Also used : SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) SoyType(com.google.template.soy.types.SoyType) MapType(com.google.template.soy.types.MapType)

Aggregations

SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)21 Expression (com.google.template.soy.jbcsrc.restricted.Expression)8 Statement (com.google.template.soy.jbcsrc.restricted.Statement)5 SoyType (com.google.template.soy.types.SoyType)4 Label (org.objectweb.asm.Label)4 Scope (com.google.template.soy.jbcsrc.TemplateVariableManager.Scope)3 Variable (com.google.template.soy.jbcsrc.TemplateVariableManager.Variable)3 LegacyObjectMapType (com.google.template.soy.types.LegacyObjectMapType)3 MapType (com.google.template.soy.types.MapType)3 ArrayList (java.util.ArrayList)3 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2 IfBlock (com.google.template.soy.jbcsrc.ControlFlow.IfBlock)2 SoyNode (com.google.template.soy.soytree.SoyNode)2 UnknownType (com.google.template.soy.types.UnknownType)2 SoyString (com.google.template.soy.data.restricted.SoyString)1 FunctionNode (com.google.template.soy.exprtree.FunctionNode)1 BasicExpressionCompiler (com.google.template.soy.jbcsrc.ExpressionCompiler.BasicExpressionCompiler)1 CodeBuilder (com.google.template.soy.jbcsrc.restricted.CodeBuilder)1 MethodRef (com.google.template.soy.jbcsrc.restricted.MethodRef)1 AppendableAndOptions (com.google.template.soy.jbcsrc.restricted.SoyJbcSrcPrintDirective.Streamable.AppendableAndOptions)1