This repository was archived by the owner on Feb 8, 2022. It is now read-only.
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.lua
More file actions
Latest commit
205 lines (193 loc) · 5.05 KB
/
Copy pathinit.lua
File metadata and controls
205 lines (193 loc) · 5.05 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
---Öbject - Base superclass that implements ÖØP.
---
---Key features of this library:
---
---+ metamethods inheritance;
---+ store all metadata in metatables (no `__junk` in actual tables);
---+ can subtly identify class membership;
---+ tiny and fast, readable source.
---@classlib.object
localObject= {
classname="lib.object",
super= {},
}
---Adds all metamethods from self and all parents to the specified table.
---Maintains the order of the hierarchy: Rect > Point > Object.
---@paramselflib.object Apply from.
---@paramapply_heretable Apply to.
localfunctionapply_meta_from_parents(self, apply_here)
forkey, valueinself:iter() do
ifapply_here[key] ==nilandstring.find(key, "__") ==1then
apply_here[key] =value
end
end
end
---Adds `__index` metamethods from self or closest parent to the table.
---@paramselflib.object Apply from.
---@paramapply_heretable Apply to.
localfunctionapply_closest_meta_index(self, apply_here)
locali=self.__index
ifi==nilthen
apply_here.__index=self
return
end
apply_here.__index=function(instance, key)
localt=type(i)
localv
ift=="function" then
v=i(instance, key)
elseift=="table" then
v=i[key]
else
error("\"__index\" must be a function or table", 2)
end
ifv~=nilthen
returnv
end
ifkey=="new" orkey=="extend" then
error("attempt to use instance as class", 2)
end
returnself[key]
end
end
---Creates **uninitialized** instance of the class.
---
---After calling this method you have to initialize the instance:
---```lua
---local rect = Rectangle:new():init(2, 4, 6, 8)
---```
---Why I can't mix `new()` with `init()`? - I can, and this is just a single
---line of code, but in this case you will not see hints from LSP :(
---
---But if you want short syntax anyway - you can just call class as function:
---```lua
---local rect = Rectangle(2, 4, 6, 8)
---```
---@genericT
---@paramselfT
---@returnT
functionObject:new()
localobj_mt= {
__index=self,
__tostring=function()
return"instance of " ..self.classname
end,
}
localobj=setmetatable({}, obj_mt)
apply_meta_from_parents(self, obj_mt)
apply_closest_meta_index(self, obj_mt)
returnobj
end
---Initializes the class.
---
---By default an object takes a table with fields and applies them to itself.
---You can (and probably should) replace this method with your own in subclass.
---@paramfields?table New fields.
functionObject:init(fields)
localt=type(fields)
ift~="table" then
error("\"Object:init()\" expected a table, but got " ..t, 3)
end
forkey, valueinpairs(fields) do
self[key] =value
end
end
---Creates a new class by inheritance.
---@genericT
---@paramselfT
---@paramnamestring New class name.
---@varargtable|lib.object? Additional properties.
---@returnT
functionObject:extend(name, ...)
iftype(name) ~="string" then
error("class must have a name", 2)
end
localcls, cls_mt= {}, {}
forkey, valueinpairs(getmetatable(self)) do
cls_mt[key] =value
end
for_, extrainipairs({ ... }) do
forkey, valueinpairs(extra) do
cls[key] =value
end
end
cls.classname=name
cls.super=self
cls_mt.__index=self
cls_mt.__tostring=function()
return"class " ..name
end
returnsetmetatable(cls, cls_mt)
end
---Returns the "membership range" between self and the checking class.
---Returns `0` if belongs to it or `false` if there is no membership.
---Positive number means number of subclasses between `self` and `Test`.
---@paramTeststring|lib.object Test class.
---@paramlimit?integer Check depth (default unlimited).
---@returninteger|boolean
functionObject:has(Test, limit)
localt=type(Test)
localsearchedname
ift=="string" then
searchedname=Test
else
ift~="table" then
returnfalse
end
searchedname=Test.classname
end
locali=0
whileself.superdo
ifself.classname==searchednamethen
returni
end
ifi==limitthen
returnfalse
end
self=self.super
i=i+1
end
returnfalse
end
---Identifies affiliation to class.
---@paramTeststring|lib.object
---@returnboolean
functionObject:is(Test)
returnself:has(Test, 0) ==0
end
---Loop iterator.
---Goes through all fields and methods (including extended)
---except those belonging to Object itself.
---@genericT,K,V
---@paramselfT<K, V>
---@paramkey?K
---@returnfun(): K, V, T
functionObject:iter(key)
localvalue
localreturned= {}
localfunctionnext_iter()
key, value=next(self, key)
ifkey~=nilthen
ifreturned[key] then
returnnext_iter()
else
returned[key] =true
returnkey, value, self
end
else
ifself~=Objectthen
self=self.super
returnnext_iter()
end
end
end
returnnext_iter
end
returnsetmetatable(Object, {
__tostring=function(self)
return"class " ..self.classname
end,
__call=function(self, ...)
returnself:new():init(...)
end,
})