cluaupp 0.2.3 → 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.
Files changed (114) hide show
  1. package/CHANGELOG.md +10 -79
  2. package/README.md +42 -88
  3. package/docs/README.md +13 -21
  4. package/docs/architecture.md +13 -76
  5. package/docs/cli.md +12 -64
  6. package/docs/comparison.md +6 -24
  7. package/docs/config.md +6 -7
  8. package/docs/examples/combat.md +19 -227
  9. package/docs/examples/hud.md +13 -81
  10. package/docs/examples/index.md +9 -16
  11. package/docs/getting-started.md +20 -137
  12. package/docs/intellisense.md +5 -41
  13. package/docs/intro.md +16 -15
  14. package/docs/migration.md +38 -0
  15. package/docs/oop/file-tags.md +12 -36
  16. package/docs/oop/index.md +8 -14
  17. package/docs/syntax.md +54 -236
  18. package/editors/vscode/extension.js +1 -1
  19. package/editors/vscode/package.json +4 -4
  20. package/examples/README.md +5 -7
  21. package/examples/game/.vscode/extensions.json +0 -3
  22. package/examples/game/.vscode/settings.json +6 -14
  23. package/examples/game/src/client/hud.client.clpp +54 -0
  24. package/examples/game/src/client/init.client.clpp +6 -0
  25. package/examples/game/src/server/combat.server.clpp +85 -0
  26. package/examples/game/src/server/leaderstats.server.clpp +28 -0
  27. package/examples/game/src/shared/PlayerData.clh +20 -0
  28. package/examples/game/src/shared/config.clp +6 -0
  29. package/examples/game/src/shared/features.clp +88 -0
  30. package/generated/cli.js +40 -24
  31. package/generated/clpp/contract.js +5 -0
  32. package/generated/clpp/index.js +27 -0
  33. package/generated/clpp/paths.js +121 -0
  34. package/generated/clpp/postprocess.js +78 -0
  35. package/generated/clpp/runner.js +102 -0
  36. package/generated/compile.js +26 -138
  37. package/generated/intellisense.js +38 -157
  38. package/generated/libs.js +1 -1
  39. package/generated/lsp.js +1 -8
  40. package/generated/preprocess.js +8 -179
  41. package/generated/system-understander.js +1 -1
  42. package/generated/transpile.js +3 -50
  43. package/generated/utils/project.js +13 -28
  44. package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +1 -1
  45. package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
  46. package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
  47. package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
  48. package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
  49. package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
  50. package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
  51. package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
  52. package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
  53. package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
  54. package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
  55. package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
  56. package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
  57. package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
  58. package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
  59. package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
  60. package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
  61. package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
  62. package/include/clpp/libs.clh +24 -0
  63. package/include/clpp/roblox.clh +31 -0
  64. package/package.json +7 -14
  65. package/src/cli.ts +39 -25
  66. package/src/clpp/contract.ts +39 -0
  67. package/src/clpp/index.ts +18 -0
  68. package/src/clpp/paths.ts +117 -0
  69. package/src/clpp/postprocess.ts +93 -0
  70. package/src/clpp/runner.ts +102 -0
  71. package/src/compile.ts +26 -149
  72. package/src/intellisense.ts +36 -165
  73. package/src/libs.ts +1 -1
  74. package/src/lsp.ts +1 -5
  75. package/src/preprocess.ts +8 -180
  76. package/src/system-understander.ts +1 -1
  77. package/src/transpile.ts +9 -52
  78. package/src/utils/project.ts +12 -28
  79. package/templates/game/.vscode/extensions.json +0 -3
  80. package/templates/game/.vscode/settings.json +6 -14
  81. package/templates/game/src/client/init.client.clpp +6 -0
  82. package/templates/game/src/server/leaderstats.server.clpp +29 -0
  83. package/templates/game/src/shared/config.clp +6 -0
  84. package/examples/game/.clangd +0 -25
  85. package/examples/game/compile_flags.txt +0 -6
  86. package/examples/game/src/client/hud.client.cpp +0 -12
  87. package/examples/game/src/client/init.client.cpp +0 -6
  88. package/examples/game/src/server/combat.server.cpp +0 -23
  89. package/examples/game/src/server/leaderstats.server.cpp +0 -29
  90. package/examples/game/src/shared/config.cpp +0 -5
  91. package/examples/game/src/shared/config.h +0 -5
  92. package/include/cluaupp/libs.hpp +0 -25
  93. package/include/cluaupp/roblox.hpp +0 -47
  94. package/src/architecture.ts +0 -500
  95. package/src/ast.ts +0 -37
  96. package/src/emit.ts +0 -609
  97. package/src/emitter/luau-codegen.ts +0 -187
  98. package/src/emitter/translators.ts +0 -168
  99. package/src/headers.ts +0 -233
  100. package/src/layout.ts +0 -114
  101. package/src/lex.ts +0 -158
  102. package/src/parse.ts +0 -729
  103. package/src/parser/collector.ts +0 -148
  104. package/src/parser/index.ts +0 -27
  105. package/src/tree-sitter-cpp.d.ts +0 -4
  106. package/src/understand.ts +0 -322
  107. package/templates/game/src/client/init.client.cpp +0 -6
  108. package/templates/game/src/server/leaderstats.server.cpp +0 -29
  109. package/templates/game/src/shared/config.cpp +0 -5
  110. package/templates/game/src/shared/config.h +0 -5
  111. /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
  112. /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
  113. /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
  114. /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
@@ -0,0 +1,6 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void init() {
5
+ post("Cluaupp client ok");
6
+ }
@@ -0,0 +1,85 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+ #include <clpp/libs/janitor.clh>
4
+
5
+ struct CombatServer {
6
+ Janitor* janitor;
7
+ signal<Player*, int> OnHit;
8
+ void PlayerEntered(Player* player);
9
+ void BindPart(BasePart* part);
10
+ void WatchWorkspace();
11
+ };
12
+
13
+ void CombatServer::BindPart(BasePart* part) {
14
+ guard (part != null) else {
15
+ return;
16
+ }
17
+
18
+ part.Touched~>Once(func [](BasePart* other) {
19
+ Instance* character = other.Parent;
20
+ guard (character != null) else {
21
+ return;
22
+ }
23
+
24
+ match (character::FindFirstChild("Humanoid")) {
25
+ Humanoid* humanoid => {
26
+ guard (humanoid.Health > 0) else {
27
+ return;
28
+ }
29
+ Players* players = GetService<Players>();
30
+ Player* player = players::GetPlayerFromCharacter(character);
31
+ guard (player != null) else {
32
+ return;
33
+ }
34
+ OnHit::Fire(player, 10);
35
+ part::Destroy();
36
+ },
37
+ _ => warn("touch without humanoid")
38
+ };
39
+ });
40
+ }
41
+
42
+ void CombatServer::PlayerEntered(Player* player) {
43
+ guard (player != null) else {
44
+ return;
45
+ }
46
+
47
+ observable int combo = 0;
48
+ OnHit~>Connect(func [](Player* victim, int amount) {
49
+ guard (victim == player) else {
50
+ return;
51
+ }
52
+ combo = combo + 1;
53
+ post(player.Name .: " combo " .: combo .: " dmg " .: amount);
54
+ });
55
+ }
56
+
57
+ [[server]]
58
+ void CombatServer::WatchWorkspace() {
59
+ workspace.ChildAdded~>Connect(func [](Instance* child) {
60
+ match (child) {
61
+ BasePart* p => BindPart(p),
62
+ Model* m => post("model spawned " .: m.Name),
63
+ _ => warn("ignored instance")
64
+ };
65
+ });
66
+ }
67
+
68
+ void init() {
69
+ CombatServer combat;
70
+ combat.janitor = new Janitor();
71
+
72
+ spawn {
73
+ task::wait(1);
74
+ post("combat ready");
75
+ };
76
+
77
+ Players* players = GetService<Players>();
78
+ for (Player* player : players::GetPlayers()) {
79
+ combat::PlayerEntered(player);
80
+ }
81
+ players::PlayerAdded~>Connect(func [](Player* p) {
82
+ combat::PlayerEntered(p);
83
+ });
84
+ combat::WatchWorkspace();
85
+ }
@@ -0,0 +1,28 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void CreateLeaderstats(Player* player) {
5
+ if (player::FindFirstChild("leaderstats") != null) {
6
+ return;
7
+ }
8
+
9
+ Folder* leaderstats = new Folder(player);
10
+ leaderstats.Name = "leaderstats";
11
+
12
+ IntValue* coins = new IntValue(leaderstats);
13
+ coins.Name = "Coins";
14
+ coins.Value = 0;
15
+
16
+ IntValue* level = new IntValue(leaderstats);
17
+ level.Name = "Level";
18
+ level.Value = 0;
19
+ }
20
+
21
+ void init() {
22
+ Players* players = GetService<Players>();
23
+ for (Player* player : players::GetPlayers()) {
24
+ CreateLeaderstats(player);
25
+ }
26
+
27
+ players::PlayerAdded::Connect(CreateLeaderstats);
28
+ }
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ #include <clpp/datatypes.clh>
4
+
5
+ struct PlayerDataCurrencies {
6
+ int Coins = 0;
7
+ int Rebirths = 0;
8
+ };
9
+
10
+ struct PlayerDataInventory {
11
+ array<int> HotBar;
12
+ array<int> Storage;
13
+
14
+ int MaxStorage = 90;
15
+ };
16
+
17
+ struct PlayerData {
18
+ PlayerDataCurrencies Currencies;
19
+ PlayerDataInventory Inventory;
20
+ };
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+ #include <clpp/roblox.clh>
3
+
4
+ const int STARTING_COINS = 0;
5
+ const string REMOTE_COINS = "Coins";
6
+ const string LEADERSTATS_FOLDER = "leaderstats";
@@ -0,0 +1,88 @@
1
+ #pragma once
2
+ #include <clpp/roblox.clh>
3
+
4
+ void ShowcaseFeatures(int coins, Player* playerRef) {
5
+ int n = 100;
6
+ float speed = 16.5;
7
+ string name = "Kartz";
8
+ bool isActive = true;
9
+ func callback = []() {};
10
+ (void)speed;
11
+ (void)isActive;
12
+ (void)callback;
13
+
14
+ array<string> names = {"Kartz", "Player1"};
15
+ dictionary<string, int> stats = {
16
+ {"Coins", 100},
17
+ {"Gems", 50}
18
+ };
19
+ (void)names;
20
+ (void)stats;
21
+
22
+ if (coins > 50) {
23
+ post("Enough balance!");
24
+ } else if (coins == 0) {
25
+ warn("No coins!");
26
+ } else {
27
+ report("Balance sync error.");
28
+ }
29
+
30
+ for (int i = 0; i < 10; i++) {
31
+ post("Count: " .: i);
32
+ }
33
+
34
+ n += 1;
35
+
36
+ observable int wallet = 100;
37
+ wallet.OnChange(func [](int newValue) {
38
+ post("Coins changed to: " .: newValue);
39
+ });
40
+
41
+ signal<Player*, int> OnCoinsUpdated;
42
+ OnCoinsUpdated~>Connect(func [](Player* player, int newAmount) {
43
+ post("New coins for " .: player.Name .: ": " .: newAmount);
44
+ });
45
+ OnCoinsUpdated~>Once(func [](Player* player, int newAmount) {
46
+ (void)newAmount;
47
+ post("First coins for " .: player.Name);
48
+ });
49
+ OnCoinsUpdated::Fire(playerRef, wallet);
50
+
51
+ guard (playerRef != null) else {
52
+ warn("Invalid player");
53
+ return;
54
+ }
55
+
56
+ playerRef::GetPropertyChangedSignal("Name")~>Connect(func []() {
57
+ post("Name changed");
58
+ });
59
+
60
+ auto [success, result] = pcall(func []() {
61
+ return 1;
62
+ });
63
+ (void)result;
64
+
65
+ const int moeda = 4;
66
+ match (moeda) {
67
+ int a => post(a),
68
+ _ => post("Not found")
69
+ };
70
+
71
+ if (success) {
72
+ post("Data loaded successfully!");
73
+ }
74
+
75
+ spawn {
76
+ task::wait(2);
77
+ post("Delay finished!");
78
+ };
79
+
80
+ parallel {
81
+ post("desync");
82
+ };
83
+
84
+ match (name) {
85
+ string s => post(s),
86
+ _ => warn("Instance not supported")
87
+ };
88
+ }
package/generated/cli.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.program = exports.init = exports.watch = void 0;
6
+ exports.hasClpp = exports.program = exports.init = exports.watch = void 0;
7
7
  exports.build = build;
8
8
  exports.dispatch = dispatch;
9
9
  const commander_1 = require("commander");
@@ -11,7 +11,10 @@ const promises_1 = __importDefault(require("node:fs/promises"));
11
11
  const node_path_1 = __importDefault(require("node:path"));
12
12
  const package_info_js_1 = require("./package-info.js");
13
13
  const lsp_js_1 = require("./lsp.js");
14
- const preprocess_js_1 = require("./preprocess.js");
14
+ const paths_js_1 = require("./clpp/paths.js");
15
+ const contract_js_1 = require("./clpp/contract.js");
16
+ const runner_js_1 = require("./clpp/runner.js");
17
+ Object.defineProperty(exports, "hasClpp", { enumerable: true, get: function () { return runner_js_1.hasClpp; } });
15
18
  const intellisense_js_1 = require("./intellisense.js");
16
19
  const rojo_mapper_js_1 = require("./utils/rojo-mapper.js");
17
20
  const process_orchestrator_js_1 = require("./utils/process-orchestrator.js");
@@ -23,7 +26,7 @@ const program = new commander_1.Command();
23
26
  exports.program = program;
24
27
  program
25
28
  .name("cluaupp")
26
- .description("Definitive transpiler from C++ subset to structured Luau")
29
+ .description("Cluaupp toolchain — compile CL++ to Luau, Rojo, and CluauppLibs")
27
30
  .version(package_info_js_1.pkg.version, "-v, --version", "print version")
28
31
  .showHelpAfterError()
29
32
  .action(() => {
@@ -44,14 +47,14 @@ program
44
47
  });
45
48
  program
46
49
  .command("build")
47
- .description("Transpila um arquivo, diretório ou projeto C++ para Luau")
50
+ .description("Compile a CL++ file, directory, or project to Luau")
48
51
  .argument("[folder]", "project folder", ".")
49
- .option("-i, --input <path>", "Arquivo ou diretório C++ de entrada")
50
- .option("-o, --output <path>", "Arquivo ou diretório Luau de saída")
51
- .option("-r, --rojo <path>", "Caminho para o default.project.json do Rojo", "./default.project.json")
52
- .option("--strict", "Emitir --!strict")
53
- .option("--format", "Rodar StyLua no output")
54
- .option("--analyze", "Rodar luau-analyze no output")
52
+ .option("-i, --input <path>", "CL++ file or directory")
53
+ .option("-o, --output <path>", "Luau file or directory")
54
+ .option("-r, --rojo <path>", "Path to Rojo default.project.json", "./default.project.json")
55
+ .option("--strict", "Emit --!strict")
56
+ .option("--format", "Run StyLua on output")
57
+ .option("--analyze", "Run luau-analyze on output")
55
58
  .action(async (folder, options) => {
56
59
  if (options.input) {
57
60
  await buildInput(options);
@@ -73,8 +76,8 @@ program
73
76
  .command("watch")
74
77
  .description("rebuild on save")
75
78
  .argument("[folder]", "project folder", ".")
76
- .option("-r, --rojo <path>", "Caminho para o default.project.json do Rojo", "./default.project.json")
77
- .option("--format", "Rodar StyLua no output")
79
+ .option("-r, --rojo <path>", "Path to Rojo default.project.json", "./default.project.json")
80
+ .option("--format", "Run StyLua on output")
78
81
  .action((folder, options) => {
79
82
  try {
80
83
  (0, project_js_1.watch)(node_path_1.default.resolve(process.cwd(), folder), {
@@ -89,7 +92,7 @@ program
89
92
  });
90
93
  program
91
94
  .command("lsp")
92
- .description("Cluaupp subset diagnostics over stdio (JSON-RPC). C++ completion is clangd.")
95
+ .description("Language server stdio (JSON-RPC). Use `clpp install` for CL++ IntelliSense.")
93
96
  .argument("[folder]", "project folder", ".")
94
97
  .action((folder) => {
95
98
  (0, lsp_js_1.start)({ projectRoot: node_path_1.default.resolve(process.cwd(), folder) });
@@ -97,18 +100,32 @@ program
97
100
  program
98
101
  .command("intellisense")
99
102
  .alias("intelisense")
100
- .description("install LLVM clangd and write compile_commands.json")
103
+ .description("Point the editor at CL++ (`clpp install`)")
101
104
  .argument("[folder]", "project folder", ".")
102
105
  .action(async (folder) => {
103
106
  try {
104
107
  const root = node_path_1.default.resolve(process.cwd(), folder);
105
108
  (0, intellisense_js_1.syncEditorSupport)(root, (0, project_js_1.loadConfig)(root));
106
- const installed = await (0, intellisense_js_1.installEditorSupport)();
107
- console.log("cluaupp: compile_commands.json, .clangd, and .vscode updated in", root);
108
- console.log("cluaupp: C++ completion is clangd (include/cluaupp/roblox.hpp)");
109
- if (installed.clangd || installed.llvm) {
110
- console.log("cluaupp: reload Cursor (Ctrl+Shift+P → Developer: Reload Window)");
109
+ await (0, intellisense_js_1.installEditorSupport)();
110
+ console.log("cluaupp: editor associations written in", root);
111
+ console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
112
+ }
113
+ catch (err) {
114
+ console.error(err instanceof Error ? err.message : err);
115
+ process.exit(1);
116
+ }
117
+ });
118
+ program
119
+ .command("language")
120
+ .description("CL++ manifest (`clpp api manifest`)")
121
+ .action(() => {
122
+ try {
123
+ (0, runner_js_1.resolveClppBinary)();
124
+ const version = (0, runner_js_1.clppVersion)();
125
+ if (version) {
126
+ console.log("clpp", version);
111
127
  }
128
+ console.log(JSON.stringify((0, runner_js_1.clppManifest)(), null, "\t"));
112
129
  }
113
130
  catch (err) {
114
131
  console.error(err instanceof Error ? err.message : err);
@@ -129,14 +146,13 @@ async function buildInput(options) {
129
146
  console.error(`[Erro] O caminho de entrada especificado não existe: ${inputPath}`);
130
147
  process.exit(1);
131
148
  }
132
- console.log("🏁 Inicializando Pipeline do Compilador Cluaupp V2...");
133
149
  const mapper = new rojo_mapper_js_1.RojoMapper(node_path_1.default.resolve(options.rojo), node_path_1.default.dirname(inputPath));
134
150
  await mapper.load();
135
151
  const inputs = (await promises_1.default.stat(inputPath)).isDirectory()
136
- ? (0, project_js_1.collectCpp)(inputPath)
152
+ ? (0, paths_js_1.collectSources)(inputPath)
137
153
  : [inputPath];
138
154
  if (inputs.length === 0) {
139
- console.error("no .cpp/.h/.hpp files in", inputPath);
155
+ console.error("no .clpp/.clp/.clh files in", inputPath);
140
156
  process.exit(1);
141
157
  }
142
158
  const outputIsFile = /\.luau$/i.test(outputPath);
@@ -154,7 +170,7 @@ async function buildInput(options) {
154
170
  srcDir: node_path_1.default.dirname(file),
155
171
  includeDirs: [node_path_1.default.dirname(file)],
156
172
  }, mapper);
157
- const dest = outputIsFile ? outputPath : node_path_1.default.join(outputPath, node_path_1.default.basename((0, preprocess_js_1.toLuauPath)(rel)));
173
+ const dest = outputIsFile ? outputPath : node_path_1.default.join(outputPath, node_path_1.default.basename((0, paths_js_1.toLuauPath)(rel)));
158
174
  await promises_1.default.mkdir(node_path_1.default.dirname(dest), { recursive: true });
159
175
  const luau = compiled.files[0]?.contents ?? "";
160
176
  await promises_1.default.writeFile(dest, luau, "utf8");
@@ -167,7 +183,7 @@ async function buildInput(options) {
167
183
  console.log("\nRelatório de Análise Estática do Luau:\n", analysisReport);
168
184
  }
169
185
  }
170
- console.log(`Transpilação concluída! ${file} → ${dest}`);
186
+ console.log(`Compiled ${file} → ${dest}`);
171
187
  }
172
188
  }
173
189
  function build(root, options = {}) {
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /** Stable CL++ ↔ Cluaupp contract. Cluaupp invokes the `clpp` binary. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CLPP_INSTALL_HINT = void 0;
5
+ exports.CLPP_INSTALL_HINT = "Install CL++ and put `clpp` on PATH: https://github.com/KartzRbx/CLPP (`cargo install --path .` then `clpp install`). Override with CLPP_PATH.";
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toLuauPath = exports.siblingHeader = exports.scriptKind = exports.isTaggedScript = exports.isSourceFile = exports.isImplFile = exports.isHeaderFile = exports.isEngineStub = exports.fileStem = exports.emitKind = exports.collectSources = exports.SOURCE_EXTS = exports.shouldSkipInit = exports.clppLuauToGame = exports.resolveClppBinary = exports.hasClpp = exports.clppVersion = exports.clppManifest = exports.compileViaClpp = exports.CLPP_INSTALL_HINT = void 0;
4
+ var contract_js_1 = require("./contract.js");
5
+ Object.defineProperty(exports, "CLPP_INSTALL_HINT", { enumerable: true, get: function () { return contract_js_1.CLPP_INSTALL_HINT; } });
6
+ var runner_js_1 = require("./runner.js");
7
+ Object.defineProperty(exports, "compileViaClpp", { enumerable: true, get: function () { return runner_js_1.compileViaClpp; } });
8
+ Object.defineProperty(exports, "clppManifest", { enumerable: true, get: function () { return runner_js_1.clppManifest; } });
9
+ Object.defineProperty(exports, "clppVersion", { enumerable: true, get: function () { return runner_js_1.clppVersion; } });
10
+ Object.defineProperty(exports, "hasClpp", { enumerable: true, get: function () { return runner_js_1.hasClpp; } });
11
+ Object.defineProperty(exports, "resolveClppBinary", { enumerable: true, get: function () { return runner_js_1.resolveClppBinary; } });
12
+ var postprocess_js_1 = require("./postprocess.js");
13
+ Object.defineProperty(exports, "clppLuauToGame", { enumerable: true, get: function () { return postprocess_js_1.clppLuauToGame; } });
14
+ Object.defineProperty(exports, "shouldSkipInit", { enumerable: true, get: function () { return postprocess_js_1.shouldSkipInit; } });
15
+ var paths_js_1 = require("./paths.js");
16
+ Object.defineProperty(exports, "SOURCE_EXTS", { enumerable: true, get: function () { return paths_js_1.SOURCE_EXTS; } });
17
+ Object.defineProperty(exports, "collectSources", { enumerable: true, get: function () { return paths_js_1.collectSources; } });
18
+ Object.defineProperty(exports, "emitKind", { enumerable: true, get: function () { return paths_js_1.emitKind; } });
19
+ Object.defineProperty(exports, "fileStem", { enumerable: true, get: function () { return paths_js_1.fileStem; } });
20
+ Object.defineProperty(exports, "isEngineStub", { enumerable: true, get: function () { return paths_js_1.isEngineStub; } });
21
+ Object.defineProperty(exports, "isHeaderFile", { enumerable: true, get: function () { return paths_js_1.isHeaderFile; } });
22
+ Object.defineProperty(exports, "isImplFile", { enumerable: true, get: function () { return paths_js_1.isImplFile; } });
23
+ Object.defineProperty(exports, "isSourceFile", { enumerable: true, get: function () { return paths_js_1.isSourceFile; } });
24
+ Object.defineProperty(exports, "isTaggedScript", { enumerable: true, get: function () { return paths_js_1.isTaggedScript; } });
25
+ Object.defineProperty(exports, "scriptKind", { enumerable: true, get: function () { return paths_js_1.scriptKind; } });
26
+ Object.defineProperty(exports, "siblingHeader", { enumerable: true, get: function () { return paths_js_1.siblingHeader; } });
27
+ Object.defineProperty(exports, "toLuauPath", { enumerable: true, get: function () { return paths_js_1.toLuauPath; } });
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SOURCE_EXTS = void 0;
7
+ exports.isSourceFile = isSourceFile;
8
+ exports.isEngineStub = isEngineStub;
9
+ exports.isHeaderFile = isHeaderFile;
10
+ exports.isImplFile = isImplFile;
11
+ exports.toLuauPath = toLuauPath;
12
+ exports.fileStem = fileStem;
13
+ exports.scriptKind = scriptKind;
14
+ exports.emitKind = emitKind;
15
+ exports.isTaggedScript = isTaggedScript;
16
+ exports.siblingHeader = siblingHeader;
17
+ exports.collectSources = collectSources;
18
+ const node_fs_1 = __importDefault(require("node:fs"));
19
+ const node_path_1 = __importDefault(require("node:path"));
20
+ exports.SOURCE_EXTS = [".clpp", ".clp", ".clh"];
21
+ function isSourceFile(fileName) {
22
+ return exports.SOURCE_EXTS.includes(node_path_1.default.extname(fileName).toLowerCase());
23
+ }
24
+ function isEngineStub(filePath) {
25
+ const normalized = filePath.replace(/\\/g, "/").toLowerCase();
26
+ return (normalized.includes("/include/cluaupp/") ||
27
+ normalized.includes("/include/clpp/") ||
28
+ normalized.includes("/include/cluau/") ||
29
+ normalized.includes("/stdlib/") ||
30
+ normalized.endsWith("/roblox.hpp") ||
31
+ normalized.endsWith("/roblox.h") ||
32
+ normalized.endsWith("/roblox.clh"));
33
+ }
34
+ function isHeaderFile(fileName) {
35
+ return node_path_1.default.extname(fileName).toLowerCase() === ".clh";
36
+ }
37
+ function isImplFile(fileName) {
38
+ const ext = node_path_1.default.extname(fileName).toLowerCase();
39
+ return ext === ".clp" || ext === ".clpp";
40
+ }
41
+ function toLuauPath(filePath) {
42
+ return String(filePath).replace(/\.(clpp|clp|clh)$/i, ".luau");
43
+ }
44
+ function fileStem(fileName) {
45
+ let name = node_path_1.default.basename(fileName);
46
+ const lower = name.toLowerCase();
47
+ for (const ext of [".clpp", ".clp", ".clh"]) {
48
+ if (lower.endsWith(ext)) {
49
+ name = name.slice(0, -ext.length);
50
+ break;
51
+ }
52
+ }
53
+ const tagged = name.toLowerCase();
54
+ for (const tag of [".legacy.server", ".legacy.client", ".legacy", ".server", ".client", ".plugin"]) {
55
+ if (tagged.endsWith(tag)) {
56
+ name = name.slice(0, -tag.length);
57
+ break;
58
+ }
59
+ }
60
+ return name;
61
+ }
62
+ function scriptKind(fileName) {
63
+ const name = node_path_1.default.basename(fileName).toLowerCase();
64
+ if (name.endsWith(".clh")) {
65
+ return "header";
66
+ }
67
+ if (name.includes(".legacy.")) {
68
+ return "legacy";
69
+ }
70
+ if (name.includes(".server.")) {
71
+ return "server";
72
+ }
73
+ if (name.includes(".client.")) {
74
+ return "client";
75
+ }
76
+ if (name.includes(".plugin.")) {
77
+ return "plugin";
78
+ }
79
+ return "module";
80
+ }
81
+ function emitKind(fileName) {
82
+ const kind = scriptKind(fileName);
83
+ if (kind === "legacy") {
84
+ return "legacy";
85
+ }
86
+ if (kind === "module" || kind === "header") {
87
+ return "module";
88
+ }
89
+ return "flat";
90
+ }
91
+ function isTaggedScript(fileName) {
92
+ const kind = scriptKind(fileName);
93
+ return kind === "server" || kind === "client" || kind === "plugin" || kind === "legacy";
94
+ }
95
+ function siblingHeader(implPath) {
96
+ if (!implPath || isHeaderFile(implPath)) {
97
+ return null;
98
+ }
99
+ const dir = node_path_1.default.dirname(implPath);
100
+ const stem = fileStem(implPath);
101
+ const candidate = node_path_1.default.join(dir, `${stem}.clh`);
102
+ if (node_fs_1.default.existsSync(candidate)) {
103
+ return candidate;
104
+ }
105
+ return null;
106
+ }
107
+ function collectSources(dir, files = []) {
108
+ if (!node_fs_1.default.existsSync(dir)) {
109
+ return files;
110
+ }
111
+ for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
112
+ const full = node_path_1.default.join(dir, entry.name);
113
+ if (entry.isDirectory()) {
114
+ collectSources(full, files);
115
+ }
116
+ else if (isSourceFile(entry.name)) {
117
+ files.push(full);
118
+ }
119
+ }
120
+ return files;
121
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldSkipInit = shouldSkipInit;
4
+ exports.clppLuauToGame = clppLuauToGame;
5
+ const libs_js_1 = require("../libs.js");
6
+ const paths_js_1 = require("./paths.js");
7
+ function insertAfterHeader(luau, block) {
8
+ const match = String(luau).match(/^(?:--[^\n]*\n)+/);
9
+ if (!match) {
10
+ return `${block}\n${luau}`;
11
+ }
12
+ const insertAt = match[0].length;
13
+ const rest = luau.slice(insertAt).replace(/^\n*/, "\n");
14
+ return `${luau.slice(0, insertAt)}\n${block}\n${rest}`;
15
+ }
16
+ function rewriteClppLibs(luau) {
17
+ return String(luau).replace(/require\(\s*ClppLibs\.([A-Za-z0-9_]+)\s*\)/g, (_all, name) => {
18
+ return (0, libs_js_1.requireCluauppLib)(name);
19
+ });
20
+ }
21
+ function ensureReplicatedStorage(luau) {
22
+ if (!luau.includes("CluauppLibs")) {
23
+ return luau;
24
+ }
25
+ if (/GetService\(\s*"ReplicatedStorage"\s*\)/.test(luau)) {
26
+ return luau;
27
+ }
28
+ return insertAfterHeader(luau, 'const ReplicatedStorage = game:GetService("ReplicatedStorage")');
29
+ }
30
+ function stripInitCall(luau) {
31
+ return String(luau).replace(/\ninit\(\)\s*\n?$/m, "\n");
32
+ }
33
+ function ensureStrict(luau, strict) {
34
+ if (!strict || /^\s*--!strict\b/m.test(luau)) {
35
+ return luau;
36
+ }
37
+ if (luau.startsWith("--")) {
38
+ return `--!strict\n${luau}`;
39
+ }
40
+ return `--!strict\n${luau}`;
41
+ }
42
+ function librarySpecs(names) {
43
+ const specs = [];
44
+ const seen = new Set();
45
+ for (const name of names || []) {
46
+ const spec = libs_js_1.MODULES[name];
47
+ if (!spec || seen.has(spec.bind)) {
48
+ continue;
49
+ }
50
+ seen.add(spec.bind);
51
+ specs.push(spec);
52
+ }
53
+ return specs;
54
+ }
55
+ function missingLibraries(luau, names) {
56
+ return librarySpecs(names).filter((spec) => {
57
+ return !luau.includes(`CluauppLibs.${spec.file}`) && !new RegExp(`\\bconst ${spec.bind}\\b`).test(luau);
58
+ });
59
+ }
60
+ function shouldSkipInit(fileName, hasSiblingHeader) {
61
+ if (!hasSiblingHeader) {
62
+ return false;
63
+ }
64
+ return !(0, paths_js_1.isTaggedScript)(fileName);
65
+ }
66
+ function clppLuauToGame(artifact, options) {
67
+ let luau = rewriteClppLibs(artifact.luau || "");
68
+ luau = ensureReplicatedStorage(luau);
69
+ if (options.skipInit) {
70
+ luau = stripInitCall(luau);
71
+ }
72
+ luau = ensureStrict(luau, options.strict);
73
+ const missing = missingLibraries(luau, artifact.libraries);
74
+ if (missing.length > 0) {
75
+ luau = (0, libs_js_1.insertPreamble)(luau, [], missing, options.outName);
76
+ }
77
+ return luau;
78
+ }