cluaupp 1.5.2 → 2.0.0-beta.2

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.
Files changed (210) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +29 -41
  3. package/api/generated/bench-latest.json +43 -21
  4. package/api/generated/lsp-index.json +1 -1
  5. package/api/manifests/roblox-target.manifest.json +5 -5
  6. package/api/normalized/roblox-target.profile.json +8729 -267
  7. package/api/roblox/luau-builtins.d.luau +185 -0
  8. package/api/roblox/surface.json +1 -0
  9. package/api/roblox-api.lock.json +11 -2
  10. package/bin/cluaupp.js +38 -0
  11. package/editors/vscode/README.md +1 -1
  12. package/editors/vscode/package.json +50 -15
  13. package/editors/vscode/snippets/flare.json +1 -1
  14. package/editors/vscode/snippets/hive.json +1 -1
  15. package/editors/vscode/syntaxes/clpp.tmLanguage.json +211 -0
  16. package/examples/README.md +9 -9
  17. package/examples/game/cluaupp.config.json +2 -2
  18. package/examples/game/default.project.json +4 -15
  19. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau +8 -0
  20. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau.map.json +13 -0
  21. package/examples/game/out/ServerScriptService/Leaderstats.server.luau +26 -0
  22. package/examples/game/out/ServerScriptService/Leaderstats.server.luau.map.json +13 -0
  23. package/examples/game/out/ServerScriptService/Main.server.luau +15 -0
  24. package/examples/game/out/ServerScriptService/Main.server.luau.map.json +13 -0
  25. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau +10 -0
  26. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau.map.json +13 -0
  27. package/examples/game/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  28. package/examples/game/src/ServerScriptService/Leaderstats.server.clp +18 -0
  29. package/examples/game/src/ServerScriptService/Main.server.clp +9 -0
  30. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  31. package/generated/api/build-profile.js +1 -1
  32. package/generated/api/loader.js +2 -2
  33. package/generated/api/surface/build.js +328 -0
  34. package/generated/api/surface/luau-defs.js +595 -0
  35. package/generated/api/surface/model.js +8 -0
  36. package/generated/api-cli.js +2 -2
  37. package/generated/cli.js +18 -17
  38. package/generated/clpp/contract.js +6 -3
  39. package/generated/clpp/handshake.js +36 -0
  40. package/generated/clpp/modules.js +20 -9
  41. package/generated/clpp/runner.js +62 -31
  42. package/generated/compile.js +18 -1
  43. package/generated/compiler/ast.js +3 -0
  44. package/generated/compiler/checker/calls.js +999 -0
  45. package/generated/compiler/checker/checker.js +1215 -0
  46. package/generated/compiler/checker/exprs.js +791 -0
  47. package/generated/compiler/checker/flow.js +168 -0
  48. package/generated/compiler/checker/members.js +763 -0
  49. package/generated/compiler/checker/statements.js +792 -0
  50. package/generated/compiler/checker/symbols.js +90 -0
  51. package/generated/compiler/checker/typeops.js +348 -0
  52. package/generated/compiler/checker/yields.js +115 -0
  53. package/generated/compiler/diagnostics.js +138 -0
  54. package/generated/compiler/emit/emitter.js +2356 -0
  55. package/generated/compiler/emit/luau-types.js +137 -0
  56. package/generated/compiler/emit/names.js +130 -0
  57. package/generated/compiler/emit/runtime.js +432 -0
  58. package/generated/compiler/lexer.js +403 -0
  59. package/generated/compiler/parser.js +1881 -0
  60. package/generated/compiler/project.js +332 -0
  61. package/generated/compiler/roblox/api.js +388 -0
  62. package/generated/compiler/roblox/context.js +100 -0
  63. package/generated/compiler/source.js +59 -0
  64. package/generated/compiler/stdlib.js +232 -0
  65. package/generated/compiler/types.js +250 -0
  66. package/generated/intellisense.js +1 -15
  67. package/generated/lsp.js +1 -1
  68. package/generated/target/build-cache.js +4 -4
  69. package/generated/target/datamodel-generate.js +12 -0
  70. package/generated/target/gen-rojo-tree.js +15 -0
  71. package/generated/target/source-map.js +61 -8
  72. package/generated/target/studio-bridge.js +1 -0
  73. package/generated/utils/project.js +104 -31
  74. package/include/README.md +5 -0
  75. package/native/bin/.gitkeep +1 -0
  76. package/package.json +17 -6
  77. package/plugins/CluauppNav/Plugin.luau +28 -4
  78. package/rust/cluaupp/Cargo.lock +795 -0
  79. package/rust/cluaupp/Cargo.toml +17 -0
  80. package/rust/cluaupp/src/main.rs +717 -0
  81. package/scripts/postinstall-native.js +56 -0
  82. package/skills/README.md +3 -3
  83. package/skills/clpp-hive-flare/SKILL.md +30 -26
  84. package/skills/clpp-language/SKILL.md +67 -74
  85. package/skills/clpp-language/compiler.md +24 -36
  86. package/skills/clpp-style/SKILL.md +31 -44
  87. package/src/api/build-profile.ts +1 -1
  88. package/src/api/loader.ts +2 -2
  89. package/src/api/surface/build.ts +374 -0
  90. package/src/api/surface/luau-defs.ts +635 -0
  91. package/src/api/surface/model.ts +96 -0
  92. package/src/api-cli.ts +2 -2
  93. package/src/cli.ts +19 -18
  94. package/src/clpp/contract.ts +20 -3
  95. package/src/clpp/handshake.ts +25 -0
  96. package/src/clpp/modules.ts +17 -10
  97. package/src/clpp/runner.ts +52 -34
  98. package/src/compile.ts +20 -2
  99. package/src/compiler/ast.ts +336 -0
  100. package/src/compiler/checker/calls.ts +1025 -0
  101. package/src/compiler/checker/checker.ts +1352 -0
  102. package/src/compiler/checker/exprs.ts +805 -0
  103. package/src/compiler/checker/flow.ts +174 -0
  104. package/src/compiler/checker/members.ts +793 -0
  105. package/src/compiler/checker/statements.ts +802 -0
  106. package/src/compiler/checker/symbols.ts +219 -0
  107. package/src/compiler/checker/typeops.ts +355 -0
  108. package/src/compiler/checker/yields.ts +120 -0
  109. package/src/compiler/diagnostics.ts +163 -0
  110. package/src/compiler/emit/emitter.ts +2486 -0
  111. package/src/compiler/emit/luau-types.ts +143 -0
  112. package/src/compiler/emit/names.ts +130 -0
  113. package/src/compiler/emit/runtime.ts +438 -0
  114. package/src/compiler/lexer.ts +444 -0
  115. package/src/compiler/parser.ts +1943 -0
  116. package/src/compiler/project.ts +354 -0
  117. package/src/compiler/roblox/api.ts +408 -0
  118. package/src/compiler/roblox/context.ts +108 -0
  119. package/src/compiler/source.ts +67 -0
  120. package/src/compiler/stdlib.ts +256 -0
  121. package/src/compiler/types.ts +313 -0
  122. package/src/intellisense.ts +1 -13
  123. package/src/lsp.ts +1 -1
  124. package/src/target/build-cache.ts +5 -8
  125. package/src/target/datamodel-generate.ts +12 -1
  126. package/src/target/gen-rojo-tree.ts +15 -0
  127. package/src/target/source-map.ts +65 -27
  128. package/src/target/studio-bridge.ts +3 -0
  129. package/src/types.ts +3 -0
  130. package/src/utils/project.ts +99 -37
  131. package/templates/README.md +7 -0
  132. package/templates/{game → game-modern}/cluaupp.config.json +2 -2
  133. package/templates/{game → game-modern}/package.json +1 -2
  134. package/templates/game-modern/rokit.toml +2 -0
  135. package/templates/game-modern/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  136. package/templates/game-modern/src/ServerScriptService/Handlers/Guard.server.clp +4 -0
  137. package/templates/game-modern/src/ServerScriptService/Main.server.clp +8 -0
  138. package/templates/game-modern/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  139. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +0 -29
  140. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +0 -13
  141. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +0 -83
  142. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +0 -13
  143. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +0 -18
  144. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +0 -13
  145. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +0 -14
  146. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +0 -13
  147. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +0 -15
  148. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +0 -13
  149. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +0 -50
  150. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +0 -13
  151. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +0 -12
  152. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +0 -13
  153. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +0 -16
  154. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +0 -13
  155. package/examples/game/src/Client/Controllers/DataController.client.clpp +0 -7
  156. package/examples/game/src/Client/Main.client.clpp +0 -4
  157. package/examples/game/src/Declarations/Net.flare +0 -5
  158. package/examples/game/src/Include/GameTypes.clh +0 -40
  159. package/examples/game/src/Modules/Core/Guard.server.clpp +0 -7
  160. package/examples/game/src/Modules/Core/PlayerHandler.server.clpp +0 -23
  161. package/examples/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  162. package/examples/game/src/Server/Main.server.clpp +0 -4
  163. package/templates/game/.clangd +0 -25
  164. package/templates/game/.vscode/extensions.json +0 -8
  165. package/templates/game/.vscode/settings.json +0 -17
  166. package/templates/game/Packages/.gitkeep +0 -0
  167. package/templates/game/compile_flags.txt +0 -6
  168. package/templates/game/default.project.json +0 -41
  169. package/templates/game/include/clpp/datatypes.clh +0 -575
  170. package/templates/game/include/clpp/generated/enums.clh +0 -4920
  171. package/templates/game/include/clpp/generated/instances.clh +0 -87182
  172. package/templates/game/include/clpp/libs/arrayindexer.clh +0 -12
  173. package/templates/game/include/clpp/libs/axiom.clh +0 -154
  174. package/templates/game/include/clpp/libs/bloom.clh +0 -58
  175. package/templates/game/include/clpp/libs/coil.clh +0 -37
  176. package/templates/game/include/clpp/libs/crest.clh +0 -22
  177. package/templates/game/include/clpp/libs/echo.clh +0 -52
  178. package/templates/game/include/clpp/libs/ember.clh +0 -17
  179. package/templates/game/include/clpp/libs/flare.clh +0 -65
  180. package/templates/game/include/clpp/libs/gleam.clh +0 -111
  181. package/templates/game/include/clpp/libs/guide.clh +0 -42
  182. package/templates/game/include/clpp/libs/helm.clh +0 -31
  183. package/templates/game/include/clpp/libs/hive.clh +0 -20
  184. package/templates/game/include/clpp/libs/keep.clh +0 -158
  185. package/templates/game/include/clpp/libs/lens.clh +0 -24
  186. package/templates/game/include/clpp/libs/mint.clh +0 -28
  187. package/templates/game/include/clpp/libs/net.clh +0 -31
  188. package/templates/game/include/clpp/libs/occlude.clh +0 -15
  189. package/templates/game/include/clpp/libs/pin.clh +0 -28
  190. package/templates/game/include/clpp/libs/promise.clh +0 -24
  191. package/templates/game/include/clpp/libs/roster.clh +0 -123
  192. package/templates/game/include/clpp/libs/shift.clh +0 -22
  193. package/templates/game/include/clpp/libs/spark.clh +0 -28
  194. package/templates/game/include/clpp/libs/stage.clh +0 -23
  195. package/templates/game/include/clpp/libs/sweep.clh +0 -23
  196. package/templates/game/include/clpp/libs/trace.clh +0 -18
  197. package/templates/game/include/clpp/libs/ward.clh +0 -19
  198. package/templates/game/include/clpp/libs.clh +0 -31
  199. package/templates/game/include/clpp/roblox.clh +0 -41
  200. package/templates/game/rokit.toml +0 -5
  201. package/templates/game/src/Client/Controllers/DataController.client.clpp +0 -7
  202. package/templates/game/src/Client/Main.client.clpp +0 -4
  203. package/templates/game/src/Declarations/Net.flare +0 -5
  204. package/templates/game/src/Include/GameTypes.clh +0 -40
  205. package/templates/game/src/Modules/Core/Guard.server.clpp +0 -7
  206. package/templates/game/src/Modules/Core/PlayerHandler.server.clpp +0 -24
  207. package/templates/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  208. package/templates/game/src/Server/Main.server.clpp +0 -4
  209. package/templates/game/stylua.toml +0 -9
  210. package/templates/game/wally.toml +0 -12
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /** CL++ types → Luau type annotations. `null` means "omit the annotation" (let Luau infer). */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.luauType = luauType;
5
+ const types_js_1 = require("../types.js");
6
+ function luauType(t, names, depth = 0) {
7
+ const p = (0, types_js_1.prune)(t);
8
+ if (depth > 8) {
9
+ return null;
10
+ }
11
+ const sub = (x) => luauType(x, names, depth + 1);
12
+ switch (p.k) {
13
+ case "int":
14
+ case "float":
15
+ return "number";
16
+ case "bool":
17
+ return "boolean";
18
+ case "string":
19
+ return "string";
20
+ case "lit":
21
+ return typeof p.value === "string" ? JSON.stringify(p.value) : typeof p.value === "boolean" ? String(p.value) : "number";
22
+ case "null":
23
+ return "nil";
24
+ case "void":
25
+ return "()";
26
+ case "any":
27
+ return "any";
28
+ case "buffer":
29
+ return "buffer";
30
+ case "thread":
31
+ return "thread";
32
+ case "list": {
33
+ const e = sub(p.elem);
34
+ return e ? `{ ${e} }` : null;
35
+ }
36
+ case "dict": {
37
+ const k = sub(p.key);
38
+ const v = sub(p.value);
39
+ return k && v ? `{ [${k}]: ${v} }` : null;
40
+ }
41
+ case "table": {
42
+ const parts = [];
43
+ for (const [k, v] of Object.entries(p.fields)) {
44
+ const vt = sub(v);
45
+ if (!vt) {
46
+ return null;
47
+ }
48
+ parts.push(`${/^[A-Za-z_][A-Za-z0-9_]*$/.test(k) ? k : `[${JSON.stringify(k)}]`}: ${vt}`);
49
+ }
50
+ return `{ ${parts.join(", ")} }`;
51
+ }
52
+ case "tuple": {
53
+ const parts = p.elems.map(sub);
54
+ return parts.every(Boolean) ? `(${parts.join(", ")})` : null;
55
+ }
56
+ case "struct": {
57
+ const base = names.struct(p.id);
58
+ if (!base) {
59
+ return null;
60
+ }
61
+ if (p.args.length) {
62
+ const args = p.args.map(sub);
63
+ return args.every(Boolean) ? `${base}<${args.join(", ")}>` : null;
64
+ }
65
+ return base;
66
+ }
67
+ case "enum":
68
+ return names.enumType(p.id) ?? "number";
69
+ case "variant": {
70
+ const parts = p.alternatives.map(sub);
71
+ return parts.every(Boolean) && parts.length ? [...new Set(parts)].join(" | ") : null;
72
+ }
73
+ case "option": {
74
+ const inner = sub(p.inner);
75
+ if (!inner) {
76
+ return null;
77
+ }
78
+ if (inner === "any") {
79
+ return "any";
80
+ }
81
+ return /->|\|/.test(inner) ? `(${inner})?` : `${inner}?`;
82
+ }
83
+ case "result": {
84
+ const ok = sub(p.ok) ?? "any";
85
+ const err = sub(p.err) ?? "any";
86
+ const opt = (x) => (x === "any" ? x : /->|\|/.test(x) ? `(${x})?` : `${x}?`);
87
+ return `{ ok: boolean, value: ${opt(ok)}, error: ${opt(err)} }`;
88
+ }
89
+ case "task": {
90
+ const r = sub(p.result);
91
+ return `ClTask<${r && r !== "()" ? r : "any"}>`;
92
+ }
93
+ case "func": {
94
+ const params = p.params.map((x) => {
95
+ const pt = sub(x.type);
96
+ return pt ? (x.optional && !pt.endsWith("?") ? (/->|\|/.test(pt) ? `(${pt})?` : `${pt}?`) : pt) : null;
97
+ });
98
+ if (!params.every(Boolean)) {
99
+ return null;
100
+ }
101
+ if (p.variadic) {
102
+ const v = sub(p.variadic);
103
+ params.push(`...${v ?? "any"}`);
104
+ }
105
+ const ret = (0, types_js_1.prune)(p.ret).k === "void" ? "()" : sub(p.ret);
106
+ if (!ret) {
107
+ return null;
108
+ }
109
+ return `(${params.join(", ")}) -> ${ret}`;
110
+ }
111
+ case "union": {
112
+ const parts = p.members.map(sub);
113
+ return parts.every(Boolean) ? [...new Set(parts)].join(" | ") : null;
114
+ }
115
+ case "param":
116
+ return p.name;
117
+ case "instance":
118
+ return p.cls === "Object" ? "Instance" : p.cls;
119
+ case "datatype":
120
+ if (p.name === "__Mutex") {
121
+ return "ClMutex";
122
+ }
123
+ return p.name;
124
+ case "rbxEnumItem":
125
+ return p.enumName === "*" ? "EnumItem" : `Enum.${p.enumName}`;
126
+ case "rbxEnum":
127
+ return "Enum";
128
+ case "rbxEnums":
129
+ return "Enums";
130
+ case "rbxSignal":
131
+ return "RBXScriptSignal";
132
+ case "clSignal":
133
+ return null;
134
+ default:
135
+ return null;
136
+ }
137
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /** Luau-safe identifiers: keywords, globals the output relies on, and non-ASCII names. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.LUAU_KEYWORDS = void 0;
5
+ exports.reservedGlobals = reservedGlobals;
6
+ exports.isReservedTypeName = isReservedTypeName;
7
+ exports.sanitizeIdentifier = sanitizeIdentifier;
8
+ exports.isIdentifier = isIdentifier;
9
+ exports.luauString = luauString;
10
+ exports.interpolationText = interpolationText;
11
+ exports.luauNumber = luauNumber;
12
+ exports.LUAU_KEYWORDS = new Set([
13
+ "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or",
14
+ "repeat", "return", "then", "true", "until", "while",
15
+ ]);
16
+ /** Names emitted code may reference as globals; user symbols are renamed away from them. */
17
+ function reservedGlobals(api) {
18
+ const out = new Set([
19
+ "self", "continue", "type", "typeof", "export",
20
+ "game", "workspace", "script", "plugin", "shared", "Enum", "Instance", "Vector3", "Vector2",
21
+ "print", "warn", "error", "assert", "tostring", "tonumber", "select", "pairs", "ipairs", "next", "pcall",
22
+ "xpcall", "require", "setmetatable", "getmetatable", "rawget", "rawset", "rawequal", "rawlen", "unpack",
23
+ "tick", "time", "wait", "delay", "spawn",
24
+ ]);
25
+ for (const name of Object.keys(api.libraries)) {
26
+ out.add(name);
27
+ }
28
+ for (const name of Object.keys(api.datatypes)) {
29
+ out.add(name);
30
+ }
31
+ return out;
32
+ }
33
+ const LUAU_BUILTIN_TYPES = new Set(["number", "string", "boolean", "any", "unknown", "never", "nil", "thread", "buffer", "userdata", "vector", "Enum", "EnumItem", "Instance"]);
34
+ /** Names that may not be used for an emitted type alias. */
35
+ function isReservedTypeName(api, name) {
36
+ return LUAU_BUILTIN_TYPES.has(name) || api.hasClass(name) || api.hasDatatype(name) || name === "RBXScriptSignal" || name === "RBXScriptConnection" || name.startsWith("Cl");
37
+ }
38
+ function sanitizeIdentifier(name) {
39
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
40
+ return name;
41
+ }
42
+ let out = "";
43
+ for (const ch of name) {
44
+ if (/[A-Za-z0-9_]/.test(ch)) {
45
+ out += ch;
46
+ }
47
+ else {
48
+ out += `_${ch.codePointAt(0).toString(16)}`;
49
+ }
50
+ }
51
+ return /^[0-9]/.test(out) ? `_${out}` : out;
52
+ }
53
+ function isIdentifier(name) {
54
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !exports.LUAU_KEYWORDS.has(name);
55
+ }
56
+ /** Luau string literal with the shortest correct escaping. */
57
+ function luauString(value) {
58
+ let out = '"';
59
+ for (const ch of value) {
60
+ const code = ch.codePointAt(0);
61
+ switch (ch) {
62
+ case '"':
63
+ out += '\\"';
64
+ break;
65
+ case "\\":
66
+ out += "\\\\";
67
+ break;
68
+ case "\n":
69
+ out += "\\n";
70
+ break;
71
+ case "\r":
72
+ out += "\\r";
73
+ break;
74
+ case "\t":
75
+ out += "\\t";
76
+ break;
77
+ case "\0":
78
+ out += "\\0";
79
+ break;
80
+ default:
81
+ out += code < 32 || code === 127 ? `\\${code}` : ch;
82
+ }
83
+ }
84
+ return `${out}"`;
85
+ }
86
+ /** Escape literal text inside a Luau interpolated string. */
87
+ function interpolationText(value) {
88
+ let out = "";
89
+ for (const ch of value) {
90
+ switch (ch) {
91
+ case "`":
92
+ out += "\\`";
93
+ break;
94
+ case "{":
95
+ out += "\\{";
96
+ break;
97
+ case "}":
98
+ out += "\\}";
99
+ break;
100
+ case "\\":
101
+ out += "\\\\";
102
+ break;
103
+ case "\n":
104
+ out += "\\n";
105
+ break;
106
+ case "\r":
107
+ out += "\\r";
108
+ break;
109
+ case "\t":
110
+ out += "\\t";
111
+ break;
112
+ default:
113
+ out += ch;
114
+ }
115
+ }
116
+ return out;
117
+ }
118
+ /** Number literal: integers stay integral, floats use the shortest round-trip form. */
119
+ function luauNumber(value) {
120
+ if (Number.isNaN(value)) {
121
+ return "(0 / 0)";
122
+ }
123
+ if (!Number.isFinite(value)) {
124
+ return value > 0 ? "math.huge" : "-math.huge";
125
+ }
126
+ if (Number.isInteger(value) && Math.abs(value) < 2 ** 53) {
127
+ return String(value);
128
+ }
129
+ return String(value);
130
+ }
@@ -0,0 +1,432 @@
1
+ "use strict";
2
+ /**
3
+ * File-local runtime helpers. Only the helpers a file uses are emitted (with their dependencies),
4
+ * as `local function`s so `--!optimize 2` can inline them. No shared runtime module, no require.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.HELPERS = void 0;
8
+ exports.helperFunctionName = helperFunctionName;
9
+ exports.resolveHelpers = resolveHelpers;
10
+ exports.HELPERS = {
11
+ __cl_idiv: {
12
+ code: `local function __cl_idiv(a: number, b: number): number
13
+ local q = a / b
14
+ return if q < 0 then math.ceil(q) else math.floor(q)
15
+ end`,
16
+ },
17
+ __cl_trunc: {
18
+ code: `local function __cl_trunc(x: number): number
19
+ return if x < 0 then math.ceil(x) else math.floor(x)
20
+ end`,
21
+ },
22
+ __cl_toint: {
23
+ deps: ["__cl_tonumber", "__cl_trunc"],
24
+ code: `local function __cl_toint(text: string): number
25
+ return __cl_trunc(__cl_tonumber(text))
26
+ end`,
27
+ },
28
+ __cl_tonumber: {
29
+ code: `local function __cl_tonumber(text: string): number
30
+ local n = tonumber(text)
31
+ if n == nil then
32
+ error(\`not a number: "{text}"\`, 2)
33
+ end
34
+ return n
35
+ end`,
36
+ },
37
+ __cl_strlen: {
38
+ code: `local function __cl_strlen(s: string): number
39
+ return utf8.len(s) or #s
40
+ end`,
41
+ },
42
+ __cl_char: {
43
+ code: `local function __cl_char(s: string, i: number): string
44
+ local from = utf8.offset(s, i + 1)
45
+ if from == nil or from > #s then
46
+ error(\`index out of range: {i} (size {utf8.len(s) or #s})\`, 2)
47
+ end
48
+ local to = (utf8.offset(s, i + 2) or #s + 1) - 1
49
+ return string.sub(s, from, to)
50
+ end`,
51
+ },
52
+ __cl_slice: {
53
+ code: `local function __cl_slice<T>(x: T, a: number, b: number): T
54
+ if type(x) == "string" then
55
+ local s = x :: any
56
+ local from = utf8.offset(s, a + 1) or #s + 1
57
+ local to = (utf8.offset(s, b + 1) or #s + 1) - 1
58
+ return string.sub(s, from, to) :: any
59
+ end
60
+ return table.move(x :: any, a + 1, b, 1, {}) :: any
61
+ end`,
62
+ },
63
+ __cl_count: {
64
+ code: `local function __cl_count(t: { [any]: any }): number
65
+ local n = 0
66
+ for _ in t do
67
+ n += 1
68
+ end
69
+ return n
70
+ end`,
71
+ },
72
+ __cl_take: {
73
+ code: `local function __cl_take<K, V>(t: { [K]: V }, key: K): V
74
+ local value = t[key]
75
+ t[key] = nil
76
+ return value
77
+ end`,
78
+ },
79
+ __cl_sorted: {
80
+ code: `local function __cl_sorted<T>(list: { T }): { T }
81
+ local out = table.clone(list)
82
+ table.sort(out :: any)
83
+ return out
84
+ end`,
85
+ },
86
+ __cl_str: {
87
+ code: `local function __cl_str(value: any): string
88
+ local kind = typeof(value)
89
+ if kind == "string" then
90
+ return value
91
+ elseif kind == "boolean" or kind == "number" or kind == "nil" then
92
+ return if value == nil then "null" else tostring(value)
93
+ elseif kind == "Vector3" then
94
+ return \`({value.X}, {value.Y}, {value.Z})\`
95
+ elseif kind == "Vector2" then
96
+ return \`({value.X}, {value.Y})\`
97
+ elseif kind ~= "table" then
98
+ return tostring(value)
99
+ end
100
+ local meta = getmetatable(value)
101
+ local fields = if type(meta) == "table" then rawget(meta, "__fields") else nil
102
+ local parts = {}
103
+ local function item(v: any): string
104
+ return if type(v) == "string" then \`"{v}"\` else __cl_str(v)
105
+ end
106
+ if fields then
107
+ for i, name in fields do
108
+ parts[i] = __cl_str(value[name])
109
+ end
110
+ return "(" .. table.concat(parts, ", ") .. ")"
111
+ end
112
+ if rawget(value, "tag") ~= nil and type(rawget(value, "tag")) == "number" then
113
+ return if value.value ~= nil then __cl_str(value.value) else tostring(value.tag)
114
+ end
115
+ if #value > 0 or next(value) == nil then
116
+ for i, v in value do
117
+ parts[i] = item(v)
118
+ end
119
+ return "[" .. table.concat(parts, ", ") .. "]"
120
+ end
121
+ for k, v in value do
122
+ table.insert(parts, \`{k}: {__cl_str(v)}\`)
123
+ end
124
+ return "{" .. table.concat(parts, ", ") .. "}"
125
+ end`,
126
+ },
127
+ __cl_copy: {
128
+ code: `local function __cl_copy<T>(value: T): T
129
+ if type(value) ~= "table" then
130
+ return value
131
+ end
132
+ local source = value :: any
133
+ local meta = getmetatable(source)
134
+ if meta ~= nil and (type(meta) ~= "table" or rawget(meta, "__fields") == nil) then
135
+ return value -- foreign object: shared by reference
136
+ end
137
+ local out = table.clone(source)
138
+ for k, v in out do
139
+ if type(v) == "table" then
140
+ out[k] = __cl_copy(v)
141
+ end
142
+ end
143
+ if meta ~= nil then
144
+ setmetatable(out, meta)
145
+ end
146
+ return out :: any
147
+ end`,
148
+ },
149
+ __cl_eq: {
150
+ code: `local function __cl_eq(a: any, b: any): boolean
151
+ if a == b then
152
+ return true
153
+ end
154
+ if type(a) ~= "table" or type(b) ~= "table" or getmetatable(a) ~= getmetatable(b) then
155
+ return false
156
+ end
157
+ for k, v in a do
158
+ if not __cl_eq(v, b[k]) then
159
+ return false
160
+ end
161
+ end
162
+ for k in b do
163
+ if a[k] == nil then
164
+ return false
165
+ end
166
+ end
167
+ return true
168
+ end`,
169
+ },
170
+ __cl_findeq: {
171
+ deps: ["__cl_eq"],
172
+ code: `local function __cl_findeq(list: { any }, value: any): number
173
+ for i, v in list do
174
+ if __cl_eq(v, value) then
175
+ return i - 1
176
+ end
177
+ end
178
+ return -1
179
+ end`,
180
+ },
181
+ __cl_task: {
182
+ types: `type ClTask<T> = { done: boolean, ok: boolean, value: T?, err: any, waiting: { thread } }`,
183
+ code: `local function __cl_spawn<T>(work: () -> T): ClTask<T>
184
+ local job: ClTask<T> = { done = false, ok = true, value = nil, err = nil, waiting = {} }
185
+ task.spawn(function()
186
+ local ok, result = pcall(work)
187
+ job.ok = ok
188
+ if ok then
189
+ job.value = result
190
+ else
191
+ job.err = result
192
+ end
193
+ job.done = true
194
+ for _, waiter in job.waiting do
195
+ task.spawn(waiter)
196
+ end
197
+ end)
198
+ return job
199
+ end
200
+
201
+ local function __cl_await<T>(job: ClTask<T>): T
202
+ if not job.done then
203
+ table.insert(job.waiting, coroutine.running())
204
+ coroutine.yield()
205
+ end
206
+ if not job.ok then
207
+ error(job.err, 0)
208
+ end
209
+ return job.value :: T
210
+ end`,
211
+ },
212
+ __cl_parallel: {
213
+ deps: ["__cl_task"],
214
+ code: `local function __cl_parallel<T>(jobs: { ClTask<T> }): { T }
215
+ local results = table.create(#jobs)
216
+ for i, job in jobs do
217
+ results[i] = __cl_await(job)
218
+ end
219
+ return results
220
+ end`,
221
+ },
222
+ __cl_mutex: {
223
+ types: `type ClMutex = { locked: boolean, queue: { thread } }`,
224
+ code: `local function __cl_mutex(): ClMutex
225
+ return { locked = false, queue = {} }
226
+ end
227
+
228
+ local function __cl_lock(m: ClMutex)
229
+ if m.locked then
230
+ table.insert(m.queue, coroutine.running())
231
+ coroutine.yield()
232
+ end
233
+ m.locked = true
234
+ end
235
+
236
+ local function __cl_unlock(m: ClMutex)
237
+ local nextThread = table.remove(m.queue, 1)
238
+ if nextThread then
239
+ task.spawn(nextThread)
240
+ else
241
+ m.locked = false
242
+ end
243
+ end`,
244
+ },
245
+ __cl_errmsg: {
246
+ code: `local function __cl_errmsg(err: any): string
247
+ if type(err) == "string" then
248
+ return (string.gsub(err, "^[^:]+:%d+: ", ""))
249
+ end
250
+ return tostring(err)
251
+ end`,
252
+ },
253
+ trim: {
254
+ code: `local function __cl_trim(text: string): string
255
+ return (string.match(text, "^%s*(.-)%s*$")) or ""
256
+ end`,
257
+ },
258
+ replace: {
259
+ code: `local function __cl_replace(text: string, target: string, replacement: string): string
260
+ if target == "" then
261
+ return text
262
+ end
263
+ local out = {}
264
+ local start = 1
265
+ while true do
266
+ local i, j = string.find(text, target, start, true)
267
+ if i == nil or j == nil then
268
+ break
269
+ end
270
+ table.insert(out, string.sub(text, start, i - 1))
271
+ table.insert(out, replacement)
272
+ start = j + 1
273
+ end
274
+ table.insert(out, string.sub(text, start))
275
+ return table.concat(out)
276
+ end`,
277
+ },
278
+ endsWith: {
279
+ code: `local function __cl_endsWith(text: string, part: string): boolean
280
+ return part == "" or string.sub(text, -#part) == part
281
+ end`,
282
+ },
283
+ toNumber: {
284
+ deps: ["__cl_tonumber"],
285
+ code: "",
286
+ },
287
+ indexOf: {
288
+ code: `local function __cl_indexOf(text: string, part: string): number
289
+ local at = string.find(text, part, 1, true)
290
+ if at == nil then
291
+ return -1
292
+ end
293
+ return (utf8.len(string.sub(text, 1, at - 1)) or (at - 1))
294
+ end`,
295
+ },
296
+ joinAll: {
297
+ deps: ["__cl_str"],
298
+ code: `local function __cl_joinAll(parts: { any }, separator: string): string
299
+ local out = table.create(#parts)
300
+ for i, part in parts do
301
+ out[i] = __cl_str(part)
302
+ end
303
+ return table.concat(out, separator)
304
+ end`,
305
+ },
306
+ jsonParse: {
307
+ code: `local function __cl_jsonParse(text: string): any
308
+ return game:GetService("HttpService"):JSONDecode(text)
309
+ end`,
310
+ },
311
+ jsonValid: {
312
+ code: `local function __cl_jsonValid(text: string): boolean
313
+ return (pcall(function()
314
+ return game:GetService("HttpService"):JSONDecode(text)
315
+ end))
316
+ end`,
317
+ },
318
+ jsonStringify: {
319
+ code: `local function __cl_jsonStringify(value: any): string
320
+ return game:GetService("HttpService"):JSONEncode(value)
321
+ end`,
322
+ },
323
+ jsonPretty: {
324
+ deps: ["jsonStringify"],
325
+ code: `local function __cl_jsonPretty(value: any): string
326
+ local text = __cl_jsonStringify(value)
327
+ local out, depth, inString = {}, 0, false
328
+ for i = 1, #text do
329
+ local ch = string.sub(text, i, i)
330
+ if ch == '"' and string.sub(text, i - 1, i - 1) ~= "\\\\" then
331
+ inString = not inString
332
+ end
333
+ if inString then
334
+ table.insert(out, ch)
335
+ elseif ch == "{" or ch == "[" then
336
+ depth += 1
337
+ table.insert(out, ch .. "\\n" .. string.rep(" ", depth))
338
+ elseif ch == "}" or ch == "]" then
339
+ depth -= 1
340
+ table.insert(out, "\\n" .. string.rep(" ", depth) .. ch)
341
+ elseif ch == "," then
342
+ table.insert(out, ",\\n" .. string.rep(" ", depth))
343
+ elseif ch == ":" then
344
+ table.insert(out, ": ")
345
+ else
346
+ table.insert(out, ch)
347
+ end
348
+ end
349
+ return table.concat(out)
350
+ end`,
351
+ },
352
+ jsonGet: {
353
+ code: `local function __cl_jsonGet(value: any, path: string): any
354
+ local node = value
355
+ for key in string.gmatch(path, "[^%.]+") do
356
+ if type(node) ~= "table" then
357
+ return nil
358
+ end
359
+ local index = tonumber(key)
360
+ node = if index ~= nil and node[index + 1] ~= nil then node[index + 1] else node[key]
361
+ end
362
+ return node
363
+ end`,
364
+ },
365
+ jsonHas: {
366
+ deps: ["jsonGet"],
367
+ code: `local function __cl_jsonHas(value: any, path: string): boolean
368
+ return __cl_jsonGet(value, path) ~= nil
369
+ end`,
370
+ },
371
+ jsonSet: {
372
+ code: `local function __cl_jsonSet(target: any, key: string, value: any): any
373
+ local copy = if type(target) == "table" then table.clone(target) else {}
374
+ local index = tonumber(key)
375
+ if index ~= nil and #copy > 0 then
376
+ copy[index + 1] = value
377
+ else
378
+ copy[key] = value
379
+ end
380
+ return copy
381
+ end`,
382
+ },
383
+ jsonKeys: {
384
+ code: `local function __cl_jsonKeys(object: any): { string }
385
+ local keys = {}
386
+ if type(object) == "table" then
387
+ for k in object do
388
+ table.insert(keys, tostring(k))
389
+ end
390
+ end
391
+ return keys
392
+ end`,
393
+ },
394
+ urlHost: {
395
+ code: `local function __cl_urlHost(url: string): string
396
+ local rest = string.match(url, "^%a[%w+.-]*://(.*)$") or url
397
+ local host = string.match(rest, "^[^/?#]*") or ""
398
+ host = string.match(host, "^[^@]*@(.*)$") or host
399
+ return (string.match(host, "^([^:]*)")) or host
400
+ end`,
401
+ },
402
+ };
403
+ /** Luau name a std helper is called by. */
404
+ function helperFunctionName(helper) {
405
+ if (helper === "toNumber") {
406
+ return "__cl_tonumber";
407
+ }
408
+ return helper.startsWith("__cl_") ? helper : `__cl_${helper}`;
409
+ }
410
+ /** Ordered, de-duplicated helper set including dependencies. */
411
+ function resolveHelpers(used) {
412
+ const out = [];
413
+ const seen = new Set();
414
+ const visit = (name) => {
415
+ if (seen.has(name)) {
416
+ return;
417
+ }
418
+ seen.add(name);
419
+ const h = exports.HELPERS[name];
420
+ if (!h) {
421
+ return;
422
+ }
423
+ for (const d of h.deps || []) {
424
+ visit(d);
425
+ }
426
+ out.push(name);
427
+ };
428
+ for (const u of used) {
429
+ visit(u);
430
+ }
431
+ return out;
432
+ }