SHOW:
|
|
- or go back to the newest paste.
1 | function class(def) | |
2 | local class = {} | |
3 | local parents = {} | |
4 | ||
5 | local upv | |
6 | local env = _G | |
7 | ||
8 | local wraps | |
9 | local function super(parent_class) | |
10 | if not parent_class then | |
11 | parent_class = parents[1] | |
12 | end | |
13 | ||
14 | local this = this | |
15 | local that = {} | |
16 | for k,v in pairs(parent_class) do | |
17 | that[k] = type(v) == 'function' and wraps(this, v) or v | |
18 | end | |
19 | ||
20 | return setmetatable(that, that) | |
21 | end | |
22 | ||
23 | function wraps(this, func) | |
24 | return function(...) | |
25 | local t = env.this | |
26 | local s = env.super | |
27 | ||
28 | env.this = this | |
29 | env.super = super | |
30 | ||
31 | local ret = pcall(func, ...) | |
32 | ||
33 | env.this = t | |
34 | env.super = s | |
35 | ||
36 | return ret | |
37 | end | |
38 | end | |
39 | ||
40 | function class.__init()end | |
41 | ||
42 | for i=1,math.huge do | |
43 | inherit, v = debug.getlocal(def, i) | |
44 | if not inherit then break end | |
45 | ||
46 | local parent_class = _G[inherit] | |
47 | for i=1,math.huge do | |
48 | local name, pclass = debug.getlocal(2,i,1) | |
49 | if not name then break | |
50 | elseif name == inherit then | |
51 | parent_class = pclass | |
52 | break | |
53 | end | |
54 | end | |
55 | ||
56 | if parent_class and type(parent_class) == 'table' then | |
57 | table.insert(parents, parent_class) | |
58 | for k,v in pairs(parent_class) do | |
59 | class[k] = v | |
60 | end | |
61 | else | |
62 | error(string.format('Class "%s" not valid.', name)) | |
63 | end | |
64 | end | |
65 | ||
66 | ||
67 | for i=1,math.huge do | |
68 | local name, value = debug.getupvalue(def, i) | |
69 | if not name then break | |
70 | elseif name == '_ENV' then | |
71 | env = value | |
72 | upv = i | |
73 | break | |
74 | end | |
75 | end | |
76 | ||
77 | local _env = setmetatable({}, { | |
78 | __index= function(t, name) | |
79 | local value = class[name] | |
80 | return value ~= nil and value or env[name] | |
81 | end, | |
82 | __newindex = function(t, name, value) | |
83 | class[name] = value | |
84 | end | |
85 | }) | |
86 | ||
87 | local function senv(env) | |
88 | if upv then debug.setupvalue(def, upv, env) | |
89 | else _G = env end | |
90 | end | |
91 | ||
92 | senv(_env) | |
93 | env.pcall(def, env.table.unpack(parents)) | |
94 | senv(env) | |
95 | ||
96 | return setmetatable({}, { | |
97 | __ipairs = function() return ipairs(class) end, | |
98 | __pairs = function() return pairs(class) end, | |
99 | __index = function(t, name) return class[name] end, | |
100 | __index_new = function(t, name, value) class[name] = value end, | |
101 | __call = function(...) | |
102 | local this = {} | |
103 | for k,v in pairs(class) do | |
104 | this[k] = type(v) == 'function' and wraps(this, v) or v | |
105 | end | |
106 | this.__class = class | |
107 | this.__init(...) | |
108 | ||
109 | return setmetatable(this, this) | |
110 | end | |
111 | }) | |
112 | - | end |
112 | + | end |
113 | ||
114 | return class |