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.
- package/CHANGELOG.md +14 -75
- package/README.md +42 -88
- package/docs/README.md +25 -21
- package/docs/architecture.md +13 -76
- package/docs/cli.md +12 -64
- package/docs/comparison.md +6 -24
- package/docs/config.md +6 -7
- package/docs/cpp-advanced.md +6 -3
- package/docs/cpp-types.md +2 -0
- package/docs/examples/combat.md +19 -227
- package/docs/examples/hud.md +13 -81
- package/docs/examples/index.md +9 -16
- package/docs/examples/leaderstats.md +44 -115
- package/docs/getting-started.md +20 -135
- package/docs/intellisense.md +5 -42
- package/docs/intro.md +16 -15
- package/docs/libraries/dataservice.md +4 -1
- package/docs/libraries/index.md +2 -1
- package/docs/libraries/more.md +3 -1
- package/docs/libraries/ui.md +76 -0
- package/docs/migration.md +38 -0
- package/docs/oop/file-tags.md +12 -36
- package/docs/oop/index.md +18 -11
- package/docs/roblox-api.md +4 -56
- package/docs/syntax.md +54 -179
- package/editors/vscode/extension.js +1 -1
- package/editors/vscode/package.json +4 -4
- package/examples/README.md +5 -7
- package/examples/game/.vscode/extensions.json +2 -2
- package/examples/game/.vscode/settings.json +6 -23
- package/examples/game/src/client/hud.client.clpp +54 -0
- package/examples/game/src/client/init.client.clpp +6 -0
- package/examples/game/src/server/combat.server.clpp +85 -0
- package/examples/game/src/server/leaderstats.server.clpp +28 -0
- package/examples/game/src/shared/PlayerData.clh +20 -0
- package/examples/game/src/shared/config.clp +6 -0
- package/examples/game/src/shared/features.clp +88 -0
- package/generated/api.js +15 -1
- package/generated/cli.js +40 -24
- package/generated/clpp/contract.js +5 -0
- package/generated/clpp/index.js +27 -0
- package/generated/clpp/paths.js +121 -0
- package/generated/clpp/postprocess.js +78 -0
- package/generated/clpp/runner.js +102 -0
- package/generated/compile.js +26 -138
- package/generated/emit.js +79 -3
- package/generated/intellisense.js +83 -207
- package/generated/lex.js +3 -0
- package/generated/libs.js +1 -1
- package/generated/lsp.js +1 -8
- package/generated/parse.js +119 -24
- package/generated/preprocess.js +8 -179
- package/generated/system-understander.js +1 -1
- package/generated/transpile.js +3 -50
- package/generated/utils/project.js +13 -28
- package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +5 -1
- package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
- package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
- package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
- package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
- package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
- package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
- package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
- package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
- package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
- package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
- package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
- package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
- package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
- package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
- package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
- package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
- package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
- package/include/clpp/libs.clh +24 -0
- package/include/clpp/roblox.clh +31 -0
- package/package.json +20 -16
- package/src/api.ts +15 -1
- package/src/cli.ts +39 -25
- package/src/clpp/contract.ts +39 -0
- package/src/clpp/index.ts +18 -0
- package/src/clpp/paths.ts +117 -0
- package/src/clpp/postprocess.ts +93 -0
- package/src/clpp/runner.ts +102 -0
- package/src/compile.ts +26 -149
- package/src/intellisense.ts +82 -211
- package/src/libs.ts +1 -1
- package/src/lsp.ts +1 -5
- package/src/preprocess.ts +8 -180
- package/src/system-understander.ts +1 -1
- package/src/transpile.ts +9 -52
- package/src/utils/project.ts +12 -28
- package/templates/game/.vscode/extensions.json +2 -2
- package/templates/game/.vscode/settings.json +6 -23
- package/templates/game/src/client/init.client.clpp +6 -0
- package/templates/game/src/server/leaderstats.server.clpp +29 -0
- package/templates/game/src/shared/config.clp +6 -0
- package/examples/game/.clangd +0 -25
- package/examples/game/.vscode/c_cpp_properties.json +0 -27
- package/examples/game/compile_flags.txt +0 -6
- package/examples/game/src/client/hud.client.cpp +0 -12
- package/examples/game/src/client/init.client.cpp +0 -6
- package/examples/game/src/server/combat.server.cpp +0 -23
- package/examples/game/src/server/leaderstats.server.cpp +0 -29
- package/examples/game/src/shared/config.cpp +0 -5
- package/examples/game/src/shared/config.h +0 -5
- package/include/cluaupp/libs.hpp +0 -25
- package/include/cluaupp/roblox.hpp +0 -47
- package/src/architecture.ts +0 -500
- package/src/ast.ts +0 -37
- package/src/emit.ts +0 -531
- package/src/emitter/luau-codegen.ts +0 -187
- package/src/emitter/translators.ts +0 -168
- package/src/headers.ts +0 -233
- package/src/layout.ts +0 -114
- package/src/lex.ts +0 -155
- package/src/parse.ts +0 -630
- package/src/parser/collector.ts +0 -148
- package/src/parser/index.ts +0 -27
- package/src/tree-sitter-cpp.d.ts +0 -4
- package/src/understand.ts +0 -322
- package/templates/game/.vscode/c_cpp_properties.json +0 -27
- package/templates/game/src/client/init.client.cpp +0 -6
- package/templates/game/src/server/leaderstats.server.cpp +0 -29
- package/templates/game/src/shared/config.cpp +0 -5
- package/templates/game/src/shared/config.h +0 -5
- /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
- /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
- /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
- /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
package/generated/lex.js
CHANGED
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) => ({
|
package/generated/parse.js
CHANGED
|
@@ -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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
161
|
+
else {
|
|
61
162
|
return null;
|
|
62
163
|
}
|
|
63
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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);
|
package/generated/preprocess.js
CHANGED
|
@@ -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
|
-
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
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 = "(
|
|
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([
|
package/generated/transpile.js
CHANGED
|
@@ -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
|
-
|
|
15
|
-
|
|
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(/\.(
|
|
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
|
|
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", "
|
|
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", "
|
|
150
|
+
syncDir(from, node_path_1.default.join(dest, "include", "clpp"));
|
|
150
151
|
}
|
|
151
152
|
function collectCpp(dir, files = []) {
|
|
152
|
-
|
|
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(/\.(
|
|
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,
|
|
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 =
|
|
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,
|
|
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) ||
|
|
345
|
-
console.error("no .
|
|
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 <
|
|
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,15 +1,15 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
// Parihsz/Chrono — custom character replication, vendored into CluauppLibs.Chrono
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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();
|