lenix 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lint/{tsconfig.json → src/tsconfig.json} +1 -1
- package/package.json +3 -3
- package/ts/dist/fetch/index.js +1 -1
- package/lua/LICENSE +0 -21
- package/lua/_dev/firstAttempt.lua +0 -202
- package/lua/_dev/secondAttempt.lua +0 -166
- package/lua/_dev/tests.lua +0 -298
- package/lua/index.lua +0 -322
- package/lua/lenix-0.1.0-1.rockspec +0 -25
- /package/lint/{lint-preset.json → src/lint-preset.json} +0 -0
- /package/lint/{lint.mts → src/lint.mts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lenix",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "The Monorepo for the software engineering community",
|
|
5
5
|
"author": "Lenix",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"ts/dist",
|
|
34
|
-
"lua",
|
|
34
|
+
"lua/dist",
|
|
35
35
|
"lint"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"typescript": "^5.3.3"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
|
-
"build": "tsc -p ts/fxmanifest/tsconfig.json && tsc-alias && tsc -p lint/tsconfig.json",
|
|
54
|
+
"build": "tsc -p ts/src/fxmanifest/tsconfig.json && tsc-alias && tsc -p lint/src/tsconfig.json",
|
|
55
55
|
"bump": "pnpm version patch"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/ts/dist/fetch/index.js
CHANGED
|
@@ -11,6 +11,6 @@ export const safeRequest = async (domain, endpoint, request) => {
|
|
|
11
11
|
throw new Error('An error occurred while making the request.', { cause: error });
|
|
12
12
|
}
|
|
13
13
|
finally {
|
|
14
|
-
console.
|
|
14
|
+
console.debug(`End of ${domain}/${endpoint} request`);
|
|
15
15
|
}
|
|
16
16
|
};
|
package/lua/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Lenix
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
local class<const> = function (fields)
|
|
2
|
-
local defined<const> = {}
|
|
3
|
-
local private<const> = fields.private or {}
|
|
4
|
-
local getter<const> = fields.get or {}
|
|
5
|
-
local setter<const> = fields.set or {}
|
|
6
|
-
local accessor<const> = fields.accessor or {}
|
|
7
|
-
local privates<const> = { static = {}, instance = {} }
|
|
8
|
-
local setProperties<const> = { static = {}, instance = {} }
|
|
9
|
-
local getProperties<const> = { static = {}, instance = {} }
|
|
10
|
-
|
|
11
|
-
local isVariableEligible<const> = function (variable, valueType, value)
|
|
12
|
-
if defined[variable] then
|
|
13
|
-
print(("`%s` is already defined"):format(variable))
|
|
14
|
-
return
|
|
15
|
-
elseif type(value) ~= valueType and valueType ~= "any" then
|
|
16
|
-
print(("type mismatch for `%s`, expected `%s`, got `%s`"):format(variable, valueType, type(value)))
|
|
17
|
-
return
|
|
18
|
-
end
|
|
19
|
-
defined[variable] = true
|
|
20
|
-
if valueType == "any" then
|
|
21
|
-
print(("variable `%s` implicitly has type `%s`"):format(variable, valueType, type(value)))
|
|
22
|
-
end
|
|
23
|
-
return true
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
local fieldPairs<const> = {
|
|
27
|
-
{private, privates},
|
|
28
|
-
{getter, getProperties},
|
|
29
|
-
{setter, setProperties},
|
|
30
|
-
{accessor, nil}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for _, pair in ipairs(fieldPairs) do
|
|
34
|
-
local source, target = pair[1], pair[2]
|
|
35
|
-
for variable, values in pairs(source) do
|
|
36
|
-
-- getPropertyValue
|
|
37
|
-
local value<const> = type(values) == "table" and values[1]
|
|
38
|
-
-- getPropertyType
|
|
39
|
-
local valueType<const> = type(values) == "table" and values[2] or "any"
|
|
40
|
-
local staticValue<const> = values and values[3] or false
|
|
41
|
-
if isVariableEligible(variable, valueType, value) then
|
|
42
|
-
-- fill table with keys and values
|
|
43
|
-
if target then
|
|
44
|
-
if staticValue then
|
|
45
|
-
target["static"][variable] = value
|
|
46
|
-
else
|
|
47
|
-
target["instance"][variable] = value
|
|
48
|
-
end
|
|
49
|
-
else
|
|
50
|
-
if staticValue then
|
|
51
|
-
getProperties["static"][variable] = value
|
|
52
|
-
setProperties["static"][variable] = value
|
|
53
|
-
else
|
|
54
|
-
getProperties["instance"][variable] = value
|
|
55
|
-
setProperties["instance"][variable] = value
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
return setmetatable({
|
|
63
|
-
new = function (self, ...)
|
|
64
|
-
local newInstanceArgs = {...}
|
|
65
|
-
print(self)
|
|
66
|
-
local constructor<const> = fields.constructor
|
|
67
|
-
constructor(self, nil, ...)
|
|
68
|
-
return setmetatable({}, {
|
|
69
|
-
__index = function (_, variableKey)
|
|
70
|
-
if getter["instance"][variableKey] then
|
|
71
|
-
return getProperties["instance"][variableKey]
|
|
72
|
-
elseif accessor["instance"][variableKey] then
|
|
73
|
-
return getProperties["instance"][variableKey]
|
|
74
|
-
end
|
|
75
|
-
end,
|
|
76
|
-
})
|
|
77
|
-
end
|
|
78
|
-
}, {
|
|
79
|
-
__index = function(_, variableKey)
|
|
80
|
-
assert(defined[variableKey], ("property `%s` not found"):format(variableKey))
|
|
81
|
-
-- isPropertyExist
|
|
82
|
-
if getter[variableKey] ~= nil then
|
|
83
|
-
if isStatic(getter, variableKey, "get") then
|
|
84
|
-
-- returnPropertyValue
|
|
85
|
-
return getProperties["static"][variableKey]
|
|
86
|
-
end
|
|
87
|
-
elseif accessor[variableKey] ~= nil then
|
|
88
|
-
if isStatic(accessor, variableKey, "accessor") then
|
|
89
|
-
return getProperties["static"][variableKey]
|
|
90
|
-
end
|
|
91
|
-
elseif private[variableKey] ~= nil then
|
|
92
|
-
print(("cannot read the private property `%s`"):format(variableKey))
|
|
93
|
-
elseif setter[variableKey] ~= nil then
|
|
94
|
-
print(("the setter only property `%s` can not be accessed"):format(variableKey))
|
|
95
|
-
else print(("something went wrong when trying to access `%s`"):format(variableKey)) end
|
|
96
|
-
end,
|
|
97
|
-
__newindex = function (_, variableKey, variableValue)
|
|
98
|
-
assert(defined[variableKey], ("property `%s` not found"):format(variableKey))
|
|
99
|
-
if setter[variableKey] ~= nil then
|
|
100
|
-
if not isStatic(setter, variableKey, "set") then
|
|
101
|
-
local valueType = setter[variableKey][2] or "any"
|
|
102
|
-
if type(variableValue) ~= valueType and valueType ~= "any" then
|
|
103
|
-
print(("cannot assign `%s` to `%s` on `%s`"):format(type(variableValue), valueType, variableKey))
|
|
104
|
-
return
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
getProperties["static"][variableKey] = variableValue
|
|
108
|
-
elseif accessor[variableKey] ~= nil then
|
|
109
|
-
if not isStatic(accessor, variableKey, "accessor") then
|
|
110
|
-
local valueType = accessor[variableKey][2] or "any"
|
|
111
|
-
if type(variableValue) ~= valueType and valueType ~= "any" then
|
|
112
|
-
print(("cannot assign `%s` to `%s` on `%s`"):format(type(variableValue), valueType, variableKey))
|
|
113
|
-
return
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
getProperties["static"][variableKey] = variableValue
|
|
117
|
-
elseif getter[variableKey] ~= nil then
|
|
118
|
-
print(("the getter only property `%s `can not be set"):format(variableKey))
|
|
119
|
-
else print(("something went wrong when trying to access `%s`"):format(variableKey)) end
|
|
120
|
-
end
|
|
121
|
-
})
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
myClass = class({
|
|
125
|
-
private = {
|
|
126
|
-
height = {197, "number"},
|
|
127
|
-
},
|
|
128
|
-
get = {
|
|
129
|
-
blood = {"O+", "any"},
|
|
130
|
-
},
|
|
131
|
-
set = {
|
|
132
|
-
date = {2005, "number"},
|
|
133
|
-
},
|
|
134
|
-
accessor = {
|
|
135
|
-
age = {20, "number"},
|
|
136
|
-
name = {"Lenix", "string"},
|
|
137
|
-
getBlood = {function(self) return self end, "function"}
|
|
138
|
-
},
|
|
139
|
-
constructor = function(self, super, name, age)
|
|
140
|
-
self.name = name
|
|
141
|
-
self.age = age
|
|
142
|
-
end
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
local Person = myClass:new("Dev", 21)
|
|
147
|
-
print(Person.name, Person.age)
|
|
148
|
-
-- Person.date = 2005
|
|
149
|
-
-- print(Person.date)
|
|
150
|
-
-- print(Person.age)
|
|
151
|
-
-- Person.age = 21
|
|
152
|
-
|
|
153
|
-
-- print(myClass.height)
|
|
154
|
-
-- print(myClass.blood)
|
|
155
|
-
-- myClass.date = 2026
|
|
156
|
-
-- print(myClass.age)
|
|
157
|
-
-- myClass.age = 21
|
|
158
|
-
-- print(myClass.age)
|
|
159
|
-
-- print(myClass.name)
|
|
160
|
-
-- myClass.name = "Dev"
|
|
161
|
-
-- print(myClass.name)
|
|
162
|
-
-- print(myClass.getBlood())
|
|
163
|
-
-- myClass.getBlood = function() return true end
|
|
164
|
-
-- print(myClass.getBlood())
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
__index = function(_, variableKey)
|
|
170
|
-
assert(defined[variableKey], ("property `%s` not found"):format(variableKey))
|
|
171
|
-
-- isPropertyExist
|
|
172
|
-
if getter[variableKey] ~= nil then
|
|
173
|
-
-- returnPropertyValue
|
|
174
|
-
return getProperties[variableKey]
|
|
175
|
-
elseif accessor[variableKey] ~= nil then
|
|
176
|
-
return getProperties[variableKey]
|
|
177
|
-
elseif private[variableKey] ~= nil then
|
|
178
|
-
print(("cannot read the private property `%s`"):format(variableKey))
|
|
179
|
-
elseif setter[variableKey] ~= nil then
|
|
180
|
-
print(("the setter only property `%s` are forbidden to be accessed"):format(variableKey))
|
|
181
|
-
else print(("something went wrong when trying to access `%s`"):format(variableKey)) end
|
|
182
|
-
end,
|
|
183
|
-
__newindex = function (_, variableKey, variableValue)
|
|
184
|
-
assert(defined[variableKey], ("property `%s` not found"):format(variableKey))
|
|
185
|
-
if setter[variableKey] ~= nil then
|
|
186
|
-
local valueType = setter[variableKey][2] or "any"
|
|
187
|
-
if type(variableValue) ~= valueType and valueType ~= "any" then
|
|
188
|
-
print(("cannot assign `%s` to `%s` on `%s`"):format(type(variableValue), valueType, variableKey))
|
|
189
|
-
return
|
|
190
|
-
end
|
|
191
|
-
getProperties[variableKey] = variableValue
|
|
192
|
-
elseif accessor[variableKey] ~= nil then
|
|
193
|
-
local valueType = accessor[variableKey][2] or "any"
|
|
194
|
-
if type(variableValue) ~= valueType and valueType ~= "any" then
|
|
195
|
-
print(("cannot assign `%s` to `%s` on `%s`"):format(type(variableValue), valueType, variableKey))
|
|
196
|
-
return
|
|
197
|
-
end
|
|
198
|
-
getProperties[variableKey] = variableValue
|
|
199
|
-
elseif getter[variableKey] ~= nil then
|
|
200
|
-
print(("the getter only property `%s `can not be set"):format(variableKey))
|
|
201
|
-
else print(("something went wrong when trying to access `%s`"):format(variableKey)) end
|
|
202
|
-
end
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
assert(_VERSION == "Lua 5.4", "THIS MODULE REQUIRES Lua 5.4")
|
|
2
|
-
|
|
3
|
-
local class<const> = function (fields)
|
|
4
|
-
local definedProperties<const> = {}
|
|
5
|
-
local promisedToBeConstructed<const> = {}
|
|
6
|
-
local private<const> = fields.private or {}
|
|
7
|
-
local getter<const> = fields.get or {}
|
|
8
|
-
local setter<const> = fields.set or {}
|
|
9
|
-
local accessor<const> = fields.accessor or {}
|
|
10
|
-
local privates<const> = {}
|
|
11
|
-
local setProperties<const> = {}
|
|
12
|
-
local getProperties<const> = {}
|
|
13
|
-
|
|
14
|
-
local isVariableEligible<const> = function (propertyKey, propertyType, propertyValue)
|
|
15
|
-
if definedProperties[propertyKey] then
|
|
16
|
-
print(("`%s` is already defined"):format(propertyKey))
|
|
17
|
-
return
|
|
18
|
-
elseif type(propertyValue) ~= propertyType and propertyType ~= "any" and propertyValue ~= nil then
|
|
19
|
-
error(("type mismatch for `%s`, defined `%s`, appointed `%s`"):format(propertyKey, propertyType, type(propertyValue)))
|
|
20
|
-
return
|
|
21
|
-
end
|
|
22
|
-
definedProperties[propertyKey] = true
|
|
23
|
-
if propertyType == "any" then
|
|
24
|
-
print(("variable `%s` implicitly has type `%s`"):format(propertyKey, propertyType, type(propertyValue)))
|
|
25
|
-
end
|
|
26
|
-
if propertyValue == nil and propertyType ~= "nil" then
|
|
27
|
-
promisedToBeConstructed[propertyKey] = true
|
|
28
|
-
end
|
|
29
|
-
return true
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
local fieldPairs<const> = {
|
|
33
|
-
{private, privates},
|
|
34
|
-
{getter, getProperties},
|
|
35
|
-
{setter, setProperties},
|
|
36
|
-
{accessor, nil}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
for _, pair in ipairs(fieldPairs) do
|
|
40
|
-
local field<const>, properties<const> = pair[1], pair[2]
|
|
41
|
-
for propertyKey, propertyValues in pairs(field) do
|
|
42
|
-
-- getPropertyValue
|
|
43
|
-
local propertyValue<const> = type(propertyValues) == "table" and propertyValues[1]
|
|
44
|
-
-- getPropertyType
|
|
45
|
-
assert(type(propertyValues) == 'table', ("syntax error at `%s`, expected `%s`, got `%s`"):format(propertyKey, "table", type(propertyValues)))
|
|
46
|
-
local propertyType<const> = propertyValues[2]
|
|
47
|
-
if isVariableEligible(propertyKey, propertyType, propertyValue) then
|
|
48
|
-
-- fill table with keys and values
|
|
49
|
-
if properties then
|
|
50
|
-
properties[propertyKey] = propertyValue
|
|
51
|
-
else
|
|
52
|
-
-- for the accessor, filling the get and set permission
|
|
53
|
-
getProperties[propertyKey], setProperties[propertyKey] = propertyValue, propertyValue
|
|
54
|
-
setter[propertyKey], getter[propertyKey] = accessor[propertyKey], accessor[propertyKey]
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
local get<const> = function (self, propertyKey)
|
|
61
|
-
if definedProperties[propertyKey] then
|
|
62
|
-
if getter[propertyKey] then
|
|
63
|
-
if type(self[propertyKey]) == 'function' then
|
|
64
|
-
return function(...) return self[propertyKey](self, ...) end
|
|
65
|
-
end
|
|
66
|
-
return self[propertyKey]
|
|
67
|
-
elseif private[propertyKey] then
|
|
68
|
-
print(("private property `%s` is not allowed to be accessed"):format(propertyKey))
|
|
69
|
-
else print(("tried to get the `%s` set-only property"):format(propertyKey)) end
|
|
70
|
-
else
|
|
71
|
-
print(("`%s` property does not exist"):format(propertyKey))
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
local set<const> = function (self, propertyKey, propertyValue)
|
|
75
|
-
if definedProperties[propertyKey] then
|
|
76
|
-
if setter[propertyKey] then
|
|
77
|
-
if type(propertyValue) == setter[propertyKey][2] or setter[propertyKey][2] == "any" then
|
|
78
|
-
self[propertyKey] = propertyValue
|
|
79
|
-
else print(("`%s` is not assignable to `%s`: on `%s`"):format(type(propertyValue), setter[propertyKey][2], propertyKey)) end
|
|
80
|
-
elseif private[propertyKey] then
|
|
81
|
-
print(("private property `%s` is not allowed to be assigned"):format(propertyKey))
|
|
82
|
-
else print(("tried to set the `%s` get-only property"):format(propertyKey)) end
|
|
83
|
-
else
|
|
84
|
-
print(("`%s` property does not exist"):format(propertyKey))
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
return setmetatable({
|
|
89
|
-
new = function(self, ...)
|
|
90
|
-
local instance<const> = {}
|
|
91
|
-
|
|
92
|
-
for _, pair in pairs(fieldPairs) do
|
|
93
|
-
for propertyKey, propertyValue in pairs(pair[2] or {}) do
|
|
94
|
-
instance[propertyKey] = propertyValue
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
setmetatable(instance, getmetatable(self))
|
|
99
|
-
|
|
100
|
-
if fields.constructor then
|
|
101
|
-
fields.constructor(instance, nil, ...)
|
|
102
|
-
else error('no constructor was provided') end
|
|
103
|
-
|
|
104
|
-
-- Constructor has finished, now validate
|
|
105
|
-
for propertyKey in pairs(promisedToBeConstructed) do
|
|
106
|
-
if instance[propertyKey] == nil then
|
|
107
|
-
error(('the `%s` was not instantiated in constructor as promised'):format(propertyKey))
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
return setmetatable({}, {
|
|
112
|
-
__index = function(_, propertyKey)
|
|
113
|
-
return get(instance, propertyKey)
|
|
114
|
-
end,
|
|
115
|
-
__newindex = function(_, propertyKey, varValue)
|
|
116
|
-
set(instance, propertyKey, varValue)
|
|
117
|
-
end
|
|
118
|
-
})
|
|
119
|
-
end
|
|
120
|
-
}, { })
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
local myClass<const> = class({
|
|
124
|
-
private = {
|
|
125
|
-
height = {nil, "number"},
|
|
126
|
-
},
|
|
127
|
-
get = {
|
|
128
|
-
blood = {nil, "string"},
|
|
129
|
-
getHeight = {function(self, new)
|
|
130
|
-
self.setHeight(self, new)
|
|
131
|
-
return self.height
|
|
132
|
-
end, "function"}
|
|
133
|
-
},
|
|
134
|
-
set = {
|
|
135
|
-
setHeight = {
|
|
136
|
-
function(new)
|
|
137
|
-
self.height = new
|
|
138
|
-
end, "function"
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
accessor = {
|
|
142
|
-
name = {nil, "string"},
|
|
143
|
-
age = {nil, "number"},
|
|
144
|
-
},
|
|
145
|
-
constructor = function(self, super, name, age, height, blood)
|
|
146
|
-
self.name = name
|
|
147
|
-
self.age = age
|
|
148
|
-
self.height = height
|
|
149
|
-
self.blood = blood
|
|
150
|
-
end
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
local Class<const> = myClass:new("Lenix", 20, 197, "O+")
|
|
155
|
-
Class.setHeight = function(self, new)
|
|
156
|
-
self.height = new
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
print(Class.getHeight(198))
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
package/lua/_dev/tests.lua
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
--[[ These are the tests that we have tried to get working with Lua-OOP, if you have any suggestions or improvements, please let us know. ]]
|
|
2
|
-
|
|
3
|
-
local User = class({
|
|
4
|
-
name = {nil, false},
|
|
5
|
-
age = {nil, false},
|
|
6
|
-
constructor = function(self, super, name, age)
|
|
7
|
-
self.name = name
|
|
8
|
-
self.age = age
|
|
9
|
-
end
|
|
10
|
-
})
|
|
11
|
-
local u = User:new("Alice", 25)
|
|
12
|
-
assert(u.name == "Alice" and u.age == 25, "Test 1 failed")
|
|
13
|
-
local User = class({
|
|
14
|
-
password = {nil, true}, -- private
|
|
15
|
-
constructor = function(self, super, pwd)
|
|
16
|
-
self.password = pwd
|
|
17
|
-
end
|
|
18
|
-
})
|
|
19
|
-
local u = User:new("secret")
|
|
20
|
-
local ok = pcall(function() print(u.password) end)
|
|
21
|
-
assert(not ok, "Test 2 failed: private property accessible")
|
|
22
|
-
|
|
23
|
-
-- Test 3: Private property accessible internally
|
|
24
|
-
local User = class({
|
|
25
|
-
password = {nil, true},
|
|
26
|
-
getPassword = {function(self) return self.password end, false},
|
|
27
|
-
constructor = function(self, super, pwd)
|
|
28
|
-
self.password = pwd
|
|
29
|
-
end
|
|
30
|
-
})
|
|
31
|
-
local u = User:new("secret")
|
|
32
|
-
assert(u.getPassword() == "secret", "Test 3 failed")
|
|
33
|
-
local User = class({
|
|
34
|
-
count = {0, false, true}, -- static
|
|
35
|
-
name = {nil, false},
|
|
36
|
-
constructor = function(self, super, name)
|
|
37
|
-
self.name = name
|
|
38
|
-
end
|
|
39
|
-
})
|
|
40
|
-
User.count = 5
|
|
41
|
-
local u = User:new("Alice")
|
|
42
|
-
local ok = pcall(function() print(u.count) end)
|
|
43
|
-
assert(not ok, "Test 4 failed: static accessible on instance")
|
|
44
|
-
assert(User.count == 5, "Test 4 failed: static not on class")
|
|
45
|
-
|
|
46
|
-
-- Test 5: Instance properties on instance, not class
|
|
47
|
-
local ok2 = pcall(function() print(User.name) end)
|
|
48
|
-
assert(not ok2, "Test 5 failed: instance accessible on class")
|
|
49
|
-
local User = class({
|
|
50
|
-
id = {1, false, false, true}, -- immutable
|
|
51
|
-
constructor = function(self, super, id)
|
|
52
|
-
self.id = id
|
|
53
|
-
end
|
|
54
|
-
})
|
|
55
|
-
local u = User:new(100)
|
|
56
|
-
local ok = pcall(function() u.id = 999 end)
|
|
57
|
-
assert(not ok, "Test 6 failed: immutable modified")
|
|
58
|
-
assert(u.id == 100, "Test 6 failed: immutable changed")
|
|
59
|
-
|
|
60
|
-
-- Test 7: Mutable property can be changed
|
|
61
|
-
local User = class({
|
|
62
|
-
name = {nil, false, false, false}, -- mutable
|
|
63
|
-
constructor = function(self, super, name)
|
|
64
|
-
self.name = name
|
|
65
|
-
end
|
|
66
|
-
})
|
|
67
|
-
local u = User:new("Alice")
|
|
68
|
-
u.name = "Bob"
|
|
69
|
-
assert(u.name == "Bob", "Test 7 failed")
|
|
70
|
-
local User = class({
|
|
71
|
-
_value = {0, true},
|
|
72
|
-
get = {
|
|
73
|
-
value = function(self) return self._value * 2 end
|
|
74
|
-
},
|
|
75
|
-
constructor = function(self, super, val)
|
|
76
|
-
self._value = val
|
|
77
|
-
end
|
|
78
|
-
})
|
|
79
|
-
local u = User:new(5)
|
|
80
|
-
assert(u.value == 10, "Test 8 failed")
|
|
81
|
-
|
|
82
|
-
-- Test 9: Setter works
|
|
83
|
-
local User = class({
|
|
84
|
-
_value = {0, true},
|
|
85
|
-
getValue = {function(self) return self._value end, false}, -- Add getter
|
|
86
|
-
set = {
|
|
87
|
-
value = function(self, val) self._value = val * 2 end
|
|
88
|
-
},
|
|
89
|
-
constructor = function(self) self._value = 0 end
|
|
90
|
-
})
|
|
91
|
-
local u = User:new()
|
|
92
|
-
u.value = 5
|
|
93
|
-
assert(u.getValue() == 10, "Test 9 failed")
|
|
94
|
-
|
|
95
|
-
-- Test 10: Getter can't be modified (correct version)
|
|
96
|
-
local User = class({
|
|
97
|
-
_value = {0, true},
|
|
98
|
-
get = {
|
|
99
|
-
value = function(self) return self._value end -- Getter only, no setter
|
|
100
|
-
},
|
|
101
|
-
constructor = function(self) self._value = 10 end
|
|
102
|
-
})
|
|
103
|
-
local u = User:new()
|
|
104
|
-
local ok = pcall(function() u.value = 20 end) -- Try to set getter-only property
|
|
105
|
-
assert(not ok, "Test 10 failed: getter modified")
|
|
106
|
-
|
|
107
|
-
local Parent = class({
|
|
108
|
-
id = {1, false},
|
|
109
|
-
constructor = function(self, super, id)
|
|
110
|
-
self.id = id
|
|
111
|
-
end
|
|
112
|
-
})
|
|
113
|
-
local Child = class({
|
|
114
|
-
name = {nil, false},
|
|
115
|
-
constructor = function(self, super, name, id)
|
|
116
|
-
super(id)
|
|
117
|
-
self.name = name
|
|
118
|
-
end
|
|
119
|
-
}, Parent)
|
|
120
|
-
local c = Child:new("Alice", 100)
|
|
121
|
-
assert(c.id == 100 and c.name == "Alice", "Test 11 failed")
|
|
122
|
-
|
|
123
|
-
-- Test 12: Child inherits parent getters
|
|
124
|
-
local Parent = class({
|
|
125
|
-
value = {10, false},
|
|
126
|
-
get = {
|
|
127
|
-
getValue = function(self) return self.value end
|
|
128
|
-
},
|
|
129
|
-
constructor = function(self, super, val)
|
|
130
|
-
self.value = val
|
|
131
|
-
end
|
|
132
|
-
})
|
|
133
|
-
local Child = class({
|
|
134
|
-
name = {nil, false},
|
|
135
|
-
constructor = function(self, super, name, val)
|
|
136
|
-
super(val)
|
|
137
|
-
self.name = name
|
|
138
|
-
end
|
|
139
|
-
}, Parent)
|
|
140
|
-
local c = Child:new("Test", 42)
|
|
141
|
-
assert(c.getValue == 42, "Test 12 failed")
|
|
142
|
-
|
|
143
|
-
-- Test 13: Child inherits parent setters
|
|
144
|
-
local Parent = class({
|
|
145
|
-
_value = {0, true},
|
|
146
|
-
getValue = {function(self) return self._value end, false},
|
|
147
|
-
set = {
|
|
148
|
-
value = function(self, val) self._value = val * 2 end
|
|
149
|
-
},
|
|
150
|
-
constructor = function(self)
|
|
151
|
-
self._value = 0
|
|
152
|
-
end
|
|
153
|
-
})
|
|
154
|
-
local Child = class({
|
|
155
|
-
name = {nil, false},
|
|
156
|
-
constructor = function(self, super, name)
|
|
157
|
-
super()
|
|
158
|
-
self.name = name
|
|
159
|
-
end
|
|
160
|
-
}, Parent)
|
|
161
|
-
local c = Child:new("Test")
|
|
162
|
-
c.value = 5
|
|
163
|
-
assert(c.getValue() == 10, "Test 13 failed")
|
|
164
|
-
local Parent = class({
|
|
165
|
-
secret = {nil, true}, -- private
|
|
166
|
-
constructor = function(self, super, sec)
|
|
167
|
-
self.secret = sec
|
|
168
|
-
end
|
|
169
|
-
})
|
|
170
|
-
local Child = class({
|
|
171
|
-
name = {nil, false},
|
|
172
|
-
constructor = function(self, super, name, sec)
|
|
173
|
-
super(sec)
|
|
174
|
-
self.name = name
|
|
175
|
-
end
|
|
176
|
-
}, Parent)
|
|
177
|
-
local c = Child:new("Alice", "password")
|
|
178
|
-
local ok = pcall(function() print(c.secret) end)
|
|
179
|
-
assert(not ok, "Test 14 failed: parent private accessible")
|
|
180
|
-
|
|
181
|
-
-- Test 15: Parent immutable property blocked in child
|
|
182
|
-
local Parent = class({
|
|
183
|
-
id = {1, false, false, true}, -- immutable
|
|
184
|
-
constructor = function(self, super, id)
|
|
185
|
-
self.id = id
|
|
186
|
-
end
|
|
187
|
-
})
|
|
188
|
-
local Child = class({
|
|
189
|
-
constructor = function(self, super, id)
|
|
190
|
-
super(id)
|
|
191
|
-
end
|
|
192
|
-
}, Parent)
|
|
193
|
-
local c = Child:new(100)
|
|
194
|
-
local ok = pcall(function() c.id = 999 end)
|
|
195
|
-
assert(not ok, "Test 15 failed: parent immutable modified")
|
|
196
|
-
local Parent = class({
|
|
197
|
-
greet = {function(self) return "Hello from parent" end, false, false, false, true},
|
|
198
|
-
constructor = function(self) end
|
|
199
|
-
})
|
|
200
|
-
local Child = class({
|
|
201
|
-
greet = {function(self) return "Hello from child" end, false, false, true, false, true},
|
|
202
|
-
constructor = function(self, super) super() end
|
|
203
|
-
}, Parent)
|
|
204
|
-
local c = Child:new()
|
|
205
|
-
print(c.greet()) -- Should print "Hello from child", probably prints "Hello from parent"
|
|
206
|
-
local Grandparent = class({
|
|
207
|
-
id = {1, false},
|
|
208
|
-
constructor = function(self, super, id)
|
|
209
|
-
self.id = id
|
|
210
|
-
end
|
|
211
|
-
})
|
|
212
|
-
local Parent = class({
|
|
213
|
-
name = {nil, false},
|
|
214
|
-
constructor = function(self, super, name, id)
|
|
215
|
-
super(id)
|
|
216
|
-
self.name = name
|
|
217
|
-
end
|
|
218
|
-
}, Grandparent)
|
|
219
|
-
local Child = class({
|
|
220
|
-
age = {nil, false},
|
|
221
|
-
constructor = function(self, super, age, name, id)
|
|
222
|
-
super(name, id)
|
|
223
|
-
self.age = age
|
|
224
|
-
end
|
|
225
|
-
}, Parent)
|
|
226
|
-
local c = Child:new(20, "Alice", 100)
|
|
227
|
-
assert(c.id == 100 and c.name == "Alice" and c.age == 20, "Test 17 failed")
|
|
228
|
-
local Parent = class({
|
|
229
|
-
count = {0, false, true}, -- static
|
|
230
|
-
constructor = function(self) end
|
|
231
|
-
})
|
|
232
|
-
local Child = class({
|
|
233
|
-
constructor = function(self, super) super() end
|
|
234
|
-
}, Parent)
|
|
235
|
-
assert(Child.count == 0, "Test 18 failed")
|
|
236
|
-
-- This might fail - test it
|
|
237
|
-
|
|
238
|
-
local User = class({
|
|
239
|
-
name = {nil, false},
|
|
240
|
-
greet = {function(self) return "Hello " .. self.name end, false},
|
|
241
|
-
constructor = function(self, super, name)
|
|
242
|
-
self.name = name
|
|
243
|
-
end
|
|
244
|
-
})
|
|
245
|
-
local u = User:new("Alice")
|
|
246
|
-
assert(u.greet() == "Hello Alice", "Test 19 failed")
|
|
247
|
-
|
|
248
|
-
-- Test 20: Static methods work
|
|
249
|
-
local User = class({
|
|
250
|
-
create = {function(self, name) return "Created " .. name end, false, true}, -- 481
|
|
251
|
-
constructor = function(self) end
|
|
252
|
-
})
|
|
253
|
-
assert(User.create("Alice") == "Created Alice", "Test 20 failed")
|
|
254
|
-
local User = class({
|
|
255
|
-
name = {nil, false},
|
|
256
|
-
constructor = function(self, super, name)
|
|
257
|
-
self.name = name
|
|
258
|
-
end
|
|
259
|
-
})
|
|
260
|
-
local u1 = User:new("Alice")
|
|
261
|
-
local u2 = User:new("Bob")
|
|
262
|
-
u1.name = "Charlie"
|
|
263
|
-
assert(u1.name == "Charlie" and u2.name == "Bob", "Test 21 failed")
|
|
264
|
-
|
|
265
|
-
-- Test 22: Metatable protection
|
|
266
|
-
local User = class({
|
|
267
|
-
constructor = function(self) end
|
|
268
|
-
})
|
|
269
|
-
local u = User:new()
|
|
270
|
-
local mt = getmetatable(u)
|
|
271
|
-
assert(mt == "access denied", "Test 22 failed: metatable exposed")
|
|
272
|
-
|
|
273
|
-
-- Test 23: Constructor validation
|
|
274
|
-
local User = class({
|
|
275
|
-
name = {nil, false},
|
|
276
|
-
age = {nil, false},
|
|
277
|
-
constructor = function(self, super, name)
|
|
278
|
-
self.name = name
|
|
279
|
-
-- Forgot to set age
|
|
280
|
-
end
|
|
281
|
-
})
|
|
282
|
-
local ok = pcall(function() User:new("Alice") end)
|
|
283
|
-
assert(not ok, "Test 23 failed: validation missed unset property")
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
local Parent = class({
|
|
287
|
-
greet = {function(self) return "Hello from parent" end, false, false, false, true},
|
|
288
|
-
constructor = function(self) end
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
local Child = class({
|
|
292
|
-
greet = {function(self) return "Hello from child" end, false, false, false, false, true},
|
|
293
|
-
constructor = function(self, super) super() end
|
|
294
|
-
}, Parent)
|
|
295
|
-
|
|
296
|
-
local c = Child:new()
|
|
297
|
-
print(c.greet()) -- Should print "Hello from child"
|
|
298
|
-
|
package/lua/index.lua
DELETED
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
assert(_VERSION == "Lua 5.4", "THIS MODULE REQUIRES Lua 5.4")
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
---@alias MemberKey string | "get" | "set" | "constructor"
|
|
5
|
-
---@alias Member ShorthandedMemberValue | MemberEntries | Getter | Setter | Constructor
|
|
6
|
-
---@alias ShorthandedMemberValue number | string | boolean | fun(self: unknown, ...: unknown): unknown?
|
|
7
|
-
---@alias MemberEntries {[1]: MemberValue, [2]?: MemberFlag, [3]?: MemberFlag, [4]?: MemberFlag, [5]?: MemberFlag, [6]?: MemberFlag}
|
|
8
|
-
---@alias MemberValue number | string | boolean | table | nil | fun(self: unknown, ...: unknown): unknown
|
|
9
|
-
---@alias MemberFlag boolean | nil
|
|
10
|
-
---@alias Getter fun(self: unknown): unknown
|
|
11
|
-
---@alias Setter fun(self: unknown, value: unknown): nil
|
|
12
|
-
---@alias Constructor fun(self: unknown, super: fun(...: any): unknown, ...: unknown): unknown
|
|
13
|
-
---@alias Members table<string, PropertyFlags>
|
|
14
|
-
---@alias MembersValues table<string, MemberValue>
|
|
15
|
-
---@alias RawMembers table<MemberKey, Member>
|
|
16
|
-
|
|
17
|
-
---@class PropertyFlags
|
|
18
|
-
---@field private MemberFlag
|
|
19
|
-
---@field static MemberFlag
|
|
20
|
-
---@field final MemberFlag
|
|
21
|
-
---@field virtual MemberFlag
|
|
22
|
-
---@field override MemberFlag
|
|
23
|
-
|
|
24
|
-
---@param Members RawMembers
|
|
25
|
-
---@param Parent? unknown
|
|
26
|
-
local class<const> = function (Members, Parent)
|
|
27
|
-
---@type Members
|
|
28
|
-
local members<const> = {}
|
|
29
|
-
---@type MembersValues
|
|
30
|
-
local membersValues<const> = {}
|
|
31
|
-
local default<const> = function(existingValue, defaultValue)
|
|
32
|
-
if existingValue ~= nil then
|
|
33
|
-
return existingValue
|
|
34
|
-
else return defaultValue end
|
|
35
|
-
end
|
|
36
|
-
---@type table<string, Getter>
|
|
37
|
-
local getters<const> = {}
|
|
38
|
-
---@type table<string, Setter>
|
|
39
|
-
local setters<const> = {}
|
|
40
|
-
|
|
41
|
-
for memberKey, member in pairs(Members) do
|
|
42
|
-
assert(member ~= nil, ("syntax error: expected member, got `%s`"):format(type(member)))
|
|
43
|
-
if memberKey == "constructor" then
|
|
44
|
-
if type(member) ~= "function" then error(("syntax error: constructor expected `function`, got `%s`"):format(type(member))) end
|
|
45
|
-
elseif memberKey == "get" then
|
|
46
|
-
if type(member) ~= "table" then error(("syntax error: get expected `table`, got `%s`"):format(type(member))) end
|
|
47
|
-
---@cast member table<string, Getter>
|
|
48
|
-
for getterKey, getter in pairs(member) do
|
|
49
|
-
if type(getter) ~= "function" then error(("syntax error: the getters(`%s`) can be only a `function`, got `%s`"):format(getterKey, type(getter))) end
|
|
50
|
-
local getterInfo<const> = debug.getinfo(getter, "u")
|
|
51
|
-
if getterInfo.nparams ~= 1 then error(("syntax error: the getters(`%s`) can not have parameters (excluding `self`)"):format(getterKey)) end
|
|
52
|
-
getters[getterKey] = getter
|
|
53
|
-
end
|
|
54
|
-
elseif memberKey == "set" then
|
|
55
|
-
if type(member) ~= "table" then error(("syntax error: set expected `table`, got `%s`"):format(type(member))) end
|
|
56
|
-
---@cast member table<string, Setter>
|
|
57
|
-
for setterKey, setter in pairs(member) do
|
|
58
|
-
if type(setter) ~= "function" then error(("syntax error: the setters(`%s`) can be only a `function`, got `%s`"):format(setterKey, type(setter))) end
|
|
59
|
-
local getterInfo<const> = debug.getinfo(setter, "u")
|
|
60
|
-
if getterInfo.nparams ~= 2 then error(("syntax error: the setters(`%s`) must have exactly one parameter (excluding `self`)"):format(setterKey)) end
|
|
61
|
-
setters[setterKey] = setter
|
|
62
|
-
end
|
|
63
|
-
else
|
|
64
|
-
members[memberKey] = {}
|
|
65
|
-
if type(member) == "table" then
|
|
66
|
-
membersValues[memberKey] = member[1]
|
|
67
|
-
members[memberKey] = {
|
|
68
|
-
private = default(member[2], true),
|
|
69
|
-
static = default(member[3], false),
|
|
70
|
-
final = default(member[4], false),
|
|
71
|
-
virtual = default(member[5], false),
|
|
72
|
-
override = default(member[6], true),
|
|
73
|
-
}
|
|
74
|
-
else
|
|
75
|
-
membersValues[memberKey] = member
|
|
76
|
-
members[memberKey] = {
|
|
77
|
-
private = true,
|
|
78
|
-
static = false,
|
|
79
|
-
final = true,
|
|
80
|
-
virtual = false,
|
|
81
|
-
override = false,
|
|
82
|
-
}
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
for memberKey, member in pairs(members) do
|
|
88
|
-
if member.override then
|
|
89
|
-
if not Parent or not Parent.__extended then
|
|
90
|
-
error(("cannot override `%s`: no parent class was derived"):format(memberKey))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
94
|
-
if not parentMember then
|
|
95
|
-
error(("override failed: no such `%s` parent method"):format(memberKey))
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
if not parentMember.virtual then
|
|
99
|
-
error(("override denied: the parent method `%s` is not virtual"):format(memberKey))
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
if Parent and Parent.__extended then
|
|
105
|
-
for memberKey, member in pairs(Parent.__extended.members) do
|
|
106
|
-
if not members[memberKey] then
|
|
107
|
-
members[memberKey] = member
|
|
108
|
-
membersValues[memberKey] = Parent.__extended.membersValues[memberKey]
|
|
109
|
-
else
|
|
110
|
-
if not members[memberKey].override then
|
|
111
|
-
error(("method `%s` already exists in parent, did you mean to use the override flag"):format(memberKey))
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
for getterKey, getter in pairs(Parent.__extended.getters) do
|
|
117
|
-
if not getters[getterKey] then
|
|
118
|
-
getters[getterKey] = getter
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
for setterKey, setter in pairs(Parent.__extended.setters) do
|
|
123
|
-
if not setters[setterKey] then
|
|
124
|
-
setters[setterKey] = setter
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
return setmetatable({
|
|
130
|
-
__extended = {
|
|
131
|
-
members = members,
|
|
132
|
-
membersValues = membersValues,
|
|
133
|
-
getters = getters,
|
|
134
|
-
setters = setters
|
|
135
|
-
},
|
|
136
|
-
new = function(self, ...)
|
|
137
|
-
---@type MembersValues
|
|
138
|
-
local instance<const> = {}
|
|
139
|
-
for memberKey, member in pairs(members) do
|
|
140
|
-
if not member.static then
|
|
141
|
-
instance[memberKey] = membersValues[memberKey]
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
if Members.constructor and not Parent then
|
|
146
|
-
Members.constructor(instance, nil, ...)
|
|
147
|
-
elseif Members.constructor and Parent then
|
|
148
|
-
local super<const> = function(...)
|
|
149
|
-
local parentInstance<const> = Parent:new(...)
|
|
150
|
-
|
|
151
|
-
local parentMetatable<const> = debug.getmetatable(parentInstance)
|
|
152
|
-
if parentMetatable and parentMetatable.__instance then
|
|
153
|
-
for memberKey, memberValue in pairs(parentMetatable.__instance) do
|
|
154
|
-
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
155
|
-
if members[memberKey] and members[memberKey].override then
|
|
156
|
-
elseif parentMember and not parentMember.private then
|
|
157
|
-
instance[memberKey] = memberValue
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
return parentInstance
|
|
163
|
-
end
|
|
164
|
-
Members.constructor(instance, super, ...)
|
|
165
|
-
else error("no constructor was provided") end
|
|
166
|
-
|
|
167
|
-
for memberKey, member in pairs(members) do
|
|
168
|
-
if not instance[memberKey] and not member.static and not member.private then
|
|
169
|
-
error(("the `%s` was not instantiated in constructor"):format(memberKey))
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
if Parent and Parent.__extended then
|
|
174
|
-
for memberKey, member in pairs(Parent.__extended.members) do
|
|
175
|
-
if not instance[memberKey] and not member.static and not member.private then
|
|
176
|
-
error(("derived member `%s` was not instantiated"):format(memberKey))
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
return setmetatable({}, {
|
|
182
|
-
__metatable = "access denied",
|
|
183
|
-
__instance = instance,
|
|
184
|
-
__index = function(_, memberKey)
|
|
185
|
-
local member<const> = members[memberKey]
|
|
186
|
-
if not member then
|
|
187
|
-
if getters[memberKey] then
|
|
188
|
-
return getters[memberKey](instance)
|
|
189
|
-
elseif Parent and Parent.__extended then
|
|
190
|
-
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
191
|
-
if parentMember then
|
|
192
|
-
if parentMember.private then
|
|
193
|
-
error(("`%s` is not a public member"):format(memberKey))
|
|
194
|
-
end
|
|
195
|
-
return instance[memberKey]
|
|
196
|
-
end
|
|
197
|
-
elseif setters[memberKey] then
|
|
198
|
-
error(("`%s` setter can not be accessed"):format(memberKey))
|
|
199
|
-
end
|
|
200
|
-
error(("`%s` does not exist"):format(memberKey))
|
|
201
|
-
end
|
|
202
|
-
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
203
|
-
assert(not member.static, ("`%s` is a static member"):format(memberKey))
|
|
204
|
-
|
|
205
|
-
local value<const> = instance[memberKey]
|
|
206
|
-
if type(value) == "function" then
|
|
207
|
-
return function(_, ...)
|
|
208
|
-
return value(instance, ...)
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
return value
|
|
213
|
-
end,
|
|
214
|
-
__newindex = function(_, memberKey, memberValue)
|
|
215
|
-
if setters[memberKey] then
|
|
216
|
-
setters[memberKey](instance, memberValue)
|
|
217
|
-
return
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
local member = members[memberKey]
|
|
221
|
-
|
|
222
|
-
if not member and Parent and Parent.__extended then
|
|
223
|
-
member = Parent.__extended.members[memberKey]
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
if not member then
|
|
227
|
-
if getters[memberKey] then
|
|
228
|
-
error(("getters can not be modified: at `%s`"):format(memberKey))
|
|
229
|
-
end
|
|
230
|
-
error(("`%s` does not exist"):format(memberKey))
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
234
|
-
assert(not member.static, ("`%s` is a static member"):format(memberKey))
|
|
235
|
-
assert(not member.final, ("`%s` is a readonly member"):format(memberKey))
|
|
236
|
-
|
|
237
|
-
instance[memberKey] = memberValue
|
|
238
|
-
end
|
|
239
|
-
})
|
|
240
|
-
end
|
|
241
|
-
}, {
|
|
242
|
-
__metatable = "access denied",
|
|
243
|
-
__index = function(self, memberKey)
|
|
244
|
-
local member<const> = members[memberKey]
|
|
245
|
-
if not member then
|
|
246
|
-
if getters[memberKey] then
|
|
247
|
-
return getters[memberKey](membersValues)
|
|
248
|
-
elseif Parent then
|
|
249
|
-
return Parent[memberKey]
|
|
250
|
-
elseif setters[memberKey] then
|
|
251
|
-
error(("setters can not be accessed: at `%s`"):format(memberKey))
|
|
252
|
-
end
|
|
253
|
-
error(("`%s` does not exist"):format(memberKey))
|
|
254
|
-
end
|
|
255
|
-
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
256
|
-
assert(member.static, ("`%s` is not a static member"):format(memberKey))
|
|
257
|
-
local value<const> = membersValues[memberKey]
|
|
258
|
-
|
|
259
|
-
if type(value) == "function" then
|
|
260
|
-
return function(...)
|
|
261
|
-
return value(membersValues, ...)
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
return value
|
|
266
|
-
end,
|
|
267
|
-
__newindex = function(self, memberKey, memberValue)
|
|
268
|
-
local member<const> = members[memberKey]
|
|
269
|
-
if not member then
|
|
270
|
-
if setters[memberKey] then
|
|
271
|
-
setters[memberKey](membersValues, memberValue)
|
|
272
|
-
return
|
|
273
|
-
elseif Parent then
|
|
274
|
-
Parent[memberKey] = memberValue
|
|
275
|
-
return
|
|
276
|
-
elseif getters[memberKey] then
|
|
277
|
-
error(("getters can not be modified: at `%s`"):format(memberKey))
|
|
278
|
-
end
|
|
279
|
-
error(("`%s` does not exist"):format(memberKey))
|
|
280
|
-
end
|
|
281
|
-
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
282
|
-
assert(member.static, ("`%s` is not a static member"):format(memberKey))
|
|
283
|
-
assert(not member.final, ("`%s` is a readonly member"):format(memberKey))
|
|
284
|
-
membersValues[memberKey] = memberValue
|
|
285
|
-
end
|
|
286
|
-
})
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
-- annotation tests section
|
|
291
|
-
local private<const>, static<const>, final<const>, virtual<const>, override<const> = true, true, true, true, true
|
|
292
|
-
class({
|
|
293
|
-
property1 = 10,
|
|
294
|
-
property4 = {10},
|
|
295
|
-
property7 = {10, private, false, final, false, override},
|
|
296
|
-
property2 = "hello",
|
|
297
|
-
property5 = {"hello"},
|
|
298
|
-
property8 = {"hello", false, static, false, virtual, false},
|
|
299
|
-
property3 = true,
|
|
300
|
-
property6 = {true},
|
|
301
|
-
property9 = {true, private, false, final, false, override},
|
|
302
|
-
property10 = nil, -- SYNTAX ERROR
|
|
303
|
-
property11 = {nil},
|
|
304
|
-
property12 = {nil, false, static, false, virtual, false},
|
|
305
|
-
method1 = function(self) end,
|
|
306
|
-
method2 = {function(self) end},
|
|
307
|
-
method3 = {function(self) end, private, false, final, false, override},
|
|
308
|
-
get = {
|
|
309
|
-
getter1 = function(self)
|
|
310
|
-
return self.property1
|
|
311
|
-
end,
|
|
312
|
-
},
|
|
313
|
-
set = {
|
|
314
|
-
setter1 = function(self, value)
|
|
315
|
-
self.property1 = value
|
|
316
|
-
end,
|
|
317
|
-
},
|
|
318
|
-
constructor = function(self, super, value)
|
|
319
|
-
super(value)
|
|
320
|
-
self.property1 = value
|
|
321
|
-
end
|
|
322
|
-
})
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
package = "lenix"
|
|
2
|
-
version = "0.1.0-1"
|
|
3
|
-
|
|
4
|
-
source = {
|
|
5
|
-
url = "git+https://github.com/lenixdev/lenix.git",
|
|
6
|
-
tag = "v0.1.0"
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
description = {
|
|
10
|
-
summary = "Lua OOP class module similar to TypeScript/JavaScript/Java/C++ classes",
|
|
11
|
-
detailed = "Lua object oriented programming class module with support for constructors, getters, setters, inheritance, static members, private members, final members, and virtual/override methods.",
|
|
12
|
-
homepage = "https://github.com/lenixdev/lenix/lua",
|
|
13
|
-
license = "MIT"
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
dependencies = {
|
|
17
|
-
"lua == 5.4"
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
build = {
|
|
21
|
-
type = "builtin",
|
|
22
|
-
modules = {
|
|
23
|
-
lenix = "index.lua"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
File without changes
|
|
File without changes
|