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