|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://angg.twu.net/LUA/middle-c.lua.html
-- http://angg.twu.net/LUA/middle-c.lua
-- (find-angg "LUA/middle-c.lua")
-- This is an attempt to implement the ideas in:
-- http://angg.twu.net/peek.html
-- file:///home/edrx/TH/L/peek.html
-- (find-TH "peek")
-- Status: this is just a proof of concept.
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2011jan06
-- License: GPL3
-- See also:
-- (find-angg "DAVINCI/peek.c")
-- (find-angg "DAVINCI/peek.lua")
-- (find-angg "DAVINCI/peek-luadecls-1.txt")
-- (find-angg "DAVINCI/peek-luadecls-2.txt")
-- (find-TH "davinci" "peek.lua")
-- http://angg.twu.net/davinci.html#peek.lua
-- file:///home/edrx/TH/L/davinci.html#peek.lua
-- Motivation:
-- The Lua interpreter has some internal data structures that I
-- do not understand well enough - namely: prototypes, stack
-- frames, coroutines, and threads. Using this and peek.c we
-- should be able to inspect these data structures from inside a
-- running Lua; also, it shouldn't be hard to implement another
-- way to access stack frames - by pointing directly to the frame
-- instead of referring to it using a thread and a level.
-- (find-lua51src "lobject.h" "Proto")
-- (find-lua51src "lobject.h" "UpVal")
-- (find-lua51src "lvm.c" "luaV_execute" "OP_TAILCALL")
-- (find-lua51src "ldo.c")
-- (find-lua51src "ldo.h")
-- (find-luamanualw3m "#pdf-debug.getinfo")
-- (find-luamanualw3m "#pdf-debug.getlocal")
-- (find-luamanualw3m "#pdf-debug.traceback")
-- (find-lua51src "ldblib.c" "dblib")
-- (find-lua51src "ldblib.c" "db_getinfo")
-- (find-lua51src "ldblib.c" "db_getlocal")
-- (find-lua51src "ldblib.c" "db_errorfb")
-- Quick index:
-- «.Class» (to "Class")
-- «.classes» (to "classes")
-- «.C___Type» (to "C___Type")
-- «.C___TypeFrom» (to "C___TypeFrom")
-- «.test-2-output» (to "test-2-output")
-- (find-es "lua5" "setvbuf")
io.stdout:setvbuf("no") -- sync errors
-- (defun c () (interactive) (find-sh "lua51 ~/LUA/middle-c.lua"))
-- (find-angg "LUA/lua50init.lua" "userocks")
userocks()
require "lpeg"
--- «Class» (to ".Class")
--- A very simple object system.
-- See: (find-angg "LUA/canvas2.lua" "Class")
-- (find-dn5 "eoo.lua")
smt = setmetatable
gmt = getmetatable
Class = {
type = "Class",
__call = function (class, o) return setmetatable(o, class) end,
}
setmetatable(Class, Class)
otype = function (o)
local mt = getmetatable(o)
return mt and mt.type or type(o)
end
--- «classes» (to ".classes")
--- «C___Type» (to ".C___Type")
--- The classes for Middle-C types.
-- Structs, unions, enums, functions and typedefs will come later.
CPrimType = Class { -- Middle-C primitive type
type = "CPrimType",
__index = {
},
}
CArrayType = Class { -- Middle-C array type
type = "CArrayType",
__index = {
},
}
CStarType = Class { -- Middle-C star type
type = "CStarType",
__index = {
},
}
--- «C___TypeFrom» (to ".C___TypeFrom")
--- Low-level functions to create types.
-- Note that "basetype" is always a string.
types = {}
CPrimTypeFrom = function (name, size, align)
types[name] = CPrimType { name = name, size = size, align = align }
return types[name]
end
CArrayTypeFrom = function (name, basetype, n)
-- PP("CArrayTypeFrom", name, basetype, n)
if not types[basetype].size then
error("Can't create "..name.." - the base type has no sizeof")
end
types[name] = CArrayType {
name = name,
basetype = basetype,
size = n and (types[basetype].size * n),
align = types[basetype].align,
}
return types[name]
end
CStarTypeFrom = function (name, basetype)
types[name] = CStarType {
name = name,
basetype = basetype,
size = 4,
align = 4,
}
return types[name]
end
--- Create a few primitive types.
CPrimTypeFrom("char", 1, 1)
CPrimTypeFrom("short", 2, 2)
CPrimTypeFrom("ushort", 2, 2)
CPrimTypeFrom("int", 4, 4)
CPrimTypeFrom("uint", 4, 4)
CPrimTypeFrom("void", nil, nil)
--- High-level functions to create types.
-- They are all based on a tricky LPeg pattern - MType - that
-- processes parts of a middle-C type...
-- (find-es "lua5" "lpeg-quickref")
MType = function (fsetsubj, fbase, farr, fstar)
local Alpha_, Alpha_num, Base, Arr, Star
Alpha_ = lpeg.R("AZ", "az", "__")
Alpha_num = lpeg.R("AZ", "az", "__", "09")
Base = (Alpha_ * Alpha_num^0) / fbase
Arr = (lpeg.P"[" * (lpeg.R("09")^0):C() * lpeg.P"]" * lpeg.Cp()) / farr
Star = (lpeg.P"*" * lpeg.Cp()) / fstar
-- Note that the patterns above are local, but MType is not...
-- The effect of this function is to define MType globally,
-- using the current values of the functions fsetsubj,
-- fbase, farr, fstar.
return lpeg.P(fsetsubj) * Base * (Arr + Star)^0
end
-- Test 0.
print "-------"
print "Test 0:"
fsetsubj = function (...) PP("setsubj", ...); return 1 end
fbase = function (...) PP("fbase", ...) end
farr = function (...) PP("farr", ...) end
fstar = function (...) PP("fstar", ...) end
PP(MType(fsetsubj, fbase, farr, fstar):match("char[23][4][]*[5]"))
-- Test 1.
print "-------"
print "Test 1:"
fsetsubj = function (s, pos) subj = s; return 1 end
fbase = function (name) PP(name, "fbase") end
farr = function (s, pos) PP(subj:sub(1, pos-1), "farr", s) end
fstar = function (pos) PP(subj:sub(1, pos-1), "fstar") end
PP(MType(fsetsubj, fbase, farr, fstar):match("char[23][4][]*[5]"))
-- Output:
-- "char" "fbase"
-- "char[23]" "farr" "23"
-- "char[23][4]" "farr" "4"
-- "char[23][4][]" "farr" ""
-- "char[23][4][]*" "fstar"
-- "char[23][4][]*[5]" "farr" "5"
-- 18
-- Test 2.
print "-------"
print "Test 2:"
temptype = nil
fsetsubj = function (s, pos) tempsubj = s; return 1 end
fbase = function (name) temptype = types[name] or error("nbt: "..name) end
farr = function (s, pos)
local name = tempsubj:sub(1, pos-1)
temptype = types[name] or CArrayTypeFrom(name, temptype.name, tonumber(s))
end
fstar = function (pos)
local name = tempsubj:sub(1, pos-1)
temptype = types[name] or CStarTypeFrom(name, temptype.name)
end
tempMType = MType(fsetsubj, fbase, farr, fstar)
PP(tempMType:match("char[23][4][]*[5]")) --> output: 18
sorted = function (tbl, f) table.sort(tbl, f); return tbl end
for _,k in ipairs(sorted(keys(types))) do
PP(k, types[k])
end
-- «test-2-output» (to ".test-2-output")
-- Output:
-- "char" {"align"=1, "name"="char", "size"=1}
-- "char[23]" {"align"=1, "basetype"="char", "name"="char[23]", "size"=23}
-- "char[23][4]" {"align"=1, "basetype"="char[23]", "name"="char[23][4]", "size"=92}
-- "char[23][4][]" {"align"=1, "basetype"="char[23][4]", "name"="char[23][4][]"}
-- "char[23][4][]*" {"align"=4, "basetype"="char[23][4][]", "name"="char[23][4][]*", "size"=4}
-- "char[23][4][]*[5]" {"align"=4, "basetype"="char[23][4][]*", "name"="char[23][4][]*[5]", "size"=20}
-- "int" {"align"=4, "name"="int", "size"=4}
-- "short" {"align"=2, "name"="short", "size"=2}
-- "uint" {"align"=4, "name"="uint", "size"=4}
-- "ushort" {"align"=2, "name"="ushort", "size"=2}
-- "void" {"name"="void"}
-- (find-sh "lua51 ~/LUA/middle-c.lua")
print "ok"
-- Local Variables:
-- coding: raw-text-unix
-- modes: (fundamental-mode lua-mode)
-- End: