|
Warning: this is an htmlized version!
The original is across this link, 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.
#
# 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/>.
#
#######
# «.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>"
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 "))
'
#*
#####
#
# 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})) --> <function> {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) --> <function> {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) --> <function> {"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 <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
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 = "<foo 45>" */
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 <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
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
'
<lhf> http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf pointed to
in http://www.lua.org/docs.html
<lhf> 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 <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
# 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))
<edrx> 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
<edrx> 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
<edrx> supposing that this guess is right
<edrx> I think that there are also some basic functions to lift a
pattern-that-can-just-succeed-or-fail
<edrx> to a pattern-with-captures
<edrx> 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
<edrx> and there are also ways to build bigger pattern-with-captures
from smaller patterns-that-just-succeed-or-fail and
patterns-with-captures
<edrx> 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
<edrx> a pattern-that-just-succeed-or-fail returns the position of the
end of the match when it succeeds and nil when it fails
<edrx> hmmm again
<edrx> 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")
<edrx> 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
<edrx> en these three cases?
<lhf> btw, the HOPL paper is done. managed to mention you wrt
metamethods.
<rici> lhf: thanks
<rici> edrx: do it the way lua.c does
<rici> try to compile the line, and see what error you get, if any
<lhf> try loadstring. if it does not fail, run the chunk. if it fails,
check the message for eof.
<rici> 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" "<eof>")
* (eepitch-lua51)
* (eepitch-lua50)
* (eechannel-xterm "A")
-- «incompletep» (to ".incompletep")
--
incompletepat = ": unexpected symbol near '<eof>'$"
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" "<rici> 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: