You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
1.7 KiB
Lua

local error = error
local pairs = pairs
local setmetatable = setmetatable
local type = type
----------
local function check(pred, msg, level)
if (not pred) then
error(msg, level+1)
end
end
----------
local api = {}
function api.class(tab)
check(type(tab) == "table", "argument must be a table", 2)
-- The generated metatable
local mt = { __metatable=true }
local ctor
-- check tab contents
for k,v in pairs(tab) do
if (k == 1) then
-- constructor: a function that returns a table
check(type(v) == "function", "tab[1] must be a function", 2)
ctor = v
elseif (type(k) == "string") then
check(#k > 0, "tab.<string> must not be empty", 2)
if (k:sub(1,2) == "__") then
if (k == "__index" and mt.__index ~= nil) then
error("tab has both __index and convenience __index entries", 2)
end
else
if (mt.__index == nil) then
mt.__index = {}
end
end
else
error("tab can contain entries at [1], or string keys", 2)
end
end
check(ctor ~= nil, "tab[1] must provide a constructor")
-- apply tab contents
for k,v in pairs(tab) do
if (type(k) == "string") then
if (k:sub(1,2) == "__") then
mt[k] = v
else
mt.__index[k] = v
end
end
end
local factory = function(...)
local t = ctor(...)
check(type(t) == "table", "constructor must return a table", 2)
return setmetatable(t, mt)
end
return factory
end
-- Done!
return api