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.
@@ -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"))