On Thursday, 2 January 2014 at 06:59:04 UTC, yazd wrote:
How much of this is done at compile-time?

Strictly speaking, just the generation of the code that writes the template to the output buffer. E.g, the code above simulating the Rails form helper would be lowered to code approximately equivalent to this (but with more fluff to add line numbers, and expose some needed hooks for the context):

```
void Temple(OutputStream __buff, TempleContext __context = null)
{
        //...
        //struct FormHelper, etc
        //...

        // The actual rendering into a buffer code

        auto __buff_tmp_0 = form_for("/shorten", "", (f) {
                __buff.put("Shorten a URL: ");
                __buff.put(to!string( f.field_for("url") ));
                __buff.put(to!string( f.submit("Shorten URL") ));
        });
        __buff.put(__buff_tmp_0);

        auto __buff_tmp_1 = form_for("/person", "person", (f) {
                __buff.put("Name: ");
                __buff.put(to!string( f.field_for("name") ));
                __buff.put("Age: ");
                __buff.put(to!string( f.field_for("age") ));
                __buff.put("DOB: ");
                __buff.put(to!string( f.field_for("date_of_birth", "date") ));
                __buff.put(to!string( f.submit ));
        });
        __buff.put(__buff_tmp_1);
}
```

I would guess that
the code is compiled but it is evaluated on each render. Is that correct? Is there a way to force compile-time evaluation of at least part of the template which does not depend on a runtime value?

Yes, generated templates themselves can be executed with CTFE (just had to make a small modification to ArrayOutputAppender, which has been pushed), as long as they don't take a context. The reason for this is that std.variant.Variant isn't CTFEable, because it uses memcpy in opAssign. I'd consider that a Phobos bug; perhaps there is a way to make std.variant CTFE compatible? That'd allow for a much wider (and more useful) range of templates to be evaluated at compile time.

Anyways, here's a working compile time evaluated, compile time generated template:

```
string templeToString(TempleFuncType* func, TempleContext context = null)
{
        auto accum = new AppenderOutputStream;
        (*func)(accum, context);
        return accum.data;
}


unittest
{
        alias render = Temple!q{
                <% if(true) { %>
                        Bort
                <% } else { %>
                        No bort!
                <% } %>

                <% auto a = capture(() { %>
                        inside a capture block
                <% }); %>

                Before capture
                <%= a %>
                After capture
        };

        const result = templeToString(&render);
        static assert(isSameRender(result, `
                Bort
                Before capture
                inside a capture block
                After capture
        `));
}
```

Reply via email to