class.lua (1725B)
1 2 local error = error 3 local pairs = pairs 4 local setmetatable = setmetatable 5 local type = type 6 7 ---------- 8 9 local function check(pred, msg, level) 10 if (not pred) then 11 error(msg, level+1) 12 end 13 end 14 15 ---------- 16 17 local api = {} 18 19 function api.class(tab) 20 check(type(tab) == "table", "argument must be a table", 2) 21 22 -- The generated metatable 23 local mt = { __metatable=true } 24 local ctor 25 26 -- check tab contents 27 for k,v in pairs(tab) do 28 if (k == 1) then 29 -- constructor: a function that returns a table 30 check(type(v) == "function", "tab[1] must be a function", 2) 31 ctor = v 32 elseif (type(k) == "string") then 33 check(#k > 0, "tab.<string> must not be empty", 2) 34 if (k:sub(1,2) == "__") then 35 if (k == "__index" and mt.__index ~= nil) then 36 error("tab has both __index and convenience __index entries", 2) 37 end 38 else 39 if (mt.__index == nil) then 40 mt.__index = {} 41 end 42 end 43 else 44 error("tab can contain entries at [1], or string keys", 2) 45 end 46 end 47 48 check(ctor ~= nil, "tab[1] must provide a constructor") 49 50 -- apply tab contents 51 for k,v in pairs(tab) do 52 if (type(k) == "string") then 53 if (k:sub(1,2) == "__") then 54 mt[k] = v 55 else 56 mt.__index[k] = v 57 end 58 end 59 end 60 61 local factory = function(...) 62 local t = ctor(...) 63 check(type(t) == "table", "constructor must return a table", 2) 64 return setmetatable(t, mt) 65 end 66 67 return factory 68 end 69 70 -- Done! 71 return api