lenix 1.3.3 → 1.3.4

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.
@@ -0,0 +1,322 @@
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
+ })
@@ -0,0 +1,25 @@
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lenix",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "The Monorepo for the software engineering community",
5
5
  "author": "Lenix",
6
6
  "license": "GPL-3.0",
@@ -31,8 +31,8 @@
31
31
  },
32
32
  "files": [
33
33
  "ts/dist",
34
- "lua/dist",
35
- "lint"
34
+ "lua",
35
+ "lint/dist"
36
36
  ],
37
37
  "dependencies": {
38
38
  "@eslint/js": "^10.0.1",