@tilua/compiler 2.4.0 → 3.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/dist/{chunk-3ZQ3EITC.js → chunk-X4DM2BX2.js} +123 -53
- package/dist/cli.cjs +131 -57
- package/dist/cli.js +1 -1
- package/dist/index.cjs +131 -57
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -1
- package/package.json +4 -3
- package/runtime/array.luau +179 -0
- package/runtime/object.luau +54 -0
- package/runtime/string.luau +119 -0
package/dist/index.cjs
CHANGED
|
@@ -28,8 +28,12 @@ __export(index_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(index_exports);
|
|
30
30
|
|
|
31
|
+
// node_modules/tsup/assets/cjs_shims.js
|
|
32
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
33
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
34
|
+
|
|
31
35
|
// src/bundle.ts
|
|
32
|
-
var
|
|
36
|
+
var import_node_fs2 = require("fs");
|
|
33
37
|
var import_node_path2 = require("path");
|
|
34
38
|
var import_parser3 = require("@tilua/parser");
|
|
35
39
|
var import_luau_parser2 = require("luau-parser");
|
|
@@ -57,10 +61,10 @@ var nil = () => ({ type: "NilLiteral", ...span() });
|
|
|
57
61
|
var boolean = (value) => ({ type: "BooleanLiteral", value, ...span() });
|
|
58
62
|
var number = (value, raw = String(value)) => ({ type: "NumberLiteral", value, raw, ...span() });
|
|
59
63
|
var string = (value) => ({ type: "StringLiteral", value, raw: "", ...span() });
|
|
60
|
-
var member = (
|
|
61
|
-
var index = (
|
|
64
|
+
var member = (object2, property) => isLuauName(property) ? { type: "MemberExpression", object: object2, property: identifier(property), ...span() } : index(object2, string(property));
|
|
65
|
+
var index = (object2, key) => ({ type: "IndexExpression", object: object2, index: key, ...span() });
|
|
62
66
|
var call = (callee, args) => ({ type: "CallExpression", callee, arguments: args, ...span() });
|
|
63
|
-
var methodCall = (
|
|
67
|
+
var methodCall = (object2, method, args) => ({ type: "MethodCallExpression", object: object2, method: identifier(method), arguments: args, ...span() });
|
|
64
68
|
var functionExpression = (func) => ({ type: "FunctionExpression", func, ...span() });
|
|
65
69
|
var binary = (operator, left, right) => ({ type: "BinaryExpression", operator, left, right, ...span() });
|
|
66
70
|
var unary = (operator, argument) => ({ type: "UnaryExpression", operator, argument, ...span() });
|
|
@@ -176,6 +180,62 @@ var Names = class _Names {
|
|
|
176
180
|
}
|
|
177
181
|
};
|
|
178
182
|
|
|
183
|
+
// src/language.ts
|
|
184
|
+
var import_node_fs = require("fs");
|
|
185
|
+
var read = (name) => (0, import_node_fs.readFileSync)(new URL(`../runtime/${name}`, importMetaUrl), "utf8");
|
|
186
|
+
var implemented = (source) => new Set([...source.matchAll(/function __NAME__\.(\w+)/g)].map((m) => m[1]));
|
|
187
|
+
var array = read("array.luau");
|
|
188
|
+
var string2 = read("string.luau");
|
|
189
|
+
var object = read("object.luau");
|
|
190
|
+
var arrayMethods = implemented(array);
|
|
191
|
+
var stringMethods = implemented(string2);
|
|
192
|
+
var objectMethods = implemented(object);
|
|
193
|
+
function every(type, is, seen = /* @__PURE__ */ new Set()) {
|
|
194
|
+
if (!type || seen.has(type)) return false;
|
|
195
|
+
seen.add(type);
|
|
196
|
+
if (type.kind === "union") {
|
|
197
|
+
return type.types.filter((m) => !(m.kind === "primitive" && m.name === "nil")).every((m) => every(m, is, seen));
|
|
198
|
+
}
|
|
199
|
+
if (type.kind === "typeParam") return every(type.constraint, is, seen);
|
|
200
|
+
return is(type);
|
|
201
|
+
}
|
|
202
|
+
var isArray = (type) => every(type, (t) => t.kind === "array" || t.kind === "tuple");
|
|
203
|
+
var isString = (type) => every(type, (t) => t.kind === "primitive" && t.name === "string" || t.kind === "literal" && t.base === "string" || t.kind === "templateLiteral");
|
|
204
|
+
function objectKeys(type) {
|
|
205
|
+
const members = type?.kind === "union" ? type.types : type ? [type] : [];
|
|
206
|
+
const orders = [];
|
|
207
|
+
let open = false;
|
|
208
|
+
for (const member2 of members) {
|
|
209
|
+
const keys = [];
|
|
210
|
+
for (const part of member2.kind === "intersection" ? member2.types : [member2]) {
|
|
211
|
+
if (part.kind !== "object") continue;
|
|
212
|
+
for (const key of part.properties.keys()) if (!keys.includes(key)) keys.push(key);
|
|
213
|
+
if (part.indexer) open = true;
|
|
214
|
+
}
|
|
215
|
+
orders.push(keys);
|
|
216
|
+
}
|
|
217
|
+
const order = JSON.stringify(orders[0] ?? []);
|
|
218
|
+
const known = orders.length && orders.every((keys) => JSON.stringify(keys) === order) ? `{ ${orders[0].map((key) => JSON.stringify(key)).join(", ")} }` : "nil";
|
|
219
|
+
return { known, open: String(open) };
|
|
220
|
+
}
|
|
221
|
+
var plugin = {
|
|
222
|
+
runtime: { array, string: string2, object },
|
|
223
|
+
methodCall({ method, receiver, use }) {
|
|
224
|
+
if (isString(receiver)) {
|
|
225
|
+
return stringMethods.has(method) ? { callee: `${use("string")}.${method}` } : void 0;
|
|
226
|
+
}
|
|
227
|
+
if (isArray(receiver)) {
|
|
228
|
+
return arrayMethods.has(method) ? { callee: `${use("array")}.${method}` } : void 0;
|
|
229
|
+
}
|
|
230
|
+
if (objectMethods.has(method)) {
|
|
231
|
+
const keys = objectKeys(receiver);
|
|
232
|
+
return { callee: `${use("object")}.${method}`, prepend: [keys.known, keys.open] };
|
|
233
|
+
}
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var languageLowering = { plugin, from: "tilua" };
|
|
238
|
+
|
|
179
239
|
// src/lower.ts
|
|
180
240
|
function lower(program2, scopes, options = {}) {
|
|
181
241
|
return new Lowerer(program2, scopes, options).run();
|
|
@@ -359,21 +419,34 @@ var Lowerer = class {
|
|
|
359
419
|
if (id === void 0) return node.name;
|
|
360
420
|
return this.scopes.bindings.get(id)?.kind === "global" ? node.name : void 0;
|
|
361
421
|
}
|
|
362
|
-
/**
|
|
363
|
-
*
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
422
|
+
/** The language's own lowering, then each library's, in load order. A
|
|
423
|
+
* runtime is named by its lowering's place here (`loweringRuntime`). */
|
|
424
|
+
get lowerings() {
|
|
425
|
+
return this.allLowerings ??= [languageLowering, ...this.options.lowerings ?? []];
|
|
426
|
+
}
|
|
427
|
+
allLowerings;
|
|
428
|
+
/** What `receiver:method(...)` becomes, when Luau alone would not run it.
|
|
429
|
+
*
|
|
430
|
+
* A method the receiver's metatable gave it — the analyzer says so, and
|
|
431
|
+
* whose metatable it was (`methodSources`) — is asked of whoever declared
|
|
432
|
+
* that metatable, and only them: the language lowers its own
|
|
433
|
+
* (`names:filter(f)` becomes a call into its runtime), a library its own,
|
|
434
|
+
* and one the program declared is taken at its word. Any other method is
|
|
435
|
+
* a member of the receiver's own, which a library may still claim
|
|
436
|
+
* (`console:log`), the last library loaded first. No answer leaves an
|
|
437
|
+
* ordinary Luau method call: `text:upper()` reaches Lua's own. */
|
|
367
438
|
loweredMethodCall(node) {
|
|
368
|
-
const lowerings = this.
|
|
369
|
-
|
|
439
|
+
const lowerings = this.lowerings;
|
|
440
|
+
const source = this.options.types?.methodSources.get(node);
|
|
441
|
+
const asked = source?.origin === "language" ? [0] : source?.origin === "library" ? lowerings.flatMap((l, i) => l.library === source.library ? [i] : []) : source?.origin === "program" ? [] : lowerings.map((_, i) => i).slice(1).reverse();
|
|
442
|
+
if (!asked.some((i) => lowerings[i].plugin.methodCall)) return void 0;
|
|
370
443
|
const receiver = this.options.types?.typeOf.get(node.object);
|
|
371
444
|
const receiverGlobal = this.globalName(node.object);
|
|
372
445
|
const info = this.lazyArguments(node.arguments);
|
|
373
|
-
for (
|
|
374
|
-
const
|
|
375
|
-
if (!
|
|
376
|
-
const answer =
|
|
446
|
+
for (const i of asked) {
|
|
447
|
+
const plugin2 = lowerings[i].plugin;
|
|
448
|
+
if (!plugin2.methodCall) continue;
|
|
449
|
+
const answer = plugin2.methodCall({
|
|
377
450
|
method: node.method.name,
|
|
378
451
|
receiver,
|
|
379
452
|
receiverGlobal,
|
|
@@ -396,15 +469,15 @@ var Lowerer = class {
|
|
|
396
469
|
}
|
|
397
470
|
/** What a library says a call to a global — `print(x)` — is. */
|
|
398
471
|
loweredGlobalCall(node) {
|
|
399
|
-
const lowerings = this.
|
|
472
|
+
const lowerings = this.lowerings;
|
|
400
473
|
if (!lowerings?.some((l) => l.plugin.globalCall)) return void 0;
|
|
401
474
|
const name = this.globalName(node.callee);
|
|
402
475
|
if (name === void 0) return void 0;
|
|
403
476
|
const info = this.lazyArguments(node.arguments);
|
|
404
477
|
for (let i = lowerings.length - 1; i >= 0; i--) {
|
|
405
|
-
const
|
|
406
|
-
if (!
|
|
407
|
-
const answer =
|
|
478
|
+
const plugin2 = lowerings[i].plugin;
|
|
479
|
+
if (!plugin2.globalCall) continue;
|
|
480
|
+
const answer = plugin2.globalCall({
|
|
408
481
|
name,
|
|
409
482
|
at: this.callSite(node.callee),
|
|
410
483
|
get arguments() {
|
|
@@ -418,7 +491,7 @@ var Lowerer = class {
|
|
|
418
491
|
}
|
|
419
492
|
/** What a library says a global read as a value — `local p = print` — is. */
|
|
420
493
|
loweredGlobalValue(node) {
|
|
421
|
-
const lowerings = this.
|
|
494
|
+
const lowerings = this.lowerings;
|
|
422
495
|
if (!lowerings?.some((l) => l.plugin.globalValue)) return void 0;
|
|
423
496
|
const name = this.globalName(node);
|
|
424
497
|
if (name === void 0) return void 0;
|
|
@@ -448,7 +521,7 @@ var Lowerer = class {
|
|
|
448
521
|
try {
|
|
449
522
|
return (0, import_luau_parser.parseExpressionFromSource)(source);
|
|
450
523
|
} catch (error) {
|
|
451
|
-
this.report(node, `'${this.
|
|
524
|
+
this.report(node, `'${this.lowerings[index2].from}' lowered this to Luau that does not parse: ${JSON.stringify(source)} (${error.message})`);
|
|
452
525
|
return void 0;
|
|
453
526
|
}
|
|
454
527
|
}
|
|
@@ -469,8 +542,8 @@ var Lowerer = class {
|
|
|
469
542
|
], true)));
|
|
470
543
|
}
|
|
471
544
|
for (const { index: index2, runtime: runtime2, name } of this.loweringUsed) {
|
|
472
|
-
const { plugin, from } = this.
|
|
473
|
-
const source =
|
|
545
|
+
const { plugin: plugin2, from } = this.lowerings[index2];
|
|
546
|
+
const source = plugin2.runtime?.[runtime2];
|
|
474
547
|
if (source === void 0) {
|
|
475
548
|
this.diagnostics.push({
|
|
476
549
|
message: `'${from}' asked for a runtime it does not have: '${runtime2}'`,
|
|
@@ -805,6 +878,7 @@ var Lowerer = class {
|
|
|
805
878
|
case "ExportTypeAliasStatement":
|
|
806
879
|
case "DeclareStatement":
|
|
807
880
|
case "DeclareClassStatement":
|
|
881
|
+
case "DeclareMetatableStatement":
|
|
808
882
|
case "ErrorStatement":
|
|
809
883
|
return [];
|
|
810
884
|
case "VariableDeclaration":
|
|
@@ -1405,11 +1479,11 @@ end
|
|
|
1405
1479
|
callValues(node) {
|
|
1406
1480
|
const chain = optionalChain(node);
|
|
1407
1481
|
if (chain) return this.optionalChainExpression(chain);
|
|
1408
|
-
const
|
|
1409
|
-
if (node.type === "CallExpression" &&
|
|
1410
|
-
return this.link(node, this.reference(
|
|
1482
|
+
const object2 = linkObject(node);
|
|
1483
|
+
if (node.type === "CallExpression" && object2.type === "Identifier") {
|
|
1484
|
+
return this.link(node, this.reference(object2));
|
|
1411
1485
|
}
|
|
1412
|
-
return this.link(node, this.expression(
|
|
1486
|
+
return this.link(node, this.expression(object2));
|
|
1413
1487
|
}
|
|
1414
1488
|
/** A call is one value in tilua, and Luau would hand on every value one
|
|
1415
1489
|
* returns in the last place of an argument list or a `return`: it is
|
|
@@ -1448,16 +1522,16 @@ end
|
|
|
1448
1522
|
}))];
|
|
1449
1523
|
}
|
|
1450
1524
|
/** One link of an access chain, read from `object`. */
|
|
1451
|
-
link(node,
|
|
1525
|
+
link(node, object2) {
|
|
1452
1526
|
switch (node.type) {
|
|
1453
1527
|
case "MemberExpression":
|
|
1454
|
-
return member(
|
|
1528
|
+
return member(object2, node.property.name);
|
|
1455
1529
|
case "IndexExpression":
|
|
1456
|
-
return index(
|
|
1530
|
+
return index(object2, this.expression(node.index));
|
|
1457
1531
|
case "CallExpression": {
|
|
1458
1532
|
const lowered = this.loweredGlobalCall(node);
|
|
1459
1533
|
const args = this.arguments(node.arguments);
|
|
1460
|
-
if (!lowered) return call(
|
|
1534
|
+
if (!lowered) return call(object2, args);
|
|
1461
1535
|
return call(calleePath(lowered.callee), [...lowered.prepend, ...args]);
|
|
1462
1536
|
}
|
|
1463
1537
|
case "MethodCallExpression": {
|
|
@@ -1466,14 +1540,14 @@ end
|
|
|
1466
1540
|
if (lowered) {
|
|
1467
1541
|
return call(calleePath(lowered.callee), [
|
|
1468
1542
|
...lowered.prepend,
|
|
1469
|
-
...lowered.passReceiver ? [
|
|
1543
|
+
...lowered.passReceiver ? [object2] : [],
|
|
1470
1544
|
...args
|
|
1471
1545
|
]);
|
|
1472
1546
|
}
|
|
1473
1547
|
if (!isLuauName(node.method.name)) {
|
|
1474
1548
|
this.report(node.method, `'${node.method.name}' is a Luau keyword and cannot be called with ':'`);
|
|
1475
1549
|
}
|
|
1476
|
-
return methodCall(
|
|
1550
|
+
return methodCall(object2, node.method.name, args);
|
|
1477
1551
|
}
|
|
1478
1552
|
}
|
|
1479
1553
|
}
|
|
@@ -1494,8 +1568,8 @@ end
|
|
|
1494
1568
|
}
|
|
1495
1569
|
return out;
|
|
1496
1570
|
}
|
|
1497
|
-
applySegment(segment,
|
|
1498
|
-
return segment.reduce((value, link) => this.link(link, value),
|
|
1571
|
+
applySegment(segment, object2) {
|
|
1572
|
+
return segment.reduce((value, link) => this.link(link, value), object2);
|
|
1499
1573
|
}
|
|
1500
1574
|
/** `a?.b:m()` as a statement:
|
|
1501
1575
|
* `do local ref = a if ref ~= nil then ref.b:m() end end` */
|
|
@@ -1571,9 +1645,9 @@ end
|
|
|
1571
1645
|
const before = [];
|
|
1572
1646
|
let target;
|
|
1573
1647
|
if (node.target.type === "MemberExpression" || node.target.type === "IndexExpression") {
|
|
1574
|
-
const
|
|
1648
|
+
const object2 = this.expression(node.target.object);
|
|
1575
1649
|
const objectName = this.names.fresh("target");
|
|
1576
|
-
before.push(local([objectName], [
|
|
1650
|
+
before.push(local([objectName], [object2]));
|
|
1577
1651
|
if (node.target.type === "MemberExpression") {
|
|
1578
1652
|
target = member(identifier(objectName), node.target.property.name);
|
|
1579
1653
|
} else {
|
|
@@ -1991,15 +2065,15 @@ async function loadLowerings(modules) {
|
|
|
1991
2065
|
for (const module2 of modules) {
|
|
1992
2066
|
try {
|
|
1993
2067
|
const loaded = await import((0, import_node_url.pathToFileURL)(module2.file).href);
|
|
1994
|
-
const
|
|
1995
|
-
if (!
|
|
2068
|
+
const plugin2 = loaded.default;
|
|
2069
|
+
if (!plugin2 || typeof plugin2 !== "object") {
|
|
1996
2070
|
problems.push({
|
|
1997
2071
|
file: module2.file,
|
|
1998
2072
|
message: `'${module2.from}' lowering module has no default export`
|
|
1999
2073
|
});
|
|
2000
2074
|
continue;
|
|
2001
2075
|
}
|
|
2002
|
-
lowerings.push({ plugin, from: module2.from });
|
|
2076
|
+
lowerings.push({ plugin: plugin2, from: module2.from, library: module2.library });
|
|
2003
2077
|
} catch (error) {
|
|
2004
2078
|
problems.push({
|
|
2005
2079
|
file: module2.file,
|
|
@@ -2251,7 +2325,7 @@ ${G} = {
|
|
|
2251
2325
|
}
|
|
2252
2326
|
function stampOf(file) {
|
|
2253
2327
|
try {
|
|
2254
|
-
const at = (0,
|
|
2328
|
+
const at = (0, import_node_fs2.statSync)(file);
|
|
2255
2329
|
return `${at.size}:${at.mtimeMs}`;
|
|
2256
2330
|
} catch {
|
|
2257
2331
|
return void 0;
|
|
@@ -2267,7 +2341,7 @@ function parseFile(file, diagnostics, directives) {
|
|
|
2267
2341
|
}
|
|
2268
2342
|
let text;
|
|
2269
2343
|
try {
|
|
2270
|
-
text = (0,
|
|
2344
|
+
text = (0, import_node_fs2.readFileSync)(file, "utf8");
|
|
2271
2345
|
} catch {
|
|
2272
2346
|
diagnostics.push({ file, message: "Cannot read file", line: 1, column: 1, category: "module" });
|
|
2273
2347
|
return void 0;
|
|
@@ -2294,14 +2368,14 @@ var libraryCache = /* @__PURE__ */ new Map();
|
|
|
2294
2368
|
function parsedLibrary(file) {
|
|
2295
2369
|
let stamp;
|
|
2296
2370
|
try {
|
|
2297
|
-
const at = (0,
|
|
2371
|
+
const at = (0, import_node_fs2.statSync)(file);
|
|
2298
2372
|
stamp = `${at.size}:${at.mtimeMs}`;
|
|
2299
2373
|
} catch {
|
|
2300
2374
|
stamp = "";
|
|
2301
2375
|
}
|
|
2302
2376
|
const cached = libraryCache.get(file);
|
|
2303
2377
|
if (cached && cached.stamp === stamp) return cached.program;
|
|
2304
|
-
const program2 = (0, import_parser3.parse)((0,
|
|
2378
|
+
const program2 = (0, import_parser3.parse)((0, import_node_fs2.readFileSync)(file, "utf8"));
|
|
2305
2379
|
libraryCache.set(file, { stamp, program: program2 });
|
|
2306
2380
|
return program2;
|
|
2307
2381
|
}
|
|
@@ -2324,7 +2398,7 @@ function analyzeModules(modules, config) {
|
|
|
2324
2398
|
const done = analyzed.get(file);
|
|
2325
2399
|
if (done) return done;
|
|
2326
2400
|
const remembered = moduleAnalyses.get(file);
|
|
2327
|
-
if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program2 && [...remembered.read].every(([
|
|
2401
|
+
if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program2 && [...remembered.read].every(([read2, stamp]) => stampOf(read2) === stamp)) {
|
|
2328
2402
|
analyzed.set(file, remembered.result);
|
|
2329
2403
|
readWhile.set(file, remembered.read);
|
|
2330
2404
|
return remembered.result;
|
|
@@ -2348,12 +2422,12 @@ function analyzeModules(modules, config) {
|
|
|
2348
2422
|
const result = { types, diagnostics: said };
|
|
2349
2423
|
if (partials === before) {
|
|
2350
2424
|
analyzed.set(file, result);
|
|
2351
|
-
const
|
|
2425
|
+
const read2 = readWhile.get(file) ?? /* @__PURE__ */ new Map();
|
|
2352
2426
|
const own = stampOf(file);
|
|
2353
|
-
if (own !== void 0)
|
|
2354
|
-
readWhile.set(file,
|
|
2355
|
-
if ([...
|
|
2356
|
-
moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program: program2, read, result });
|
|
2427
|
+
if (own !== void 0) read2.set(file, own);
|
|
2428
|
+
readWhile.set(file, read2);
|
|
2429
|
+
if ([...read2.values()].every((stamp) => stamp !== void 0)) {
|
|
2430
|
+
moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program: program2, read: read2, result });
|
|
2357
2431
|
}
|
|
2358
2432
|
}
|
|
2359
2433
|
return result;
|
|
@@ -2362,11 +2436,11 @@ function analyzeModules(modules, config) {
|
|
|
2362
2436
|
const target = (0, import_parser3.resolveModulePath)(file, specifier, config);
|
|
2363
2437
|
if (!target) return void 0;
|
|
2364
2438
|
const noteRead = () => {
|
|
2365
|
-
const
|
|
2366
|
-
readWhile.set(file,
|
|
2439
|
+
const read2 = readWhile.get(file) ?? /* @__PURE__ */ new Map();
|
|
2440
|
+
readWhile.set(file, read2);
|
|
2367
2441
|
const stamp = stampOf(target);
|
|
2368
|
-
if (stamp !== void 0)
|
|
2369
|
-
for (const [below, belowStamp] of readWhile.get(target) ?? [])
|
|
2442
|
+
if (stamp !== void 0) read2.set(target, stamp);
|
|
2443
|
+
for (const [below, belowStamp] of readWhile.get(target) ?? []) read2.set(below, belowStamp);
|
|
2370
2444
|
};
|
|
2371
2445
|
if (inProgress.has(target)) {
|
|
2372
2446
|
partials++;
|
|
@@ -2380,7 +2454,7 @@ function analyzeModules(modules, config) {
|
|
|
2380
2454
|
let program2 = byFile.get(target)?.program;
|
|
2381
2455
|
if (!program2) {
|
|
2382
2456
|
try {
|
|
2383
|
-
program2 = (0, import_parser3.parse)((0,
|
|
2457
|
+
program2 = (0, import_parser3.parse)((0, import_node_fs2.readFileSync)(target, "utf8"));
|
|
2384
2458
|
} catch {
|
|
2385
2459
|
return void 0;
|
|
2386
2460
|
}
|
|
@@ -2422,7 +2496,7 @@ function allStatements(statements) {
|
|
|
2422
2496
|
}
|
|
2423
2497
|
|
|
2424
2498
|
// src/compile.ts
|
|
2425
|
-
var
|
|
2499
|
+
var import_node_fs3 = require("fs");
|
|
2426
2500
|
var import_node_path3 = require("path");
|
|
2427
2501
|
var import_parser4 = require("@tilua/parser");
|
|
2428
2502
|
var import_luau_parser3 = require("luau-parser");
|
|
@@ -2450,7 +2524,7 @@ async function compile(source, config) {
|
|
|
2450
2524
|
diagnostics.push({ message: p.message, line: p.line ?? 1, column: p.column ?? 1 });
|
|
2451
2525
|
}
|
|
2452
2526
|
for (const p of loweringProblems) diagnostics.push({ message: p.message, line: 1, column: 1 });
|
|
2453
|
-
const libs = libraries.files.map((file) => (0, import_parser4.parse)((0,
|
|
2527
|
+
const libs = libraries.files.map((file) => (0, import_parser4.parse)((0, import_node_fs3.readFileSync)(file, "utf8")));
|
|
2454
2528
|
const lowered = lower(program2, scopes, {
|
|
2455
2529
|
types: (0, import_parser4.analyzeTypes)(program2, scopes, { libs, diagnostics: false }),
|
|
2456
2530
|
lowerings,
|
package/dist/index.d.cts
CHANGED
|
@@ -29,6 +29,10 @@ interface LoadedLowering {
|
|
|
29
29
|
readonly plugin: LoweringPlugin;
|
|
30
30
|
/** The package it came from, for reporting. */
|
|
31
31
|
readonly from: string;
|
|
32
|
+
/** The package's definitions, as their index in the libraries the
|
|
33
|
+
* analyzer was given: a method read from a metatable they declare is
|
|
34
|
+
* this lowering's to answer. Absent for the language's own. */
|
|
35
|
+
readonly library?: number;
|
|
32
36
|
}
|
|
33
37
|
interface LoweringProblem {
|
|
34
38
|
readonly file: string;
|
|
@@ -40,6 +44,7 @@ interface LoweringProblem {
|
|
|
40
44
|
declare function loadLowerings(modules: readonly {
|
|
41
45
|
file: string;
|
|
42
46
|
from: string;
|
|
47
|
+
library?: number;
|
|
43
48
|
}[]): Promise<{
|
|
44
49
|
lowerings: LoadedLowering[];
|
|
45
50
|
problems: LoweringProblem[];
|
package/dist/index.d.ts
CHANGED
|
@@ -29,6 +29,10 @@ interface LoadedLowering {
|
|
|
29
29
|
readonly plugin: LoweringPlugin;
|
|
30
30
|
/** The package it came from, for reporting. */
|
|
31
31
|
readonly from: string;
|
|
32
|
+
/** The package's definitions, as their index in the libraries the
|
|
33
|
+
* analyzer was given: a method read from a metatable they declare is
|
|
34
|
+
* this lowering's to answer. Absent for the language's own. */
|
|
35
|
+
readonly library?: number;
|
|
32
36
|
}
|
|
33
37
|
interface LoweringProblem {
|
|
34
38
|
readonly file: string;
|
|
@@ -40,6 +44,7 @@ interface LoweringProblem {
|
|
|
40
44
|
declare function loadLowerings(modules: readonly {
|
|
41
45
|
file: string;
|
|
42
46
|
from: string;
|
|
47
|
+
library?: number;
|
|
43
48
|
}[]): Promise<{
|
|
44
49
|
lowerings: LoadedLowering[];
|
|
45
50
|
problems: LoweringProblem[];
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tilua/compiler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Compiles tilua to Luau: lowers the @tilua/parser AST to a luau-parser AST and prints it",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"tilua": "dist/cli.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
|
-
"dist"
|
|
12
|
+
"dist",
|
|
13
|
+
"runtime"
|
|
13
14
|
],
|
|
14
15
|
"exports": {
|
|
15
16
|
".": {
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
"type": "module",
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"luau-parser": "^1.0.3",
|
|
40
|
-
"@tilua/parser": "^
|
|
41
|
+
"@tilua/parser": "^3.0.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^22.20.2",
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
local __NAME__ = {}
|
|
2
|
+
|
|
3
|
+
function __NAME__.find(t, test)
|
|
4
|
+
for i = 1, #t do
|
|
5
|
+
if test(t[i], i) then
|
|
6
|
+
return t[i]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
return nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
function __NAME__.findIndex(t, test)
|
|
13
|
+
for i = 1, #t do
|
|
14
|
+
if test(t[i], i) then
|
|
15
|
+
return i
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
return nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
function __NAME__.filter(t, test)
|
|
22
|
+
local out = {}
|
|
23
|
+
for i = 1, #t do
|
|
24
|
+
if test(t[i], i) then
|
|
25
|
+
out[#out + 1] = t[i]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
return out
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
function __NAME__.map(t, transform)
|
|
32
|
+
local out = {}
|
|
33
|
+
for i = 1, #t do
|
|
34
|
+
out[i] = transform(t[i], i)
|
|
35
|
+
end
|
|
36
|
+
return out
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
function __NAME__.forEach(t, visit)
|
|
40
|
+
for i = 1, #t do
|
|
41
|
+
visit(t[i], i)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
function __NAME__.some(t, test)
|
|
46
|
+
for i = 1, #t do
|
|
47
|
+
if test(t[i], i) then
|
|
48
|
+
return true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
return false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
function __NAME__.every(t, test)
|
|
55
|
+
for i = 1, #t do
|
|
56
|
+
if not test(t[i], i) then
|
|
57
|
+
return false
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
return true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
function __NAME__.reduce(t, step, initial)
|
|
64
|
+
local total = initial
|
|
65
|
+
for i = 1, #t do
|
|
66
|
+
total = step(total, t[i], i)
|
|
67
|
+
end
|
|
68
|
+
return total
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
function __NAME__.includes(t, value)
|
|
72
|
+
for i = 1, #t do
|
|
73
|
+
if t[i] == value then
|
|
74
|
+
return true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
return false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
function __NAME__.indexOf(t, value, start)
|
|
81
|
+
for i = start or 1, #t do
|
|
82
|
+
if t[i] == value then
|
|
83
|
+
return i
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
return nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
function __NAME__.join(t, separator)
|
|
90
|
+
local out = {}
|
|
91
|
+
for i = 1, #t do
|
|
92
|
+
out[i] = tostring(t[i])
|
|
93
|
+
end
|
|
94
|
+
return table.concat(out, separator or ",")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
function __NAME__.concat(t, ...)
|
|
98
|
+
local out = {}
|
|
99
|
+
table.move(t, 1, #t, 1, out)
|
|
100
|
+
for i = 1, select("#", ...) do
|
|
101
|
+
local part = select(i, ...)
|
|
102
|
+
table.move(part, 1, #part, #out + 1, out)
|
|
103
|
+
end
|
|
104
|
+
return out
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
-- An inclusive range, as `string.sub` takes: `slice(2, 3)` is the second and
|
|
108
|
+
-- third elements, and a negative counts back from the last.
|
|
109
|
+
function __NAME__.slice(t, start, stop)
|
|
110
|
+
local n = #t
|
|
111
|
+
local from = start or 1
|
|
112
|
+
local to = stop or n
|
|
113
|
+
if from < 0 then from = n + from + 1 end
|
|
114
|
+
if to < 0 then to = n + to + 1 end
|
|
115
|
+
if from < 1 then from = 1 end
|
|
116
|
+
if to > n then to = n end
|
|
117
|
+
local out = {}
|
|
118
|
+
for i = from, to do
|
|
119
|
+
out[#out + 1] = t[i]
|
|
120
|
+
end
|
|
121
|
+
return out
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
-- One level, as JavaScript's `flat()` does by default.
|
|
125
|
+
function __NAME__.flat(t)
|
|
126
|
+
local out = {}
|
|
127
|
+
for i = 1, #t do
|
|
128
|
+
local value = t[i]
|
|
129
|
+
if type(value) == "table" then
|
|
130
|
+
table.move(value, 1, #value, #out + 1, out)
|
|
131
|
+
else
|
|
132
|
+
out[#out + 1] = value
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
return out
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
function __NAME__.reverse(t)
|
|
139
|
+
local n = #t
|
|
140
|
+
for i = 1, n // 2 do
|
|
141
|
+
t[i], t[n - i + 1] = t[n - i + 1], t[i]
|
|
142
|
+
end
|
|
143
|
+
return t
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
function __NAME__.sort(t, compare)
|
|
147
|
+
if compare then
|
|
148
|
+
table.sort(t, compare)
|
|
149
|
+
else
|
|
150
|
+
table.sort(t)
|
|
151
|
+
end
|
|
152
|
+
return t
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
function __NAME__.push(t, ...)
|
|
156
|
+
local n = #t
|
|
157
|
+
for i = 1, select("#", ...) do
|
|
158
|
+
t[n + i] = select(i, ...)
|
|
159
|
+
end
|
|
160
|
+
return #t
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
function __NAME__.pop(t)
|
|
164
|
+
local n = #t
|
|
165
|
+
local last = t[n]
|
|
166
|
+
t[n] = nil
|
|
167
|
+
return last
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
function __NAME__.shift(t)
|
|
171
|
+
return table.remove(t, 1)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
function __NAME__.unshift(t, ...)
|
|
175
|
+
for i = select("#", ...), 1, -1 do
|
|
176
|
+
table.insert(t, 1, (select(i, ...)))
|
|
177
|
+
end
|
|
178
|
+
return #t
|
|
179
|
+
end
|