cluaupp 0.1.4 → 0.2.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 +21 -0
- package/README.md +12 -7
- package/bin/cluau.js +1 -1
- package/bin/cluaupp.js +1 -1
- package/docs/README.md +1 -1
- package/docs/architecture.md +52 -77
- package/docs/cli.md +29 -9
- package/docs/comparison.md +3 -3
- package/docs/config.md +6 -6
- package/docs/cpp-organization.md +2 -2
- package/docs/examples/index.md +2 -0
- package/docs/getting-started.md +7 -5
- package/docs/intellisense.md +49 -31
- package/docs/intro.md +2 -2
- package/docs/oop/file-tags.md +16 -17
- package/docs/oop/index.md +2 -2
- package/docs/oop/modules.md +3 -1
- package/docs/oop/services.md +7 -14
- package/docs/syntax.md +6 -5
- package/editors/vscode/extension.js +97 -146
- package/editors/vscode/package.json +6 -6
- package/examples/README.md +18 -0
- package/examples/game/.clangd +25 -0
- package/examples/game/.vscode/c_cpp_properties.json +27 -0
- package/examples/game/.vscode/extensions.json +5 -0
- package/examples/game/.vscode/settings.json +27 -0
- package/examples/game/Packages/.gitkeep +0 -0
- package/examples/game/cluaupp.config.json +6 -0
- package/examples/game/compile_flags.txt +6 -0
- package/examples/game/default.project.json +39 -0
- package/examples/game/package.json +9 -0
- package/examples/game/rokit.toml +5 -0
- package/examples/game/src/client/hud.client.cpp +12 -0
- package/{src → examples/game/src}/client/init.client.cpp +1 -0
- package/examples/game/src/server/combat.server.cpp +23 -0
- package/{src → examples/game/src}/server/leaderstats.server.cpp +1 -0
- package/examples/game/wally.toml +11 -0
- package/generated/api.js +51 -0
- package/generated/architecture.js +473 -0
- package/generated/ast.js +2 -0
- package/generated/cli.js +191 -0
- package/generated/compile.js +115 -0
- package/generated/editor-install.js +170 -0
- package/generated/emit.js +503 -0
- package/generated/emitter/luau-codegen.js +167 -0
- package/generated/emitter/translators.js +164 -0
- package/generated/headers.js +220 -0
- package/generated/index.html +49 -0
- package/generated/intellisense.js +277 -0
- package/generated/layout.js +112 -0
- package/generated/lex.js +146 -0
- package/generated/libs.js +484 -0
- package/generated/lsp.js +55 -0
- package/generated/package-info.js +11 -0
- package/generated/parse.js +607 -0
- package/generated/parser/collector.js +100 -0
- package/generated/parser/index.js +30 -0
- package/generated/preprocess.js +181 -0
- package/generated/system-understander.js +443 -0
- package/generated/transpile.js +66 -0
- package/generated/types.js +2 -0
- package/generated/understand.js +298 -0
- package/generated/utils/process-orchestrator.js +63 -0
- package/generated/utils/project.js +491 -0
- package/generated/utils/rojo-mapper.js +181 -0
- package/generated/utils/safe-paths.js +104 -0
- package/package.json +25 -8
- package/src/api.ts +53 -0
- package/src/{architecture.js → architecture.ts} +80 -33
- package/src/ast.ts +37 -0
- package/src/cli.ts +214 -0
- package/src/compile.ts +118 -0
- package/src/editor-install.ts +182 -0
- package/src/{emit.js → emit.ts} +5 -6
- package/src/emitter/luau-codegen.ts +187 -0
- package/src/emitter/translators.ts +168 -0
- package/src/headers.ts +233 -0
- package/src/intellisense.ts +286 -0
- package/src/{layout.js → layout.ts} +114 -129
- package/src/{lex.js → lex.ts} +4 -6
- package/src/{libs.js → libs.ts} +119 -46
- package/src/lsp.ts +60 -0
- package/src/package-info.ts +7 -0
- package/src/{parse.js → parse.ts} +3 -4
- package/src/parser/collector.ts +115 -0
- package/src/parser/index.ts +27 -0
- package/src/{preprocess.js → preprocess.ts} +64 -32
- package/src/system-understander.ts +501 -0
- package/src/transpile.ts +64 -0
- package/src/tree-sitter-cpp.d.ts +4 -0
- package/src/types.ts +81 -0
- package/src/{understand.js → understand.ts} +24 -213
- package/src/utils/process-orchestrator.ts +72 -0
- package/src/utils/project.ts +506 -0
- package/src/utils/rojo-mapper.ts +190 -0
- package/src/utils/safe-paths.ts +98 -0
- package/templates/game/.clangd +9 -0
- package/templates/game/.vscode/c_cpp_properties.json +1 -1
- package/templates/game/.vscode/extensions.json +5 -6
- package/templates/game/.vscode/settings.json +7 -6
- package/templates/game/cluaupp.config.json +2 -2
- package/templates/game/compile_flags.txt +1 -0
- package/templates/game/rokit.toml +5 -0
- package/templates/game/src/client/init.client.cpp +1 -0
- package/templates/game/src/server/leaderstats.server.cpp +1 -0
- package/src/api.js +0 -57
- package/src/cli.js +0 -481
- package/src/compile.js +0 -56
- package/src/editor-install.js +0 -218
- package/src/intellisense.js +0 -1368
- package/src/lsp.js +0 -227
- /package/{src → examples/game/src}/shared/config.cpp +0 -0
- /package/{src → examples/game/src}/shared/config.h +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.translateCppType = translateCppType;
|
|
4
|
+
exports.translateGetService = translateGetService;
|
|
5
|
+
exports.translateConstant = translateConstant;
|
|
6
|
+
exports.translateAlias = translateAlias;
|
|
7
|
+
exports.translateStruct = translateStruct;
|
|
8
|
+
exports.translateFunction = translateFunction;
|
|
9
|
+
const compile_js_1 = require("../compile.js");
|
|
10
|
+
const TYPE_MAP = {
|
|
11
|
+
"std::string": "string",
|
|
12
|
+
"std::string_view": "string",
|
|
13
|
+
string: "string",
|
|
14
|
+
string_view: "string",
|
|
15
|
+
bool: "boolean",
|
|
16
|
+
int: "number",
|
|
17
|
+
int8_t: "number",
|
|
18
|
+
int16_t: "number",
|
|
19
|
+
int32_t: "number",
|
|
20
|
+
int64_t: "number",
|
|
21
|
+
uint8_t: "number",
|
|
22
|
+
uint16_t: "number",
|
|
23
|
+
uint32_t: "number",
|
|
24
|
+
uint64_t: "number",
|
|
25
|
+
float: "number",
|
|
26
|
+
double: "number",
|
|
27
|
+
size_t: "number",
|
|
28
|
+
void: "()",
|
|
29
|
+
auto: "any",
|
|
30
|
+
};
|
|
31
|
+
function translateCppType(cppType) {
|
|
32
|
+
const trimmed = cppType
|
|
33
|
+
.replace(/\b(?:const|constexpr|volatile|static|inline|restrict)\b/g, "")
|
|
34
|
+
.replace(/\s+/g, " ")
|
|
35
|
+
.replace(/&/g, "")
|
|
36
|
+
.replace(/\*/g, "")
|
|
37
|
+
.trim();
|
|
38
|
+
if (!trimmed) {
|
|
39
|
+
return "any";
|
|
40
|
+
}
|
|
41
|
+
if (TYPE_MAP[trimmed]) {
|
|
42
|
+
return TYPE_MAP[trimmed];
|
|
43
|
+
}
|
|
44
|
+
const generic = trimmed.match(/^(?:std::)?(?:vector|array|span|LuaArray)\s*<\s*([^>]+)\s*>$/);
|
|
45
|
+
if (generic) {
|
|
46
|
+
return `{${translateCppType(generic[1])}}`;
|
|
47
|
+
}
|
|
48
|
+
const optional = trimmed.match(/^(?:std::)?optional\s*<\s*([^>]+)\s*>$/);
|
|
49
|
+
if (optional) {
|
|
50
|
+
return `${translateCppType(optional[1])}?`;
|
|
51
|
+
}
|
|
52
|
+
return trimmed.replace(/^::/, "");
|
|
53
|
+
}
|
|
54
|
+
function translateGetService(node) {
|
|
55
|
+
const functionNode = node.childForFieldName("function") || node.namedChildren[0];
|
|
56
|
+
if (!functionNode) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const text = functionNode.text.replace(/\s+/g, "");
|
|
60
|
+
const generic = text.match(/GetService<(\w+)>/);
|
|
61
|
+
if (generic) {
|
|
62
|
+
return generic[1];
|
|
63
|
+
}
|
|
64
|
+
if (!text.includes("GetService")) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const args = functionNode.namedChildren.find((child) => child.type === "template_argument_list");
|
|
68
|
+
if (args) {
|
|
69
|
+
const ident = args.namedChildren.find((child) => child.type === "type_identifier" || child.type === "identifier");
|
|
70
|
+
if (ident) {
|
|
71
|
+
return ident.text;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const callText = node.text.replace(/\s+/g, "");
|
|
75
|
+
const match = callText.match(/GetService<(\w+)>/);
|
|
76
|
+
return match ? match[1] : null;
|
|
77
|
+
}
|
|
78
|
+
function translateConstant(node) {
|
|
79
|
+
const declarator = node.childForFieldName("declarator");
|
|
80
|
+
if (!declarator) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const name = identifierOf(declarator);
|
|
84
|
+
const valueNode = node.childForFieldName("value") ||
|
|
85
|
+
declarator.childForFieldName("value") ||
|
|
86
|
+
namedOf(declarator, "initializer") ||
|
|
87
|
+
node.namedChildren[node.namedChildren.length - 1];
|
|
88
|
+
if (!name || !valueNode || valueNode === declarator) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
let value = valueNode.text.replace(/;$/, "").trim();
|
|
92
|
+
if (value.startsWith("=")) {
|
|
93
|
+
value = value.slice(1).trim();
|
|
94
|
+
}
|
|
95
|
+
if (!value) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return `const ${name} = ${value}`;
|
|
99
|
+
}
|
|
100
|
+
function translateAlias(node, mapType) {
|
|
101
|
+
const nameNode = node.childForFieldName("name") || namedOf(node, "type_identifier") || node.namedChildren[1];
|
|
102
|
+
const typeNode = node.childForFieldName("type") || namedOf(node, "type_descriptor") || node.namedChildren[0];
|
|
103
|
+
if (!nameNode || !typeNode) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return `type ${nameNode.text} = ${mapType(typeNode.text)}`;
|
|
107
|
+
}
|
|
108
|
+
function translateStruct(node, mapType) {
|
|
109
|
+
const nameNode = node.childForFieldName("name") || namedOf(node, "type_identifier");
|
|
110
|
+
const body = node.childForFieldName("body") || namedOf(node, "field_declaration_list");
|
|
111
|
+
if (!nameNode) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (!body) {
|
|
115
|
+
return `type ${nameNode.text} = {}`;
|
|
116
|
+
}
|
|
117
|
+
const fields = [];
|
|
118
|
+
for (const field of body.namedChildren) {
|
|
119
|
+
if (field.type !== "field_declaration") {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const fieldType = field.childForFieldName("type");
|
|
123
|
+
const fieldDecl = field.childForFieldName("declarator");
|
|
124
|
+
const fieldName = fieldDecl ? identifierOf(fieldDecl) : namedOf(field, "field_identifier")?.text;
|
|
125
|
+
if (!fieldName) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
fields.push(`\t${fieldName}: ${mapType(fieldType?.text || "any")},`);
|
|
129
|
+
}
|
|
130
|
+
if (fields.length === 0) {
|
|
131
|
+
return `type ${nameNode.text} = {}`;
|
|
132
|
+
}
|
|
133
|
+
return `type ${nameNode.text} = {\n${fields.join("\n")}\n}`;
|
|
134
|
+
}
|
|
135
|
+
function translateFunction(node, fileName) {
|
|
136
|
+
try {
|
|
137
|
+
const luau = (0, compile_js_1.compileSource)(node.text, fileName, { skipHeader: true });
|
|
138
|
+
const trimmed = String(luau || "").trim();
|
|
139
|
+
return trimmed || null;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
const name = identifierOf(node.childForFieldName("declarator") || node) || "fn";
|
|
143
|
+
return `-- function ${name} (não traduzida)`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function identifierOf(node) {
|
|
147
|
+
if (node.type === "identifier" || node.type === "field_identifier" || node.type === "type_identifier") {
|
|
148
|
+
return node.text;
|
|
149
|
+
}
|
|
150
|
+
const direct = node.childForFieldName("declarator") || namedOf(node, "identifier") || namedOf(node, "field_identifier");
|
|
151
|
+
if (direct) {
|
|
152
|
+
return identifierOf(direct);
|
|
153
|
+
}
|
|
154
|
+
for (const child of node.namedChildren) {
|
|
155
|
+
const found = identifierOf(child);
|
|
156
|
+
if (found) {
|
|
157
|
+
return found;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
function namedOf(node, type) {
|
|
163
|
+
return node.namedChildren.find((child) => child.type === type) || null;
|
|
164
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
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.emitHeaderModule = emitHeaderModule;
|
|
7
|
+
exports.primaryHeaderName = primaryHeaderName;
|
|
8
|
+
exports.collectHeaderShape = collectHeaderShape;
|
|
9
|
+
// @ts-nocheck
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const api_js_1 = require("./api.js");
|
|
12
|
+
function fileStem(fileName) {
|
|
13
|
+
return node_path_1.default.basename(String(fileName || "module")).replace(/\.(h|hpp|hh|cpp|cc|cxx|c)$/i, "");
|
|
14
|
+
}
|
|
15
|
+
function emitValue(node) {
|
|
16
|
+
if (!node) {
|
|
17
|
+
return "nil";
|
|
18
|
+
}
|
|
19
|
+
if (node.type === "number") {
|
|
20
|
+
return node.value;
|
|
21
|
+
}
|
|
22
|
+
if (node.type === "string") {
|
|
23
|
+
return `"${node.value}"`;
|
|
24
|
+
}
|
|
25
|
+
if (node.type === "bool") {
|
|
26
|
+
return node.value ? "true" : "false";
|
|
27
|
+
}
|
|
28
|
+
if (node.type === "null") {
|
|
29
|
+
return "nil";
|
|
30
|
+
}
|
|
31
|
+
if (node.type === "initlist") {
|
|
32
|
+
const inner = (node.fields || []).map((field) => `${field.name} = ${emitValue(field.value)}`).join(", ");
|
|
33
|
+
return `{ ${inner} }`;
|
|
34
|
+
}
|
|
35
|
+
return "nil";
|
|
36
|
+
}
|
|
37
|
+
function collectHeaderShape(ast, fileName) {
|
|
38
|
+
const owners = new Map();
|
|
39
|
+
const ensure = (name) => {
|
|
40
|
+
if (!owners.has(name)) {
|
|
41
|
+
owners.set(name, { fields: [], methods: [] });
|
|
42
|
+
}
|
|
43
|
+
return owners.get(name);
|
|
44
|
+
};
|
|
45
|
+
const freeProtos = [];
|
|
46
|
+
const consts = [];
|
|
47
|
+
for (const decl of ast.body || []) {
|
|
48
|
+
if (decl.type === "decl" && decl.owner) {
|
|
49
|
+
ensure(decl.owner).fields.push(decl);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (decl.type === "decl") {
|
|
53
|
+
consts.push(decl);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if ((decl.type === "proto" || decl.type === "function") && decl.owner) {
|
|
57
|
+
ensure(decl.owner).methods.push(decl);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (decl.type === "proto") {
|
|
61
|
+
freeProtos.push(decl);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const nested = new Set();
|
|
65
|
+
for (const [ownerName, spec] of owners) {
|
|
66
|
+
for (const field of spec.fields) {
|
|
67
|
+
if (field.valueType && owners.has(field.valueType) && field.valueType !== ownerName) {
|
|
68
|
+
nested.add(field.valueType);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const roots = [...owners.keys()].filter((name) => !nested.has(name));
|
|
73
|
+
const withMethods = roots.filter((name) => ensure(name).methods.length > 0);
|
|
74
|
+
const stem = fileStem(fileName);
|
|
75
|
+
let primary = withMethods[0] || (freeProtos.length ? stem : roots[0] || stem);
|
|
76
|
+
return { owners, nested, roots, freeProtos, consts, primary, stem };
|
|
77
|
+
}
|
|
78
|
+
function primaryHeaderName(ast, fileName) {
|
|
79
|
+
return collectHeaderShape(ast, fileName).primary;
|
|
80
|
+
}
|
|
81
|
+
function methodType(fn, owner) {
|
|
82
|
+
const params = [];
|
|
83
|
+
if (owner) {
|
|
84
|
+
params.push(`self: ${owner}`);
|
|
85
|
+
}
|
|
86
|
+
for (const param of fn.params || []) {
|
|
87
|
+
if (typeof param === "string") {
|
|
88
|
+
params.push(param);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const typeAnn = (0, api_js_1.luauType)(param.valueType);
|
|
92
|
+
params.push(typeAnn ? `${param.name}: ${typeAnn}` : param.name);
|
|
93
|
+
}
|
|
94
|
+
const ret = (0, api_js_1.luauType)(fn.returnType);
|
|
95
|
+
const retAnn = !ret || ret === "()" ? "()" : ret;
|
|
96
|
+
return `(${params.join(", ")}) -> ${retAnn}`;
|
|
97
|
+
}
|
|
98
|
+
function fieldType(field, owners) {
|
|
99
|
+
if (field.valueType && owners.has(field.valueType)) {
|
|
100
|
+
return field.valueType;
|
|
101
|
+
}
|
|
102
|
+
return (0, api_js_1.luauType)(field.valueType) || "any";
|
|
103
|
+
}
|
|
104
|
+
function emitExportType(lines, name, spec, owners, extraMethods, extraFields) {
|
|
105
|
+
lines.push(`export type ${name} = {`);
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
for (const field of [...((spec && spec.fields) || []), ...(extraFields || [])]) {
|
|
108
|
+
if (!field.name || seen.has(field.name)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
seen.add(field.name);
|
|
112
|
+
lines.push(` ${field.name}: ${fieldType(field, owners)},`);
|
|
113
|
+
}
|
|
114
|
+
for (const method of (spec && spec.methods) || []) {
|
|
115
|
+
if (!method.name || seen.has(method.name)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
seen.add(method.name);
|
|
119
|
+
lines.push(` ${method.name}: ${methodType(method, name)},`);
|
|
120
|
+
}
|
|
121
|
+
for (const method of extraMethods || []) {
|
|
122
|
+
if (!method.name || seen.has(method.name)) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
seen.add(method.name);
|
|
126
|
+
lines.push(` ${method.name}: ${methodType(method, null)},`);
|
|
127
|
+
}
|
|
128
|
+
lines.push("}");
|
|
129
|
+
lines.push("");
|
|
130
|
+
}
|
|
131
|
+
function emitDataConstructor(lines, name, spec, owners) {
|
|
132
|
+
const emitField = (field) => {
|
|
133
|
+
if (field.valueType && owners.has(field.valueType)) {
|
|
134
|
+
const nested = owners.get(field.valueType);
|
|
135
|
+
const inner = nested.fields.map((item) => `${item.name} = ${emitValue(item.value)}`).join(", ");
|
|
136
|
+
return `{ ${inner} }`;
|
|
137
|
+
}
|
|
138
|
+
if (field.value && field.value.type === "initlist") {
|
|
139
|
+
return emitValue(field.value);
|
|
140
|
+
}
|
|
141
|
+
return emitValue(field.value);
|
|
142
|
+
};
|
|
143
|
+
lines.push(`const function ${name}(): ${name}`);
|
|
144
|
+
lines.push(" return {");
|
|
145
|
+
for (const field of spec.fields) {
|
|
146
|
+
lines.push(` ${field.name} = ${emitField(field)},`);
|
|
147
|
+
}
|
|
148
|
+
lines.push(" }");
|
|
149
|
+
lines.push("end");
|
|
150
|
+
lines.push("");
|
|
151
|
+
}
|
|
152
|
+
function emitHeaderModule(ast, options = {}) {
|
|
153
|
+
const strict = options.strict === true;
|
|
154
|
+
const fileName = options.relativeName || options.filePath || "header.h";
|
|
155
|
+
const shape = collectHeaderShape(ast, fileName);
|
|
156
|
+
const lines = [];
|
|
157
|
+
if (strict) {
|
|
158
|
+
lines.push("--!strict");
|
|
159
|
+
}
|
|
160
|
+
lines.push("-- Compiled by Cluaupp — C++ × Luau");
|
|
161
|
+
lines.push("");
|
|
162
|
+
const typeOrder = [...shape.nested, ...shape.roots];
|
|
163
|
+
for (const name of typeOrder) {
|
|
164
|
+
const extra = name === shape.primary ? shape.freeProtos : [];
|
|
165
|
+
emitExportType(lines, name, shape.owners.get(name), shape.owners, extra);
|
|
166
|
+
}
|
|
167
|
+
if (shape.freeProtos.length && !shape.owners.has(shape.primary)) {
|
|
168
|
+
emitExportType(lines, shape.primary, { fields: [], methods: [] }, shape.owners, shape.freeProtos, shape.consts);
|
|
169
|
+
}
|
|
170
|
+
for (const decl of shape.consts) {
|
|
171
|
+
const typeAnn = (0, api_js_1.luauType)(decl.valueType);
|
|
172
|
+
const typed = typeAnn ? `: ${typeAnn}` : "";
|
|
173
|
+
lines.push(`const ${decl.name}${typed} = ${emitValue(decl.value)}`);
|
|
174
|
+
}
|
|
175
|
+
if (shape.consts.length) {
|
|
176
|
+
lines.push("");
|
|
177
|
+
}
|
|
178
|
+
const hasMethods = shape.roots.some((name) => shape.owners.get(name).methods.length > 0) || shape.freeProtos.length > 0;
|
|
179
|
+
const implName = hasMethods ? options.headerImplName : null;
|
|
180
|
+
if (!hasMethods && shape.roots.length > 0) {
|
|
181
|
+
for (const name of shape.roots) {
|
|
182
|
+
emitDataConstructor(lines, name, shape.owners.get(name), shape.owners);
|
|
183
|
+
}
|
|
184
|
+
lines.push(`return ${shape.primary}`);
|
|
185
|
+
lines.push("");
|
|
186
|
+
return lines.join("\n");
|
|
187
|
+
}
|
|
188
|
+
if (!hasMethods && shape.consts.length > 0) {
|
|
189
|
+
lines.push("return {");
|
|
190
|
+
for (const decl of shape.consts) {
|
|
191
|
+
lines.push(` ${decl.name} = ${decl.name},`);
|
|
192
|
+
}
|
|
193
|
+
lines.push("}");
|
|
194
|
+
lines.push("");
|
|
195
|
+
return lines.join("\n");
|
|
196
|
+
}
|
|
197
|
+
const tableName = shape.primary;
|
|
198
|
+
const spec = shape.owners.get(tableName) || { fields: [], methods: [] };
|
|
199
|
+
const methods = [...spec.methods, ...shape.freeProtos];
|
|
200
|
+
lines.push(`const ${tableName}: ${tableName} = {`);
|
|
201
|
+
if (implName) {
|
|
202
|
+
for (const field of spec.fields) {
|
|
203
|
+
if (field.valueType && shape.owners.has(field.valueType) && field.valueType !== tableName) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
lines.push(` ${field.name} = ${implName}.${field.name},`);
|
|
207
|
+
}
|
|
208
|
+
for (const method of methods) {
|
|
209
|
+
lines.push(` ${method.name} = ${implName}.${method.name},`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const decl of shape.consts) {
|
|
213
|
+
lines.push(` ${decl.name} = ${decl.name},`);
|
|
214
|
+
}
|
|
215
|
+
lines.push("}");
|
|
216
|
+
lines.push("");
|
|
217
|
+
lines.push(`return ${tableName}`);
|
|
218
|
+
lines.push("");
|
|
219
|
+
return lines.join("\n");
|
|
220
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Docs · Cluaupp V2 Specification</title>
|
|
7
|
+
<style>
|
|
8
|
+
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #0f0f14; color: #c9d1d9; padding: 40px; line-height: 1.6; }
|
|
9
|
+
h1, h2, h3 { color: #58a6ff; border-bottom: 1px solid #21262d; padding-bottom: 8px; }
|
|
10
|
+
code { background-color: #161b22; padding: 4px 8px; border-radius: 4px; font-family: 'Courier New', Courier, monospace; color: #ff7b72; }
|
|
11
|
+
pre { background-color: #161b22; padding: 16px; border-radius: 8px; border: 1px solid #30363d; overflow-x: auto; }
|
|
12
|
+
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
|
13
|
+
.card { background: #1f242c; border: 1px solid #30363d; padding: 20px; border-radius: 8px; }
|
|
14
|
+
.badge { background-color: #238636; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; }
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<h1>Cluaupp Compiler Core V2 <span class="badge">TypeScript Migration</span></h1>
|
|
19
|
+
<p>Documentação da API atualizada para o novo Pipeline de Transpilação baseado em Coletores Estruturados.</p>
|
|
20
|
+
|
|
21
|
+
<h2>A Nova Ordem Crítica do Output</h2>
|
|
22
|
+
<p>O compilador Cluaupp agora garante deterministicamente um arquivo Luau limpo, agrupado por blocos ordenados:</p>
|
|
23
|
+
<pre>1. game:GetService() Clientes Automatizados
|
|
24
|
+
2. Módulos Locais Resolvidos via require() do Rojo
|
|
25
|
+
3. Definições e Aliases de Tipos Estritos
|
|
26
|
+
4. Declarações Globais de Constantes Imutáveis
|
|
27
|
+
5. Lógica das Funções e Ciclos do Script</pre>
|
|
28
|
+
|
|
29
|
+
<h2>Mudanças Importantes na Tabela de Tipos</h2>
|
|
30
|
+
<div class="grid">
|
|
31
|
+
<div class="card">
|
|
32
|
+
<h3>Como era (Cluaupp V1)</h3>
|
|
33
|
+
<ul>
|
|
34
|
+
<li>Uso de tipos primitivos crus: <code>string</code></li>
|
|
35
|
+
<li>Injeção manual de variáveis de serviço globais</li>
|
|
36
|
+
<li>Geração de código procedural inline desordenada</li>
|
|
37
|
+
</ul>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="card">
|
|
40
|
+
<h3>Como é Agora (Cluaupp V2)</h3>
|
|
41
|
+
<ul>
|
|
42
|
+
<li>Suporte a tipos idiomáticos: <code>std::string</code> e <code>std::string_view</code> viram <code>string</code></li>
|
|
43
|
+
<li>Injeção automática pelo analisador ao ler <code>GetService<T>()</code></li>
|
|
44
|
+
<li>Pós-processamento automático nativo com <code>StyLua</code> e <code>Luau-Analyze</code></li>
|
|
45
|
+
</ul>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|