####### # # 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. # # 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 # or at . # See also , # , # , # and . # ####### # «.quick-presentation» (to "quick-presentation") # «.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") # «.0-based» (to "0-based") # «.vararg» (to "vararg") # «.lua-arg» (to "lua-arg") # «.for» (to "for") # «.each2» (to "each2") # «.lua5.1-require» (to "lua5.1-require") # «.lua5.1-package» (to "lua5.1-package") # «.io.output» (to "io.output") # «.posix-lua51» (to "posix-lua51") # «.posix-install» (to "posix-install") # «.load_posix» (to "load_posix") # «.gsub-with-alternatives» (to "gsub-with-alternatives") # «.C-calls-lua» (to "C-calls-lua") # «.luastackPP» (to "luastackPP") # «.string.gsub» (to "string.gsub") # «.makewith» (to "makewith") # «.pil» (to "pil") # «.pil2» (to "pil2") # «.bitlib-51» (to "bitlib-51") # «.io.popen» (to "io.popen") # «.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") # «.objective-lua» (to "objective-lua") # «.tokenf» (to "tokenf") # «.ex» (to "ex") # «.xpcall» (to "xpcall") # «.metamethods-pseudocode» (to "metamethods-pseudocode") # «.generators-pseudocode» (to "generators-pseudocode") # «.pil24.1» (to "pil24.1") # «.pixeltoaster» (to "pixeltoaster") # «.compressing-jpgs» (to "compressing-jpgs") # «.matrix.lua» (to "matrix.lua") # «.lpeg» (to "lpeg") # «.lpeg-quickref» (to "lpeg-quickref") # «.lpeg-ex-arith-1» (to "lpeg-ex-arith-1") # «.lpeg-ex-arith-2» (to "lpeg-ex-arith-2") # «.lpeg-elisp-hyperlinks» (to "lpeg-elisp-hyperlinks") # «.sheadsymbol-roberto» (to "sheadsymbol-roberto") # «.lpeg-0.5-bug» (to "lpeg-0.5-bug") # «.loadstring_and_eof» (to "loadstring_and_eof") # «.incompletep» (to "incompletep") # «.ldb-from-tgz» (to "ldb-from-tgz") # «.ldb» (to "ldb") # «.lua-mode.el» (to "lua-mode.el") # «.risclua» (to "risclua") # «.functionnames» (to "functionnames") # «.cinvoke» (to "cinvoke") # «.cinvoke-libtcl» (to "cinvoke-libtcl") # «.tlbridge.c» (to "tlbridge.c") # «.luatclbridge» (to "luatclbridge") # «.lunatic-python» (to "lunatic-python") # «.kepler» (to "kepler") # «.helper-threads» (to "helper-threads") # «.loona» (to "loona") # «.pseudo-spreadsheet» (to "pseudo-spreadsheet") # «.CGI.lua» (to "CGI.lua") # «.kepler-1.1» (to "kepler-1.1") # «.kepler-1.1-hasbang» (to "kepler-1.1-hasbang") # «.markdown.lua» (to "markdown.lua") # «.ctrace» (to "ctrace") ##### # # 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-pilw3m "2.html" "eight basic types") # (find-luamanualw3m "#2.2" "eight basic types") # (find-luamanualw3m "#pdf-type") # Basic data types lua51 -e ' 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 ' # # (find-luamanualw3m "#2.5.9" "f = function () body end") # (find-pilw3m "6.html") # Functions are values lua51 -e ' function square(a) return a*a end square = function (a) return a*a end print(square, square(2)) ' # # (find-pilw3m "5.1.html" "Multiple Results") # (find-luamanualw3m "#2.4.3" "Assignment") # (find-luamanualw3m "#2.5" "Expressions") # Functions can return several values lua51 -e ' 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, foo() print(zero, one, two, three, four) --> 0 1 2 3 nil ' # # (find-luamanualw3m "#2.2.1" "Coercion") # (find-pilw3m "2.4.html" "coercions") # Coercion lua51 -e ' print(1+"2") --> 3 print("<".. 11 .. 22 ..">") --> <1122> ' # # String literals # (find-luamanualw3m "#2.1" "Literal strings") # (find-luamanualw3m "#2.1" "Literal strings can also be defined") # # (find-luamanualw3m "#2.5.7" "Table Constructors") # (find-pilw3m "2.5.html" "Tables") # Tables echo $LUA_INIT lua51 -e ' a = {10, 20, 30} print(200, "some string", a) PP (200, "some string", a) b = {11, a, "foo", print} PP(b) ' # # Tables (2) lua51 -e ' c = {11, 22, 33} c[2] = c[2]+c[3] c[5] = 55 c["foo"] = "FOO" PP(c) d = {11, 22, 33, [5]=555, ["bar"]="BAR", [c]="!"} PP(d) d[2] = nil d[c] = nil PP(d) ' # # (find-luamanualw3m "#2.3" "environments") # Global variables lua51 -e ' for key,val in _G do print(key, val) end ' # # (find-luamanualw3m "#pdf-_G") # Global variables lua51 -e ' print(print) print(_G["print"]) print(_G.print) print(_G) print(_G._G) ' # # Local variables lua51 -e ' a = 22 do print(a) local a = 33 print(a) end print(a) ' # # assert lua51 -e ' print(22) print(assert(22, 33)) print(assert(nil, "Error! Error!")) ' # # loadstring lua51 -e ' s = [[ print("oi") ]] f, err = loadstring(s) print(f, err) f() print(loadstring([[ print("oi ) ]])) print(loadstring([[ print("oi ) ]], "nome do bloco")) print("ok") ' # # loadstring lua51 -e ' s = [[ print("foo") return function (x) print("bar", x) end ]] print(s) f = assert(loadstring(s)) g = f() g(223) ' # # Capture of local variables lua51 -e ' foo = function () local storage return function () return storage end, function (x) storage = x; return x end end get1, set1 = foo() get2, set2 = foo() print(set1(22), get1()) --> 22 22 print(set2(33), get1(), get2()) --> 33 22 33 ' # # (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-luamanualw3m "#2.11") -- (find-luamanualw3m "#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) 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) 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) 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 "luacourse" "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.__call = function (arr, ...) print(arr.name, unpack(arg)) end arr(20, 30, 40) --> 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 ")) ' # ##### # # Functions with a variable number of parameters # 2003mar13 # ##### # «vararg» (to ".vararg") # (find-lua50ref "__call") # (find-lua50ref "Function Definitions" "arg={5, 8; n=2}") ##### # # arg # 2004sep07 # ##### # «lua-arg» (to ".lua-arg") # (find-man "1 lua") # (find-luafile "src/lua/lua.c" "\"arg\"") # (find-zshnode "Process Substitution") # lua50 -e 'PP(arg)' lua50 =(<<<'PP(arg)') Arg1 Arg2 lua50 =(<<<'print(unpack(arg))') Arg1 Arg2 # ##### # # the several flavors of "for" # 2003feb27 # ##### # «for» (to ".for") # (find-luamanualw3m+ "for") # lua50e 'for i=1,4 do P(i) end' ;# 1 2 3 4 lua50e 'for i=5,-2,-2 do P(i) end' ;# 5 3 1 -1 lua50e 'for i=2,2 do P(i) end' ;# 2 lua50e 'for i=2,0 do P(i) end' ;# lua50e 'for key,val in {4,5,k="K"} do P(key, val) end' ;# 1 4 / 2 5 / "k" "K" lua50e 'a={4,5,k="K"}; for i=1,table.getn(a) do P(i, a[i]) end' ;# 1 4 / 2 5 # # (find-lua50ref "next") # lua50e 'a={4,5,k="K"}; P(next(a))' lua50e 'a={4,5,k="K"}; i=nil P(next(a,i)); i=next(a,i) P(next(a,i)); i=next(a,i) P(next(a,i)); i=next(a,i) P(next(a,i)); i=next(a,i) ' # # (find-luamanualw3m+ "for") # (find-lua50ref "For Statement" "generators") # (find-lua50ref "For Statement" "generators" "equivalent to") # (find-lua50ref "Basic Functions" ". ipairs") # (find-lua50ref "Basic Functions" ". pairs") # lua50e 'a={4,5,k="K"}; for key,val in a do P(key,val) end' lua50e 'a={4,5,k="K"}; for key,val in pairs(a) do P(key,val) end' lua50e 'a={4,5,k="K"}; for key,val in ipairs(a) do P(key,val) end' lua50e 'a={4,5,k="K"}; P(ipairs(a))' lua50e 'a={4,5,k="K"}; f,state,key=ipairs(a); PP(ipairs(a)) key,val=f(state,key); PP(f,state,key,val) key,val=f(state,key); PP(f,state,key,val) key,val=f(state,key); PP(f,state,key,val) ' # # (find-lua50ref "table.foreach") # (find-lua50ref "table.foreachi") # (find-lua50ref "io.lines") * explist is evaluated only once. Its results are an iterator function, a state, and an initial value for the first iterator variable. * _f and _s are invisible variables. The names are here for explanatory purposes only. * The behavior is undefined if you assign to var_1 inside the block. * You can use break to exit a for loop. * The loop variables var_i are local to the statement; you cannot use their values after the for ends. If you need these values, then assign them to other variables before breaking or exiting the loop. # # (find-luamanualw3m+ "for" "The generic for statement") # (find-luamanualw3m+ "for" "iterator function,") # (find-luamanualw3m+ "next") # (find-lua50tag "luaB_next") # (find-lua50tag "lua_next") # (find-lua50tag "luaH_next") lua50e ' PP(ipairs({10, 20})) --> {1=10,2=20} 0 itf, state, v = ipairs({10, 20}) PP(itf ' # lua50e ' T = {10,20} f, s, a0 = ipairs(T); PP(f, s, a0) --> {1=10,2=20} 0 a1, b1, c1 = f(s, a0); PP(a1, b1, c1) --> 1 10 nil a2, b2, c2 = f(s, a1); PP(a2, b2, c2) --> 2 20 nil a3, b3, c3 = f(s, a2); PP(a3, b3, c3) --> nil ' # lua50e ' T = {b="B", a="A"} f, s, a0 = pairs(T); PP(f, s, a0) --> {"a"="A","b"="B"} a1, b1, c1 = f(s, a0); PP(a1, b1, c1) --> "a" "A" nil a2, b2, c2 = f(s, a1); PP(a2, b2, c2) --> "b" "B" nil a3, b3, c3 = f(s, a2); PP(a3, b3, c3) --> nil ' # # «each2» (to ".each2") # (find-angg "LUA/lua50init.lua" "each2") # (find-pilw3m "7.1.html" "Iterators and Closures")  (eepitch-lua51) each2 = function (tbl) local i = 1 return function () if i <= table.getn(tbl) then i = i + 2 return tbl[i - 2], tbl[i - 1] end end end for a,b in each2(split("aa bb cc dd ee ff")) do print(a, b) end f, s, a0 = iterator(); PP(f, s, a0) a1, b1, c1 = f(s, a0); PP(a1, b1, c1) a2, b2, c2 = f(s, a1); PP(a2, b2, c2) a3, b3, c3 = f(s, a2); PP(a3, b3, c3) while true do ##### # # "require" and the "package" table in lua5.1 # 2007mar06 # ##### # «lua5.1-require» (to ".lua5.1-require") # http://www.inf.puc-rio.br/~roberto/pil2/chapter15.pdf # (find-luamanualw3m "#pdf-require") # (to "compat-5.1") # (find-compat51file "") # (find-compat51file "compat-5.1.lua") # (find-compat51file "compat-5.1.lua" "LUA_PATH") # (find-lua51file "") # (find-lua51tag "ll_require") # «lua5.1-package» (to ".lua5.1-package")  (eepitch-lua51) loadcinvoke() for k,v in pairs(package) do print(k) end PP(package.preload) PP(package.loadlib) for k,v in pairs(package.loaded) do print(k) end = package.loaded.cinvoke_lua PP(package.loaders) = package.cpath = package.config = package.path = package.seeall #### # # C calling lua # 2004feb25 # #### # «C-calls-lua» (to ".C-calls-lua") # rm -Rv ~/tmp/ccallslua/ mkdir ~/tmp/ccallslua/ cd ~/tmp/ccallslua/ cat > script.lua <<'%%%' luafunction = function (a, b) return "<"..a.." "..b..">" end %%% # (find-lua50ref "Getting Values from the Stack") # (find-lua50ref "The Stack and Indices" "negative index") # (find-lua50ref "Pushing Values onto the Stack") # (find-lua50ref "Calling Functions" "a = f(\"how\", t.x, 14)") # (find-lua50ref "Manipulating Tables") # (find-luatag "luaopen_base") # (find-luatag "openstdlibs") # (find-luatag "lualibs") # (find-lua50ref "Standard Libraries" "luaopen_string") cat > callit.c <<'%%%' #include #include #include #include void PP(lua_State *L, int index) { lua_pushstring(L, "PP"); lua_gettable(L, LUA_GLOBALSINDEX); lua_pushvalue(L, index<0?index-1:index); lua_call(L, 1, 0); } int main(int argc, char **argv) { lua_State *L; char *rslt; L = lua_open(); luaopen_base(L); /* pushes 1 thing */ luaopen_string(L); /* pushes 1 thing */ luaopen_table(L); /* pushes 1 thing */ luaopen_io(L); /* pushes 3 things */ lua_pop(L, 6); /* removes these 1+1+1+3 things */ lua_dofile(L, "/home/edrx/LUA/lua50init.lua"); /* for "PP" and debug stuff */ lua_dofile(L, "script.lua"); lua_pushstring(L, "luafunction"); /* function name: "luafunction" */ lua_gettable(L, LUA_GLOBALSINDEX); /* -> function: luafunction */ lua_pushstring(L, "foo"); /* argument 1: "foo" */ lua_pushnumber(L, 45); /* argument 2: 45 */ lua_call(L, 2, 1); /* call with 2 args and 1 result */ rslt = lua_tostring(L, -1); /* rslt = "" */ lua_pop(L, 1); /* remove rslt */ printf("rslt = \"%s\"\n", rslt); lua_close(L); } %%% # (find-node "(gcc-300)Link Options") # -L$HOME/usrc/lua-5.0.2/lib -llualib -llua gcc -g -o callit callit.c -ldl -lm \ -I$HOME/usrc/lua-5.0.2/include \ ~/usrc/lua-5.0.2/lib/liblua.a \ ~/usrc/lua-5.0.2/lib/liblualib.a \ ./callit # # (eegud-gdb t "/home/edrx/tmp/ccallslua/" "callit") # (find-node "(gdb)Calling") # (find-node "(gdb)Define") define depth p lua_gettop(L) end define PP call PP(L, $arg0) end br main run # ##### # # inspecting the Lua stack # 2004sep02 # ##### # «luastackPP» (to ".luastackPP") # rm -Rv ~/tmp/luastackPP/ mkdir ~/tmp/luastackPP/ cd ~/tmp/luastackPP/ cat > luastackPP.c <<'%%%' #include #include #include #include void PP(lua_State *L, int index) { lua_pushstring(L, "PP"); lua_gettable(L, LUA_GLOBALSINDEX); lua_pushvalue(L, index<0?index-1:index); lua_call(L, 1, 0); } LUALIB_API int luastackPP_init(lua_State *L) { /* nothing to do on the Lua side; we're only adding C functions */ return 0; } %%% gcc -g -Wall -shared -I$LUASRC/include -o luastackPP.so luastackPP.c cp -v ~/tmp/luastackPP/luastackPP.so \ ~/lib/lua5/luastackPP.so # cat > /tmp/testPP.lua <<'%%%' LIBDIR = os.getenv("HOME").."/lib/lua5" assert(loadlib(LIBDIR.."/luastackPP.so", "luastackPP_init"))() math.sin(0) -- print(1, 2+"3", string.sub) print("aa", "bb", "cc", "dd", "ee") %%% cat /tmp/testPP.lua > /tmp/testPP.lst luac -p -l /tmp/testPP.lua >> /tmp/testPP.lst lua50 /tmp/testPP.lua # # (let ((eebd-function-is nil)) (eegud-gdb t ee-luadir "bin/lua")) # (find-fline "/tmp/testPP.lst") # (find-node "(gdb)Calling") # (find-node "(gdb)Define") define depth p lua_gettop(L) end define PP call PP(L, $arg0) end set args /tmp/testPP.lua # br main br math_sin run # # # (find-fline "/tmp/luabit/lbitlib.c") ##### # # string.sub # 2004dec24 # ##### # «string.gsub» (to ".string.gsub") # (find-lua50ref "string.gsub") # lua50 -e ' print(string.gsub("hello world", "(%w+)", "%1 %1")) --> "hello hello world world" print(string.gsub("hello world", "(%w+)", "%1 %1", 1)) --> "hello hello world" print(string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")) --> "world hello Lua from" print(string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)) --> "home = /home/roberto, user = roberto" print(string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return loadstring(s)() end)) --> "4+5 = 9" local t = {name="lua", version="5.0"} print(string.gsub("$name_$version.tar.gz", "%$(%w+)", function (v) return t[v] end)) --> "lua_5.0.tar.gz" ' # # (find-angg "LUA/lua50init.lua" "ee_expand") lua50 -e ' print(ee_expand("~/foo")) print(ee_expand("foo/~/bar")) print(ee_expand("$S/http/www.foo.org/~bar/")) ' # ##### # # downloading a local copy of "programming in Lua" # 2005nov02 # ##### # «pil» (to ".pil") # # http://www.lua.org/pil/index.html # http://www.lua.org/pil/capa.jpg # http://www.lua.org/lua.css cat $S/http/www.lua.org/pil/index.html \ | lua50e ' f = function (s) print(s); return "" end string.gsub(io.read("*a"), "href=\"(.-).html\"", f) ' \ | tee ~/o # cd $S/http/www.lua.org/pil/ for i in $(cat ~/o); do j=$i.html if [[ ! -e $j ]]; then wget http://www.lua.org/pil/$i.html fi done # # (code-c-d "pil" "$S/http/www.lua.org/pil/") # (find-pilfile "") # (find-pilw3m "index.html") # (find-pilw3m "4.3.5.html" "Generic for") # (find-pilw3m "7.1.html" "Iterators and Closures") # (find-pilw3m "9.1.html" "Coroutine Basics") # (find-pilw3m "24.2.3.html" "stackDump") # «pil2» (to ".pil2") # PiL2 has some extra chapters, and only chapter 15 # ("Modules and Packages") is online... # http://www.inf.puc-rio.br/~roberto/pil2/ # http://www.inf.puc-rio.br/~roberto/pil2/chapter15.pdf ##### # # Reuben Thomas's bitlib on lua5.1 # 2007apr13 # ##### # «bitlib-51» (to ".bitlib-51") # http://rrt.sc3d.org/Software/Lua/ # http://luaforge.net/frs/download.php/2084/bitlib-21.tar.gz # rm -Rv ~/usrc/bitlib-21/ tar -C ~/usrc/ -xvzf \ $S/http/luaforge.net/frs/download.php/2084/bitlib-21.tar.gz cd ~/usrc/bitlib-21/ rm -v lbitlib.o gcc -g -Wall -shared -I$LUA51SRC/src \ -o lbitlib.so lbitlib.c lua51 -e ' assert(package.loadlib("./lbitlib.so", "luaopen_bit"))() PP(bit) print(bit.band(9, 10)) ' # # (code-c-d "bitlib" "~/usrc/bitlib-21/") # (find-bitlibfile "") ##### # # io.popen # 2005nov06 # ##### # «io.popen» (to ".io.popen") # http://lua-users.org/lists/lua-l/2005-11/msg00071.html # (find-lua50file "src/lib/") # (find-lua50file "src/lib/liolib.c") # (find-node "(libc)Function Index" "* popen:") # (find-man "3 popen") # (find-busyboxtag "popen") # (find-uclibcfile "libc/stdio/popen.c") # cd ~/eev-current/examples/ lua50 -e ' pipe = assert(io.popen("ls -la *.e")) for li in pipe:lines() do print("("..li..")") end pipe:close() ' # ##### # # calling Lua from C # 2006jul14 # ##### # «calling-Lua-from-C» (to ".calling-Lua-from-C") # (find-es "swig") # (find-luamanual-ff "pushing") # (find-luamanualw3m+ "pushing") # (find-luamanual-ff "3.14") # (find-luamanualw3m+ "3.14") The following example shows how the host program may do the equivalent to this Lua code: a = f("how", t.x, 14) Here it is in C: lua_pushstring(L, "t"); lua_gettable(L, LUA_GLOBALSINDEX); /* global `t' (for later use) */ lua_pushstring(L, "a"); /* var name */ lua_pushstring(L, "f"); /* function name */ lua_gettable(L, LUA_GLOBALSINDEX); /* function to be called */ lua_pushstring(L, "how"); /* 1st argument */ lua_pushstring(L, "x"); /* push the string "x" */ lua_gettable(L, -5); /* push result of t.x (2nd arg) */ lua_pushnumber(L, 14); /* 3rd argument */ lua_call(L, 3, 1); /* call function with 3 arguments and 1 result */ lua_settable(L, LUA_GLOBALSINDEX); /* set global variable `a' */ lua_pop(L, 1); /* remove `t' from the stack */ # (find-luamanualw3m+ "pushing") # file:///home/edrx/usrc/lua-5.0.2/doc/manual2.html#pushing # file:///home/edrx/usrc/lua-5.0.2/doc/manual2.html#3.14 /* * Ve se um masked_phone_number consta da tabela de monitorados. * Esta funcao e' um wrapper em C para uma funcao em Lua com o mesmo nome. * «monitored_p_C» (to ".monitored_p_C") * (find-es "swig" "mla.c") */ int monitored_p(char *masked_phone_number) { /* pseudocode */ lua_pushstring(L, "monitored_p"); /* function name */ lua_gettable(L, LUA_GLOBALSINDEX); /* function to be called */ lua_pushstring(L, masked_phone_number); /* 1st (and only) argument */ lua_call(L, 1, 1); /* call function with 1 argument and 1 result */ /* now convert the returned value to an int and return it */ } ##### # # Calling the interactive interpreter inside a Lua program # 2006jul18 # ##### # «debug.debug» (to ".debug.debug") # (find-luamanualw3m+ "debug.debug") # (find-lua50tag "debug") # (find-lua50file "") # (find-lua50file "src/lib/ldblib.c") # (find-lua50file "src/lib/ldblib.c" "\"traceback\"") # (find-lua50file "src/lib/ldblib.c" "static int errorfb")  (eepitch-shell) lua50 -e ' bar = function () local b=33; debug.debug() end foo = function () local a=22; bar() end foo() ' PP(debug.getinfo(1)) PP(debug.getinfo(2)) PP(debug.getinfo(3)) -- bar PP(debug.getinfo(4)) -- foo PP(debug.getinfo(print)) PP(debug.getinfo(foo)) This function returns a table with information about a function. You can give the function directly, or you can give a number as the value of function, which means the function running at level function of the call stack: Level 0 is the current function (getinfo itself); level 1 is the function that called getinfo; and so on. If function is a number larger than the number of active functions, then getinfo returns nil. The returned table contains all the fields returned by lua_getinfo, with the string what describing which fields to fill in. The default for what is to get all information available. If present, the option `f´ adds a field named func with the function itself. For instance, the expression debug.getinfo(1,"n").name returns the name of the current function, if a reasonable name can be found, and debug.getinfo(print) returns a table with all available information about the print function. debug.getlocal (level, local) ##### # # long comment syntax # 2006jul28 # ##### # (find-lua51w3m "doc/manual.html") # (find-lua51w3m "doc/manual.html" "]====]") # LUA51=$HOME/usrc/lua-5.1.1/src/lua $LUA51 -e ' print "a" --[=[ print "b" --]=] print "c" ' # ##### # # getouput # 2006jul28 # ##### # «getoutput» (to ".getoutput") # (find-angg "LUA/lua50init.lua" "getoutput") # The name is taken from python... -- -- (eeb-lua0) -- (find-es "lua5" "io.popen") -- (find-man "3tcl exec") -- (find-man "perlfunc" "system PROGRAM LIST") -- (find-man "perlop" "qx/STRING/") -- (find-node "(libc)Function Index" "* system:") -- (find-node "(bashref)Command Substitution") -- (find-rubymanualw3m "IO.html" "popen(command [, mode])") -- (find-pylibnode "commands" "`getoutput(cmd)'") getoutput = function (command) local pipe = assert(io.popen(command)) local output = pipe:read("*a") pipe:close() return output end print(getoutput "echo > /tmp/foo; stat -c %Y /tmp/foo") -- ##### # # question about captured variables # 2006aug10 # ##### # «captured-variables» (to ".captured-variables") # (find-eevex "lua.e" "quick-presentation") # (find-eevex "lua.e" "quick-presentation" "Capture of local variables") # http://angg.twu.net/eev-current/examples/lua.e.html#quick-presentation # The question: # http://rafb.net/paste/ # (eekill "where do local variables captured by closures live") # Capture of local variables # (find-luamanualw3m+ "func-def" "closure") lua50 -e ' foo = function () local storage return function () return storage end, function (x) storage = x; return x end end get1, set1 = foo() get2, set2 = foo() print(set1(22), get1()) --> 22 22 print(set2(33), get1(), get2()) --> 33 22 33 ' http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf pointed to in http://www.lua.org/docs.html the bottom line is that while external local vars are in the normal stack everything is fine. as soon as their scope is gone, they are moved to a special place in the closure. # http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf # (find-lua50file "src/lfunc.c" "void luaF_close (lua_State *L, StkId level)") # (code-xpdf "luaimp" "$S/http/www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf") # (find-luaimppage 9) # The eps: # http://www.tecgraf.puc-rio.br/~lhf/tmp/upval.eps # http://www.tecgraf.puc-rio.br/~lhf/tmp/upval.fig # # Printing the implementation paper: cp $S/http/www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf /tmp/luaimp.pdf cd /tmp/ pdftops luaimp.pdf luaimp.ps psnup -2 < luaimp.ps > luaimp.2.ps gv luaimp.2.ps # ##### # # xpcall and tracebacks # 2005dec21 # ##### # «xpcall-traceback» (to ".xpcall-traceback") -- -- (eelua-bounded) io.stderr = io.stdout for i=1,200 do print("blablablaaaaaaaaaaaa stdout: "..i) end error("Bla!") -- -- (eelua-bounded) myeval = function (str, chunkname) local chunk = assert(loadstring(str, "chunkname")) print("2:xpcall:", xpcall(chunk, function (...) print("1:traceback:", debug.traceback ("1:message:")) end )) end myeval [[ io.stderr = io.stdout for i=1,20 do print("blablablaaaaaaaaaaaa stdout: "..i) end error("Bla!") ]] -- -- (find-lua50file "") -- (find-lua50file "src/lib/ldblib.c") -- (find-lua50file "src/lib/ldblib.c" "{\"traceback\", errorfb}") -- (find-lua50file "src/lib/ldblib.c" "static int errorfb (lua_State *L)") -- (find-lua50file "src/lib/ldblib.c" "LUALIB_API int luaopen_debug (lua_State *L)") -- (find-lua50grep "grep -niH -e traceback $(cat .files.ch)") -- (find-lua50grep "grep -niH -e lcall $(cat .files.ch)") ##### # # xpcall # 2006sep16 # ##### # «xpcall» (to ".xpcall") # (to "ldb") # (find-luamanualw3m "#pdf-xpcall") # (find-luamanualw3m "#pdf-debug.traceback")  (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) -- (find-lua51file "src/ldebug.c") -- (find-lua51file "src/ldblib.c") -- (find-lua51file "src/ldblib.c" "{\"traceback\", db_errorfb},") -- (find-lua51tag "db_errorfb") -- -- (eeb-lua) print "foo" a = function () bang() end b = function () return 1+a() end c = function () return 1+b() end mytraceback = function (errmsg) io.output():flush() print(debug.traceback(errmsg)) end -- c() xpcall(c, mytraceback) -- # Output with "c()", i.e., without flush/xpcall: # (Note that the traceback appears before "foo") lua50: /home/edrx/.eev/ee.lua:5: attempt to call global `bang' (a nil value) stack traceback: /home/edrx/.eev/ee.lua:5: in function `a' /home/edrx/.eev/ee.lua:6: in function `b' /home/edrx/.eev/ee.lua:7: in function `c' /home/edrx/.eev/ee.lua:15: in main chunk [C]: ? foo # Output with "mytraceback", i.e., with flush and xpcall: # (Note that the "foo" appears before the traceback, as expected) foo /home/edrx/.eev/ee.lua:5: attempt to call global `bang' (a nil value) stack traceback: /home/edrx/.eev/ee.lua:13: in function `bang' /home/edrx/.eev/ee.lua:5: in function `a' /home/edrx/.eev/ee.lua:6: in function `b' /home/edrx/.eev/ee.lua:7: in function `c' [C]: in function `xpcall' /home/edrx/.eev/ee.lua:17: in main chunk [C]: ? ##### # # my own traceback (for porting blogme to lua 5.1) # 2006oct26 # ##### # (find-pilw3m "23.1.html" "function traceback ()") a = function () bang() end b = function () return 1+a() end c = function () return 1+b() end ##### # # pseudocode for some metatable behaviours # 2006oct09 # ##### # «metamethods-pseudocode» (to ".metamethods-pseudocode") -- (find-luamanualw3m "" "\"index\":") -- (find-pilw3m "13.4.1.html" "The __index Metamethod") -- t[key] -- t.mt.__index(t, key) -- t.mt.__index[key] -- (find-luamanualw3m "" "\"newindex\":") -- (find-pilw3m "13.4.2.html" "The __newindex Metamethod") -- t[key] = value -- t.mt.__newindex(t, key, value) -- t.mt.__newindex[key] = value -- (find-luamanualw3m "" "\"call\":") -- f(...) -- t.mt.__call(t, ...) # «generators-pseudocode» (to ".generators-pseudocode") -- (find-pilw3m "index.html") -- (find-pilw3m "7.1.html" "Iterators and Closures") -- (find-luamanualw3m "" "local _f, _s, var_1 = explist") -- for a,b,c in generator() do block(a, b, c) end -- f, s, a0 = generator() -- a1, b1, c1 = f(s, a0); block(a1, b1, c1) -- a2, b2, c2 = f(s, a1); block(a2, b2, c2) -- a3, b3, c3 = f(s, a2); block(a3, b3, c3) -- a4, b4, c4 = f(s, a3); -- a4 == nil: break To do: generic for pseudocode coroutines pseudocode ##### # # 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") # rm -Rv /tmp/pil24_1/ mkdir /tmp/pil24_1/ cd /tmp/pil24_1/ cat > pil24_1.c <<'---' #include #include #include #include #include // 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 # 2007jan01 # ##### # «lpeg» (to ".lpeg") # (find-angg "LUA/lua50init.lua" "loadlpeg") # http://www.inf.puc-rio.br/~roberto/lpeg.html # http://www.inf.puc-rio.br/~roberto/lpeg-0.5.tar.gz # http://pdos.csail.mit.edu/~baford/packrat/popl04/peg-popl04.pdf # http://pdos.csail.mit.edu/~baford/packrat/ # http://en.wikipedia.org/wiki/Parsing_expression_grammar # http://lua-users.org/lists/lua-l/2006-12/msg00532.html # (code-c-d "lpeg" "~/usrc/lpeg-0.5/") # (find-lpegw3m "doc.html") # (find-lpegfile "og") # (find-lpegfile "re.lua") # (find-lpegfile "test.lua") # (find-lpegfile "") # rm -Rfv ~/usrc/lpeg-0.5/ tar -C ~/usrc/ -xvzf $S/http/www.inf.puc-rio.br/~roberto/lpeg-0.5.tar.gz cd ~/usrc/lpeg-0.5/ chmod 644 lpeg.c # http://lua-users.org/lists/lua-l/2007-03/msg00616.html # http://lua-users.org/lists/lua-l/2007-03/msg00620.html patch -p0 lpeg.c <<'%%%' 470c470,471 < capture[captop - 1].siz = s - capture[captop - 1].s + 1; --- > /* capture[captop - 1].siz = s - capture[captop - 1].s + 1; */ > capture[captop - 1].siz = (s - getoff(p)) - capture[captop - 1].s + 1; %%% # export LUA51SRC=~/usrc/lua-5.1.2 # echo $LUA51SRC gcc -g -Wall -shared -I$LUA51SRC/src \ -o lpeg.so lpeg.c |& tee og lua51 test.lua # # (code-c-d "lpeg" "~/usrc/lpeg-0.6/") # (find-lpegw3m "doc.html") # http://www.inf.puc-rio.br/~roberto/lpeg.html # (find-lpegw3m "doc.html") # rm -Rfv ~/usrc/lpeg-0.6/ tar -C ~/usrc/ -xvzf $S/http/www.inf.puc-rio.br/~roberto/lpeg-0.6.tar.gz cd ~/usrc/lpeg-0.6/ gcc -g -Wall -shared -I$LUA51SRC/src \ -o lpeg.so lpeg.c |& tee og lua51 test.lua # (code-ps "pegford" "$S/http/pdos.csail.mit.edu/~baford/packrat/popl04/peg-popl04.pdf") (find-pegfordpage 3) (find-pegfordpage 5) # http://www.inf.puc-rio.br/~roberto/lpeg.html # (find-sh0 "cd /tmp/; cat mozilla.ps | pstops '1:@.9(1cm,1cm)' | psnup -2 > mozilla.2.ps") # (find-pspage "/tmp/mozilla.2.ps") # (find-lpegfile "test.lua")  (eepitch-shell) cd ~/usrc/lpeg-0.4/ lua51 require "lpeg" PP(lpeg)  (eepitch-at-dir-comint ee-lpegdir "lpeg-lua" "lua51") require "lpeg" PP(lpeg)  (eepitch-lua51) loadlpeg() PP(lpeg) -- (find-lpegw3m "doc.html" "function split (s, sep)") -- (find-lpegfile "lpeg.c" "** Printing patterns") sep1 = lpeg.P(" ") sep = sep1^1 elem = lpeg.C((1 - sep)^0) elems = elem * (sep * elem)^0 = sep sep1:print() sep:print() elem:print() elems:print() PP(elems:match(" foo bar ")) ##### # # lpeg quickref # 2007mar05 # ##### # «lpeg-quickref» (to ".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 is 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 - "[A-Za-z]" lpeg.S("abc") matches any char in set - "[abc]" #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 - "patt*" patt ^ 1 at least 1 occurrence of patt - "patt+" patt ^ 2 at least 2 occurrences of patt patt ^ -1 at most 1 occurrence of patt - "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 example: arithmetic expressions, take 1 # 2007mar05 # ##### # «lpeg-ex-arith-1» (to ".lpeg-ex-arith-1") # (find-lpegfile "") # (find-lpegw3m "doc.html") # (find-lpegw3m "doc.html#ex") # http://www.inf.puc-rio.br/~roberto/lpeg.html#ex  (eepitch-lua51) loadlpeg() -- Lexical Elements -- local Space Number, FactorOp, TermOp, Open, Close Space = lpeg.S(" \n\t")^0 Number = lpeg.C(lpeg.P"-"^-1 * lpeg.R("09")^1) * Space FactorOp = lpeg.C(lpeg.S("+-")) * Space TermOp = lpeg.C(lpeg.S("*/")) * Space Open = "(" * Space Close = ")" * Space -- Grammar -- local V -- local Exp, Term, Factor V = lpeg.V Exp, Term, Factor = 1, 2, 3 G = lpeg.P{ [Exp] = lpeg.Ct(V(Factor) * (FactorOp * V(Factor))^0); [Factor] = lpeg.Ct(V(Term) * (TermOp * V(Term))^0); [Term] = Number + Open * V(Exp) * Close; } G = Space * G * -1 -- Evaluator function eval (x) if type(x) == "string" then return tonumber(x) else local op1 = eval(x[1]) for i = 2, #x, 2 do local op = x[i] local op2 = eval(x[i + 1]) if (op == "+") then op1 = op1 + op2 elseif (op == "-") then op1 = op1 - op2 elseif (op == "*") then op1 = op1 * op2 elseif (op == "/") then op1 = op1 / op2 end end return op1 end end -- Parser/Evaluator function evalExp (s) local t = lpeg.match(G, s) if not t then error("syntax error", 2) end return eval(t) end -- small example print(evalExp"3 + 5*9 / (1+1) - 12") G:print() ##### # # lpeg example: arithmetic expressions, take 2 # 2007mar05 # ##### # «lpeg-ex-arith-2» (to ".lpeg-ex-arith-2") # (find-lpegfile "") # (find-lpegw3m "doc.html") # (find-lpegw3m "doc.html#ex") # http://www.inf.puc-rio.br/~roberto/lpeg.html#ex  (eepitch-lua51) loadlpeg() -- Lexical Elements -- local Space Number, FactorOp, TermOp, Open, Close Space = lpeg.S(" \n\t")^0 Number = lpeg.C(lpeg.P"-"^-1 * lpeg.R("09")^1) * Space FactorOp = lpeg.C(lpeg.S("+-")) * Space TermOp = lpeg.C(lpeg.S("*/")) * Space Open = "(" * Space Close = ")" * Space -- Auxiliary function function eval (v1, op, v2) if (op == "+") then return v1 + v2 elseif (op == "-") then return v1 - v2 elseif (op == "*") then return v1 * v2 elseif (op == "/") then return v1 / v2 end end -- Grammar -- local V -- local Exp, Term, Factor V = lpeg.V Exp, Term, Factor = 1, 2, 3 G = lpeg.P { [Exp] = lpeg.Ca(V(Factor) * (FactorOp * V(Factor) / eval)^0); [Factor] = lpeg.Ca(V(Term) * (TermOp * V(Term) / eval)^0); [Term] = Number / tonumber + Open * V(Exp) * Close; } -- small example print(lpeg.match(G, "3 + 5*9 / (1+1) - 12")) G:print() ##### # # lpeg patterns as several layers # 2007mar02 # ##### # (find-fline "~/LOGS/2007mar01.lua" "pattern-with-captures") # (find-fline "~/LOGS/2007mar01.lua") # (find-iconbookpage (+ 22 87)) # (find-iconbookpage (+ 22 305)) as I understand it there's the PEG layer, where we have just patterns that can succeed or fail, but we don't have a way to specify and return captures on top of that the full thing with the captures is built - and I imagine that there should be a way to "project" a pattern-with-captures into the world of patterns-that-just-succeed-or-fail supposing that this guess is right I think that there are also some basic functions to lift a pattern-that-can-just-succeed-or-fail to a pattern-with-captures like: in case of success return the match as a string (a substring of the subject), or return the starting point of the match, or the end of the match and there are also ways to build bigger pattern-with-captures from smaller patterns-that-just-succeed-or-fail and patterns-with-captures hmmm, actually it seems that there's a natural embedding of the world of patterns-that-just-succeed-or-fail into the world of patterns-with-captures a pattern-that-just-succeed-or-fail returns the position of the end of the match when it succeeds and nil when it fails hmmm again it seems that there is also the world of patterns-that-might-be-resumed versus patterns-that-on-success-have-no-backtracking-information ##### # # Roberto Ierusalimschy's solution to the SHeadSymbol problem # 2007mar15 # ##### # «sheadsymbol-roberto» (to ".sheadsymbol-roberto") # http://lua-users.org/lists/lua-l/2007-03/msg00355.html # http://lua-users.org/lists/lua-l/2007-03/msg00358.html # (find-blogmefile "text2html.lua")  (eepitch-lua51) loadlpeg() --------[ Anchor ]-------- -- (find-anggfile "TH/Generate") -- (find-anggfile "TH/Generate" "txt2html") AnchorChar = lpeg.R ... Anchor = "«" * AnchorChar^1 * "»" --------[ Url ]-------- UrlProtocol = lpeg.P("http") + lpeg.P("ftp") + lpeg.P("shttp") UrlDomainChar = lpeg.R("az", "09") + lpeg.S("-") UrlDomain = UrlDomainChar^1 * ("." * UrlDomainChar^1)^1 UrlPathChar = ... --------[ SSexpLink ]-------- SStringChar = 1 - lpeg.S "\"\n" SStringBsl = "\\" * (1 - lpeg.S "\n") SString = "\"" * SStringChar^0 * "\"" SNumber = lpeg.P"-"^-1 * lpeg.R"09"^1 SNonSymbolChar = lpeg.S "\"#'(),.[\\]`" SSymbolChar = lpeg.R "!~" - SNonSymbolChar - lpeg.S "{}" SSymbol = SSymbolChar^1 headsymbols = { ["info"]=true, ["man"]=true } SHeadSymbol = lpeg.P(function (subj, pos) local e = lpeg.match(SSymbol, subj, pos) if not e then return nil end local symbol = string.sub(subj, pos, e - 1) return headsymbols[symbol] and pos end) SAtom = SString + SNumber + SSymbol SSpace = lpeg.S " \t" SSpaces = SSpace^1 Eos = lpeg.P(-1) Eol = -(lpeg.S "\n" + Eos) SSexpLink = "(" * lpeg.C(SHeadSymbol) * (Spaces * lpeg.C(SAtom))^0 * ")" * Eol ##### # # loadstring and eof # 2007jan17 # ##### # «loadstring_and_eof» (to ".loadstring_and_eof") # (find-es "tcl" "info_complete") hi all - sorry if this is an obvious questions (pointers welcome) but: suppose that I have my own function for reading a line, "getline", say - how do I implement something like lua's interactive mode - in lua - using it and the debug library? I need to concatenate the lines that I've read and see if the result either (1) is a complete command, (2) is an incomplete command, (3) is "wrong" - how do I distinguish betwe en these three cases? btw, the HOPL paper is done. managed to mention you wrt metamethods. lhf: thanks edrx: do it the way lua.c does try to compile the line, and see what error you get, if any try loadstring. if it does not fail, run the chunk. if it fails, check the message for eof. right # (find-fline "~/LOGS/2007jan17.lua" "check the message for eof") # (find-lua51file "src/") # (find-lua51file "src/lparser.c") # (find-lua51file "src/lparser.c" "unexpected symbol") # (find-lua51file "src/lua.c" "")  (eepitch-lua51)  (eepitch-lua50)  (eechannel-xterm "A") -- «incompletep» (to ".incompletep") -- incompletepat = ": unexpected symbol near ''$" incompletep = function (errmsg) if errmsg and string.find(errmsg, incompletepat) then return true end end myloadstring = function (T) T.code, T.err = loadstring(table.concat(T, "\n")) T.incomplete = incompletep(T.err) return T end myreadmore = function (T) io.write(prompt or (table.getn(T) == 0 and "-> " or "->> ")) local line = io.read() if line then table.insert(T, line); return true end end myreadlines = function (T) if myreadmore(T) then while myloadstring(T).incomplete and myreadmore(T) do end end return T end T = {}; PP(myreadlines(T)) print( 22+33) PP(T) ##### # # ldb - rici lake's replacement for debug.debug # 2007apr05 # ##### # «ldb» (to ".ldb") # (to "xpcall") # (find-angg "LUA/lua50init.lua" "loadldb") # (find-fline "~/LOGS/2007apr04.lua") # (find-fline "~/LOGS/2007apr04.lua" " debug.traceback = ldb") # Rici keeps an old version of ldb at this url: # http://primero.ricilake.net/lua/ldb.lua # The new version has to be fetched by CVStrac from: # http://primero.ricilake.net:8008/ldb/getfile?f=ldb/ldb.lua # Download from cvstrac (2007apr12):  (eepitch-shell) cd ~/LUA/ { URL='http://primero.ricilake.net:8008/ldb/getfile?f=ldb/ldb.lua' echo "-- From: $URL" echo "-- See: (find-es \"lua5\" \"ldb\")" echo "--" wget -O - $URL } > ldb.lua # (find-fline "~/LUA/" "ldb.lua") # (find-fline "~/LUA/ldb.lua")  (eepitch-shell) cd $S/http/primero.ricilake.net/lua/ lua51 ldb = require "ldb" debug.traceback = ldb 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 help backtrace  (eepitch-shell) cd $S/http/primero.ricilake.net/lua/ lua51 loadldb() debug.traceback = ldb 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 help backtrace ##### # # lua-mode.el # 2007feb05 # ##### # «lua-mode.el» (to ".lua-mode.el") # (find-angg ".emacs" "lua-mode") # (find-angg "elisp/lua-mode.el") # http://luaforge.net/projects/lua-mode/ # http://luaforge.net/frs/download.php/2074/lua-mode-20061208.tar.gz # tar -C ~/elisp/ -xvzf \ $S/http/luaforge.net/frs/download.php/2074/lua-mode-20061208.tar.gz # # Local Variables: # coding: raw-text-unix # ee-delimiter-hash: "\n#\n" # ee-delimiter-percent: "\n%\n" # ee-anchor-format: "«%s»" # modes: (fundamental-mode lua-mode c-mode) # End: