---------------------------------------------------------------------- -- Lazy evaluation extension for Lua. -- The distinctive mark of lazy constructions is the "%" sign. These -- constructions are: -- -- * lazy values: an expression preceded by "%". It creates a thunk, -- i.e. an unevaluated lazy expression. -- -- * thunk forcing: %! thunk will force the evaluation of the thunk, -- and return that value. the evaluation's result is cached, so -- that it won't be computed twice if the thunk is forceed twice. -- It is legal to force a non-thunk: it simply returns the value -- directly. -- -- * lazy table: %{ ... } is a special case: all values in the table -- are created as thunks, and a proxy is returned, which forces them -- on demand, so that users aren't even aware that the table is lazy. -- -- * lazy function: it supposes that all parameters are potentially -- lazy, and therefore add %! thunk=forcing operators around all -- of their usages in the function's body. Such a function is created -- by replacing the parameters' opening parenthese with a "%(". -- -- * lazy call: all parameters are automatically put into thunks. -- The caleld function must therefore be lazy, or it won't know how -- to force the thunks. It only has an interest if some of the args -- are expansive-to-compute expressions. ---------------------------------------------------------------------- -- -- Currently incomplete: only lazy tables, lazy val and forcing -- are implemented. -- ---------------------------------------------------------------------- ---------------------------------------------------------------------- -- Take an AST, return the AST of the thunk which forces to that AST. ---------------------------------------------------------------------- local mk_thunk = |x| +{lazy.thunk(||-{x})} ---------------------------------------------------------------------- -- Build a table where all values are put in thunks, and return a -- proxy which forces them transparently on demand. ---------------------------------------------------------------------- local function lazy_table_builder(x) local c = x[1] local d = `Table for i = 1, #c do if c[i].tag=="Key" then d[i] = `Key{ c[i][1], mk_thunk (c[i][2]) } else d[i] = mk_thunk (c[i]) end end return +{ lazy.table(-{d})} end ---------------------------------------------------------------------- -- Keywords declaration, simple operators and lazy tables: ---------------------------------------------------------------------- mlp.lexer:add{ "%", "%(", "%{", "%!" } mlp.expr.prefix:add{ "%", prec=30, builder= |_,x| mk_thunk(x) } mlp.expr.prefix:add{ "%!", prec=30, builder= |_,x| +{lazy.force(-{x})} } mlp.expr.primary:add{ "%{", mlp.table_content, "}", builder=lazy_table_builder } method_args_parser:add{ "%{", mlp.table_content, "}", builder=|x| { lazy_table_builder(x) } }