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: