-- This file: -- http://anggtwu.net/LUA/PrintFunction1.lua.html -- http://anggtwu.net/LUA/PrintFunction1.lua -- (find-angg "LUA/PrintFunction1.lua") -- Author: Eduardo Ochs -- -- Also here: -- (find-angg "LUA/lua50init.lua" "PrintFunction") -- -- This file defines the class `PrintFunction', that is used by `help' -- and by `PreTraceback'. For example: -- -- > = help(split) -- (find-luatb "~/LUA/lua50init.lua 351 357") -- -- -- Old comments -- ============ -- ...and stack frames either in a very compact format that looks like -- this (that I took from a pretraceback), -- -- [ C ] C function (unknown name) -- [Lua] stdin line 1 -- (find-luatb "~/LUA/lua50init.lua 2325 2329 global run_repl3_now") -- (find-luatb "~/LUA/Repl3.lua 146 148 method repl") -- -- or, with the method :v(), in a low-level "vertical" format that -- looks like this: -- -- { "currentline"=2329, -- "func"=, -- "lastlinedefined"=2330, -- "linedefined"=2325, -- "name"="run_repl3_now", -- "namewhat"="global", -- "nups"=0, -- "short_src"="/home/edrx/LUA/lua50init.lua", -- "source"="@/home/edrx/LUA/lua50init.lua", -- "what"="Lua" -- } -- -- debug.getinfo only fills the fields "name" and "namewhat" for stack -- frames, so -- -- PrintFunction.from(run_repl3_now) -- -- returns just: -- -- (find-luatb "~/LUA/lua50init.lua 2325 2330") -- -- instead of: -- -- (find-luatb "~/LUA/lua50init.lua 2325 2329 global run_repl3_now") -- -- PrintFunction was inspired by the traceback in Prosody, -- -- http://angg.twu.net/LUA/Prosody1.lua.html -- (find-angg "LUA/Prosody1.lua") -- -- but I changed the output format completely. -- -- Based on/supersedes: -- (find-angg "LUA/DGetInfo1.lua" "DGetInfo") -- See: -- (find-angg "LUA/PreTraceback1.lua") -- (find-TH "Repl3" "PrintFunction1.lua") -- (find-lua51manual "#pdf-debug.getinfo") -- (find-lua51manual "#pdf-debug.getlocal") -- -- (defun e () (interactive) (find-angg "LUA/PrintFunction1.lua")) -- «.ObjToFunction» (to "ObjToFunction") -- «.ObjToFunction-tests» (to "ObjToFunction-tests") -- «.PrintFunction» (to "PrintFunction") -- «.PrintFunction-any» (to "PrintFunction-any") -- «.PrintFunction-keys» (to "PrintFunction-keys") -- «.PrintFunction-tests» (to "PrintFunction-tests") require "SortedKeys2" -- (find-angg "LUA/SortedKeys2.lua") -- ___ _ _ _____ _____ _ _ -- / _ \| |__ (_)_ _|__ | ___| _ _ __ ___| |_(_) ___ _ __ -- | | | | '_ \| | | |/ _ \| |_ | | | | '_ \ / __| __| |/ _ \| '_ \ -- | |_| | |_) | | | | (_) | _|| |_| | | | | (__| |_| | (_) | | | | -- \___/|_.__// | |_|\___/|_| \__,_|_| |_|\___|\__|_|\___/|_| |_| -- |__/ -- `ObjToFunction.from(o)' is used by PrintFunction to make it -- support (my) classes: -- it returns functions unchanged, -- it returns the __tostring method of a class when it exists, -- it returns the __tostring method of the class of an object -- when that makes sense and the __tostring method exists, -- and it has some _unreliable hacks_ for classes without a -- a __tostring method, and for objects of those classes. -- -- In the code below: -- "C" means "`C'lass", -- "TM" means "`T'able with `M'etatable", -- "CWT" means "`C'lass `W'ith a __`T'ostring", and -- "CWOT" means "`C'lass `W'ith`O'ut a __`T'ostring". -- -- «ObjToFunction» (to ".ObjToFunction") -- Also here: (find-angg "LUA/lua50init.lua" "ObjToFunction") -- ObjToFunction = Class { type = "ObjToFunction", from = function (o) return ObjToFunction{}:from(o) end, __index = { tt = function (a,o) return type(o) == "table" end, ts = function (a,o) return type(o) == "string" end, tf = function (a,o) return (type(o) == "function") and o end, tm = function (a,o) return a:tt(o) and getmetatable(o) end, isc = function (a,c) return a:tt(c) and a:tt(c.__index) and a:ts(c.type) end, iscwt = function (a,c) return a:isc(c) and a:tf(c.__tostring) end, -- -- `fft': First function in the table T -- `ffc': first function in the class C ffc = function (a,C) return a:fft(C) or a:fft(C.__index) end, fft = function (a,T) for _,k in ipairs(sortedkeys(T)) do if a:tf(T[k]) then return T[k] end end end, from = function (a,o) return a:tf(o) -- o is a function, or a:iscwt(o) -- o is a CWT, or (a:tm(o) and a:iscwt(a:tm(o))) -- o is an object of a CWT, or (a:isc(o) and a:ffc(o)) -- o is a CWOT, or (a:isc(a:tm(o)) and a:ffc(a:tm(o))) -- o is an object of a CWOT or (a:tt(o) and a:fft(o)) -- no `__tostring', no `__index' or error("Objfunction{}:from(o) failed") end, }, } -- «ObjToFunction-tests» (to ".ObjToFunction-tests") --[[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) dofile "PrintFunction1.lua" foo = function (o) return PrintFunction.fromf(ObjToFunction{}:from(o)) end = foo(foo) = foo(Set) = foo(Set {}) = foo(Tos) = foo(Tos {}) = foo(Class) --]] -- ____ _ _ _____ _ _ -- | _ \ _ __(_)_ __ | |_| ___| _ _ __ ___| |_(_) ___ _ __ -- | |_) | '__| | '_ \| __| |_ | | | | '_ \ / __| __| |/ _ \| '_ \ -- | __/| | | | | | | |_| _|| |_| | | | | (__| |_| | (_) | | | | -- |_| |_| |_|_| |_|\__|_| \__,_|_| |_|\___|\__|_|\___/|_| |_| -- -- `PrintFunction.fromf' expects a function. -- `PrintFunction.fromfunction' is a hack to support (my) classes: -- it returns functions unchanged, -- it returns the __tostring method of a class when it exists, -- it returns the __tostring method of the class of an object -- when that makes sense and the __tostring method exists, -- and it has some _unreliable hacks_ for classes without a -- a __tostring method, and for objects of those classes. -- -- In the code below: -- "C" means "`C'lass", -- "TM" means "`T'able with `M'etatable", -- "CWT" means "`C'lass `W'ith a __`T'ostring", and -- "CWOT" means "`C'lass `W'ith`O'ut a __`T'ostring". -- -- «PrintFunction» (to ".PrintFunction") -- Also here: (find-angg "LUA/lua50init.lua" "PrintFunction") -- PrintFunction = Class { type = "PrintFunction", tostring = function (o) return PrintFunction.from(o):tostring() end, fromf = function (f) return PrintFunction(debug.getinfo(f, "nSluf")) end, from = function (o) return PrintFunction.fromf(ObjToFunction.from(o)) end, -- __tostring = function (pf) return pf:tostring() end, __index = { tostring = function (pf) return pf:_any() end, tostring2 = function (pf) return pf:sks() end, tostring3 = function (pf) return tostring(VTable(copy(pf))) end, -- -- «PrintFunction-any» (to ".PrintFunction-any") -- `pf:_any()' returns a line like `(find-luatb "..." 42)' or `[C]' _shortsrc0 = function (pf) return ee_shorten(pf.short_src) end, _shortsrc0 = function (pf) return ee_shorten(pf.source:sub(2)) end, _shortsrc = function (pf) return pf.short_src and pf:_shortsrc0() end, _name0 = function (pf) return pf.name and format("%q", pf.name) end, _name = function (pf) return pf:_name0() or "(unknown name)" end, _linedef = function (pf) return pf.linedefined end, _linelast = function (pf) return pf.lastlinedefined end, _linecurr0 = function (pf) return pf.currentline end, _linecurr = function (pf) return pf:_linecurr0()~=-1 and pf:_linecurr0() end, _line1 = function (pf) return pf:_linedef() end, _line2 = function (pf) return pf:_linecurr() or pf:_linelast() end, _tailcall0 = function (pf) return "[Lua] tail call" end, _main0 = function (pf) return "[Lua] "..pf:_shortsrc() .." line "..pf:_linecurr() end, _C0 = function (pf) return "[ C ] "..pf.namewhat .." C function "..pf:_name() end, _tbbody0 = function (pf) return (pf:_shortsrc() or "") .." "..(pf:_line1() or "") .." "..(pf:_line2() or "") .." "..(pf.namewhat or "") .." "..(pf.name or "") end, _tbbody = function (pf) return rtrim(pf:_tbbody0()) end, _findluatb = function (pf) return format('(find-luatb \"%s\")', pf:_tbbody()) end, _any = function (pf) if pf.short_src == "[C]" then return pf:_C0() end if pf.what == "main" then return pf:_main0() end if pf.short_src == "(tail call)" then return pf:_tailcall0() end return pf:_findluatb() end, -- -- «PrintFunction-keys» (to ".PrintFunction-keys") -- Returns a multi-line string with all the key-value pairs of -- `pf', grouped and sorted in a nice way. Needs SortedKeys2. keys = [[ what namewhat source short_src linedefined lastlinedefined currentline nups ]], sk1 = function (pf,k) return format("%-15s -> %s", k, mytostring(pf[k])) end, skL = function (pf,ks) local f = function (k) return pf:sk1(k) end return mapconcat(f,ks,"\n") end, sks = function (pf) return pf:skL(SortedKeys.from(pf, pf.keys).list) end, }, } help = function (o) return PrintFunction.tostring(o) end -- «PrintFunction-tests» (to ".PrintFunction-tests") --[[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) dofile "PrintFunction1.lua" = help(split) = help(print) = help(mytostring) = help(Set) = help(Set {}) Foo = Class { type = "Foo", __mul = function (a,b) return a[1]*b[1] end, __index = { }, } = help(Foo) = help(Foo {2}) = help(Tos) = help(Tos {}) = help(Class) o = print o = split = PrintFunction.from(o):tostring() = PrintFunction.from(o):tostring2() = PrintFunction.from(o):tostring3() --]] -- (find-angg "LUA/DGetInfo1.lua" "DGetInfos") -- Local Variables: -- coding: utf-8-unix -- End: