lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Jan 15, 2010 at 6:13 AM, Tobias Kieslich <tobias@justdreams.de> wrote:

> Parclate basically parses xml into a DOM table representation and
> serializes that into a function that concatenates a table for good
> performance when that gets serialized. So there are two pathes a
> template can take:
>  - inline compilation
>  - write to a file that can be require()

Interesting. My approach is to use a Lua script as the source.
Although it is convenient to have a full language available instead of
hacks for macros and subroutines (got tired of parsing
if/while/for/forelse special tags/commands), the mental effort to
switch between environments makes me wonder if it is really a good
idea. The good news is that writing a "driver" for reading XML and
then passing it to the code generator is somewhat easy.

Although I just did a quick glance at your code I see that you use a
table for holding the output, and then concatenates at the exit point.
Our code generator expects a vararg function to be called (named
"out") that, well, outputs the generated (x)html. The code generator
tries to optimize constants by concatenating adjacent strings and
automatically sanitize dynamic expressions.

An example:

~~ template.lua

return
html{
  head{ title 'My Website - Under construction' },
  body{
    p{
      _for = 'i = 1, 10',
      span{ class = '${ i % 2 == 0 and "odd" or "even" }',
        'Hello, ${ i } world'
      }
    }
} }

~~ generated code

return function( out, env )
local __buildattr, __sanitize = __buildattr, __sanitize
setfenv(1,env)
out( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\";>\
<html>\
<head><title>My Website - Under construction</title></head>\
<body>" )
for i = 1, 10 do
    out( "\
<p><span", __buildattr( "class", i % 2 == 0 and "even" or "odd"  ),
">Hello, ", __sanitize(  i  ), " world</span></p>" )
end
out( "</body></html>" )
end

(the "setfenv" part is just to illustrate that the generated function
will be called with a user-supplied global environment)

__buildattr checks if the expression returns nil. If so, it omits the attr.

Do you plan to implement a forelse special attribute (i.e: if the loop
never enters, then the "else" value shall be evaluated). If so, with
what semantics?

--rb