cluaupp 0.2.2 → 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 (129) hide show
  1. package/CHANGELOG.md +14 -75
  2. package/README.md +42 -88
  3. package/docs/README.md +25 -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/cpp-advanced.md +6 -3
  9. package/docs/cpp-types.md +2 -0
  10. package/docs/examples/combat.md +19 -227
  11. package/docs/examples/hud.md +13 -81
  12. package/docs/examples/index.md +9 -16
  13. package/docs/examples/leaderstats.md +44 -115
  14. package/docs/getting-started.md +20 -135
  15. package/docs/intellisense.md +5 -42
  16. package/docs/intro.md +16 -15
  17. package/docs/libraries/dataservice.md +4 -1
  18. package/docs/libraries/index.md +2 -1
  19. package/docs/libraries/more.md +3 -1
  20. package/docs/libraries/ui.md +76 -0
  21. package/docs/migration.md +38 -0
  22. package/docs/oop/file-tags.md +12 -36
  23. package/docs/oop/index.md +18 -11
  24. package/docs/roblox-api.md +4 -56
  25. package/docs/syntax.md +54 -179
  26. package/editors/vscode/extension.js +1 -1
  27. package/editors/vscode/package.json +4 -4
  28. package/examples/README.md +5 -7
  29. package/examples/game/.vscode/extensions.json +2 -2
  30. package/examples/game/.vscode/settings.json +6 -23
  31. package/examples/game/src/client/hud.client.clpp +54 -0
  32. package/examples/game/src/client/init.client.clpp +6 -0
  33. package/examples/game/src/server/combat.server.clpp +85 -0
  34. package/examples/game/src/server/leaderstats.server.clpp +28 -0
  35. package/examples/game/src/shared/PlayerData.clh +20 -0
  36. package/examples/game/src/shared/config.clp +6 -0
  37. package/examples/game/src/shared/features.clp +88 -0
  38. package/generated/api.js +15 -1
  39. package/generated/cli.js +40 -24
  40. package/generated/clpp/contract.js +5 -0
  41. package/generated/clpp/index.js +27 -0
  42. package/generated/clpp/paths.js +121 -0
  43. package/generated/clpp/postprocess.js +78 -0
  44. package/generated/clpp/runner.js +102 -0
  45. package/generated/compile.js +26 -138
  46. package/generated/emit.js +79 -3
  47. package/generated/intellisense.js +83 -207
  48. package/generated/lex.js +3 -0
  49. package/generated/libs.js +1 -1
  50. package/generated/lsp.js +1 -8
  51. package/generated/parse.js +119 -24
  52. package/generated/preprocess.js +8 -179
  53. package/generated/system-understander.js +1 -1
  54. package/generated/transpile.js +3 -50
  55. package/generated/utils/project.js +13 -28
  56. package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +5 -1
  57. package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
  58. package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
  59. package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
  60. package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
  61. package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
  62. package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
  63. package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
  64. package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
  65. package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
  66. package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
  67. package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
  68. package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
  69. package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
  70. package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
  71. package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
  72. package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
  73. package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
  74. package/include/clpp/libs.clh +24 -0
  75. package/include/clpp/roblox.clh +31 -0
  76. package/package.json +20 -16
  77. package/src/api.ts +15 -1
  78. package/src/cli.ts +39 -25
  79. package/src/clpp/contract.ts +39 -0
  80. package/src/clpp/index.ts +18 -0
  81. package/src/clpp/paths.ts +117 -0
  82. package/src/clpp/postprocess.ts +93 -0
  83. package/src/clpp/runner.ts +102 -0
  84. package/src/compile.ts +26 -149
  85. package/src/intellisense.ts +82 -211
  86. package/src/libs.ts +1 -1
  87. package/src/lsp.ts +1 -5
  88. package/src/preprocess.ts +8 -180
  89. package/src/system-understander.ts +1 -1
  90. package/src/transpile.ts +9 -52
  91. package/src/utils/project.ts +12 -28
  92. package/templates/game/.vscode/extensions.json +2 -2
  93. package/templates/game/.vscode/settings.json +6 -23
  94. package/templates/game/src/client/init.client.clpp +6 -0
  95. package/templates/game/src/server/leaderstats.server.clpp +29 -0
  96. package/templates/game/src/shared/config.clp +6 -0
  97. package/examples/game/.clangd +0 -25
  98. package/examples/game/.vscode/c_cpp_properties.json +0 -27
  99. package/examples/game/compile_flags.txt +0 -6
  100. package/examples/game/src/client/hud.client.cpp +0 -12
  101. package/examples/game/src/client/init.client.cpp +0 -6
  102. package/examples/game/src/server/combat.server.cpp +0 -23
  103. package/examples/game/src/server/leaderstats.server.cpp +0 -29
  104. package/examples/game/src/shared/config.cpp +0 -5
  105. package/examples/game/src/shared/config.h +0 -5
  106. package/include/cluaupp/libs.hpp +0 -25
  107. package/include/cluaupp/roblox.hpp +0 -47
  108. package/src/architecture.ts +0 -500
  109. package/src/ast.ts +0 -37
  110. package/src/emit.ts +0 -531
  111. package/src/emitter/luau-codegen.ts +0 -187
  112. package/src/emitter/translators.ts +0 -168
  113. package/src/headers.ts +0 -233
  114. package/src/layout.ts +0 -114
  115. package/src/lex.ts +0 -155
  116. package/src/parse.ts +0 -630
  117. package/src/parser/collector.ts +0 -148
  118. package/src/parser/index.ts +0 -27
  119. package/src/tree-sitter-cpp.d.ts +0 -4
  120. package/src/understand.ts +0 -322
  121. package/templates/game/.vscode/c_cpp_properties.json +0 -27
  122. package/templates/game/src/client/init.client.cpp +0 -6
  123. package/templates/game/src/server/leaderstats.server.cpp +0 -29
  124. package/templates/game/src/shared/config.cpp +0 -5
  125. package/templates/game/src/shared/config.h +0 -5
  126. /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
  127. /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
  128. /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
  129. /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
package/generated/lex.js CHANGED
@@ -33,6 +33,9 @@ const KEYWORDS = new Set([
33
33
  "case",
34
34
  "default",
35
35
  "break",
36
+ "static",
37
+ "constexpr",
38
+ "inline",
36
39
  ]);
37
40
  function tokenize(source) {
38
41
  const tokens = [];
package/generated/libs.js CHANGED
@@ -259,7 +259,7 @@ function walk(node, visit) {
259
259
  function modulesFromIncludes(source) {
260
260
  const found = new Set();
261
261
  for (const line of String(source).split(/\r?\n/)) {
262
- const match = line.match(/^\s*#\s*include\s+<cluaupp\/(?:libs\/)?([A-Za-z0-9]+)\.hpp>/);
262
+ const match = line.match(/^\s*#\s*include\s+<(?:clpp|cluaupp)\/(?:libs\/)?([A-Za-z0-9]+)\.(?:clh|hpp)>/);
263
263
  if (!match) {
264
264
  continue;
265
265
  }
package/generated/lsp.js CHANGED
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.start = start;
7
- const node_path_1 = __importDefault(require("node:path"));
8
4
  const node_1 = require("vscode-languageserver/node");
9
5
  const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
10
6
  const intellisense_js_1 = require("./intellisense.js");
@@ -28,10 +24,7 @@ function start(options = {}) {
28
24
  }));
29
25
  const publish = (document) => {
30
26
  const file = uriPath(document.uri);
31
- const items = (0, intellisense_js_1.diagnosticsFor)(document.getText(), file, {
32
- filePath: file,
33
- includeDirs: [node_path_1.default.dirname(file), node_path_1.default.join(projectRoot, "src"), node_path_1.default.join(projectRoot, "include")],
34
- });
27
+ const items = (0, intellisense_js_1.diagnosticsFor)(document.getText(), file);
35
28
  connection.sendDiagnostics({
36
29
  uri: document.uri,
37
30
  diagnostics: items.map((item) => ({
@@ -46,21 +46,124 @@ function parse(source, fileName) {
46
46
  eat("op", ">");
47
47
  return name;
48
48
  };
49
+ const CAST_NAMES = new Set(["static_cast", "const_cast", "reinterpret_cast", "dynamic_cast"]);
50
+ function skipSpecifiers() {
51
+ let isConst = false;
52
+ while (at("kw", "static") || at("kw", "inline") || at("kw", "constexpr") || at("kw", "const")) {
53
+ if (at("kw", "constexpr") || at("kw", "const")) {
54
+ isConst = true;
55
+ }
56
+ i += 1;
57
+ }
58
+ return isConst;
59
+ }
60
+ function looksLikePrimaryStart() {
61
+ if (at("ident") || at("number") || at("string")) {
62
+ return true;
63
+ }
64
+ if (at("kw", "true") || at("kw", "false") || at("kw", "nullptr") || at("kw", "new")) {
65
+ return true;
66
+ }
67
+ return at("op", "(") || at("op", "{") || at("op", "[") || at("op", "-") || at("op", "!");
68
+ }
69
+ function parseLambda() {
70
+ eat("op", "[");
71
+ while (!at("eof") && !at("op", "]")) {
72
+ i += 1;
73
+ }
74
+ eat("op", "]");
75
+ const params = [];
76
+ if (at("op", "(")) {
77
+ i += 1;
78
+ if (!at("op", ")")) {
79
+ params.push(parseParam());
80
+ while (at("op", ",")) {
81
+ i += 1;
82
+ params.push(parseParam());
83
+ }
84
+ }
85
+ eat("op", ")");
86
+ }
87
+ const body = parseBlock();
88
+ return { type: "lambda", params, body };
89
+ }
90
+ function parseNamedCast() {
91
+ i += 1;
92
+ eat("op", "<");
93
+ const valueType = parseType() || "any";
94
+ eat("op", ">");
95
+ const args = parseArgs();
96
+ return { type: "cast", valueType, argument: args[0] || { type: "null" } };
97
+ }
98
+ function parseParenPrimary() {
99
+ eat("op", "(");
100
+ const saved = i;
101
+ skipSpecifiers();
102
+ const valueType = parseType();
103
+ if (valueType && at("op", ")")) {
104
+ i += 1;
105
+ if (looksLikePrimaryStart()) {
106
+ return { type: "cast", valueType, argument: parseUnary() };
107
+ }
108
+ }
109
+ i = saved;
110
+ const expr = parseExpr();
111
+ eat("op", ")");
112
+ return expr;
113
+ }
114
+ function eatGeneric() {
115
+ let text = "";
116
+ let depth = 0;
117
+ while (!at("eof")) {
118
+ const token = peek();
119
+ if (at("op", "<")) {
120
+ depth += 1;
121
+ text += "<";
122
+ i += 1;
123
+ continue;
124
+ }
125
+ if (at("op", ">")) {
126
+ depth -= 1;
127
+ text += ">";
128
+ i += 1;
129
+ if (depth === 0) {
130
+ return text;
131
+ }
132
+ continue;
133
+ }
134
+ if (token.type === "string") {
135
+ text += `"${token.value}"`;
136
+ }
137
+ else {
138
+ text += token.value;
139
+ }
140
+ i += 1;
141
+ }
142
+ return text;
143
+ }
49
144
  function parseType() {
50
145
  if (at("kw", "const")) {
51
146
  i += 1;
52
147
  }
148
+ let name = null;
53
149
  if (at("kw", "auto") || at("kw", "void") || at("kw", "int") || at("kw", "bool") || at("kw", "float") || at("kw", "double")) {
54
- const name = eat("kw").value;
55
- while (at("op", "*")) {
150
+ name = eat("kw").value;
151
+ }
152
+ else if (at("ident")) {
153
+ name = eat("ident").value;
154
+ while (at("op", "::")) {
56
155
  i += 1;
156
+ if (at("ident")) {
157
+ name += `::${eat("ident").value}`;
158
+ }
57
159
  }
58
- return name;
59
160
  }
60
- if (!at("ident")) {
161
+ else {
61
162
  return null;
62
163
  }
63
- const name = eat("ident").value;
164
+ if (at("op", "<")) {
165
+ name += eatGeneric();
166
+ }
64
167
  while (at("op", "*")) {
65
168
  i += 1;
66
169
  }
@@ -129,14 +232,17 @@ function parse(source, fileName) {
129
232
  eat("op", ")");
130
233
  return { type: "getService", service };
131
234
  }
235
+ if (at("ident") && CAST_NAMES.has(peek().value) && peek(1).value === "<") {
236
+ return parseNamedCast();
237
+ }
132
238
  if (at("ident")) {
133
239
  return { type: "ident", name: eat("ident").value };
134
240
  }
241
+ if (at("op", "[")) {
242
+ return parseLambda();
243
+ }
135
244
  if (at("op", "(")) {
136
- i += 1;
137
- const expr = parseExpr();
138
- eat("op", ")");
139
- return expr;
245
+ return parseParenPrimary();
140
246
  }
141
247
  if (at("op", "{")) {
142
248
  return parseInitList();
@@ -309,11 +415,8 @@ function parse(source, fileName) {
309
415
  throw error("only range-for is supported: for (auto* x : list)");
310
416
  }
311
417
  function parseDeclOrExpr() {
312
- const isConst = at("kw", "const");
313
- if (isConst) {
314
- i += 1;
315
- }
316
418
  const saved = i;
419
+ const isConst = skipSpecifiers();
317
420
  const maybeType = parseType();
318
421
  if (maybeType && at("ident") && (peek(1).value === "=" || peek(1).value === ";")) {
319
422
  const name = eat("ident").value;
@@ -325,9 +428,6 @@ function parse(source, fileName) {
325
428
  return { type: "decl", name, valueType: maybeType, value, isConst: isConst || maybeType === "const" };
326
429
  }
327
430
  i = saved;
328
- if (isConst) {
329
- i = saved - 1;
330
- }
331
431
  return { type: "expr", expr: parseExpr() };
332
432
  }
333
433
  function parseStmt() {
@@ -380,6 +480,7 @@ function parse(source, fileName) {
380
480
  };
381
481
  }
382
482
  function parseFunction() {
483
+ skipSpecifiers();
383
484
  const returnType = parseType();
384
485
  if (!returnType || !at("ident")) {
385
486
  throw error("invalid function declaration");
@@ -449,10 +550,7 @@ function parse(source, fileName) {
449
550
  continue;
450
551
  }
451
552
  const saved = i;
452
- const isConst = at("kw", "const");
453
- if (isConst) {
454
- i += 1;
455
- }
553
+ const isConst = skipSpecifiers();
456
554
  const valueType = parseType();
457
555
  if (valueType && at("ident")) {
458
556
  if (peek(1).value === "(") {
@@ -573,10 +671,7 @@ function parse(source, fileName) {
573
671
  continue;
574
672
  }
575
673
  const saved = i;
576
- const isConst = at("kw", "const");
577
- if (isConst) {
578
- i += 1;
579
- }
674
+ const isConst = skipSpecifiers();
580
675
  const maybeType = parseType();
581
676
  if (maybeType && at("ident")) {
582
677
  const next = peek(1);
@@ -1,181 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SOURCE_EXTS = void 0;
7
- exports.isSourceFile = isSourceFile;
8
- exports.isHeaderFile = isHeaderFile;
9
- exports.toLuauPath = toLuauPath;
10
- exports.isEngineStub = isEngineStub;
11
- exports.siblingImplementation = siblingImplementation;
12
- exports.siblingHeader = siblingHeader;
13
- exports.implOutName = implOutName;
14
- exports.resolveInclude = resolveInclude;
15
- exports.scanHeaderExports = scanHeaderExports;
16
- exports.applyPragmas = applyPragmas;
17
- exports.preprocess = preprocess;
18
- const node_fs_1 = __importDefault(require("node:fs"));
19
- const node_path_1 = __importDefault(require("node:path"));
20
- exports.SOURCE_EXTS = [".cpp", ".cc", ".cxx", ".c", ".h", ".hpp", ".hh"];
21
- function isSourceFile(fileName) {
22
- return exports.SOURCE_EXTS.includes(node_path_1.default.extname(fileName).toLowerCase());
23
- }
24
- function isHeaderFile(fileName) {
25
- return [".h", ".hpp", ".hh"].includes(node_path_1.default.extname(fileName).toLowerCase());
26
- }
27
- function toLuauPath(filePath) {
28
- return filePath.replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, ".luau");
29
- }
30
- function isEngineStub(filePath) {
31
- const normalized = filePath.replace(/\\/g, "/").toLowerCase();
32
- return (normalized.includes("/include/cluaupp/") ||
33
- normalized.includes("/include/cluau/") ||
34
- normalized.endsWith("/roblox.hpp") ||
35
- normalized.endsWith("/roblox.h"));
36
- }
37
- function includeVariants(name) {
38
- const variants = [name];
39
- if (/\.h$/i.test(name)) {
40
- variants.push(name.replace(/\.h$/i, ".hpp"), name.replace(/\.h$/i, ".hh"));
41
- }
42
- else if (/\.hpp$/i.test(name)) {
43
- variants.push(name.replace(/\.hpp$/i, ".h"), name.replace(/\.hpp$/i, ".hh"));
44
- }
45
- else if (/\.hh$/i.test(name)) {
46
- variants.push(name.replace(/\.hh$/i, ".h"), name.replace(/\.hh$/i, ".hpp"));
47
- }
48
- return [...new Set(variants)];
49
- }
50
- function siblingImplementation(headerPath) {
51
- if (!headerPath || !isHeaderFile(headerPath)) {
52
- return null;
53
- }
54
- const base = headerPath.replace(/\.(h|hpp|hh)$/i, "");
55
- for (const ext of [".cpp", ".cc", ".cxx", ".c"]) {
56
- if (node_fs_1.default.existsSync(base + ext)) {
57
- return base + ext;
58
- }
59
- }
60
- return null;
61
- }
62
- function siblingHeader(implPath) {
63
- if (!implPath || isHeaderFile(implPath)) {
64
- return null;
65
- }
66
- const base = String(implPath).replace(/\.(cpp|cc|cxx|c)$/i, "");
67
- if (base === String(implPath)) {
68
- return null;
69
- }
70
- for (const ext of [".h", ".hpp", ".hh"]) {
71
- if (node_fs_1.default.existsSync(base + ext)) {
72
- return base + ext;
73
- }
74
- }
75
- return null;
76
- }
77
- function implOutName(rel) {
78
- return String(rel)
79
- .replace(/\\/g, "/")
80
- .replace(/\.(cpp|cc|cxx|c)$/i, "Impl.luau");
81
- }
82
- function resolveInclude(name, fromFile, includeDirs) {
83
- const bases = [node_path_1.default.dirname(fromFile), ...(includeDirs || [])];
84
- for (const base of bases) {
85
- for (const variant of includeVariants(name)) {
86
- const candidate = node_path_1.default.resolve(base, variant);
87
- if (node_fs_1.default.existsSync(candidate) && node_fs_1.default.statSync(candidate).isFile()) {
88
- return candidate;
89
- }
90
- }
91
- }
92
- return null;
93
- }
94
- function scanHeaderExports(source) {
95
- const consts = [];
96
- const structs = [];
97
- for (const match of String(source).matchAll(/\bconst\s+(?:int|bool|float|double|auto|string)\s+(\w+)/g)) {
98
- if (!consts.includes(match[1])) {
99
- consts.push(match[1]);
100
- }
101
- }
102
- for (const match of String(source).matchAll(/\bstruct\s+(\w+)/g)) {
103
- if (!structs.includes(match[1])) {
104
- structs.push(match[1]);
105
- }
106
- }
107
- const hasProtos = /\b(?:void|int|bool|float|double|auto|string|[\w:]+)\s+\w+\s*\([^;]*\)\s*;/.test(String(source));
108
- return { consts, structs, hasProtos };
109
- }
110
- function pushModuleInclude(options, resolved, impl) {
111
- options.moduleIncludes = options.moduleIncludes || [];
112
- const srcDir = options.srcDir || null;
113
- const moduleFile = impl || resolved;
114
- const rel = srcDir ? node_path_1.default.relative(srcDir, moduleFile).replace(/\\/g, "/") : node_path_1.default.basename(moduleFile);
115
- const headerText = node_fs_1.default.readFileSync(resolved, "utf8");
116
- options.moduleIncludes.push({
117
- name: node_path_1.default.basename(resolved).replace(/\.(h|hpp|hh)$/i, ""),
118
- outRel: rel.replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, ".luau"),
119
- header: resolved,
120
- impl: impl || null,
121
- exports: scanHeaderExports(headerText),
122
- });
123
- }
124
- function applyPragmas(source, options) {
125
- let nstrict = false;
126
- let strict = false;
127
- for (const line of String(source).split(/\r?\n/)) {
128
- if (/^\s*#\s*pragma\s+nstrict\b/i.test(line)) {
129
- nstrict = true;
130
- }
131
- else if (/^\s*#\s*pragma\s+strict\b/i.test(line)) {
132
- strict = true;
133
- }
134
- }
135
- if (nstrict) {
136
- options.strict = false;
137
- }
138
- else if (strict) {
139
- options.strict = true;
140
- }
141
- }
142
- function preprocess(source, filePath, options = {}) {
143
- if (!options.pragmaResolved) {
144
- options.pragmaResolved = true;
145
- applyPragmas(source, options);
146
- }
147
- const seen = options.seen || new Set();
148
- options.seen = seen;
149
- const includeDirs = options.includeDirs || [];
150
- const resolvedSelf = filePath ? node_path_1.default.resolve(filePath) : null;
151
- if (resolvedSelf) {
152
- seen.add(resolvedSelf);
153
- }
154
- const lines = String(source).split(/\r?\n/);
155
- const out = [];
156
- for (const line of lines) {
157
- const quoted = line.match(/^\s*#\s*include\s+"([^"]+)"/);
158
- if (quoted) {
159
- const resolved = resolveInclude(quoted[1], filePath || process.cwd(), includeDirs);
160
- if (!resolved || isEngineStub(resolved) || seen.has(resolved)) {
161
- continue;
162
- }
163
- const impl = siblingImplementation(resolved);
164
- const including = filePath ? node_path_1.default.resolve(filePath) : null;
165
- const ownHeader = Boolean(impl && including && node_path_1.default.resolve(impl) === including);
166
- if (!ownHeader) {
167
- pushModuleInclude(options, resolved, impl);
168
- continue;
169
- }
170
- seen.add(resolved);
171
- const inner = node_fs_1.default.readFileSync(resolved, "utf8");
172
- out.push(preprocess(inner, resolved, { ...options, seen }));
173
- continue;
174
- }
175
- if (/^\s*#\s*include\s+</.test(line)) {
176
- continue;
177
- }
178
- out.push(line);
179
- }
180
- return out.join("\n");
181
- }
3
+ exports.siblingHeader = exports.toLuauPath = exports.isEngineStub = exports.isHeaderFile = exports.isSourceFile = exports.SOURCE_EXTS = void 0;
4
+ var paths_js_1 = require("./clpp/paths.js");
5
+ Object.defineProperty(exports, "SOURCE_EXTS", { enumerable: true, get: function () { return paths_js_1.SOURCE_EXTS; } });
6
+ Object.defineProperty(exports, "isSourceFile", { enumerable: true, get: function () { return paths_js_1.isSourceFile; } });
7
+ Object.defineProperty(exports, "isHeaderFile", { enumerable: true, get: function () { return paths_js_1.isHeaderFile; } });
8
+ Object.defineProperty(exports, "isEngineStub", { enumerable: true, get: function () { return paths_js_1.isEngineStub; } });
9
+ Object.defineProperty(exports, "toLuauPath", { enumerable: true, get: function () { return paths_js_1.toLuauPath; } });
10
+ Object.defineProperty(exports, "siblingHeader", { enumerable: true, get: function () { return paths_js_1.siblingHeader; } });
@@ -11,7 +11,7 @@ exports.scoreIntents = scoreIntents;
11
11
  exports.determineArchitecture = determineArchitecture;
12
12
  exports.understandSystem = understandSystem;
13
13
  const node_path_1 = __importDefault(require("node:path"));
14
- const EXT = "(cpp|cc|cxx|c|h|hpp|hh)";
14
+ const EXT = "(clpp|clp|clh)";
15
15
  const EXT_REGEX = new RegExp(`\\.${EXT}$`, "i");
16
16
  const SCORE_THRESHOLD = 2;
17
17
  const TREE_NAME_TYPES = new Set([
@@ -3,64 +3,17 @@ 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.collectState = collectState;
7
6
  exports.transpileSource = transpileSource;
8
7
  exports.outputNameFor = outputNameFor;
9
8
  const node_path_1 = __importDefault(require("node:path"));
10
- const collector_js_1 = require("./parser/collector.js");
11
- const index_js_1 = require("./parser/index.js");
12
- const luau_codegen_js_1 = require("./emitter/luau-codegen.js");
13
9
  const compile_js_1 = require("./compile.js");
14
- const system_understander_js_1 = require("./system-understander.js");
15
- function shouldMerge(name, contents) {
16
- const file = String(name || "").replace(/\\/g, "/");
17
- if (/\.json$/i.test(file) || /\.meta\.json$/i.test(file)) {
18
- return false;
19
- }
20
- const trimmed = String(contents || "").trim();
21
- return !(trimmed.startsWith("{") || trimmed.startsWith("["));
22
- }
23
- function collectState(source, mapper, options) {
24
- const tree = (0, index_js_1.parseCpp)(source);
25
- if (!tree) {
26
- const state = luau_codegen_js_1.LuauCodeEmitter.emptyState(options.strict === true);
27
- return state;
28
- }
29
- const collector = new collector_js_1.ASTCollector(mapper, {
30
- fileName: options.relativeName || options.filePath || "input.cpp",
31
- sourcePath: options.filePath,
32
- srcDir: options.srcDir,
33
- outDir: options.outDir,
34
- strict: options.strict,
35
- });
36
- const state = collector.collect(tree.rootNode);
37
- const report = (0, system_understander_js_1.determineArchitecture)(options.relativeName || options.filePath || "input.cpp", null, tree.rootNode);
38
- for (const service of report.injectedServices) {
39
- state.robloxServices.add(service);
40
- }
41
- for (const line of report.reasoning) {
42
- state.headerLines.push(`-- ${line}`);
43
- }
44
- return state;
45
- }
46
- function transpileSource(source, fileName, options, mapper) {
47
- const state = collectState(source, mapper, options);
48
- if (state.strict) {
49
- options.strict = true;
50
- }
51
- const compiled = (0, compile_js_1.compileService)(source, fileName, options);
52
- return {
53
- ...compiled,
54
- files: compiled.files.map((file) => ({
55
- ...file,
56
- contents: shouldMerge(file.name, file.contents) ? luau_codegen_js_1.LuauCodeEmitter.merge(state, file.contents) : file.contents,
57
- })),
58
- };
10
+ function transpileSource(source, fileName, options, _mapper) {
11
+ return (0, compile_js_1.compileService)(source, fileName, options);
59
12
  }
60
13
  function outputNameFor(inputFile, outputPath) {
61
14
  if (/\.luau$/i.test(outputPath)) {
62
15
  return outputPath;
63
16
  }
64
- const base = node_path_1.default.basename(inputFile).replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, ".luau");
17
+ const base = node_path_1.default.basename(inputFile).replace(/\.(clpp|clp|clh)$/i, ".luau");
65
18
  return node_path_1.default.join(outputPath, base);
66
19
  }
@@ -3,6 +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.collectSourcesFiles = void 0;
6
7
  exports.loadConfig = loadConfig;
7
8
  exports.collectCpp = collectCpp;
8
9
  exports.build = build;
@@ -11,7 +12,7 @@ exports.watch = watch;
11
12
  const node_fs_1 = __importDefault(require("node:fs"));
12
13
  const node_path_1 = __importDefault(require("node:path"));
13
14
  const package_info_js_1 = require("../package-info.js");
14
- const preprocess_js_1 = require("../preprocess.js");
15
+ const paths_js_1 = require("../clpp/paths.js");
15
16
  const intellisense_js_1 = require("../intellisense.js");
16
17
  const process_orchestrator_js_1 = require("./process-orchestrator.js");
17
18
  const rojo_mapper_js_1 = require("./rojo-mapper.js");
@@ -142,27 +143,16 @@ function copyRuntime(dest) {
142
143
  syncDir(runtime, node_path_1.default.join(dest, "libs"));
143
144
  }
144
145
  function copyHeaders(dest) {
145
- const from = node_path_1.default.join(__dirname, "..", "..", "include", "cluaupp");
146
+ const from = node_path_1.default.join(__dirname, "..", "..", "include", "clpp");
146
147
  if (!node_fs_1.default.existsSync(from)) {
147
148
  return;
148
149
  }
149
- syncDir(from, node_path_1.default.join(dest, "include", "cluaupp"));
150
+ syncDir(from, node_path_1.default.join(dest, "include", "clpp"));
150
151
  }
151
152
  function collectCpp(dir, files = []) {
152
- if (!node_fs_1.default.existsSync(dir)) {
153
- return files;
154
- }
155
- for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
156
- const full = node_path_1.default.join(dir, entry.name);
157
- if (entry.isDirectory()) {
158
- collectCpp(full, files);
159
- }
160
- else if ((0, preprocess_js_1.isSourceFile)(entry.name)) {
161
- files.push(full);
162
- }
163
- }
164
- return files;
153
+ return (0, paths_js_1.collectSources)(dir, files);
165
154
  }
155
+ exports.collectSourcesFiles = paths_js_1.collectSources;
166
156
  function collectFiles(dir, files = []) {
167
157
  if (!node_fs_1.default.existsSync(dir)) {
168
158
  return files;
@@ -186,9 +176,9 @@ function posixRel(from, file) {
186
176
  return node_path_1.default.relative(from, file).replace(/\\/g, "/");
187
177
  }
188
178
  function sourcePrefixes(rel) {
189
- const noExt = rel.replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, "");
179
+ const noExt = rel.replace(/\.(clpp|clp|clh)$/i, "");
190
180
  const noTag = noExt.replace(/\.(server|client)$/i, "");
191
- return [...new Set([noExt, noTag, (0, preprocess_js_1.toLuauPath)(rel).replace(/\\/g, "/")])];
181
+ return [...new Set([noExt, noTag, (0, paths_js_1.toLuauPath)(rel).replace(/\\/g, "/")])];
192
182
  }
193
183
  function matchesPrefix(relOut, prefixes) {
194
184
  const n = relOut.replace(/\\/g, "/").toLowerCase();
@@ -253,7 +243,7 @@ function createMapper(root, config, rojoPath) {
253
243
  }
254
244
  function compileProject(root, config, mapper) {
255
245
  const srcDir = node_path_1.default.join(root, config.rootDir);
256
- const files = collectCpp(srcDir);
246
+ const files = (0, paths_js_1.collectSources)(srcDir);
257
247
  const jobs = [];
258
248
  const errors = [];
259
249
  for (const file of files) {
@@ -264,7 +254,7 @@ function compileProject(root, config, mapper) {
264
254
  ...config,
265
255
  filePath: file,
266
256
  relativeName: rel,
267
- outName: (0, preprocess_js_1.toLuauPath)(rel),
257
+ outName: (0, paths_js_1.toLuauPath)(rel),
268
258
  architecture: config.architecture === true,
269
259
  includeDirs: [node_path_1.default.dirname(file), srcDir, node_path_1.default.join(root, "include")],
270
260
  srcDir,
@@ -341,8 +331,8 @@ function build(root, options = {}) {
341
331
  ensureVendor(root);
342
332
  }
343
333
  const srcDir = node_path_1.default.join(root, config.rootDir);
344
- if (!node_fs_1.default.existsSync(srcDir) || collectCpp(srcDir).length === 0) {
345
- console.error("no .cpp/.h/.hpp files in", config.rootDir);
334
+ if (!node_fs_1.default.existsSync(srcDir) || (0, paths_js_1.collectSources)(srcDir).length === 0) {
335
+ console.error("no .clpp/.clp/.clh files in", config.rootDir);
346
336
  if (!holdOnError) {
347
337
  pruneOut(root, config, new Set(), []);
348
338
  }
@@ -400,16 +390,11 @@ async function init(dest) {
400
390
  copyDir(include, node_path_1.default.join(target, "include"));
401
391
  copyRuntime(target);
402
392
  (0, intellisense_js_1.syncEditorSupport)(target);
403
- const installed = await (0, intellisense_js_1.installEditorSupport)();
404
393
  console.log("Cluaupp ready in", target);
394
+ console.log(" clpp install (CL++ highlighting + IntelliSense)");
405
395
  console.log(" rokit install");
406
396
  console.log(" cluaupp build");
407
397
  console.log(" rojo serve");
408
- if (installed.local.length ||
409
- (installed.clangd && (installed.clangd.status === "installed" || installed.clangd.status === "already")) ||
410
- (installed.llvm && (installed.llvm.status === "installed" || installed.llvm.status === "already"))) {
411
- console.log(" reload Cursor (Ctrl+Shift+P → Developer: Reload Window)");
412
- }
413
398
  }
414
399
  function pidAlive(pid) {
415
400
  try {
@@ -1,5 +1,5 @@
1
1
  #pragma once
2
- #include <cluaupp/generated/enums.hpp>
2
+ #include <clpp/generated/enums.clh>
3
3
  using Enum::EasingStyle;
4
4
  using Enum::EasingDirection;
5
5
  using Enum::Material;
@@ -17,6 +17,10 @@ using Enum::Axis;
17
17
 
18
18
  using string = const char*;
19
19
 
20
+ // Variadic join. Cluaupp emits Luau a .. b .. c.
21
+ template <typename... Args>
22
+ string string_concat(Args... args);
23
+
20
24
  struct Instance;
21
25
  struct Player;
22
26
 
@@ -1,5 +1,5 @@
1
1
  #pragma once
2
- #include <cluaupp/datatypes.hpp>
2
+ #include <clpp/datatypes.clh>
3
3
 
4
4
  struct Object;
5
5
  struct AnimatedImageTrack;
@@ -1,15 +1,15 @@
1
1
  #pragma once
2
2
 
3
3
  // Parihsz/Chrono — custom character replication, vendored into CluauppLibs.Chrono
4
- class ChronoHolder {};
5
- class ChronoEntity {};
6
- class ChronoStats {};
7
- class ChronoConfig {};
8
- class ChronoReplicationRules {};
9
- class ChronoEvents {};
10
- class ChronoSnapshots {};
11
- class ChronoServerClock {};
12
- class ChronoPlayer {};
4
+ struct ChronoHolder {};
5
+ struct ChronoEntity {};
6
+ struct ChronoStats {};
7
+ struct ChronoConfig {};
8
+ struct ChronoReplicationRules {};
9
+ struct ChronoEvents {};
10
+ struct ChronoSnapshots {};
11
+ struct ChronoServerClock {};
12
+ struct ChronoPlayer {};
13
13
 
14
14
  namespace Chrono {
15
15
  void Start();