Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
####### # # E-scripts on material for a mini-course on Lua and related stuff. # # Note 1: use the eev command (defined in eev.el) and the # ee alias (in my .zshrc) to execute parts of this file. # Executing this file as a whole makes no sense. # An introduction to eev can be found here: # # (find-eev-quick-intro) # http://angg.twu.net/eev-intros/find-eev-quick-intro.html # # Note 2: be VERY careful and make sure you understand what # you're doing. # # Note 3: If you use a shell other than zsh things like |& # and the for loops may not work. # # Note 4: I always run as root. # # Note 5: some parts are too old and don't work anymore. Some # never worked. # # Note 6: the definitions for the find-xxxfile commands are on my # .emacs. # # Note 7: if you see a strange command check my .zshrc -- it may # be defined there as a function or an alias. # # Note 8: the sections without dates are always older than the # sections with dates. # # This file is at <http://angg.twu.net/e/lua5.e> # or at <http://angg.twu.net/e/lua5.e.html>. # See also <http://angg.twu.net/emacs.html>, # <http://angg.twu.net/.zshrc[.html]>, # <http://angg.twu.net/escripts.html>, # and <http://angg.twu.net/>. # ####### # «.how-to-use» (to "how-to-use") # «.quick-presentation» (to "quick-presentation") # «.intro:types» (to "intro:types") # «.intro:LUA_INIT» (to "intro:LUA_INIT") # «.intro:PP» (to "intro:PP") # «.intro:functions» (to "intro:functions") # «.intro:lists» (to "intro:lists") # «.intro:coercion» (to "intro:coercion") # «.intro:string-literals» (to "intro:string-literals") # «.intro:table-constructors» (to "intro:table-constructors") # «.intro:keys» (to "intro:keys") # «.intro:length» (to "intro:length") # «.intro:for» (to "intro:for") # «.intro:global-vars» (to "intro:global-vars") # «.intro:local-vars» (to "intro:local-vars") # «.intro:eval» (to "intro:eval") # «.intro:assert» (to "intro:assert") # «.intro:closures» (to "intro:closures") # «.intro:iterators» (to "intro:iterators") # «.intro:__tostring» (to "intro:__tostring") # «.intro:metamethods» (to "intro:metamethods") # «.intro:io» (to "intro:io") # «.intro:string.gsub» (to "intro:string.gsub") # «.intro:string.format» (to "intro:string.format") # «.coroutines» (to "coroutines") # «.bytecode:captures» (to "bytecode:captures") # «.captures-data-structures» (to "captures-data-structures") # «.install-5.1.2» (to "install-5.1.2") # «.minimal_GCW_SUGAR» (to "minimal_GCW_SUGAR") # «.invoking-arrays» (to "invoking-arrays") # «.string.find» (to "string.find") # «.string.gfind» (to "string.gfind") # «.emptycaptures» (to "emptycaptures") # «.C-calls-lua» (to "C-calls-lua") # «.xpcall-traceback» (to "xpcall-traceback") # «.calling-Lua-from-C» (to "calling-Lua-from-C") # «.monitored_p_C» (to "monitored_p_C") # «.debug.debug» (to "debug.debug") # «.getoutput» (to "getoutput") # «.captured-variables» (to "captured-variables") # «.xpcall» (to "xpcall") # «.pil24.1» (to "pil24.1") # «.lpeg-quickref» (to "lpeg-quickref") # «.lpeg-basic» (to "lpeg-basic") # «.lpeg-export» (to "lpeg-export") # «.lpeg-P» (to "lpeg-P") # «.lpeg-re-quickref» (to "lpeg-re-quickref") # «.lpeg-re-1» (to "lpeg-re-1") # «.lpeg-re-infix-1» (to "lpeg-re-infix-1") # «.lpeg-re-infix-2» (to "lpeg-re-infix-2") # «.lua-mode.el» (to "lua-mode.el") # «.patrick» (to "patrick") ##### # # How to use this # 2021aug21 # ##### # «how-to-use» (to ".how-to-use") # This hands-on tutorial uses lua5.1, that is the version of # Lua that I use in most of my Lua scripts. My main reason # for preferring Lua5.1 is the "=" trick in the REPL, that # is explained here: # # (find-angg "edrxrepl/edrxrepl.lua" "Repl") * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) sudo apt-get install -y lua5.1 lua5.1-dev lua5.1-doc * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) # See: http://angg.twu.net/LUA/lua50init.lua.html mkdir ~/LUA/ cd ~/LUA/ rm -v lua50init.lua wget http://angg.twu.net/LUA/lua50init.lua * (getenv "LUA_INIT") * (setenv "LUA_INIT" (format "@%s/LUA/lua50init.lua" (getenv "HOME"))) * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) A = {22, "22"} PP(A, nil) -- (find-wgeta "http://angg.twu.net/e/lua-intro.e") -- (find-wgeta "http://angg.twu.net/e/lua-intro.e" "intro:types") ##### # # Quick presentation (updated to lua51) # 2004sep02 # ##### # «quick-presentation» (to ".quick-presentation") # Also at: (find-eev "examples/lua.e" "quick-presentation") # (find-pilw3m "index.html") # (find-pil2page 8 "Contents") # (find-pil2text 8 "Contents") #* (defun nxt () (interactive) (search-forward "***")) (defun nxt1 () (interactive) (nxt) (eek "3*DEL # SPC <delete> < <end> >")) «intro:types» (to ".intro:types") Lua has just a few basic data types. We will see later that file handlers are not basic data types. (find-pil2page (+ 19 9) "eight basic types") (find-pil2text (+ 19 9) "eight basic types") (find-pilw3m "2.html" "eight basic types") (find-lua51manual "#2.2" "eight basic types") (find-lua51manual "#pdf-type") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) print(1, type(1)) --> 1 number print(1.0, type(1.0)) --> 1 number print("abc", type("abc")) --> abc string print(nil, type(nil)) --> nil nil print(true, type(true)) --> true boolean print(false, type(false)) --> false boolean print(print, type(print)) --> function: 0x804d218 function print({2,3,5}, type({})) --> table: 0x8053ab0 table «intro:LUA_INIT» (to ".intro:LUA_INIT") This is a hack to make Lua interpreters started from Emacs - like the ones that are run by (eepitch-lua51) - load my init file. # (find-lua51manual "#6" "Lua Stand-alone" "LUA_INIT" "@filename") # (find-angg "LUA/lua50init.lua") # http://angg.twu.net/LUA/lua50init.lua # http://angg.twu.net/LUA/lua50init.lua.html * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) mkdir ~/LUA/ cd ~/LUA/ wget -nc http://angg.twu.net/LUA/lua50init.lua * * (getenv "LUA_INIT") * (setenv "LUA_INIT" (concat "@" (ee-expand "~/LUA/lua50init.lua"))) «intro:PP» (to ".intro:PP") I will sometimes use the function "PP", defined in my init file, instead of "print". (find-angg "LUA/lua50init.lua" "PP") (find-angg "LUA/lua50init.lua" nil "LUA_INIT") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) print(22, "22", print) --> 22 22 function: 0x9f11388 PP (22, "22", print) --> 22 "22" <function: 0x9f11388> print({2, 3, 5}) --> table: 0x9f1df70 PP ({2, 3, 5}) --> {1=2, 2=3, 3=5} «intro:functions» (to ".intro:functions") Functions are values, and "function f(args) body end" is just syntactical sugar for "f=function(args) body end". (find-lua51manual "#2.5.9" "f = function () body end") (find-lua51manual "#2.5.9" "f = function () body end") (find-pilw3m "6.html" "More about Functions") (find-pil2page (+ 19 45) "More About Functions") (find-pil2text (+ 19 45) "More About Functions") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) function square(a) return a*a end square = function (a) return a*a end print(square, square(2)) --> function: 0xa067dc0 4 «intro:lists» (to ".intro:lists") Expressions may return lists of results, and there are two ways to truncate lists to a single result. Multiple assignments work similarly to functions receiving multiple arguments. (find-lua51manual "#2.4.3" "Assignment") (find-lua51manual "#2.5" "Expressions") (find-pilw3m "5.1.html" "Multiple Results") (find-pil2page (+ 19 36) "Multiple Results") (find-pil2text (+ 19 36) "Multiple Results") Vlists: http://lua-users.org/lists/lua-l/2011-02/msg01467.html Dracula: http://lua-users.org/lists/lua-l/2011-02/msg01477.html * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) function foo() return 1, 2, 3 end print(1, 2, 3) --> 1 2 3 print(foo()) --> 1 2 3 print(99, foo()) --> 99 1 2 3 print(99, foo(), 200) --> 99 1 200 print(99, (foo())) --> 99 1 zero, one, two, three, four = 0, 1, 2, 3, nil zero, one, two, three, four = 0, 1, 2, 3 zero, one, two, three, four = 0, foo() print(zero, one, two, three, four) --> 0 1 2 3 nil f = function (zero, one, two, three, four) print(zero, one, two, three, four) end f(0, foo()) --> 0 1 2 3 nil «intro:coercion» (to ".intro:coercion") Numbers are automatically coerced to strings (and vice-versa) in certain situations. (find-lua51manual "#2.2.1" "Coercion") (find-lua51manual "#2.5.4" "Concatenation" "..") (find-pilw3m "2.4.html" "coercions") (find-pil2page (+ 19 13) "coercions") (find-pil2text (+ 19 13) "coercions") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) print(1+"2") --> 3 print("ab".."cd") --> abcd print("<".. 11 .. 22 ..">") --> <1122> «intro:string-literals» (to ".intro:string-literals") String literals can be quoted with '', "", [[]], and also with [=[...]=], [==[...]==], etc. There's a similar syntax for multi-line comments. (find-lua51manual "#2.1" "Literal strings") (find-lua51manual "#2.1" "Literal strings can also be defined") (find-lua51manual "#2.1" "opening long bracket of level n") -- A multi-line comment delimited by long brackets of level 4: --[====[ (inside the comment) --]====] * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) = "foo\nbar" = [[foo\nbar]] = [==[foo[[plic ploc]]bar]==] «intro:table-constructors» (to ".intro:table-constructors") Table constructors (find-lua51manual "#2.5.7" "Table Constructors") (find-pilw3m "2.5.html" "Tables") (find-pil2page (+ 19 13) "2.5 Tables") (find-pil2text (+ 19 13) "2.5 Tables") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) a = {10, 20, 30} print(a[2]) --> 20 print(200, "some string", a) --> 200 some string table: 0x8e2eee0 PP (200, "some string", a) --> 200 "some string" {1=10, 2=20, 3=30} b = {11, a, "foo", print} PP(b) --> {1=11, 2={1=10, 2=20, 3=30}, 3="foo", 4=<function: 0x8e1e020>} function foo() return 30, 40, 50 end c = {10, 20, foo()} --> {1=10, 2=20, 3=30, 4=40, 5=50} PP(c) «intro:keys» (to ".intro:keys") More on tables: keys and values don't need to be numbers, reading and changing key/value pairs, the {..., [key]=val, ...} syntax. * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) c = {11, 22, 33} c[2] = c[2]+c[3] -- change c[2] to 55 c[5] = 55 -- change c[5] to 55 (note that there's no c[4]) c["foo"] = "FOO" -- change c["foo"] to "FOO" print(c) --> table: 0x84ee130 PP(c) --> {1=11, 2=55, 3=33, 5=55, "foo"="FOO"} d = {11, 22, 33, [5]=555, ["bar"]="BAR", [c]="!"} PP(d) --> {1=11, 2=22, 3=33, 5=555, "bar"="BAR", {...}="!"} d[2] = nil -- delete d[2] d[c] = nil -- delete d[c] PP(d, d[2]) --> {1=11, 3=33, 5=555, "bar"="BAR"} <nil> x = {10, 20} y = {10, 20} PP(x, y) --> {1=10, 2=20} {1=10, 2=20} print(x, y) --> table: 0x84fc048 table: 0x84fb770 x[1] = 1000 PP(x, y) --> {1=1000, 2=20} {1=10, 2=20} «intro:length» (to ".intro:length") The somewhow non-deterministic "#" operator (find-lua51manual "#2.5.5" "The Length Operator") The four "#"s: http://lua-users.org/lists/lua-l/2011-04/msg00013.html "is"/"or": http://lua-users.org/lists/lua-l/2011-04/msg00065.html * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) f = function (T) printf("#%s = %d\n", mytostring(T), #T) end s = function (n) a[n] = n; f(a) end r = function (n) a[n] = nil; f(a) end a = {1, 2, 3, 4, 5} r(3) --> #{1=1, 2=2, 4=4, 5=5} = 5 s(7) --> #{1=1, 2=2, 4=4, 5=5, 7=7} = 5 s(6) --> #{1=1, 2=2, 4=4, 5=5, 6=6, 7=7} = 7 r(2) --> #{1=1, 4=4, 5=5, 6=6, 7=7} = 7 r(7) --> #{1=1, 4=4, 5=5, 6=6} = 6 s(100) --> #{1=1, 4=4, 5=5, 6=6, 100=100} = 1 f("Foo") --> #"Foo" = 3 «intro:for» (to ".intro:for") The "for" statement in its two forms. (find-es "lua5" "for") (find-lua51manual "#2.4.5" "For Statement") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) -- Numeric for: for i=1,4 do print(i) end --> 1 2 3 4 for i=5,-2,-2 do print(i) end --> 5 3 1 -1 for i=2,2 do print(i) end --> 2 for i=2,0 do print(i) end --> (nothing) -- Introduction to the generic for: a={4, 5, k="V"} PP(a) --> {1=4, 2=5, "k"="V"} for i=1,#a do print(i, a[i]) end --> 1 4 / 2 5 for key,val in pairs(a) do print(key, val) end --> 1 4 / 2 5 / k V for key,val in ipairs(a) do print(key, val) end --> 1 4 / 2 5 -- pairs(T) and ipairs(T) return "iterators". a={4,5,k="V"} print(a) --> table: 0x8237440 print(pairs(a)) --> function: 0x82279e8 table: 0x8237440 nil print(ipairs(a)) --> function: 0x8228370 table: 0x8237440 0 «intro:global-vars» (to ".intro:global-vars") Global variables are stored in a table (usually called _G). The T.key syntax is syntactic sugar for T["key"]. (find-lua51manual "#2.3" "environments") (find-lua51manual "#pdf-_G") (find-pil2page (+ 19 129) "The Environment") (find-pil2text (+ 19 129) "The Environment") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) for key,val in pairs(_G) do print(key, val) end print(string) --> table: 0x9961910 print(string.format) --> function: 0x9963d68 print(string["format"]) --> function: 0x9963d68 print(string.format("1+2=%d", 1+2)) --> 1+2=3 for key,val in pairs(string) do print(key, val) end print(print) --> function: 0x9961388 print(_G["print"]) --> function: 0x9961388 print(_G.print) --> function: 0x9961388 print(_G) --> table: 0x9960450 print(_G["_G"]) --> table: 0x9960450 print(_G._G) --> table: 0x9960450 «intro:local-vars» (to ".intro:local-vars") Each block can have local variables. Local variables are created dynamically by "local". (find-lua51manual "#2.3") (find-pil2page (+ 19 28) "4.2 Local Variables and Blocks") (find-pil2text (+ 19 28) "4.2 Local Variables and Blocks") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) a = 22 do print(a) --> 22 local a = 33 -- the local "a" shadows the previous "a" print(a) --> 33 end -- discard the local "a" print(a) --> 22 «intro:eval» (to ".intro:eval") The interpreter reads code as a string, and executes that. This is done in two steps, both acessible by the user: "f = loadstring(str)" converts str to a function, f, and "f()" executes that function. (This is similar to Lisp's "read" and "eval", by the way). Actually we should use "f, err = loadstring(str)". See: (find-pil2page (+ 19 64) "loadstring") (find-pil2text (+ 19 64) "loadstring") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) str = [[ print("hello") ]] print(str) --> print("hello") f, err = loadstring(str) print(f, err) --> function: 0x88ee6c8 nil f() --> hello str = [[ print("no closing quo ]] print(str) --> print("no closing quo f, err = loadstring(str) print(f, err) --> nil ...: unfinished string near '<eof>' = loadstring "2+()" = loadstring "return 2+3,4" = (loadstring "return 2+3,4")() = (loadstring "local a,b=...; return a*b,a")(10,20) «intro:assert» (to ".intro:assert") See: (find-lua51manual "#pdf-assert") (find-pilw3m "8.3.html" "assert") (find-pil2page (+ 19 64) "assert(loadstring(s))()") (find-pil2text (+ 19 64) "assert(loadstring(s))()") (find-pil2page (+ 19 67) "8.3 Errors") (find-pil2text (+ 19 67) "8.3 Errors") (find-pil2text (+ 19 67) "8.3 Errors" "assert") (find-pil2page (+ 19 68) "assert") http://lua-users.org/wiki/FinalizedExceptions * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) print(assert(10, 20, 30)) --> 10 20 30 print(assert(nil)) --> assertion failed print(assert(nil, "Error message")) --> error message str = [[ print("no closing quo ]] print (loadstring(str)) assert(loadstring(str)) str = "print('foo'); return 1+2" print(assert(loadstring(str))()) --> foo / 3 «intro:closures» (to ".intro:closures") Capture of local variables (a.k.a. "closures"). (find-pilw3m "6.1.html" "closures") (find-pil2page (+ 19 47) "6.1 Closures") (find-pil2text (+ 19 47) "6.1 Closures") (find-es "lua5" "closure-reductions") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) foo = function () -- foo returns two functions... local storage return function () return storage end, -- a "getter", function (x) storage = x; return x end -- and a "setter". end get1, set1 = foo() -- get1 and set1 use a first "storage" get2, set2 = foo() -- get2 and set2 use a second, different "storage" print(set1(22), get1()) --> 22 22 print(set2(33), get1(), get2()) --> 33 22 33 «intro:iterators» (to ".intro:iterators") We can use closures to construct "iterators" for the generic for. (find-pilw3m "7.1.html" "Iterators and Closures") (find-pil2page (+ 19 55) "7.1 Iterators and Closures") (find-pil2text (+ 19 55) "7.1 Iterators and Closures") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) myiterator = function (n) return function () n = n / 2 if n >= 1 then return n end end end for n in myiterator(1024) do print(n) end --> 512 256 128 64 32 16 8 4 2 1 «intro:__tostring» (to ".intro:__tostring") Introduction to metatables: the "__tostring" metamethod (find-lua51manual "#2.8" "__add") (find-lua51manual "#pdf-tostring" "__tostring") (find-pil2page (+ 19 122) "mt.__tostring") (find-pil2text (+ 19 122) "mt.__tostring") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) mt = {} A = { name = "A" } B = { name = "B" } setmetatable(A, mt) setmetatable(B, mt) print(A) --> table: 0x9622d50 mt.__tostring = function (a) return a.name end print(A) --> A print(B) --> B PP(A) --> {"name"="A"} PP(B) --> {"name"="B"} PP({A, B}) --> {1={"name"="A"}, 2={"name"="B"}} = string.format("%s", A) -- error «intro:metamethods» (to ".intro:metamethods") Metatables: other metamethods besides __add and __tostring (find-lua51manual "#2.8" "__add") (find-pil2page (+ 19 123) "The __index metamethod") (find-pil2text (+ 19 123) "The __index metamethod") See also: http://angg.twu.net/__mt.html (find-TH "__mt") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) mt = {} mt.__tostring = function (a) return a.name end A = setmetatable({name = "A"}, mt) A = setmetatable({name = "B"}, mt) testmt = function (methodname) mt[methodname] = function (a, b) return methodname.."("..tostring(a)..", "..tostring(b)..")" end end testmt("__add"); print(A+1, 1+A) --> __add(A, 1) __add(1, A) testmt("__sub"); print(A-2, 2-A) --> __sub(A, 2) __sub(2, A) testmt("__mul"); print(A*3, 3*A) --> __mul(A, 3) __mul(3, A) testmt("__div"); print(A/4, 4/A) --> __div(A, 4) __div(4, A) testmt("__mod"); print(A%5, 5%A) --> __mod(A, 5) __mod(5, A) testmt("__pow"); print(A^6, 6^A) --> __pow(A, 6) __pow(6, A) testmt("__concat"); print(A..7) --> __concat(A, 7) testmt("__index"); print(A[8]) --> __index(A, 8) testmt("__unm"); print(-A) --> __unm(A, A) testmt("__call"); print(A(10)) --> __call(A, A) -- Or: mt = {} mt.__tostring = function (a) return a.name end mt.__add = function (a, b) return mab("__add", a, b) end mab = function (m, a, b) return m.."("..tostring(a)..", "..tostring(b)..")" end A = setmetatable({name = "A"}, mt) B = setmetatable({name = "B"}, mt) = A = B = A+B testmt = function (m) mt[m] = function (a, b) return mab(m, a, b) end end testmt("__add"); print(A+1, 1+A) --> __add(A, 1) __add(1, A) testmt("__sub"); print(A-2, 2-A) --> __sub(A, 2) __sub(2, A) testmt("__mul"); print(A*3, 3*A) --> __mul(A, 3) __mul(3, A) testmt("__div"); print(A/4, 4/A) --> __div(A, 4) __div(4, A) testmt("__mod"); print(A%5, 5%A) --> __mod(A, 5) __mod(5, A) testmt("__pow"); print(A^6, 6^A) --> __pow(A, 6) __pow(6, A) testmt("__concat"); print(A..7) --> __concat(A, 7) testmt("__index"); print(A[8]) --> __index(A, 8) testmt("__unm"); print(-A) --> __unm(A, A) testmt("__call"); print(A(10)) --> __call(A, 10) PP(getmetatable(A)) t = setmetatable({}, {__div = function() return 1, 2 end}) = t / t --> 1 Missing: (find-lua51manual "#2.8" "\"len\":") (find-lua51manual "#2.8" "\"eq\":") (find-lua51manual "#2.8" "\"eq\":" "getcomphandler") (find-lua51manual "#2.8" "\"lt\":") (find-lua51manual "#2.8" "\"le\":") (find-lua51manual "#2.8" "\"newindex\":") «intro:io» (to ".intro:io") Files and IO (find-lua51manual "#5.7" "Input and Output Facilities") (find-pilw3m "21.1.html") (find-pil2page (+ 19 193) "The I/O Library") (find-pil2text (+ 19 193) "The I/O Library") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) print(io) for key,val in pairs(io) do print(key) end print(io.stdin) print(getmetatable(io.stdin)) print(getmetatable(io.stdin).__index) for key,val in pairs(getmetatable(io.stdin)) do print(key) end «intro:string.gsub» (to ".intro:string.gsub") Strings: string.gsub (find-lua51manual "#pdf-string.gsub") (find-lua51manual "#5.4.1" "Patterns") (find-pilw3m "20.html" "The String Library") (find-pil2page (+ 19 175) "The String Library") (find-pil2text (+ 19 175) "The String Library") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) pg = function (...) print(string.gsub(...)) end pg = function (...) PP((string.gsub(...))) end pg = function (...) PP(string.gsub(...)) end t = {name="lua", ver="5.1.4"} tv = function (v) return t[v] end run = function (s) return loadstring(s)() end PP(tv("ver")) --> "5.1.4" PP(run("return 22, 33")) --> 22 33 PP(os.getenv("HOME")) --> "/home/edrx" PP(os.getenv("FOO")) --> <nil> pg("hel wo", "(%w+)", "%1 %1") --> "hel hel wo wo" 2 pg("hel wo", "(%w+)", "%1 %1", 1) --> "hel hel wo" 1 pg("hel wo fr Lu", "(%w+)%s*(%w+)", "%2 %1") --> "wo hel Lu fr" 2 pg("ho=$HOME, u=$USER", "%$(%w+)", os.getenv) --> "ho=/home/edrx, u=edrx" 2 pg("ho=$HOME, u=$FOO", "%$(%w+)", os.getenv) --> "ho=/home/edrx, u=$FOO" 2 pg("4+5=$return 4+5$", "%$(.-)%$", run) --> "4+5=9" 1 pg("$name_$ver.tar.gz", "%$(%w+)", tv) --> "lua_5.1.tar.gz" 2 «intro:string.format» (to ".intro:string.format") Strings: string.format (find-lua51manual "#pdf-string.format") (find-pil2page (+ 19 177) "string.format") (find-pil2text (+ 19 177) "string.format") (find-man "3 printf") (find-node "(libc)Formatted Output") (find-node "(libc)Floating-Point Conversions") testmt("__len"); print(#A) testmt("__lt"); print(A<B, B<A) print(mytostring_table(string, ",\n ")) mttest = function (field) a.__mt[field] = function (...) PP(field, unpack(arg)) end end #* # (find-dn4file "dednat41.lua" "string-methods") # Metatables lua51 -e ' a = {} PP(getmetatable(a)) f = io.open("/tmp/o", "w") P(getmetatable(f)) for key,val = ' #* ##### # # coroutines # 2007may23 # ##### # «coroutines» (to ".coroutines") # (find-pilfile "") # (find-pilw3m "index.html") # (find-pilw3m "9.html" "Coroutines) # (find-pilw3m "9.1.html" "Coroutine Basics") # (find-pilw3m "9.2.html" "Pipes and Filters") # (find-pilw3m "9.3.html" "Coroutines as Iterators") # (find-pilw3m "9.4.html" "Non-Preemptive Multithreading") -- (find-pilw3m "9.1.html" "Coroutine Basics") -- (find-lua51manual "#2.11") -- (find-lua51manual "#pdf-coroutine.resume") -- (find-lua51file "") -- (find-lua51file "src/lbaselib.c" "** Coroutine library") -- (find-lua51file "src/lbaselib.c" "static const luaL_Reg co_funcs[] =") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) co = coroutine.create(function () print("hi") end) print(co) --> thread: 0x8071d98 print(coroutine.status(co)) --> suspended coroutine.resume(co) --> hi print(coroutine.status(co)) --> dead * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) co = coroutine.create(function () for i=1,4 do print("co", i) coroutine.yield() end end) coroutine.resume(co) --> co 1 print(coroutine.status(co)) --> suspended coroutine.resume(co) --> co 2 coroutine.resume(co) --> co 3 coroutine.resume(co) --> co 4 print(coroutine.status(co)) --> suspended coroutine.resume(co) --> (nothing) print(coroutine.status(co)) --> dead coroutine.resume(co) --> (nothing) * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) co = coroutine.create(function (a, b) print(a, b) print(coroutine.yield("foo", "bar")) print(coroutine.yield("bletch")) return "plic", "ploc" end) print(coroutine.resume(co, 22, 33)) --> 22 33 / true foo bar print(coroutine.resume(co, 44, 55)) --> 44 55 / true bletch print(coroutine.resume(co, 66, 77)) --> 66 77 / true plic ploc print(coroutine.status(co)) --> dead print(coroutine.resume(co, 88, 99)) --> false cannot resume dead coroutine ##### # # Understanding the bytecode: closures and capture of local variables # 2007jun10 # ##### # «bytecode:captures» (to ".bytecode:captures") # A closure is roughly a "prototype" - that holds the bytecode - # plus a vector of upvalues. # In the example below we are naming the prototypes according to where # they start and end; so, for example, Proto_1_6 is the prototype that # corresponds to the "function () ... end" thing that extends from # lines 1 to 6, and Proto_1_8 is the "main prototype" of the chunk. #* cat > /tmp/foo.lua <<'%%%' foo = function () --> Proto_1_6 local storage return function () return storage end, --> Proto_4_4 function (x) storage = x; return x end --> Proto_5_5 end get1, set1 = foo() get2, set2 = foo() %%% #* # (find-lua51w3m "doc/luac.html") # (find-sh "luac51 -p -l /tmp/foo.lua") # (find-sh "luac51 -l /tmp/foo.lua") # «captures-data-structures» (to ".captures-data-structures") # (find-lua51file "src/lobject.h" "typedef struct Proto ") # (find-lua51file "src/lobject.h" "typedef struct LClosure ") # (find-lua51file "src/lobject.h" "typedef struct LocVar ") # (find-lua51file "src/lobject.h" "typedef struct UpVal ") # (find-lua51file "src/lstate.h" "typedef struct CallInfo ") # http://www.lua.org/source/5.1/lobject.h.html#Proto # http://www.lua.org/source/5.1/lobject.h.html#LClosure # http://www.lua.org/source/5.1/lobject.h.html#LocVar # http://www.lua.org/source/5.1/lobject.h.html#UpVal # http://www.lua.org/source/5.1/lstate.h.html#CallInfo # (find-lua51file "src/lvm.c" "case OP_CLOSURE:") # (find-fline "~/LOGS/2007jun09.lua") Proto_4_4 = { k = { [-5] = "set2", [-4] = "get2", [-3] = "set1", [-2] = "get1", [-1] = "foo" }, p = { [0] = Proto_1_6 }, code = { "1 [4] GETUPVAL 0 0", -- R[0] = U[0] -- storage "2 [4] RETURN 0 2", -- return R[0] "3 [4] RETURN 0 1", -- (unreachable code) } } Proto_5_5 = { upvalues = { [0] = "storage" }, -- ??? locvars = { [0] = "x" }, -- ??? - x is an argument code = { "1 [5] SETUPVAL 0 0", -- U[0] = R[0] -- storage = x "2 [5] RETURN 0 2", -- return R[0] "3 [5] RETURN 0 1", -- (unreachable code) } } Proto_1_6 = { k = { [-5] = "set2", [-4] = "get2", [-3] = "set1", [-2] = "get1", [-1] = "foo" }, p = { [0] = Proto_4_4, [1] = Proto_5_5 }, locvars = { [0] = "storage" } code = { "1 [4] CLOSURE 1 0", -- R[1] = closure(p[0], -- Proto_4_4, "2 [4] MOVE 0 0", -- LOCAL_0) -- storage "3 [5] CLOSURE 2 1", -- R[2] = closure(p[1], -- Proto_5_5, "4 [5] MOVE 0 0", -- LOCAL_0) -- storage "5 [5] RETURN 1 3", -- return R[1], R[2] "6 [6] RETURN 0 1", -- (unreachable code) } } Proto_1_8 = { k = { [-5] = "set2", [-4] = "get2", [-3] = "set1", [-2] = "get1", [-1] = "foo" }, p = { [0] = Proto_1_6 }, code = { "1 [6] CLOSURE 0 0", -- R[0] = closure(p[0]) -- Proto_1_6 "2 [6] SETGLOBAL 0 -1", -- G[k[-1]] = R[0] -- foo = ^ "3 [7] GETGLOBAL 0 -1", -- R[0] = G[k[-1]] -- foo "4 [7] CALL 0 1 3", -- R[0], R[1] = R[0]() -- () "5 [7] SETGLOBAL 1 -3", -- G[k[-3]] = R[1] -- set1 = ^ "6 [7] SETGLOBAL 0 -2", -- G[k[-2]] = R[0] -- get1 = ^ "7 [8] GETGLOBAL 0 -1", -- R[0] = G[k[0]] -- foo "8 [8] CALL 0 1 3", -- R[0], R[1] = R[0]() -- () "9 [8] SETGLOBAL 1 -5", -- G[k[-5]] = R[1] -- set2 = ^ "10 [8] SETGLOBAL 0 -4", -- G[k[-4]] = R[0] -- get2 = ^ "11 [8] RETURN 0 1", -- return } } # (find-luanofrillspage 1) # (find-luanofrillspage 52 "Closures and Closing") # (find-luanofrillspage 28 "CALL") # (find-luanofrillstext "-28-" -15 "CALL") # An important diagram (that needs more details): # (find-luaimppage 9) ##### # # building lua-5.1.2 # 2007apr04 # ##### # «install-5.1.2» (to ".install-5.1.2") # http://www.lua.org/ftp/lua-5.1.2.tar.gz # (code-c-d "lua51" "~/usrc/lua-5.1.2/") # (find-lua51file "") # (find-lua51file "INSTALL") # (find-lua51file "oml") # (find-lua51file "src/Makefile") # (find-node "(make)Phony Targets" "`.PHONY'") #* mkdir ~/usrc/ rm -Rfv ~/usrc/lua-5.1.2/ mkdir ~/usrc/lua-5.1.2/ tar -C ~/usrc/ -xvzf $S/http/www.lua.org/ftp/lua-5.1.2.tar.gz cd ~/usrc/lua-5.1.2/ # (to "risclua") # «minimal_GCW_SUGAR» (to ".minimal_GCW_SUGAR") # (find-lua51file "src/llex.c" "#ifdef GCW_SUGAR") # (find-lua51file "src/llex.c.orig" "case '=':") # (find-tkdiff (ee-lua51file "src/llex.c") (ee-lua51file "src/llex.c.orig")) # cp -iv src/llex.c src/llex.c.orig patch -p0 src/llex.c <<'%%%' 370a371,376 > #ifdef GCW_SUGAR > switch(ls->current) { > case '=': next(ls); return TK_EQ; break; > case '>': next(ls); return TK_RETURN; break; > default: return '='; } > #else 372a379 > #endif 373a381,386 > #ifdef GCW_SUGAR > case '\\': { > next(ls); > return TK_FUNCTION; > } > #endif %%% # Pre-compile llex.c with GCW_SUGAR=1 # cd src; gcc -O2 -Wall -DLUA_USE_LINUX -DGCW_SUGAR -c -o llex.o llex.c; cd .. # Instead: # (find-lua51file "src/Makefile") patch -p0 src/Makefile <<'%%%' 11c11 < CFLAGS= -O2 -Wall $(MYCFLAGS) --- > CFLAGS= -O2 -Wall $(MYCFLAGS) -DGCW_SUGAR -g %%% find * -name '*.[ch]' | sort > .files.ch etags $(<.files.ch) make linux test |& tee oml # Make a .so # (find-lua50file "Makefile" "so:") # (find-lua51file "src/Makefile" "CORE_O=") cd src; ld -o liblua.so -shared $(ar t liblua.a); cd .. # (find-lua51file "oml") # (find-lua51file "oml2") #* cd ~/usrc/lua-5.1.2/src/ cp -iv lua ~/bin/lua51 cp -iv luac ~/bin/luac51 #* # Test dlopen on lpeg # (to "lpeg") cd ~/usrc/lpeg-0.5/ ~/usrc/lua-5.1.1/src/lua test.lua ~/usrc/lua-5.1.2/src/lua test.lua #* # (find-lua51file "src/Makefile") # (find-lua51file "src/Makefile" "linux:") # (find-lua51file "Makefile") # (find-lua51file "oml") make MYCFLAGS=-DGCW_SUGAR linux test |& tee oml ##### # # argpatch # 2007jun09 # ##### # (find-es "lua5" "argpatch") * (eepitch-shell) lua51 -e 'PP(arg)' echo "PP(arg)" > /tmp/foo.lua lua51 /tmp/foo.lua ##### # # Invoking arrays # 2003jan08 # ##### # «invoking-arrays» (to ".invoking-arrays") # (find-lua50ref "__call") # (find-lua50ref "setmetatable") # (find-lua50ref "sec3.7") #* lua50 -e ' arr = {} -- (find-lua50ref "sec3.7") setmetatable(arr, arr) -- (find-lua50ref "setmetatable") arr.__call = print -- (find-lua50ref "__call") arr(20, 30, 40) --> table:0xxxxxxxxx 20 30 40 arr.name = "<arr>" arr.__call = function (arr, ...) print(arr.name, unpack(arg)) end arr(20, 30, 40) --> <arr> 20 30 40 ' #* lua50 -e ' a = {} mt = {} setmetatable(a, mt) mtset = function (mtfield) mt[mtfield] = function (...) P(mtfield, unpack(arg)) end end mtset("__add"); b = a + 1 mtset("__sub"); b = a - 2 mtset("__mul"); b = a * 3 mtset("__div"); b = a / 4 mtset("__pow"); b = a ^ 5 mtset("__unm"); b = - a mtset("__concat"); b = a .. 6 mtset("__eq"); b = a == a mtset("__lt"); b = a < 9 mtset("__le"); b = a <= 10 ' #* mtset("__concat"); b = a[20] mtset("__eq"); b = a[20] mtset("__lt"); b = a[20] mtset("__le"); b = a[20] mtset("__index"); b = a[20] mtset("__newindex"); b = a[20] b = a[20] # (find-lua50file "src/") # (find-lua50file "src/lapi.c" "lua_getmetatable") # (find-lua50file "src/lobject.h" "typedef struct Table") # (find-lua50file "src/ltests.c" "static int metatable") # (find-lua50file "src/ltm.c") # (find-lua50file "src/lvm.c") # (find-lua50file "src/lvm.c" "case OP_CALL:") # (find-lua50file "src/lobject.h" "#define hvalue(o)") ##### # # string.find # 2003mar12 # ##### # «string.find» (to ".string.find") # (find-lua50ref "String Manipulation" "string.find") # string.find (s, pattern [, init [, plain]]) # --> begpos endpos captstr1 captstr2 ... #* lua50e 'P(string.find("0123456789", "3(45)(67)", 4)) --> 4 8 "45" "67"' lua50e 'P(string.find("0123456789", "3(45)(67)", 5)) -->' #* # «string.gfind» (to ".string.gfind") # (find-lua50ref "String Manipulation" "string.gfind") lua50e 'for w,s in string.gfind("aa!b!!c", "([^!]*)(!?)") do P(w, s) end' lua50e 'for w,s in string.gfind("aa!b!!c!", "([^!]*)(!?)") do P(w, s) end' #* ##### # # empty captures in patterns # 2004jan14 # ##### # «emptycaptures» (to ".emptycaptures") # (find-lua50ref "String Manipulation" ". string.find") # (find-lua50ref "Captures" "the empty capture ()") # (to "split") #* lua50e ' P(string.find("abbc", "()(b+)()", 1)) --> 2 3 2 "bb" 4 P(string.find("abbc", "()(b+)()", 2)) --> 2 3 2 "bb" 4 P(string.find("abbc", "()(b+)()", 3)) --> 3 3 3 "b" 4 P(string.find("abbc", "()(b+)()", 4)) --> ' #* lua50e ' split = function (str) local arr, pos = {}, 1 while 1 do local _, __, word, newpos = string.find(str, "^[%s]*([^%s]+)()", pos) if newpos then table.insert(arr, word); pos = newpos else return arr end end end PP(split(" abc de ")) ' #* #### # # C calling lua # 2004feb25 # #### # «C-calls-lua» (to ".C-calls-lua") # (find-es "lua5" "C-calls-lua") # (find-es "lua5" "luastackPP") # (find-es "lua5" "pil") # (find-es "lua5" "getoutput") # (find-angg "LUA/lua50init.lua" "getoutput") ##### # # xpcall # 2006sep16 # ##### # «xpcall» (to ".xpcall") # (to "ldb") # (find-lua51manual "#pdf-xpcall") # (find-lua51manual "#pdf-debug.traceback") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) err = function () print("foo"); io.output():flush(); error("bar") end inner = function () return 1+err() end middle = function () return 1+inner() end outer = function () return 1+middle() end outer() -- "foo", then traceback pcall(outer) -- "foo", no traceback xpcall(outer, PP) xpcall(outer, function() print(debug.traceback()) end) printtraceback = function() print(debug.traceback()) end xpcall(outer, printtraceback) xpcall(outer, debug.debug) cont -- (find-lua51file "src/ldebug.c") -- (find-lua51file "src/ldblib.c") -- (find-lua51file "src/ldblib.c" "{\"traceback\", db_errorfb},") -- (find-lua51tag "db_errorfb") ##### # # pil 24.1: calling Lua from C # 2006oct21 # ##### # «pil24.1» (to ".pil24.1") # (find-es "icon" "icon-lua") # (find-lua51file "") # (find-lua51file "oml" "liblua.a") # (find-lua51file "src/lua.c") # (find-lua51file "src/" "liblua.a") #* # (eev-bounded) rm -Rv /tmp/pil24_1/ mkdir /tmp/pil24_1/ cd /tmp/pil24_1/ cat > pil24_1.c <<'---' #include <stdio.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h> #include <string.h> // for strlen int main (void) { char buff[256]; int error; lua_State *L = luaL_newstate(); /* opens Lua */ luaL_openlibs(L); /* opens the standard libraries */ while (fgets(buff, sizeof(buff), stdin) != NULL) { error = luaL_loadbuffer(L, buff, strlen(buff), "line") || lua_pcall(L, 0, 0, 0); if (error) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1); /* pop error message from the stack */ } } lua_close(L); return 0; } --- export LUA51SRC=$HOME/usrc/lua-5.1.1 gcc -O2 -Wall -I$LUA51SRC/src -c -o pil24_1.o pil24_1.c # (find-lua51file "oml" "liblua.a") # (find-lua51file "oml" "gcc -o lua ") # gcc -o lua lua.o liblua.a -lm -Wl,-E -ldl -lreadline -lhistory -lncurses # gcc -o pil24_1 pil24_1.o $LUA51SRC/src/liblua.a -lm -Wl,-E -ldl -lreadline -lhistory -lncurses gcc -o pil24_1 pil24_1.o $LUA51SRC/src/liblua.a -lm -Wl,-E -ldl echo 'print(1+2, "hello")' | ./pil24_1 #* # (find-node "(gcc)Invoking GCC") # (find-node "(gcc)Link Options") ##### # # lpeg quickref # 2007mar05 # ##### # «lpeg-quickref» (to ".lpeg-quickref") # (find-es "lua5" "lpeg-quickref") # http://www.inf.puc-rio.br/~roberto/lpeg.html # (find-lpegfile "lpeg.c") # (find-lpegfile "lpeg.c" "{\"match\", matchl},") lpeg.P(str) matches str lpeg.P(0) matches always lpeg.P(1) matches one char (".") lpeg.P(2) matches two chars ("..") lpeg.P(-1) matches if there isn't another char (end of string) lpeg.P(-2) matches if there aren't two more chars lpeg.P(p) return the pattern p unmodified lpeg.P(f) if f(subj, pos) returns a valid newpos then matches until it lpeg.P(gra) matches the first entry (gra[1]) in the grammar gra (a table) lpeg.V(2) matches the second entry (gra[2]) in the grammar above this lpeg.R("az", "AZ") matches any char in ranges - like "[A-Za-z]" lpeg.S("abd") matches any char in set - like "[abd]" #patt like patt, but without consuming input -patt like #patt, but negating the result p1 * p2 concatenation: "p1p2" p1 + p2 bounded prioritized choice - roughly like "p1|p2" p1 - p2 equivalent to -p2 * p1 1 - cset a char not in cset patt ^ 0 at least 0 occurrences of patt - like "patt*" patt ^ 1 at least 1 occurrence of patt - like "patt+" patt ^ 2 at least 2 occurrences of patt patt ^ -1 at most 1 occurrence of patt - like "patt?" patt ^ -2 at most 2 occurrences of patt lpeg.C(patt) the substring matched by patt (then patt's other captures) lpeg.Ca(patt) if patt captures a,f,g,h then h(g(f(a))) <--- WRONG! lpeg.Cc(v) matches the empty string, captures the value v lpeg.Cs(patt) the substring matched by patt, after substitutions lpeg.Ct(patt) all captures made by patt as a table patt / f if patt captured a,b,c then f(a, b, c) patt / "_%2_" if patt captured "foo" and "bar" then "_bar_" patt / tbl if patt captured a and b then tbl[a] ##### # # Lpeg: basic demos (but with "test" and "export") # 2014aug30 # ##### # «lpeg-basic» (to ".lpeg-basic") # «lpeg-export» (to ".lpeg-export") # file:///usr/share/doc/lua-lpeg-dev/lpeg.html * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) require "lpeg" loadlpeg() lpeg.test = function (pat, str, ...) PP(pat:C():match(str, ...)) end lpeg.export = function (str) for name in str:gmatch"%w+" do _G[name] = lpeg[name] end end lpeg.export "P R S C Cp Ct Cc" sp = S" " ^1 -- space (no captures) w = (R"az"^1):C() -- word (one capture) m = sp * w -- one more word (one capture) ms = (sp * w)^1 -- more words (one capture for each) num = (R"09"^1):C() nop = function () end id = function (...) return ... end pre0 = function (...) return 0, ... end swap = function (a, b) return b, a end swap = function (a, b) return "<", b, a, ">" end ( w * m ):test "abc def ghi jkl" ( w * ms ):test "abc def ghi jkl" ( w * ms ):test "abc def ghi" ( w * ms ):test "abc def" ( w * ms ):test "abc" ( w * ms ):test "" ( w * m/"_%1_" ):test "abc def ghi jkl" ( w * (m/"_%1_") ):test "abc def ghi jkl" ( w * (m * m /"_%1_%2_") * m ):test "abc def ghi jkl" ( w * (m * m / swap) * m ):test "abc def ghi jkl" ( w * (m/"_%1_") * (m/"<%1>")):test "abc def ghi jkl" ( w * (m/nop) * (m/"<%1>")):test "abc def ghi jkl" ( w * (m/id) * (m/"<%1>")):test "abc def ghi jkl" ( w * (m/pre0) * (m/"<%1>")):test "abc def ghi jkl" ( w * Cc(20, 30, 40) * (m/"_%1_")):test "abc def ghi jkl" ( (w * Cc(20, 30, 40)):Ct() * (m/"_%1_")):test "abc def ghi jkl" ( (w * Cc(20, 30, 40)):Ct() * (m/"_%1_")):test "abc def ghi jkl" -- (find-es "lua5" "lpeg-re") require "re" re_extras = " _ -> ' '* " re_extras = "" string.retest = function (r, str) re.compile(r..re_extras):test(str) end (" 'a'* "):retest "aaabbb" -- «lpeg-P» (to ".lpeg-P") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) require "lpeg" lpeg.test = function (pat, str, ...) PP(pat:C():match(str, ...)) end lpeg.export = function (str) for w in str:gmatch"%w+" do _G[w]=lpeg[w] end end lpeg.export "P R S C Cp Ct Cc" -- lpeg.P(f) if f(subj, pos) returns a valid newpos then matches until it ##### # # lpeg-re-quickref # 2021sep04 # ##### # «lpeg-re-quickref» (to ".lpeg-re-quickref") ##### # # lpeg-re # 2014oct03 # ##### # «lpeg-re-1» (to ".lpeg-re-1") # (find-angg "LUA/lua50init.lua" "syntree") # file:///usr/share/doc/lua-lpeg-dev/re.html#ex * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) require "re" ang = function (s) return "<"..s..">" end retest = function (p) return function (s) print(re.match(s, p)) end end retest "[0-9]" "123abc" --> 2 retest "[0-9]+" "123abc" --> 4 retest "{[0-9]+}" "123abc" --> 123 retest "{ [0-9]+ }" "123abc" --> 123 retest "da <- d a d <- {[0-9]+} a <- {[a-z]+}" "123abc456" --> 123 abc retest "da <- {d} {a} d <- [0-9]+ a <- [a-z]+" "123abc456" --> 123 abc retest "da <- {d a} d <- [0-9]+ a <- [a-z]+" "123abc456" --> 123abc retest "da <- {d a} -> ang d <- [0-9]+ a <- [a-z]+" "123abc456" --> 123abc # «lpeg-re-infix-1» (to ".lpeg-re-infix-1") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) require "re" g = function (...) return "("..table.concat({...}, " ")..")" end f = function (...) local A={...}; return #A==1 and A[1] or g(...) end defs = { f = f } c = function (pat) return re.compile(pat, defs) end retest = function (p) return function (s) print(re.match(s, c(p))) end end retest [[ e <- e3 e3 <- (e2 ({"+"} e2)*) -> f e2 <- (e1 ({"*"} e1)*) -> f e1 <- (e0 ({"^"} e0)*) -> f e0 <- "(" e3 ")" / {[0-9]+} ]] "1*2+3^4*5^6+7^8" --> ((1 * 2) + ((3 ^ 4) * (5 ^ 6)) + (7 ^ 8)) g = syntreeg retest [[ e <- e3 e3 <- (e2 ({"+"} e2)*) -> f e2 <- (e1 ({"*"} e1)*) -> f e1 <- (e0 ({"^"} e0)*) -> f e0 <- "(" e3 ")" / {[0-9]+} ]] "1*2+3^4*5^6+7^8" --> +_____+___________. -- | | | -- *__. *_____. ^__. -- | | | | | | -- 1 2 ^__. ^__. 7 8 -- | | | | -- 3 4 5 6 # «lpeg-re-infix-2» (to ".lpeg-re-infix-2") # (find-angg "LUA/lua50init.lua" "re_expand_INFIX") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) require "re" g = syntreeg f = function (...) local A={...}; return #A==1 and A[1] or g(...) end defs = { f = f } c = function (pat) return re.compile(pat, defs) end retest = function (p) return function (s) print(re.match(s, c(p))) end end gram = re_expand_INFIX [=[ e <- e3 e3 <- INFIX( e2 s + - ) -> f e2 <- INFIX( e1 s * / ) -> f e1 <- INFIX( e0 ss ^ ) -> f e0 <- {[0-9]+} s <- ' '* ss <- ' '+ ]=] = gram retest (gram) "1*2+3^4*5^6+7^8" ##### # # lua-mode.el # 2007feb05 # ##### # «lua-mode.el» (to ".lua-mode.el") # (find-es "lua5" "lua-mode.el") ##### # # Patrick # 2017mai16 # ##### # «patrick» (to ".patrick") # (defun u () (interactive) (find-escript-upload-links "lua-intro" "patrick")) # (defun e () (interactive) (find-es "lua-intro" "patrick")) # http://angg.twu.net/e/lua-intro.e.html#patrick # http://angg.twu.net/e/lua-intro.e.html # (find-wget "http://angg.twu.net/e/lua-intro.e" "<patrick-1>") # <patrick-1> # Instructions: * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) sudo apt-get install lua5.1 lua5.1-doc # http://angg.twu.net/e/lua-intro.e mkdir -p $S/http/angg.twu.net/e/ cd $S/http/angg.twu.net/e/ rm -v 'http://angg.twu.net/e/lua-intro.e' wget 'http://angg.twu.net/e/lua-intro.e' echo 'http://angg.twu.net/e/lua-intro.e' >> ~/.psne.log mkdir ~/LUA/ cd ~/LUA/ rm -v lua50init.lua wget http://angg.twu.net/LUA/lua50init.lua export LUA_INIT=@$HOME/LUA/lua50init.lua * (setenv "LUA_INIT" (concat "@" (ee-expand "~/LUA/lua50init.lua"))) * (defun eejump-3 () (find-fline "$S/http/angg.twu.net/e/lua-intro.e")) * (defun eejump-33 () (find-anchor "$S/http/angg.twu.net/e/lua-intro.e" "patrick")) * (defun eejump-33 () (find-fline "$S/http/angg.twu.net/e/lua-intro.e" "<patrick-1>")) * (defun eepitch-lua51 () (interactive) (eepitch-comint "lua5.1" "lua5.1")) * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) (defun find-lua51manual (&optional anchor &rest rest) (brg (format "file:///usr/share/doc/lua5.1-doc/doc/manual.html%s" (or anchor "")))) (defun find-lua51manual (&optional anchor &rest rest) (find-lua51manual anchor)) ;; (find-lua51manual "#2.2" "eight basic types") ;; (find-lua51manual "#2.2" "eight basic types") ;; (find-lua51manual "#pdf-type") # (find-man "mkdir") # (find-man "rm") # (find-man "wget") # (find-man "echo") # (find-man "bash" " cd ") mkdir ~/LUA/ cd ~/LUA/ rm -v lua50init.lua wget http://angg.twu.net/LUA/lua50init.lua export LUA_INIT=@$HOME/LUA/lua50init.lua # <patrick-gab> # (find-wget "http://angg.twu.net/e/lua-intro.e" "<patrick-gab>") * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) # http://angg.twu.net/gabp/ rm -Rv ~/gabp/ mkdir ~/gabp/ cd ~/gabp/ wget http://angg.twu.net/gabp/gab.lua wget http://angg.twu.net/gabp/gab-tests.lua # Copie isto para o seu .emacs: (code-c-d "angg" "~/" :anchor) ;; (find-angg "LUA/") ;; (find-angg "LUA/lua50init.lua") (code-c-d "gabp" "~/gabp/" :anchor) ;; (find-gabp "") ;; (find-gabp "gab.lua") ;; (find-gabp "gab-tests.lua") # Local Variables: # coding: utf-8-unix # modes: (fundamental-mode lua-mode c-mode) # End: