-
Notifications
You must be signed in to change notification settings - Fork 1
/
init.lua
137 lines (128 loc) · 2.76 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
local huge = math.huge
---## `PRÖTØ`
---### The simplest implementation of a prototype ÖØP in Lua.
---@class lib.table.proto
local proto = {}
---Link T2 to T1 via `__index`.
---@generic T1, T2
---@param t1 T1
---@param t2 T2
---@param name? string
---@return T1|T2 result
function proto.link(t1, t2, name)
local _, mt = proto.set_name(t1, name)
mt.__index = t2
return t1
end
---Constructor.
---If table have method `init`, it will be `:called()`.
---
---```lua
---local function Vector:init()
--- if type(self[1]) == "string" then self[1] == tonumber(self[1]) end
--- return self
---end
---
---local size = proto.new(Vector, {"640", 480})
---```
---@generic T
---@param super T
---@param init? T
---@param name? string
---@return T
function proto.new(super, init, name)
name = name or ("new " .. tostring(super))
local result = proto.link(init or {}, super, name)
if result.init then
return result:init()
end
return result
end
---Create a copy of self.
---@generic T
---@param t T
---@return T
function proto.copy(t)
local new = {}
for key, value in proto.slots(t) do
new[key] = value
end
local mt = getmetatable(t)
if mt then
setmetatable(new, { __tostring = mt.__tostring })
end
return new
end
---Parents iterator.
---@param t table
---@param limit number
---@return fun(): table
function proto.parents(t, limit)
limit = limit or huge
local counter = 0
local function next_iter()
if counter < limit then
local mt = getmetatable(t)
if type(mt) == "table" and type(mt.__index) == "table" then
t = mt.__index
counter = counter + 1
return t
end
end
end
return next_iter
end
---Slots iterator.
---@param t table
---@param limit number
---@return fun(): any, any, table
function proto.slots(t, limit)
limit = limit or huge
local counter = 0
local key, value
local function next_iter()
if counter < limit then
key, value = next(t, key)
if key then
return key, value, t
else
local mt = getmetatable(t)
if type(mt) == "table" and type(mt.__index) == "table" then
t = mt.__index
counter = counter + 1
return next_iter()
end
end
end
end
return next_iter
end
---Helper for getting __index.
---@param t table
---@return table?
function proto.get_index(t)
local mt = getmetatable(t)
if mt then
return mt.__index
end
end
---Helper for setting __tostring.
---@generic T
---@param t T
---@param name? string
---@return T
---@return table metatable
function proto.set_name(t, name)
local mt = getmetatable(t)
if not mt then
mt = {}
setmetatable(t, mt)
end
if name then
mt.__tostring = function()
return name
end
end
return t, mt
end
return proto:set_name("PRÖTØ v0.3.2")