Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- definers.lua: blogme3's def, DEF and friends, rewritten. -- This file: -- http://angg.twu.net/blogme4/definers.lua.html -- http://angg.twu.net/blogme4/definers.lua -- (find-blogme4 "definers.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011feb17 -- License: GPL3 -- -- See: (find-angg "LUA/canvas2.lua" "Class") -- (find-blogme3 "definers.lua") -- (find-blogme3 "definers.lua" "def") -- «.undollar» (to "undollar") -- «.BlogmeWord» (to "BlogmeWord") -- «.def» (to "def") -- «.test-def» (to "test-def") require "eoo" -- (find-blogme4 "eoo.lua") -- «undollar» (to ".undollar") -- undollar: apply three kinds of "string interpolations" on code. -- This is very hard to understand without examples, so: -- -- undollar [[ "foo $bar plic" ]] --> [[ "foo "..bar.." plic" ]] -- undollar [[ "foo$(bar)plic" ]] --> [[ "foo"..(bar).."plic" ]] -- undollar " [[foo$[1+2]bar]] " --> " [[foo]]..(1+2)..[[bar]] " -- undollar = function (code) code = code:gsub("%$([a-z]+)", "\"..%1..\"") code = code:gsub("%$(%b())", "\"..%1..\"") code = code:gsub("%$(%b[])", function (s) return "]]..("..s:sub(2, -2)..")..[[" end) return code end wrap_f = function (arglist, statements) return "function ("..arglist..")\n"..statements.."\nend" end wrap_fr = function (arglist, expr) return "function ("..arglist..")\nreturn "..expr.."\nend" end wrap_rf = function (arglist, statements) return "return function ("..arglist..")\n"..statements.."\nend" end wrap_rfr = function (arglist, expr) return "return function ("..arglist..")\nreturn "..expr.."\nend" end -- wrap_fu = function (argl, body) return wrap_f (argl, undollar(body)) end -- wrap_fru = function (argl, body) return wrap_fr(argl, undollar(body)) end -- «BlogmeWord» (to ".BlogmeWord") -- The class of blogme words, -- and a way to create a bword from a string. -- See: (find-blogme4 "eoo.lua") -- BlogmeWord = Class { type = "BlogmeWord", __index = { fu = function (bw) return wrap_f (bw.arglist, undollar(bw.body)) end, fru = function (bw) return wrap_fr(bw.arglist, undollar(bw.body)) end, }, __call = function (bw, ...) return bw.fun(...) end, } BlogmeWordFrom = function (defspec) local name, argp, arglist, body = string.match(defspec, "^%s*(%S+)%s+(%S+)%s+(%S+)%s(.*)") assert(name, "defspec is not of the form \"name argp arglist body\"") local bw = BlogmeWord {name=name, argp=argp, arglist=arglist, body=body} return bw end -- «def» (to ".def") -- Old version: (find-blogme3 "definers.lua" "def") -- Examples of usage: (find-blogme4 "anggdefs.lua") -- Here we define Def_, Def, def_ and def, where: -- Def_ and def_ store a BW in _B, -- Def and def store a BW in _B and in _G. -- Def_ and Def expect a series of statements, -- def_ and def expect an expression. -- and: -- _G is the table of global symbols (usually lua functions), -- _B is the table of blogme words (instances of BlogmeWord). -- Here's the trick for remembering which function does what. -- In "Def_" and "Def" everything is bigger: they start with an -- uppercase letter (yeah!) and they expect a longer, more serious -- piece of code, made of several statements, possibly even starting -- with declarations of local variables, and usually ending with a -- "return". In contrast, "def_" and "def" are for smaller things, -- and they expect an expression (because internally they prepend a -- "return " to their code). -- An "_" always suggests "low-level", so "Def_" and "def_" do less -- than "Def" and "def". "Def_" and "def_" install the newly-defined -- word only in _B, while "Def" and "def" also copy it to _G. _B = {} Def_ = function (defspec, prefix) local bw = BlogmeWordFrom(defspec) local arglist = bw.arglist local body = bw.body local code = wrap_rf(arglist, (prefix or "")..undollar(body)) -- PP(bw.name, code) bw.fun = assert(loadstring(code, bw.name))() _B[bw.name] = bw return bw end Def = function (defspec, prefix) local bw = Def_(defspec, prefix) _G[bw.name] = bw return bw end def_ = function (defspec) return Def_(defspec, "return ") end def = function (defspec) return Def (defspec, "return ") end -- dump-to: tests --[==[ -- «test-def» (to ".test-def") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) -- userocks() -- chdir "~/blogme4/" require "def" _B = {} def [[ H2 1 str "<h2>$str</h2>\n" ]] PP(_B) --> {"H2"={"arglist"="str", "body"=" \"<h2>$str</h2>\\n\" ", "fun"=<function: 0x9763268>, "name"="H2", "nargs"="1"}} PP(_B.H2) --> {"arglist"="str", "body"=" \"<h2>$str</h2>\\n\" ", "fun"=<function: 0x9763268>, "name"="H2", "nargs"="1"} = _B.H2:fru() --> function (str) -- return "<h2>"..str.."</h2>\n" -- end = _B.H2 "foo" --> <h2>foo</h2> = H2 "foo" --> <h2>foo</h2> = undollar [[ "foo $bar plic" ]] --> "foo "..bar.." plic" = undollar [[ "foo$(bar)plic" ]] --> "foo"..(bar).."plic" = undollar " [[foo$[1+2]bar]] " --> [[foo]]..(1+2)..[[bar]] --]==] -- Local Variables: -- coding: raw-text-unix -- ee-anchor-format: "«%s»" -- End: