luau-obfuscator 1.0.0
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/.github/workflows/release.yml +57 -0
- package/dist/index.cjs +1097 -0
- package/dist/index.d.cts +79 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +1068 -0
- package/generated/final.luau +1029 -0
- package/package.json +38 -0
- package/scripts/example.luau +1174 -0
- package/scripts/test.js +8 -0
- package/src/config.ts +80 -0
- package/src/index.ts +22 -0
- package/src/passes/ConstantArray.ts +90 -0
- package/src/passes/EncryptNumbers.ts +66 -0
- package/src/passes/EncryptStrings.ts +83 -0
- package/src/passes/GlobalMapping.ts +194 -0
- package/src/passes/InsertJunk.ts +185 -0
- package/src/passes/Minify.ts +6 -0
- package/src/passes/NumbersToExpressions.ts +86 -0
- package/src/passes/RenameVariables.ts +32 -0
- package/src/passes/StringsToExpressions.ts +56 -0
- package/src/passes/StripTypes.ts +192 -0
- package/src/passes/WrapInFunction.ts +32 -0
- package/src/passes/nodeFactory.ts +143 -0
- package/src/passes/walk.ts +173 -0
- package/src/pipeline.ts +58 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,1174 @@
|
|
|
1
|
+
--!nolint
|
|
2
|
+
|
|
3
|
+
----------------------------------------------------------------
|
|
4
|
+
-- 1. Primitive values / literals
|
|
5
|
+
----------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
local nilValue = nil
|
|
8
|
+
local booleanValue = true
|
|
9
|
+
local falseValue = false
|
|
10
|
+
|
|
11
|
+
local integer = 123
|
|
12
|
+
local negative = -456
|
|
13
|
+
local decimal = 123.456
|
|
14
|
+
local exponent = 1.5e3
|
|
15
|
+
|
|
16
|
+
local hex = 0xFF
|
|
17
|
+
local binary = 0b10101010
|
|
18
|
+
|
|
19
|
+
local separatedInteger = 1_000_000
|
|
20
|
+
local separatedHex = 0xFF_FF
|
|
21
|
+
local separatedBinary = 0b1010_1010
|
|
22
|
+
|
|
23
|
+
local stringValue = "hello"
|
|
24
|
+
local singleQuoted = 'world'
|
|
25
|
+
|
|
26
|
+
local longString = [[
|
|
27
|
+
This is a long string.
|
|
28
|
+
It can contain "quotes" and 'quotes'.
|
|
29
|
+
]]
|
|
30
|
+
|
|
31
|
+
local escaped = "line\nnext\tcolumn\\slash\"quote"
|
|
32
|
+
|
|
33
|
+
----------------------------------------------------------------
|
|
34
|
+
-- 2. String interpolation
|
|
35
|
+
----------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
local name = "Luau"
|
|
38
|
+
local version = 1
|
|
39
|
+
|
|
40
|
+
local interpolated = `Hello, {name}!`
|
|
41
|
+
local interpolatedExpression = `Version: {version + 1}`
|
|
42
|
+
local nestedInterpolation = `Result: {if version > 0 then "valid" else "invalid"}`
|
|
43
|
+
|
|
44
|
+
----------------------------------------------------------------
|
|
45
|
+
-- 3. Basic operators
|
|
46
|
+
----------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
local add = 10 + 20
|
|
49
|
+
local subtract = 20 - 10
|
|
50
|
+
local multiply = 5 * 4
|
|
51
|
+
local divide = 20 / 4
|
|
52
|
+
local floorDivide = 21 // 4
|
|
53
|
+
local modulo = 21 % 4
|
|
54
|
+
local power = 2 ^ 8
|
|
55
|
+
local concat = "hello" .. " " .. "world"
|
|
56
|
+
|
|
57
|
+
local equal = 1 == 1
|
|
58
|
+
local notEqual = 1 ~= 2
|
|
59
|
+
local less = 1 < 2
|
|
60
|
+
local lessEqual = 1 <= 2
|
|
61
|
+
local greater = 2 > 1
|
|
62
|
+
local greaterEqual = 2 >= 1
|
|
63
|
+
|
|
64
|
+
local logicalAnd = true and false
|
|
65
|
+
local logicalOr = false or true
|
|
66
|
+
local logicalNot = not false
|
|
67
|
+
|
|
68
|
+
local length = #"hello"
|
|
69
|
+
|
|
70
|
+
----------------------------------------------------------------
|
|
71
|
+
-- 4. Compound assignments
|
|
72
|
+
----------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
local compound = "value"
|
|
75
|
+
|
|
76
|
+
compound += 1
|
|
77
|
+
compound -= 2
|
|
78
|
+
compound *= 3
|
|
79
|
+
compound /= 2
|
|
80
|
+
compound //= 2
|
|
81
|
+
compound %= 3
|
|
82
|
+
compound ^= 2
|
|
83
|
+
compound ..= "!"
|
|
84
|
+
|
|
85
|
+
----------------------------------------------------------------
|
|
86
|
+
-- 5. Local declarations
|
|
87
|
+
----------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
local a
|
|
90
|
+
local b, c
|
|
91
|
+
local d = 1
|
|
92
|
+
local e, f = 2, 3
|
|
93
|
+
local g, h, i = 4, 5, 6
|
|
94
|
+
|
|
95
|
+
----------------------------------------------------------------
|
|
96
|
+
-- 6. Tables
|
|
97
|
+
----------------------------------------------------------------
|
|
98
|
+
local emptyTable = {}
|
|
99
|
+
|
|
100
|
+
local array = {
|
|
101
|
+
10,
|
|
102
|
+
20,
|
|
103
|
+
30,
|
|
104
|
+
40,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
local recordTable = {
|
|
108
|
+
name = "Luau",
|
|
109
|
+
version = 1,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
local explicitStringKey = {
|
|
113
|
+
["key"] = "value",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
local computedStringKey = {
|
|
117
|
+
["complex" .. "Key"] = 123,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
local explicitNumberKey = {
|
|
121
|
+
[1] = "value",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
local nestedTable = {
|
|
125
|
+
{
|
|
126
|
+
id = 1,
|
|
127
|
+
name = "one",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id = 2,
|
|
131
|
+
name = "two",
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
----------------------------------------------------------------
|
|
135
|
+
-- 7. Table access / assignment
|
|
136
|
+
----------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
----------------------------------------------------------------
|
|
139
|
+
-- 8. Functions
|
|
140
|
+
----------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
local function noArguments()
|
|
143
|
+
return 42
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
local function oneArgument(value)
|
|
147
|
+
return value
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
local function multipleArguments(a, b, c)
|
|
151
|
+
return a + b + c
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
local function multipleReturns()
|
|
155
|
+
return "hello", 123, true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
local function ignoredReturn()
|
|
159
|
+
local x, y, z = multipleReturns()
|
|
160
|
+
|
|
161
|
+
return x, y, z
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
----------------------------------------------------------------
|
|
165
|
+
-- 9. Anonymous functions
|
|
166
|
+
----------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
local anonymous = function(value)
|
|
169
|
+
return value * 2
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
local function makeMultiplier(multiplier)
|
|
173
|
+
return function(value)
|
|
174
|
+
return value * multiplier
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
local double = makeMultiplier(2)
|
|
179
|
+
local quadruple = makeMultiplier(4)
|
|
180
|
+
|
|
181
|
+
----------------------------------------------------------------
|
|
182
|
+
-- 10. Method syntax
|
|
183
|
+
----------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
local object = {
|
|
186
|
+
value = 10,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function object:getValue()
|
|
190
|
+
return self.value
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
function object:setValue(value)
|
|
194
|
+
self.value = value
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
function object:add(value)
|
|
198
|
+
self.value += value
|
|
199
|
+
return self
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
object:setValue(20)
|
|
203
|
+
object:add(5)
|
|
204
|
+
|
|
205
|
+
----------------------------------------------------------------
|
|
206
|
+
-- 11. Colon function declaration
|
|
207
|
+
----------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
local calculator = {}
|
|
210
|
+
|
|
211
|
+
function calculator:add(a, b)
|
|
212
|
+
return a + b
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
function calculator:subtract(a, b)
|
|
216
|
+
return a - b
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
----------------------------------------------------------------
|
|
220
|
+
-- 12. Nested function names
|
|
221
|
+
----------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
local module = {
|
|
224
|
+
utils = {
|
|
225
|
+
math = {},
|
|
226
|
+
},
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function module.utils.identity(value)
|
|
230
|
+
return value
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
function module.utils.math.add(a, b)
|
|
234
|
+
return a + b
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
----------------------------------------------------------------
|
|
238
|
+
-- 13. If statements
|
|
239
|
+
----------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
local condition = true
|
|
242
|
+
|
|
243
|
+
if condition then
|
|
244
|
+
print("true")
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
if condition then
|
|
248
|
+
print("true")
|
|
249
|
+
else
|
|
250
|
+
print("false")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
if a == 1 then
|
|
254
|
+
print("one")
|
|
255
|
+
elseif a == 2 then
|
|
256
|
+
print("two")
|
|
257
|
+
elseif a == 3 then
|
|
258
|
+
print("three")
|
|
259
|
+
else
|
|
260
|
+
print("other")
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
----------------------------------------------------------------
|
|
264
|
+
-- 14. If expressions
|
|
265
|
+
----------------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
local result = if condition then "yes" else "no"
|
|
268
|
+
|
|
269
|
+
local numberResult = if a > 10 then 100 elseif a > 5 then 50 else 0
|
|
270
|
+
|
|
271
|
+
local nestedIfExpression = if condition
|
|
272
|
+
then if a > 0 then "positive" else "zero"
|
|
273
|
+
else "disabled"
|
|
274
|
+
|
|
275
|
+
----------------------------------------------------------------
|
|
276
|
+
-- 15. Do blocks
|
|
277
|
+
----------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
do
|
|
280
|
+
local scoped = "inside"
|
|
281
|
+
print(scoped)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
do
|
|
285
|
+
local x = 10
|
|
286
|
+
|
|
287
|
+
do
|
|
288
|
+
local y = 20
|
|
289
|
+
print(x + y)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
----------------------------------------------------------------
|
|
294
|
+
-- 16. While loop
|
|
295
|
+
----------------------------------------------------------------
|
|
296
|
+
|
|
297
|
+
local counter = 0
|
|
298
|
+
|
|
299
|
+
while counter < 5 do
|
|
300
|
+
counter += 1
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
----------------------------------------------------------------
|
|
304
|
+
-- 17. Repeat loop
|
|
305
|
+
----------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
local repeatCounter = 0
|
|
308
|
+
|
|
309
|
+
repeat
|
|
310
|
+
repeatCounter += 1
|
|
311
|
+
until repeatCounter >= 5
|
|
312
|
+
|
|
313
|
+
----------------------------------------------------------------
|
|
314
|
+
-- 18. Numeric for
|
|
315
|
+
----------------------------------------------------------------
|
|
316
|
+
|
|
317
|
+
for index = 1, 10 do
|
|
318
|
+
print(index)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
for index = 10, 1, -1 do
|
|
322
|
+
print(index)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
for index = 1, 100, 2 do
|
|
326
|
+
print(index)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
----------------------------------------------------------------
|
|
330
|
+
-- 19. Generic for / ipairs
|
|
331
|
+
----------------------------------------------------------------
|
|
332
|
+
|
|
333
|
+
for index, value in ipairs(array) do
|
|
334
|
+
print(index, value)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
----------------------------------------------------------------
|
|
338
|
+
-- 20. Generic for / pairs
|
|
339
|
+
----------------------------------------------------------------
|
|
340
|
+
|
|
341
|
+
----------------------------------------------------------------
|
|
342
|
+
-- 21. Generic iteration with multiple variables
|
|
343
|
+
----------------------------------------------------------------
|
|
344
|
+
|
|
345
|
+
local entries = {
|
|
346
|
+
{ name = "A", value = 1 },
|
|
347
|
+
{ name = "B", value = 2 },
|
|
348
|
+
{ name = "C", value = 3 },
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for index, entry in ipairs(entries) do
|
|
352
|
+
print(index, entry.name, entry.value)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
----------------------------------------------------------------
|
|
356
|
+
-- 22. Break / continue
|
|
357
|
+
----------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
for i = 1, 100 do
|
|
360
|
+
if i == 10 then
|
|
361
|
+
break
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
for i = 1, 20 do
|
|
366
|
+
if i % 2 == 0 then
|
|
367
|
+
continue
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
print(i)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
----------------------------------------------------------------
|
|
374
|
+
-- 23. Nested loops
|
|
375
|
+
----------------------------------------------------------------
|
|
376
|
+
|
|
377
|
+
for i = 1, 5 do
|
|
378
|
+
for j = 1, 5 do
|
|
379
|
+
if i == j then
|
|
380
|
+
print("diagonal", i, j)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
----------------------------------------------------------------
|
|
386
|
+
-- 24. Multiple assignment
|
|
387
|
+
----------------------------------------------------------------
|
|
388
|
+
|
|
389
|
+
local x1, x2 = 10, 20
|
|
390
|
+
x1, x2 = x2, x1
|
|
391
|
+
|
|
392
|
+
local r1, r2, r3 = multipleReturns()
|
|
393
|
+
|
|
394
|
+
----------------------------------------------------------------
|
|
395
|
+
-- 25. Function calls
|
|
396
|
+
----------------------------------------------------------------
|
|
397
|
+
|
|
398
|
+
print("hello")
|
|
399
|
+
print("a", "b", "c")
|
|
400
|
+
print(object:getValue())
|
|
401
|
+
|
|
402
|
+
local callResult = anonymous(10)
|
|
403
|
+
|
|
404
|
+
----------------------------------------------------------------
|
|
405
|
+
-- 26. String call syntax
|
|
406
|
+
----------------------------------------------------------------
|
|
407
|
+
|
|
408
|
+
local stringCall = print "hello"
|
|
409
|
+
|
|
410
|
+
----------------------------------------------------------------
|
|
411
|
+
-- 27. Table call syntax
|
|
412
|
+
----------------------------------------------------------------
|
|
413
|
+
|
|
414
|
+
local tableCall = print {
|
|
415
|
+
value = 123,
|
|
416
|
+
message = "hello",
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
----------------------------------------------------------------
|
|
420
|
+
-- 28. Parenthesized expressions
|
|
421
|
+
----------------------------------------------------------------
|
|
422
|
+
|
|
423
|
+
local grouped = (1 + 2) * (3 + 4)
|
|
424
|
+
|
|
425
|
+
local functionResult = (anonymous)(100)
|
|
426
|
+
|
|
427
|
+
----------------------------------------------------------------
|
|
428
|
+
-- 29. Type aliases - Luau
|
|
429
|
+
----------------------------------------------------------------
|
|
430
|
+
|
|
431
|
+
type UserId = number
|
|
432
|
+
type UserName = string
|
|
433
|
+
type Enabled = boolean
|
|
434
|
+
|
|
435
|
+
type StringArray = {string}
|
|
436
|
+
type NumberArray = {number}
|
|
437
|
+
|
|
438
|
+
type StringMap = {
|
|
439
|
+
[string]: string,
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
type NumberMap = {
|
|
443
|
+
[string]: number,
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
----------------------------------------------------------------
|
|
447
|
+
-- 30. Named table types
|
|
448
|
+
----------------------------------------------------------------
|
|
449
|
+
|
|
450
|
+
type User = {
|
|
451
|
+
id: number,
|
|
452
|
+
name: string,
|
|
453
|
+
active: boolean,
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
type Point = {
|
|
457
|
+
x: number,
|
|
458
|
+
y: number,
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
type OptionalUser = {
|
|
462
|
+
id: number,
|
|
463
|
+
name: string?,
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
----------------------------------------------------------------
|
|
467
|
+
-- 31. Optional properties
|
|
468
|
+
----------------------------------------------------------------
|
|
469
|
+
|
|
470
|
+
type Config = {
|
|
471
|
+
name: string,
|
|
472
|
+
debug: boolean?,
|
|
473
|
+
retries: number?,
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
----------------------------------------------------------------
|
|
477
|
+
-- 32. Union types
|
|
478
|
+
----------------------------------------------------------------
|
|
479
|
+
|
|
480
|
+
type StringOrNumber = string | number
|
|
481
|
+
|
|
482
|
+
type Result =
|
|
483
|
+
{
|
|
484
|
+
ok: true,
|
|
485
|
+
value: string,
|
|
486
|
+
}
|
|
487
|
+
|
|
|
488
|
+
{
|
|
489
|
+
ok: false,
|
|
490
|
+
error: string,
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
----------------------------------------------------------------
|
|
494
|
+
-- 33. Intersection types
|
|
495
|
+
----------------------------------------------------------------
|
|
496
|
+
|
|
497
|
+
type Named = {
|
|
498
|
+
name: string,
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
type Identified = {
|
|
502
|
+
id: number,
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
type NamedIdentified = Named & Identified
|
|
506
|
+
|
|
507
|
+
----------------------------------------------------------------
|
|
508
|
+
-- 34. Function types
|
|
509
|
+
----------------------------------------------------------------
|
|
510
|
+
|
|
511
|
+
type Callback = (number) -> string
|
|
512
|
+
type BinaryOperation = (number, number) -> number
|
|
513
|
+
type NoArguments = () -> ()
|
|
514
|
+
type VariadicFunction = (...string) -> ()
|
|
515
|
+
|
|
516
|
+
----------------------------------------------------------------
|
|
517
|
+
-- 35. Function type with multiple returns
|
|
518
|
+
----------------------------------------------------------------
|
|
519
|
+
|
|
520
|
+
type ParseResult = (string) -> (boolean, string)
|
|
521
|
+
|
|
522
|
+
----------------------------------------------------------------
|
|
523
|
+
-- 36. Type annotations on variables
|
|
524
|
+
----------------------------------------------------------------
|
|
525
|
+
|
|
526
|
+
local typedNumber: number = 123
|
|
527
|
+
local typedString: string = "hello"
|
|
528
|
+
local typedBoolean: boolean = true
|
|
529
|
+
|
|
530
|
+
local typedArray: {number} = {1, 2, 3}
|
|
531
|
+
|
|
532
|
+
local typedPoint: Point = {
|
|
533
|
+
x = 10,
|
|
534
|
+
y = 20,
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
local typedCallback: Callback = function(value)
|
|
538
|
+
return tostring(value)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
----------------------------------------------------------------
|
|
542
|
+
-- 37. Typed function parameters / return values
|
|
543
|
+
----------------------------------------------------------------
|
|
544
|
+
|
|
545
|
+
local function typedIdentity(value: string): string
|
|
546
|
+
return value
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
local function addNumbers(a: number, b: number): number
|
|
550
|
+
return a + b
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
local function createPoint(x: number, y: number): Point
|
|
554
|
+
return {
|
|
555
|
+
x = x,
|
|
556
|
+
y = y,
|
|
557
|
+
}
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
----------------------------------------------------------------
|
|
561
|
+
-- 38. Optional parameters
|
|
562
|
+
----------------------------------------------------------------
|
|
563
|
+
|
|
564
|
+
local function greet(name: string?)
|
|
565
|
+
if name then
|
|
566
|
+
return `Hello, {name}`
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
return "Hello"
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
----------------------------------------------------------------
|
|
573
|
+
-- 39. Variadic parameters
|
|
574
|
+
----------------------------------------------------------------
|
|
575
|
+
|
|
576
|
+
local function collect(...: string): {string}
|
|
577
|
+
local result: {string} = {}
|
|
578
|
+
|
|
579
|
+
for _, value in ipairs({...}) do
|
|
580
|
+
table.insert(result, value)
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
return result
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
----------------------------------------------------------------
|
|
587
|
+
-- 40. Generic type aliases
|
|
588
|
+
----------------------------------------------------------------
|
|
589
|
+
|
|
590
|
+
type Pair<T> = {
|
|
591
|
+
first: T,
|
|
592
|
+
second: T,
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
type Dictionary<K, V> = {
|
|
596
|
+
[K]: V,
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
type Box<T> = {
|
|
600
|
+
value: T,
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
----------------------------------------------------------------
|
|
604
|
+
-- 41. Generic functions
|
|
605
|
+
----------------------------------------------------------------
|
|
606
|
+
|
|
607
|
+
local function identity<T>(value: T): T
|
|
608
|
+
return value
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
local function makePair<T>(first: T, second: T): Pair<T>
|
|
612
|
+
return {
|
|
613
|
+
first = first,
|
|
614
|
+
second = second,
|
|
615
|
+
}
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
local function first<T>(values: {T}): T?
|
|
619
|
+
return values[1]
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
----------------------------------------------------------------
|
|
623
|
+
-- 42. Generic type packs
|
|
624
|
+
----------------------------------------------------------------
|
|
625
|
+
|
|
626
|
+
type CallbackPack<A...> = (A...) -> ()
|
|
627
|
+
|
|
628
|
+
----------------------------------------------------------------
|
|
629
|
+
-- 43. Generic function with type pack
|
|
630
|
+
----------------------------------------------------------------
|
|
631
|
+
|
|
632
|
+
local function passthrough<A...>(...: A...): A...
|
|
633
|
+
return ...
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
----------------------------------------------------------------
|
|
637
|
+
-- 44. Type casts
|
|
638
|
+
----------------------------------------------------------------
|
|
639
|
+
|
|
640
|
+
local unknownValue: any = "hello"
|
|
641
|
+
|
|
642
|
+
local castedString = unknownValue :: string
|
|
643
|
+
|
|
644
|
+
local castedNumber = (unknownValue :: any) :: number
|
|
645
|
+
|
|
646
|
+
----------------------------------------------------------------
|
|
647
|
+
-- 45. typeof
|
|
648
|
+
----------------------------------------------------------------
|
|
649
|
+
|
|
650
|
+
local runtimeValue = 123
|
|
651
|
+
|
|
652
|
+
type RuntimeValueType = typeof(runtimeValue)
|
|
653
|
+
type UserType = typeof(createPoint)
|
|
654
|
+
|
|
655
|
+
----------------------------------------------------------------
|
|
656
|
+
-- 46. typeof expressions
|
|
657
|
+
----------------------------------------------------------------
|
|
658
|
+
|
|
659
|
+
local inferredPoint = createPoint(10, 20)
|
|
660
|
+
local inferredType = inferredPoint :: typeof(inferredPoint)
|
|
661
|
+
|
|
662
|
+
----------------------------------------------------------------
|
|
663
|
+
-- 47. Type aliases referencing other aliases
|
|
664
|
+
----------------------------------------------------------------
|
|
665
|
+
|
|
666
|
+
type UserList = {User}
|
|
667
|
+
type UserDictionary = {[number]: User}
|
|
668
|
+
|
|
669
|
+
local users: UserList = {
|
|
670
|
+
{
|
|
671
|
+
id = 1,
|
|
672
|
+
name = "Alice",
|
|
673
|
+
active = true,
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
id = 2,
|
|
677
|
+
name = "Bob",
|
|
678
|
+
active = false,
|
|
679
|
+
},
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
----------------------------------------------------------------
|
|
683
|
+
-- 48. Type annotations on multiple locals
|
|
684
|
+
----------------------------------------------------------------
|
|
685
|
+
|
|
686
|
+
local width: number, height: number = 100, 200
|
|
687
|
+
|
|
688
|
+
----------------------------------------------------------------
|
|
689
|
+
-- 49. Const declarations
|
|
690
|
+
----------------------------------------------------------------
|
|
691
|
+
|
|
692
|
+
const constantNumber: number = 123
|
|
693
|
+
const constantString: string = "constant"
|
|
694
|
+
|
|
695
|
+
const constantTable: {
|
|
696
|
+
value: number,
|
|
697
|
+
} = {
|
|
698
|
+
value = 10,
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const constA, constB = 1, 2
|
|
702
|
+
|
|
703
|
+
----------------------------------------------------------------
|
|
704
|
+
-- 50. Const function
|
|
705
|
+
----------------------------------------------------------------
|
|
706
|
+
|
|
707
|
+
const function constantFunction(value: number): number
|
|
708
|
+
return value * 2
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
----------------------------------------------------------------
|
|
712
|
+
-- 51. Exported type aliases
|
|
713
|
+
----------------------------------------------------------------
|
|
714
|
+
|
|
715
|
+
export type PublicPoint = {
|
|
716
|
+
x: number,
|
|
717
|
+
y: number,
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
export type PublicUser = {
|
|
721
|
+
id: number,
|
|
722
|
+
name: string,
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
----------------------------------------------------------------
|
|
726
|
+
-- 52. Exported generic type
|
|
727
|
+
----------------------------------------------------------------
|
|
728
|
+
|
|
729
|
+
export type PublicBox<T> = {
|
|
730
|
+
value: T,
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
----------------------------------------------------------------
|
|
734
|
+
-- 53. Type function declarations
|
|
735
|
+
-- Kept as syntax coverage for current Luau grammar.
|
|
736
|
+
----------------------------------------------------------------
|
|
737
|
+
|
|
738
|
+
----------------------------------------------------------------
|
|
739
|
+
-- 54. Attributes
|
|
740
|
+
----------------------------------------------------------------
|
|
741
|
+
|
|
742
|
+
@deprecated
|
|
743
|
+
local function oldFunction()
|
|
744
|
+
return 123
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
@native
|
|
748
|
+
local function nativeCandidate(value: number): number
|
|
749
|
+
return value + 1
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
----------------------------------------------------------------
|
|
753
|
+
-- 55. Attribute on local function
|
|
754
|
+
----------------------------------------------------------------
|
|
755
|
+
|
|
756
|
+
@deprecated
|
|
757
|
+
local function deprecatedFunction(value: string): string
|
|
758
|
+
return value
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
----------------------------------------------------------------
|
|
762
|
+
-- 56. Attribute on method/function declaration
|
|
763
|
+
----------------------------------------------------------------
|
|
764
|
+
|
|
765
|
+
local attributedObject = {}
|
|
766
|
+
|
|
767
|
+
@native
|
|
768
|
+
function attributedObject:calculate(value: number): number
|
|
769
|
+
return value * 2
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
----------------------------------------------------------------
|
|
773
|
+
-- 57. Closures
|
|
774
|
+
----------------------------------------------------------------
|
|
775
|
+
|
|
776
|
+
local function makeCounter()
|
|
777
|
+
local value = 0
|
|
778
|
+
|
|
779
|
+
return function()
|
|
780
|
+
value += 1
|
|
781
|
+
return value
|
|
782
|
+
end
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
local counterFunction = makeCounter()
|
|
786
|
+
|
|
787
|
+
counterFunction()
|
|
788
|
+
counterFunction()
|
|
789
|
+
counterFunction()
|
|
790
|
+
|
|
791
|
+
----------------------------------------------------------------
|
|
792
|
+
-- 58. Nested closures
|
|
793
|
+
----------------------------------------------------------------
|
|
794
|
+
|
|
795
|
+
local function outer(a: number)
|
|
796
|
+
local function middle(b: number)
|
|
797
|
+
local function inner(c: number): number
|
|
798
|
+
return a + b + c
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
return inner
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
return middle
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
local closure = outer(1)(2)
|
|
808
|
+
local closureResult = closure(3)
|
|
809
|
+
|
|
810
|
+
----------------------------------------------------------------
|
|
811
|
+
-- 59. Recursive function
|
|
812
|
+
----------------------------------------------------------------
|
|
813
|
+
|
|
814
|
+
local function factorial(n: number): number
|
|
815
|
+
if n <= 1 then
|
|
816
|
+
return 1
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
return n * factorial(n - 1)
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
----------------------------------------------------------------
|
|
823
|
+
-- 60. Mutual recursion
|
|
824
|
+
----------------------------------------------------------------
|
|
825
|
+
|
|
826
|
+
local isEven: (number) -> boolean
|
|
827
|
+
local isOdd: (number) -> boolean
|
|
828
|
+
|
|
829
|
+
function isEven(value)
|
|
830
|
+
if value == 0 then
|
|
831
|
+
return true
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
return isOdd(value - 1)
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
function isOdd(value)
|
|
838
|
+
if value == 0 then
|
|
839
|
+
return false
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
return isEven(value - 1)
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
----------------------------------------------------------------
|
|
846
|
+
-- 61. Method chaining
|
|
847
|
+
----------------------------------------------------------------
|
|
848
|
+
|
|
849
|
+
local chainObject = {
|
|
850
|
+
value = 0,
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function chainObject:addValue(value: number)
|
|
854
|
+
self.value += value
|
|
855
|
+
return self
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
function chainObject:multiplyValue(value: number)
|
|
859
|
+
self.value *= value
|
|
860
|
+
return self
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
local chainResult = chainObject
|
|
864
|
+
:addValue(10)
|
|
865
|
+
:multiplyValue(2)
|
|
866
|
+
:addValue(5)
|
|
867
|
+
|
|
868
|
+
----------------------------------------------------------------
|
|
869
|
+
-- 62. Complex indexing
|
|
870
|
+
----------------------------------------------------------------
|
|
871
|
+
|
|
872
|
+
local complex = {
|
|
873
|
+
items = {
|
|
874
|
+
{
|
|
875
|
+
value = 10,
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
value = 20,
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
local complexValue = complex.items[1].value
|
|
884
|
+
|
|
885
|
+
complex.items[2].value = 999
|
|
886
|
+
|
|
887
|
+
----------------------------------------------------------------
|
|
888
|
+
-- 63. Metatable syntax
|
|
889
|
+
----------------------------------------------------------------
|
|
890
|
+
|
|
891
|
+
----------------------------------------------------------------
|
|
892
|
+
-- 64. Metamethods
|
|
893
|
+
----------------------------------------------------------------
|
|
894
|
+
|
|
895
|
+
local MetaVector = {}
|
|
896
|
+
MetaVector.__index = MetaVector
|
|
897
|
+
|
|
898
|
+
function MetaVector.new(x: number, y: number)
|
|
899
|
+
return setmetatable({
|
|
900
|
+
x = x,
|
|
901
|
+
y = y,
|
|
902
|
+
}, MetaVector)
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
function MetaVector.__add(a, b)
|
|
906
|
+
return MetaVector.new(
|
|
907
|
+
a.x + b.x,
|
|
908
|
+
a.y + b.y
|
|
909
|
+
)
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
function MetaVector.__sub(a, b)
|
|
913
|
+
return MetaVector.new(
|
|
914
|
+
a.x - b.x,
|
|
915
|
+
a.y - b.y
|
|
916
|
+
)
|
|
917
|
+
end
|
|
918
|
+
|
|
919
|
+
function MetaVector.__tostring(value)
|
|
920
|
+
return `({value.x}, {value.y})`
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
local vectorA = MetaVector.new(1, 2)
|
|
924
|
+
local vectorB = MetaVector.new(3, 4)
|
|
925
|
+
|
|
926
|
+
local vectorC = vectorA + vectorB
|
|
927
|
+
local vectorD = vectorC - vectorA
|
|
928
|
+
|
|
929
|
+
print(vectorD)
|
|
930
|
+
|
|
931
|
+
----------------------------------------------------------------
|
|
932
|
+
-- 65. Protected calls
|
|
933
|
+
----------------------------------------------------------------
|
|
934
|
+
|
|
935
|
+
local success, result = pcall(function()
|
|
936
|
+
return 123
|
|
937
|
+
end)
|
|
938
|
+
|
|
939
|
+
local success2, result2 = xpcall(
|
|
940
|
+
function()
|
|
941
|
+
error("example")
|
|
942
|
+
end,
|
|
943
|
+
function(errorMessage)
|
|
944
|
+
return tostring(errorMessage)
|
|
945
|
+
end
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
----------------------------------------------------------------
|
|
949
|
+
-- 66. Assert
|
|
950
|
+
----------------------------------------------------------------
|
|
951
|
+
|
|
952
|
+
local value = 123
|
|
953
|
+
|
|
954
|
+
assert(value ~= nil)
|
|
955
|
+
assert(type(value) == "number", "value must be a number")
|
|
956
|
+
|
|
957
|
+
----------------------------------------------------------------
|
|
958
|
+
-- 67. Error / return
|
|
959
|
+
----------------------------------------------------------------
|
|
960
|
+
|
|
961
|
+
local function requirePositive(value: number): number
|
|
962
|
+
if value <= 0 then
|
|
963
|
+
error("value must be positive")
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
return value
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
----------------------------------------------------------------
|
|
970
|
+
-- 68. Short-circuit expressions
|
|
971
|
+
----------------------------------------------------------------
|
|
972
|
+
|
|
973
|
+
local maybeName: string? = nil
|
|
974
|
+
|
|
975
|
+
local displayName = maybeName or "Anonymous"
|
|
976
|
+
local hasName = maybeName ~= nil and true or false
|
|
977
|
+
|
|
978
|
+
----------------------------------------------------------------
|
|
979
|
+
-- 69. Function as table values
|
|
980
|
+
----------------------------------------------------------------
|
|
981
|
+
|
|
982
|
+
local operations: {[string]: (number, number) -> number} = {
|
|
983
|
+
add = function(a, b)
|
|
984
|
+
return a + b
|
|
985
|
+
end,
|
|
986
|
+
|
|
987
|
+
subtract = function(a, b)
|
|
988
|
+
return a - b
|
|
989
|
+
end,
|
|
990
|
+
|
|
991
|
+
multiply = function(a, b)
|
|
992
|
+
return a * b
|
|
993
|
+
end,
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
local operationResult = operations.add(10, 20)
|
|
997
|
+
|
|
998
|
+
----------------------------------------------------------------
|
|
999
|
+
-- 70. Nested type structures
|
|
1000
|
+
----------------------------------------------------------------
|
|
1001
|
+
|
|
1002
|
+
type Service = {
|
|
1003
|
+
name: string,
|
|
1004
|
+
enabled: boolean,
|
|
1005
|
+
|
|
1006
|
+
config: {
|
|
1007
|
+
retries: number,
|
|
1008
|
+
timeout: number,
|
|
1009
|
+
},
|
|
1010
|
+
|
|
1011
|
+
run: (self: Service) -> (),
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
----------------------------------------------------------------
|
|
1015
|
+
-- 71. Recursive type
|
|
1016
|
+
----------------------------------------------------------------
|
|
1017
|
+
|
|
1018
|
+
type TreeNode = {
|
|
1019
|
+
value: number,
|
|
1020
|
+
left: TreeNode?,
|
|
1021
|
+
right: TreeNode?,
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
local tree: TreeNode = {
|
|
1025
|
+
value = 10,
|
|
1026
|
+
left = {
|
|
1027
|
+
value = 5,
|
|
1028
|
+
left = nil,
|
|
1029
|
+
right = nil,
|
|
1030
|
+
},
|
|
1031
|
+
right = {
|
|
1032
|
+
value = 15,
|
|
1033
|
+
left = nil,
|
|
1034
|
+
right = nil,
|
|
1035
|
+
},
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
----------------------------------------------------------------
|
|
1039
|
+
-- 72. Type aliases with unions
|
|
1040
|
+
----------------------------------------------------------------
|
|
1041
|
+
|
|
1042
|
+
type State = "idle" | "running" | "finished" | "failed"
|
|
1043
|
+
|
|
1044
|
+
local state: State = "idle"
|
|
1045
|
+
|
|
1046
|
+
if state == "idle" then
|
|
1047
|
+
state = "running"
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
----------------------------------------------------------------
|
|
1051
|
+
-- 73. Singleton types
|
|
1052
|
+
----------------------------------------------------------------
|
|
1053
|
+
|
|
1054
|
+
type Success = {
|
|
1055
|
+
kind: "success",
|
|
1056
|
+
value: string,
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
type Failure = {
|
|
1060
|
+
kind: "failure",
|
|
1061
|
+
error: string,
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
type OperationResult = Success | Failure
|
|
1065
|
+
|
|
1066
|
+
----------------------------------------------------------------
|
|
1067
|
+
-- 74. Discriminated union
|
|
1068
|
+
----------------------------------------------------------------
|
|
1069
|
+
|
|
1070
|
+
local operation: OperationResult = {
|
|
1071
|
+
kind = "success",
|
|
1072
|
+
value = "done",
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
if operation.kind == "success" then
|
|
1076
|
+
print(operation.value)
|
|
1077
|
+
else
|
|
1078
|
+
print(operation.error)
|
|
1079
|
+
end
|
|
1080
|
+
|
|
1081
|
+
----------------------------------------------------------------
|
|
1082
|
+
-- 75. Generic dictionary
|
|
1083
|
+
----------------------------------------------------------------
|
|
1084
|
+
|
|
1085
|
+
local scores: Dictionary<string, number> = {
|
|
1086
|
+
Alice = 100,
|
|
1087
|
+
Bob = 80,
|
|
1088
|
+
Charlie = 95,
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
----------------------------------------------------------------
|
|
1092
|
+
-- 76. Generic pair
|
|
1093
|
+
----------------------------------------------------------------
|
|
1094
|
+
|
|
1095
|
+
local numberPair: Pair<number> = {
|
|
1096
|
+
first = 10,
|
|
1097
|
+
second = 20,
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
local stringPair: Pair<string> = {
|
|
1101
|
+
first = "hello",
|
|
1102
|
+
second = "world",
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
----------------------------------------------------------------
|
|
1106
|
+
-- 77. Repeat complex expressions
|
|
1107
|
+
----------------------------------------------------------------
|
|
1108
|
+
|
|
1109
|
+
local complexExpression =
|
|
1110
|
+
((10 + 20) * 3 - 5) / 2
|
|
1111
|
+
+ (4 ^ 2)
|
|
1112
|
+
- (100 // 3)
|
|
1113
|
+
% 7
|
|
1114
|
+
|
|
1115
|
+
----------------------------------------------------------------
|
|
1116
|
+
-- 78. Anonymous nested table callbacks
|
|
1117
|
+
----------------------------------------------------------------
|
|
1118
|
+
|
|
1119
|
+
local processors = {
|
|
1120
|
+
{
|
|
1121
|
+
name = "double",
|
|
1122
|
+
process = function(value: number): number
|
|
1123
|
+
return value * 2
|
|
1124
|
+
end,
|
|
1125
|
+
},
|
|
1126
|
+
|
|
1127
|
+
{
|
|
1128
|
+
name = "square",
|
|
1129
|
+
process = function(value: number): number
|
|
1130
|
+
return value ^ 2
|
|
1131
|
+
end,
|
|
1132
|
+
},
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
for _, processor in ipairs(processors) do
|
|
1136
|
+
print(
|
|
1137
|
+
processor.name,
|
|
1138
|
+
processor.process(10)
|
|
1139
|
+
)
|
|
1140
|
+
end
|
|
1141
|
+
|
|
1142
|
+
----------------------------------------------------------------
|
|
1143
|
+
-- 79. Multiple return propagation
|
|
1144
|
+
----------------------------------------------------------------
|
|
1145
|
+
|
|
1146
|
+
local function getCoordinates(): (number, number)
|
|
1147
|
+
return 100, 200
|
|
1148
|
+
end
|
|
1149
|
+
|
|
1150
|
+
local function useCoordinates()
|
|
1151
|
+
local x, y = getCoordinates()
|
|
1152
|
+
|
|
1153
|
+
return x + 10, y + 20
|
|
1154
|
+
end
|
|
1155
|
+
|
|
1156
|
+
local finalX, finalY = useCoordinates()
|
|
1157
|
+
|
|
1158
|
+
----------------------------------------------------------------
|
|
1159
|
+
-- 80. Final parser smoke test
|
|
1160
|
+
----------------------------------------------------------------
|
|
1161
|
+
|
|
1162
|
+
local function smokeTest(value: string): string
|
|
1163
|
+
local prefix = if value == "" then "empty" else "value"
|
|
1164
|
+
|
|
1165
|
+
local result = {
|
|
1166
|
+
prefix = prefix,
|
|
1167
|
+
value = value,
|
|
1168
|
+
length = #value,
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
return `{result.prefix}: {result.value} ({result.length})`
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
print(smokeTest("Luau"))
|