@tilua/compiler 6.1.0 → 7.0.1
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/README.md +80 -22
- package/dist/{chunk-574KDV5W.js → chunk-WGXXYKEU.js} +567 -82
- package/dist/cli.cjs +570 -91
- package/dist/cli.js +4 -10
- package/dist/index.cjs +567 -83
- package/dist/index.d.cts +165 -115
- package/dist/index.d.ts +165 -115
- package/dist/index.js +1 -2
- package/package.json +2 -2
- package/runtime/json.luau +255 -0
package/dist/cli.cjs
CHANGED
|
@@ -44,7 +44,7 @@ var index = (object2, key) => ({ type: "IndexExpression", object: object2, index
|
|
|
44
44
|
var call = (callee, args2) => ({ type: "CallExpression", callee, arguments: args2, ...span() });
|
|
45
45
|
var methodCall = (object2, method, args2) => ({ type: "MethodCallExpression", object: object2, method: identifier(method), arguments: args2, ...span() });
|
|
46
46
|
var functionExpression = (func) => ({ type: "FunctionExpression", func, ...span() });
|
|
47
|
-
var binary = (operator, left, right) => ({ type: "BinaryExpression", operator, left, right, ...span() });
|
|
47
|
+
var binary = (operator, left, right) => ({ type: "BinaryExpression", operator, left: operator === "^" && left.type === "UnaryExpression" ? parenthesized(left) : left, right, ...span() });
|
|
48
48
|
var unary = (operator, argument) => ({ type: "UnaryExpression", operator, argument, ...span() });
|
|
49
49
|
var parenthesized = (expression) => ({ type: "ParenthesizedExpression", expression, ...span() });
|
|
50
50
|
var table = (fields) => ({ type: "TableExpression", fields, ...span() });
|
|
@@ -103,19 +103,19 @@ var Names = class _Names {
|
|
|
103
103
|
* a name shared across modules (the module table) collides with none. */
|
|
104
104
|
static from(...programs) {
|
|
105
105
|
const taken = /* @__PURE__ */ new Set(["select", "pairs", "table", "tostring", "setmetatable", "error"]);
|
|
106
|
-
const
|
|
106
|
+
const walk2 = (value) => {
|
|
107
107
|
if (!value || typeof value !== "object") return;
|
|
108
108
|
if (Array.isArray(value)) {
|
|
109
|
-
for (const item of value)
|
|
109
|
+
for (const item of value) walk2(item);
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
112
|
const node = value;
|
|
113
113
|
if (typeof node.name === "string" && node.name) taken.add(node.name);
|
|
114
114
|
for (const [key, child] of Object.entries(value)) {
|
|
115
|
-
if (key !== "line" && key !== "column")
|
|
115
|
+
if (key !== "line" && key !== "column") walk2(child);
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
-
for (const program2 of programs)
|
|
118
|
+
for (const program2 of programs) walk2(program2);
|
|
119
119
|
return new _Names(taken);
|
|
120
120
|
}
|
|
121
121
|
/** A copy that goes on to take names independently — one per module, each
|
|
@@ -123,6 +123,10 @@ var Names = class _Names {
|
|
|
123
123
|
fork() {
|
|
124
124
|
return new _Names(new Set(this.taken));
|
|
125
125
|
}
|
|
126
|
+
/** `name`, chosen elsewhere, is not to be chosen again here. */
|
|
127
|
+
take(name) {
|
|
128
|
+
this.taken.add(name);
|
|
129
|
+
}
|
|
126
130
|
/** `base`, or `base2`, `base3`, ... — whichever is free first. */
|
|
127
131
|
fresh(base) {
|
|
128
132
|
let name = base;
|
|
@@ -140,6 +144,7 @@ var implemented = (source) => new Set([...source.matchAll(/function __NAME__\.(\
|
|
|
140
144
|
var array = read("array.luau");
|
|
141
145
|
var string2 = read("string.luau");
|
|
142
146
|
var object = read("object.luau");
|
|
147
|
+
var json = read("json.luau");
|
|
143
148
|
var arrayMethods = implemented(array);
|
|
144
149
|
var stringMethods = implemented(string2);
|
|
145
150
|
var objectMethods = implemented(object);
|
|
@@ -172,7 +177,7 @@ function objectKeys(type) {
|
|
|
172
177
|
return { known, open: String(open) };
|
|
173
178
|
}
|
|
174
179
|
var plugin = {
|
|
175
|
-
runtime: { array, string: string2, object },
|
|
180
|
+
runtime: { array, string: string2, object, json },
|
|
176
181
|
methodCall({ method, receiver, use }) {
|
|
177
182
|
if (isString(receiver)) {
|
|
178
183
|
return stringMethods.has(method) ? { callee: `${use("string")}.${method}` } : void 0;
|
|
@@ -261,6 +266,141 @@ var plugin2 = {
|
|
|
261
266
|
var standardLowering = { plugin: plugin2, from: "tilua (standard library)" };
|
|
262
267
|
|
|
263
268
|
// src/lower.ts
|
|
269
|
+
function syntaxOf(lowerings) {
|
|
270
|
+
return new Set((lowerings ?? []).flatMap((l) => l.plugin.syntax ?? []));
|
|
271
|
+
}
|
|
272
|
+
var SharedRuntime = class {
|
|
273
|
+
constructor(names) {
|
|
274
|
+
this.names = names;
|
|
275
|
+
}
|
|
276
|
+
names;
|
|
277
|
+
byKey = /* @__PURE__ */ new Map();
|
|
278
|
+
/** Each group of names and the statements that declare them as locals,
|
|
279
|
+
* in the order they were first defined: each after what it uses. */
|
|
280
|
+
definitions = [];
|
|
281
|
+
defined = /* @__PURE__ */ new Set();
|
|
282
|
+
/** The name the helper `key` goes by, in every module. */
|
|
283
|
+
name(key, base) {
|
|
284
|
+
let name = this.byKey.get(key);
|
|
285
|
+
if (!name) {
|
|
286
|
+
name = this.names.fresh(base);
|
|
287
|
+
this.byKey.set(key, name);
|
|
288
|
+
}
|
|
289
|
+
return name;
|
|
290
|
+
}
|
|
291
|
+
/** `statements` declare `names`. Only the first module to say so is heard:
|
|
292
|
+
* the others' are the same. */
|
|
293
|
+
define(names, statements) {
|
|
294
|
+
if (names.every((name) => this.defined.has(name))) return;
|
|
295
|
+
for (const name of names) this.defined.add(name);
|
|
296
|
+
this.definitions.push({ names, statements });
|
|
297
|
+
}
|
|
298
|
+
/** Tree shaking: leave out of each runtime table the members nothing
|
|
299
|
+
* reads. `code` is everything else the output holds — the modules —
|
|
300
|
+
* and a member is read when it, or a member read already, names it:
|
|
301
|
+
* `tilua_array.filter(xs, f)` keeps `filter`, and whatever `filter`
|
|
302
|
+
* itself calls. A table used as anything but `table.member` — handed
|
|
303
|
+
* on, walked, indexed by what only the running program knows — keeps
|
|
304
|
+
* every member. */
|
|
305
|
+
shake(code) {
|
|
306
|
+
const names = new Set(this.definitions.flatMap((group) => group.names));
|
|
307
|
+
const read3 = /* @__PURE__ */ new Map();
|
|
308
|
+
const use = (name, key) => {
|
|
309
|
+
const now = read3.get(name);
|
|
310
|
+
if (now === "all") return;
|
|
311
|
+
if (key === void 0) {
|
|
312
|
+
read3.set(name, "all");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
read3.set(name, (now ?? /* @__PURE__ */ new Set()).add(key));
|
|
316
|
+
};
|
|
317
|
+
const isRead = (name, key) => {
|
|
318
|
+
const now = read3.get(name);
|
|
319
|
+
return now === "all" || (now?.has(key) ?? false);
|
|
320
|
+
};
|
|
321
|
+
const scan = (value) => {
|
|
322
|
+
if (!value || typeof value !== "object") return;
|
|
323
|
+
if (Array.isArray(value)) return void value.forEach(scan);
|
|
324
|
+
const node = value;
|
|
325
|
+
const object2 = node.object;
|
|
326
|
+
if (object2?.type === "Identifier" && names.has(object2.name)) {
|
|
327
|
+
if (node.type === "MemberExpression") return use(object2.name, node.property.name);
|
|
328
|
+
if (node.type === "MethodCallExpression") {
|
|
329
|
+
use(object2.name, node.method.name);
|
|
330
|
+
return scan(node.arguments);
|
|
331
|
+
}
|
|
332
|
+
if (node.type === "IndexExpression") {
|
|
333
|
+
const index2 = node.index;
|
|
334
|
+
if (index2.type === "StringLiteral") return use(object2.name, String(index2.value));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (node.type === "Identifier" && names.has(node.name)) return use(node.name);
|
|
338
|
+
if (node.type === "LocalFunctionStatement") return scan(node.func);
|
|
339
|
+
for (const [key, child] of Object.entries(node)) {
|
|
340
|
+
if (key !== "line" && key !== "column") scan(child);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const defines = (statement, own) => {
|
|
344
|
+
if (statement.type === "FunctionDeclarationStatement") {
|
|
345
|
+
const target = statement.target;
|
|
346
|
+
if (own.includes(target.base.name) && target.path.length === 1 && !target.method) {
|
|
347
|
+
return { name: target.base.name, key: target.path[0].name, value: statement.func };
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (statement.type === "AssignmentStatement" && statement.targets.length === 1 && statement.values.length === 1) {
|
|
351
|
+
const target = statement.targets[0];
|
|
352
|
+
if (target.object?.type === "Identifier" && own.includes(target.object.name)) {
|
|
353
|
+
if (target.type === "MemberExpression") return { name: target.object.name, key: target.property.name, value: statement.values[0] };
|
|
354
|
+
if (target.type === "IndexExpression" && target.index?.type === "StringLiteral") {
|
|
355
|
+
return { name: target.object.name, key: String(target.index.value), value: statement.values[0] };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return void 0;
|
|
360
|
+
};
|
|
361
|
+
scan(code);
|
|
362
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
363
|
+
let more = true;
|
|
364
|
+
while (more) {
|
|
365
|
+
more = false;
|
|
366
|
+
for (const group of this.definitions) {
|
|
367
|
+
for (const statement of group.statements) {
|
|
368
|
+
if (scanned.has(statement)) continue;
|
|
369
|
+
const definition = defines(statement, group.names);
|
|
370
|
+
if (definition && !isRead(definition.name, definition.key)) continue;
|
|
371
|
+
scanned.add(statement);
|
|
372
|
+
more = true;
|
|
373
|
+
scan(definition ? definition.value : statement);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
for (const group of this.definitions) {
|
|
378
|
+
group.statements = group.statements.filter((statement) => {
|
|
379
|
+
const definition = defines(statement, group.names);
|
|
380
|
+
return !definition || isRead(definition.name, definition.key);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/** Luau setting up the helpers `used` for a chunk whose code names them:
|
|
385
|
+
* `declare` goes before that code, which reads each as an upvalue, and
|
|
386
|
+
* `define` after it — before any of it runs, and after what a helper
|
|
387
|
+
* reads as it is set up (the line map). Each definition runs in a
|
|
388
|
+
* function of its own, so what it keeps to itself stays there. */
|
|
389
|
+
chunk(used) {
|
|
390
|
+
const groups = this.definitions.filter((group) => group.names.some((name) => used.has(name)));
|
|
391
|
+
const all = groups.flatMap((group) => group.names);
|
|
392
|
+
const declare = [];
|
|
393
|
+
for (let i = 0; i < all.length; i += 100) declare.push(local(all.slice(i, i + 100), []));
|
|
394
|
+
const define = groups.map((group) => assign(
|
|
395
|
+
group.names.map((name) => identifier(name)),
|
|
396
|
+
[call(parenthesized(functionExpression(functionBody([], [
|
|
397
|
+
...group.statements,
|
|
398
|
+
returns(group.names.map((name) => identifier(name)))
|
|
399
|
+
]))), [])]
|
|
400
|
+
));
|
|
401
|
+
return { declare, define };
|
|
402
|
+
}
|
|
403
|
+
};
|
|
264
404
|
function lower(program2, scopes, options = {}) {
|
|
265
405
|
const result2 = new Lowerer(program2, scopes, options).run();
|
|
266
406
|
dropUnreachable(result2.statements);
|
|
@@ -291,7 +431,7 @@ var Lowerer = class {
|
|
|
291
431
|
this.source = source;
|
|
292
432
|
this.scopes = scopes;
|
|
293
433
|
this.options = options;
|
|
294
|
-
this.
|
|
434
|
+
this.syntax = syntaxOf(options.lowerings);
|
|
295
435
|
this.names = options.names ? options.names.fork() : Names.from(source);
|
|
296
436
|
this.exportsName = this.names.fresh("exports");
|
|
297
437
|
for (const binding of scopes.bindings.values()) {
|
|
@@ -316,6 +456,11 @@ var Lowerer = class {
|
|
|
316
456
|
names;
|
|
317
457
|
diagnostics = [];
|
|
318
458
|
helpers = /* @__PURE__ */ new Map();
|
|
459
|
+
/** The shared helpers this file names. */
|
|
460
|
+
sharedUsed = /* @__PURE__ */ new Set();
|
|
461
|
+
/** While a shared helper is written: it is defined outside every module,
|
|
462
|
+
* where none of a module's own names shadows a global. */
|
|
463
|
+
rawGlobals = false;
|
|
319
464
|
/** The binding each declaration node creates. */
|
|
320
465
|
bindingByDeclaration = /* @__PURE__ */ new Map();
|
|
321
466
|
/** tilua names that are Luau keywords, and what they are called instead. */
|
|
@@ -331,8 +476,8 @@ var Lowerer = class {
|
|
|
331
476
|
tryFrames = [];
|
|
332
477
|
/** The loops being lowered in the current function, innermost last. */
|
|
333
478
|
loops = [];
|
|
334
|
-
/**
|
|
335
|
-
|
|
479
|
+
/** What the output's Lua can write beyond Lua 5.1 (`syntaxOf`). */
|
|
480
|
+
syntax;
|
|
336
481
|
/** The source line each emitted statement came from. */
|
|
337
482
|
origins = /* @__PURE__ */ new WeakMap();
|
|
338
483
|
/** The name each class written as a value is known by. */
|
|
@@ -340,15 +485,19 @@ var Lowerer = class {
|
|
|
340
485
|
run() {
|
|
341
486
|
const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
|
|
342
487
|
const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
|
|
488
|
+
this.rawGlobals = this.options.shared !== void 0;
|
|
343
489
|
const helpers = this.helperDefinitions();
|
|
490
|
+
const classes = this.classRuntimeStatements();
|
|
491
|
+
this.rawGlobals = false;
|
|
344
492
|
const captured = [...this.builtins].map(([global, local2]) => local([local2], [identifier(global)]));
|
|
345
493
|
return {
|
|
346
|
-
statements: [...captured, ...helpers, ...scriptArgs, ...
|
|
494
|
+
statements: [...captured, ...helpers, ...scriptArgs, ...classes, ...body],
|
|
347
495
|
exportsName: this.exportsName,
|
|
348
496
|
module: this.info,
|
|
349
497
|
diagnostics: this.diagnostics,
|
|
350
498
|
origins: this.origins,
|
|
351
|
-
usesScriptArgs: this.usesScriptArgs
|
|
499
|
+
usesScriptArgs: this.usesScriptArgs,
|
|
500
|
+
shared: [...this.sharedUsed]
|
|
352
501
|
};
|
|
353
502
|
}
|
|
354
503
|
/** Whether the file reads `scriptArgs`, the language's own global. */
|
|
@@ -381,6 +530,7 @@ var Lowerer = class {
|
|
|
381
530
|
/** A global the generated code calls — `pairs`, `table`, ... — under a name
|
|
382
531
|
* the source cannot have shadowed. */
|
|
383
532
|
builtin(global) {
|
|
533
|
+
if (this.rawGlobals) return identifier(global);
|
|
384
534
|
let local2 = this.builtins.get(global);
|
|
385
535
|
if (!local2) {
|
|
386
536
|
const shadowed = [...this.scopes.bindings.values()].some((b) => b.name === global && b.kind !== "global");
|
|
@@ -392,16 +542,31 @@ var Lowerer = class {
|
|
|
392
542
|
}
|
|
393
543
|
/** `table.move`. Lua 5.1 has none, and gets a function that does the same. */
|
|
394
544
|
move() {
|
|
395
|
-
return this.
|
|
545
|
+
return this.helper("move");
|
|
396
546
|
}
|
|
397
547
|
helper(kind) {
|
|
398
548
|
let name = this.helpers.get(kind);
|
|
399
549
|
if (!name) {
|
|
400
|
-
name = this.
|
|
550
|
+
name = this.sharedName(`helper:${kind}`, `tilua_${kind === "array" ? "asArray" : kind}`);
|
|
401
551
|
this.helpers.set(kind, name);
|
|
402
552
|
}
|
|
403
553
|
return identifier(name);
|
|
404
554
|
}
|
|
555
|
+
/** A fresh name for a helper — in a bundle, the one every module calls
|
|
556
|
+
* that helper by. */
|
|
557
|
+
sharedName(key, base) {
|
|
558
|
+
const shared = this.options.shared;
|
|
559
|
+
if (!shared) return this.names.fresh(base);
|
|
560
|
+
const name = shared.name(key, base);
|
|
561
|
+
this.names.take(name);
|
|
562
|
+
this.sharedUsed.add(name);
|
|
563
|
+
return name;
|
|
564
|
+
}
|
|
565
|
+
/** `statements` declare `names`: in this file, or once for the bundle. */
|
|
566
|
+
define(names, statements, out2) {
|
|
567
|
+
if (this.options.shared) this.options.shared.define(names, statements);
|
|
568
|
+
else out2.push(...statements);
|
|
569
|
+
}
|
|
405
570
|
// `typeof v` tells an array from an object, which Luau cannot: both are
|
|
406
571
|
// tables. So every array the program makes — `[a, b]`, a rest parameter,
|
|
407
572
|
// what `:map` answers — is written down as one, in a table that holds its
|
|
@@ -434,7 +599,8 @@ var Lowerer = class {
|
|
|
434
599
|
const key = `${index2}:${runtime2}`;
|
|
435
600
|
let name = this.loweringNames.get(key);
|
|
436
601
|
if (!name) {
|
|
437
|
-
|
|
602
|
+
const lines = this.lowerings[index2].plugin.runtime?.[runtime2]?.includes("__LINES__") ? this.options.module?.lines : "";
|
|
603
|
+
name = this.sharedName(`lowering:${key}:${lines}`, `tilua_${runtime2.replace(/[^A-Za-z0-9_]/g, "_")}`);
|
|
438
604
|
this.loweringNames.set(key, name);
|
|
439
605
|
this.loweringUsed.push({ index: index2, runtime: runtime2, name });
|
|
440
606
|
}
|
|
@@ -634,19 +800,25 @@ var Lowerer = class {
|
|
|
634
800
|
const runtimes = this.runtimeDefinitions();
|
|
635
801
|
if (this.helpers.has("concat")) this.helper("array");
|
|
636
802
|
if (this.helpers.has("concat")) this.move();
|
|
803
|
+
const unpack = this.helpers.get("unpack");
|
|
804
|
+
if (unpack) {
|
|
805
|
+
this.define([unpack], (0, import_luau_parser.parse)(
|
|
806
|
+
`local ${unpack} = ${this.builtin("table").name}.unpack or ${this.builtin("unpack").name}`
|
|
807
|
+
).body.statements, out2);
|
|
808
|
+
}
|
|
637
809
|
const move = this.helpers.get("move");
|
|
638
810
|
if (move) {
|
|
639
|
-
|
|
640
|
-
local
|
|
811
|
+
this.define([move], (0, import_luau_parser.parse)(`
|
|
812
|
+
local ${move} = ${this.builtin("table").name}.move or function(from, first, last, at, to)
|
|
641
813
|
for i = first, last do
|
|
642
814
|
to[at + i - first] = from[i]
|
|
643
815
|
end
|
|
644
816
|
return to
|
|
645
|
-
end`).body.statements);
|
|
817
|
+
end`).body.statements, out2);
|
|
646
818
|
}
|
|
647
819
|
const each = this.helpers.get("each");
|
|
648
820
|
if (each) {
|
|
649
|
-
|
|
821
|
+
this.define([each], (0, import_luau_parser.parse)(`
|
|
650
822
|
local function ${each}(source, ...)
|
|
651
823
|
if ${this.builtin("type").name}(source) == "function" then
|
|
652
824
|
return source, ...
|
|
@@ -656,7 +828,7 @@ local function ${each}(source, ...)
|
|
|
656
828
|
return meta.__iter(source)
|
|
657
829
|
end
|
|
658
830
|
return ${this.builtin("next").name}, source
|
|
659
|
-
end`).body.statements);
|
|
831
|
+
end`).body.statements, out2);
|
|
660
832
|
}
|
|
661
833
|
const marker = this.helpers.get("array");
|
|
662
834
|
const typeOf = this.helpers.get("typeof");
|
|
@@ -664,19 +836,19 @@ end`).body.statements);
|
|
|
664
836
|
const arrays = this.arrays();
|
|
665
837
|
const own = this.helpers.get("arrays");
|
|
666
838
|
if (own) {
|
|
667
|
-
|
|
839
|
+
this.define([own], (0, import_luau_parser.parse)(`local ${own} = ${this.builtin("setmetatable").name}({}, { __mode = "k" })`).body.statements, out2);
|
|
668
840
|
}
|
|
669
841
|
if (marker) {
|
|
670
|
-
|
|
842
|
+
this.define([marker], (0, import_luau_parser.parse)(`
|
|
671
843
|
local function ${marker}(t)
|
|
672
844
|
${arrays}[t] = true
|
|
673
845
|
return t
|
|
674
|
-
end`).body.statements);
|
|
846
|
+
end`).body.statements, out2);
|
|
675
847
|
}
|
|
676
848
|
if (typeOf) {
|
|
677
|
-
|
|
849
|
+
this.define([typeOf], (0, import_luau_parser.parse)(`
|
|
678
850
|
local function ${typeOf}(value, known)
|
|
679
|
-
local name = ${this.builtin(
|
|
851
|
+
local name = (${this.builtin("typeof").name} or ${this.builtin("type").name})(value)
|
|
680
852
|
if name ~= "table" then
|
|
681
853
|
return name
|
|
682
854
|
end
|
|
@@ -693,22 +865,22 @@ local function ${typeOf}(value, known)
|
|
|
693
865
|
return "array"
|
|
694
866
|
end
|
|
695
867
|
return "object"
|
|
696
|
-
end`).body.statements);
|
|
868
|
+
end`).body.statements, out2);
|
|
697
869
|
}
|
|
698
870
|
}
|
|
699
871
|
const add = this.helpers.get("add");
|
|
700
872
|
if (add) {
|
|
701
|
-
|
|
873
|
+
this.define([add], (0, import_luau_parser.parse)(`
|
|
702
874
|
local function ${add}(a, b)
|
|
703
875
|
if ${this.builtin("type").name}(a) == "string" or ${this.builtin("type").name}(b) == "string" then
|
|
704
876
|
return ${this.builtin("tostring").name}(a) .. ${this.builtin("tostring").name}(b)
|
|
705
877
|
end
|
|
706
878
|
return a + b
|
|
707
|
-
end`).body.statements);
|
|
879
|
+
end`).body.statements, out2);
|
|
708
880
|
}
|
|
709
881
|
const instanceOf = this.helpers.get("instanceof");
|
|
710
882
|
if (instanceOf) {
|
|
711
|
-
|
|
883
|
+
this.define([instanceOf], (0, import_luau_parser.parse)(`
|
|
712
884
|
local function ${instanceOf}(value, class)
|
|
713
885
|
if ${this.builtin("type").name}(value) ~= "table" then
|
|
714
886
|
return false
|
|
@@ -721,11 +893,11 @@ local function ${instanceOf}(value, class)
|
|
|
721
893
|
current = current.ParentClass
|
|
722
894
|
end
|
|
723
895
|
return false
|
|
724
|
-
end`).body.statements);
|
|
896
|
+
end`).body.statements, out2);
|
|
725
897
|
}
|
|
726
898
|
const accessors = this.helpers.get("accessors");
|
|
727
899
|
if (accessors) {
|
|
728
|
-
|
|
900
|
+
this.define([accessors], (0, import_luau_parser.parse)(`
|
|
729
901
|
local function ${accessors}(target, getters, setters)
|
|
730
902
|
return ${this.builtin("setmetatable").name}(target, {
|
|
731
903
|
-- Read by a spread, which copies what the getters give.
|
|
@@ -749,11 +921,11 @@ local function ${accessors}(target, getters, setters)
|
|
|
749
921
|
${this.builtin("rawset").name}(self, key, value)
|
|
750
922
|
end,
|
|
751
923
|
})
|
|
752
|
-
end`).body.statements);
|
|
924
|
+
end`).body.statements, out2);
|
|
753
925
|
}
|
|
754
926
|
const assign2 = this.helpers.get("assign");
|
|
755
927
|
if (assign2) {
|
|
756
|
-
|
|
928
|
+
this.define([assign2], (0, import_luau_parser.parse)(`
|
|
757
929
|
local function ${assign2}(target, ...)
|
|
758
930
|
for i = 1, ${this.builtin("select").name}("#", ...) do
|
|
759
931
|
local source = (${this.builtin("select").name}(i, ...))
|
|
@@ -771,12 +943,12 @@ local function ${assign2}(target, ...)
|
|
|
771
943
|
end
|
|
772
944
|
end
|
|
773
945
|
return target
|
|
774
|
-
end`).body.statements);
|
|
946
|
+
end`).body.statements, out2);
|
|
775
947
|
}
|
|
776
|
-
|
|
948
|
+
for (const { names, statements } of runtimes) this.define(names, statements, out2);
|
|
777
949
|
const concat = this.helpers.get("concat");
|
|
778
950
|
if (concat) {
|
|
779
|
-
|
|
951
|
+
this.define([concat], [localFunction(concat, functionBody([], [
|
|
780
952
|
local(["result"], [this.array(table([]))]),
|
|
781
953
|
numericFor("i", number(1), selectCount(this.builtin("select")), [
|
|
782
954
|
local(["part"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
|
|
@@ -789,7 +961,7 @@ end`).body.statements);
|
|
|
789
961
|
]))
|
|
790
962
|
]),
|
|
791
963
|
returns([identifier("result")])
|
|
792
|
-
], true)));
|
|
964
|
+
], true))], out2);
|
|
793
965
|
}
|
|
794
966
|
return out2;
|
|
795
967
|
}
|
|
@@ -809,7 +981,12 @@ end`).body.statements);
|
|
|
809
981
|
}
|
|
810
982
|
const lines = this.options.module?.lines ?? "nil";
|
|
811
983
|
const fail = this.options.module?.fail ?? "nil";
|
|
812
|
-
|
|
984
|
+
const group = {
|
|
985
|
+
names: [name],
|
|
986
|
+
statements: (0, import_luau_parser.parse)(source.replace(/__NAME__/g, name).replace(/__LINES__/g, lines).replace(/__FAIL__/g, fail).replace(/__ARRAYS__/g, () => this.arrays()).replace(/__ARRAY__/g, () => this.helper("array").name).replace(/__JSON__/g, () => this.loweringRuntime(0, "json"))).body.statements
|
|
987
|
+
};
|
|
988
|
+
if (index2 === 0 && runtime2 === "json") out2.unshift(group);
|
|
989
|
+
else out2.push(group);
|
|
813
990
|
}
|
|
814
991
|
return out2;
|
|
815
992
|
}
|
|
@@ -824,7 +1001,8 @@ end`).body.statements);
|
|
|
824
1001
|
* util = require("util") -- the imports
|
|
825
1002
|
* ... -- the rest, in source order */
|
|
826
1003
|
module(context) {
|
|
827
|
-
const
|
|
1004
|
+
const shaken = this.options.shaken;
|
|
1005
|
+
const statements = shaken ? this.source.body.statements.filter((s) => !shaken.removed.has(s)) : this.source.body.statements;
|
|
828
1006
|
const exportsTable = () => identifier(this.exportsName);
|
|
829
1007
|
const { names, links, stars } = this.info;
|
|
830
1008
|
const locals = [];
|
|
@@ -863,13 +1041,24 @@ end`).body.statements);
|
|
|
863
1041
|
};
|
|
864
1042
|
for (const statement of statements) {
|
|
865
1043
|
if (statement.type !== "ImportStatement" || statement.isTypeOnly) continue;
|
|
1044
|
+
if (!statement.defaultImport && !statement.namespaceImport && !statement.specifiers.length) {
|
|
1045
|
+
const key2 = resolve4(statement.source);
|
|
1046
|
+
if (key2 !== void 0) load(key2);
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
866
1049
|
const specifiers = [
|
|
867
1050
|
...statement.defaultImport ? [{ local: statement.defaultImport, imported: "default" }] : [],
|
|
868
1051
|
...statement.namespaceImport ? [{ local: statement.namespaceImport, imported: void 0 }] : [],
|
|
869
1052
|
...statement.specifiers.map((s) => ({ local: s.local, imported: s.imported.name }))
|
|
870
1053
|
];
|
|
871
|
-
const used = specifiers.filter((s) => (this.bindingByDeclaration.get(s.local)?.references
|
|
872
|
-
if (!used.length)
|
|
1054
|
+
const used = specifiers.filter((s) => (this.bindingByDeclaration.get(s.local)?.references ?? []).some((reference) => !shaken?.dead.has(reference)));
|
|
1055
|
+
if (!used.length) {
|
|
1056
|
+
if (shaken?.runs(statement.source.value)) {
|
|
1057
|
+
const key2 = resolve4(statement.source);
|
|
1058
|
+
if (key2 !== void 0) load(key2);
|
|
1059
|
+
}
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
873
1062
|
const key = resolve4(statement.source);
|
|
874
1063
|
if (key === void 0) continue;
|
|
875
1064
|
const local2 = moduleLocal(key);
|
|
@@ -911,6 +1100,7 @@ end`).body.statements);
|
|
|
911
1100
|
break;
|
|
912
1101
|
}
|
|
913
1102
|
case "ExportAllStatement": {
|
|
1103
|
+
if (shaken && !shaken.needed(statement.source.value)) break;
|
|
914
1104
|
const key = resolve4(statement.source);
|
|
915
1105
|
if (key === void 0) break;
|
|
916
1106
|
load(key);
|
|
@@ -1185,7 +1375,7 @@ end`).body.statements);
|
|
|
1185
1375
|
case "VariableDeclaration":
|
|
1186
1376
|
return this.variableDeclaration(node, "declare");
|
|
1187
1377
|
case "FunctionDeclaration":
|
|
1188
|
-
return [{ ...localFunction(this.name(node.name.name), this.functionBody(node.func)), attributes: this.
|
|
1378
|
+
return [{ ...localFunction(this.name(node.name.name), this.functionBody(node.func)), attributes: this.syntax.has("attributes") ? node.attributes : void 0 }];
|
|
1189
1379
|
case "FunctionDeclarationStatement":
|
|
1190
1380
|
return [this.functionDeclarationStatement(node)];
|
|
1191
1381
|
case "ClassDeclaration":
|
|
@@ -1197,7 +1387,7 @@ end`).body.statements);
|
|
|
1197
1387
|
const join2 = node.operator === "+=" ? this.options.types?.joins.get(node) : void 0;
|
|
1198
1388
|
if (join2 === "dynamic") return this.dynamicAddition(node);
|
|
1199
1389
|
const operator = join2 === "concat" ? "..=" : node.operator;
|
|
1200
|
-
if (this.
|
|
1390
|
+
if (!this.syntax.has("compoundAssignment")) return this.compoundAssignment51(node, operator);
|
|
1201
1391
|
return [{
|
|
1202
1392
|
type: "CompoundAssignmentStatement",
|
|
1203
1393
|
operator,
|
|
@@ -1235,10 +1425,10 @@ end`).body.statements);
|
|
|
1235
1425
|
case "RepeatStatement": {
|
|
1236
1426
|
const body = this.block(node.body);
|
|
1237
1427
|
const condition = this.expression(node.condition);
|
|
1238
|
-
if (this.
|
|
1428
|
+
if (!this.syntax.has("continue") && hasOwnJump(body.statements, "ContinueStatement")) {
|
|
1239
1429
|
const hidden = declaredNames(body.statements).filter((name) => mentions(condition, name));
|
|
1240
1430
|
if (hidden.length) {
|
|
1241
|
-
this.report(node, `'continue' in a 'repeat' whose 'until' reads ${hidden.map((n) => `'${n}'`).join(", ")} cannot be compiled
|
|
1431
|
+
this.report(node, `'continue' in a 'repeat' whose 'until' reads ${hidden.map((n) => `'${n}'`).join(", ")} cannot be compiled to Lua, which has no 'continue' to lower it to. Move what the condition reads out of the loop body, or use a 'while' loop \u2014 or load a library whose Lua has 'continue' ("luau").`);
|
|
1242
1432
|
}
|
|
1243
1433
|
}
|
|
1244
1434
|
return [{ type: "RepeatStatement", body: this.loopBody51(body), condition, ...spanOf(node) }];
|
|
@@ -1279,8 +1469,8 @@ end`).body.statements);
|
|
|
1279
1469
|
let source = this.expression(node.iterator);
|
|
1280
1470
|
if (form.viaIter) source = methodCall(source, "__iter", []);
|
|
1281
1471
|
const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
|
|
1282
|
-
let iterators = form.walks === "iteration" ? [call(this.
|
|
1283
|
-
if (this.
|
|
1472
|
+
let iterators = form.walks === "iteration" ? [call(this.helper("unpack"), [source, number(1), number(3)])] : [source];
|
|
1473
|
+
if (!this.syntax.has("iteration") && form.walks === "values") {
|
|
1284
1474
|
const kind = form.viaIter ? void 0 : this.options.types?.typeOf.get(node.iterator)?.kind;
|
|
1285
1475
|
iterators = [call(kind === "array" || kind === "tuple" ? this.builtin("ipairs") : this.helper("each"), [source])];
|
|
1286
1476
|
}
|
|
@@ -1436,8 +1626,8 @@ end`).body.statements);
|
|
|
1436
1626
|
classHelpers;
|
|
1437
1627
|
classRuntime() {
|
|
1438
1628
|
return this.classHelpers ??= {
|
|
1439
|
-
build: this.
|
|
1440
|
-
accessors: this.
|
|
1629
|
+
build: this.sharedName("class:build", "tilua_class"),
|
|
1630
|
+
accessors: this.sharedName("class:accessors", "tilua_accessors")
|
|
1441
1631
|
};
|
|
1442
1632
|
}
|
|
1443
1633
|
/** The helpers, as Luau — emitted only in a file that declares a class.
|
|
@@ -1455,7 +1645,8 @@ end`).body.statements);
|
|
|
1455
1645
|
if (!this.classHelpers) return [];
|
|
1456
1646
|
const { build, accessors } = this.classHelpers;
|
|
1457
1647
|
const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
|
|
1458
|
-
|
|
1648
|
+
const out2 = [];
|
|
1649
|
+
this.define([build, accessors], (0, import_luau_parser.parse)(`
|
|
1459
1650
|
local function ${build}(base, name)
|
|
1460
1651
|
local class = { __getters = {}, __setters = {} }
|
|
1461
1652
|
class.__index = class
|
|
@@ -1493,7 +1684,8 @@ local function ${accessors}(class)
|
|
|
1493
1684
|
rawset(this, key, value)
|
|
1494
1685
|
end
|
|
1495
1686
|
end
|
|
1496
|
-
`).body.statements;
|
|
1687
|
+
`).body.statements, out2);
|
|
1688
|
+
return out2;
|
|
1497
1689
|
}
|
|
1498
1690
|
/** The class being lowered, so `super` knows what to name. */
|
|
1499
1691
|
classContext;
|
|
@@ -1637,7 +1829,7 @@ end
|
|
|
1637
1829
|
isMethod,
|
|
1638
1830
|
func,
|
|
1639
1831
|
// `@native` and the like are Luau's.
|
|
1640
|
-
attributes: this.
|
|
1832
|
+
attributes: this.syntax.has("attributes") ? node.attributes : void 0,
|
|
1641
1833
|
...spanOf(node)
|
|
1642
1834
|
};
|
|
1643
1835
|
}
|
|
@@ -1877,7 +2069,7 @@ end
|
|
|
1877
2069
|
if (join2 === "concat") return binary("..", left, right);
|
|
1878
2070
|
if (join2 === "dynamic") return call(this.helper("add"), [this.keptToOne(left), this.keptToOne(right)]);
|
|
1879
2071
|
}
|
|
1880
|
-
if (this.
|
|
2072
|
+
if (!this.syntax.has("floorDivision") && node.operator === "//") return this.floorDivide(left, right);
|
|
1881
2073
|
return binary(node.operator, left, right);
|
|
1882
2074
|
}
|
|
1883
2075
|
case "UnaryExpression":
|
|
@@ -1911,7 +2103,7 @@ end
|
|
|
1911
2103
|
case "AsConstExpression":
|
|
1912
2104
|
return this.expression(node.expression);
|
|
1913
2105
|
case "IfElseExpression":
|
|
1914
|
-
if (this.
|
|
2106
|
+
if (!this.syntax.has("ifExpression")) return this.ifElse51(node);
|
|
1915
2107
|
return {
|
|
1916
2108
|
type: "IfElseExpression",
|
|
1917
2109
|
clauses: node.clauses.map((c) => ({ condition: this.expression(c.condition), body: this.expression(c.body) })),
|
|
@@ -1958,7 +2150,7 @@ end
|
|
|
1958
2150
|
const last2 = list.length - 1;
|
|
1959
2151
|
return lowered.length && !many.has(list[last2]) ? [...lowered.slice(0, -1), this.keptToOne(lowered[last2])] : lowered;
|
|
1960
2152
|
}
|
|
1961
|
-
const unpack = (value) => call(this.
|
|
2153
|
+
const unpack = (value) => call(this.helper("unpack"), [value]);
|
|
1962
2154
|
const last = list[list.length - 1];
|
|
1963
2155
|
if (spreads.length === 1 && last.type === "SpreadElement") {
|
|
1964
2156
|
return [...list.slice(0, -1).map((a) => this.expression(a)), unpack(this.expression(last.argument))];
|
|
@@ -2072,7 +2264,7 @@ end
|
|
|
2072
2264
|
const segments = this.segments(chain);
|
|
2073
2265
|
const base = this.expression(chain.base);
|
|
2074
2266
|
const last = chain.links[chain.links.length - 1];
|
|
2075
|
-
if (
|
|
2267
|
+
if (this.syntax.has("ifExpression") && base.type === "Identifier" && segments.length === 1 && last.type !== "CallExpression" && last.type !== "MethodCallExpression") {
|
|
2076
2268
|
return {
|
|
2077
2269
|
type: "IfElseExpression",
|
|
2078
2270
|
clauses: [{ condition: binary("==", base, nil()), body: nil() }],
|
|
@@ -2099,7 +2291,7 @@ end
|
|
|
2099
2291
|
nullish(node) {
|
|
2100
2292
|
const left = this.keptToOne(this.expression(node.left));
|
|
2101
2293
|
const right = this.keptToOne(this.expression(node.right));
|
|
2102
|
-
if (
|
|
2294
|
+
if (this.syntax.has("ifExpression") && left.type === "Identifier") {
|
|
2103
2295
|
return {
|
|
2104
2296
|
type: "IfElseExpression",
|
|
2105
2297
|
clauses: [{ condition: binary("~=", left, nil()), body: left }],
|
|
@@ -2186,14 +2378,19 @@ end
|
|
|
2186
2378
|
let target;
|
|
2187
2379
|
if (node.target.type === "MemberExpression" || node.target.type === "IndexExpression") {
|
|
2188
2380
|
const object2 = this.expression(node.target.object);
|
|
2189
|
-
const
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
target = member(identifier(objectName), node.target.property.name);
|
|
2381
|
+
const key = node.target.type === "IndexExpression" ? node.target.index : void 0;
|
|
2382
|
+
if (object2.type === "Identifier" && (key === void 0 || key.type === "StringLiteral" || key.type === "NumberLiteral")) {
|
|
2383
|
+
target = key === void 0 ? member(object2, node.target.property.name) : index(object2, this.expression(key));
|
|
2193
2384
|
} else {
|
|
2194
|
-
const
|
|
2195
|
-
before.push(local([
|
|
2196
|
-
target
|
|
2385
|
+
const objectName = this.names.fresh("target");
|
|
2386
|
+
before.push(local([objectName], [object2]));
|
|
2387
|
+
if (node.target.type === "MemberExpression") {
|
|
2388
|
+
target = member(identifier(objectName), node.target.property.name);
|
|
2389
|
+
} else {
|
|
2390
|
+
const keyName = this.names.fresh("key");
|
|
2391
|
+
before.push(local([keyName], [this.expression(node.target.index)]));
|
|
2392
|
+
target = index(identifier(objectName), identifier(keyName));
|
|
2393
|
+
}
|
|
2197
2394
|
}
|
|
2198
2395
|
} else {
|
|
2199
2396
|
target = this.expression(node.target);
|
|
@@ -2214,7 +2411,7 @@ end
|
|
|
2214
2411
|
* done, and breaks for real there. A body with no `continue` is left
|
|
2215
2412
|
* exactly as it was. */
|
|
2216
2413
|
loopBody51(body) {
|
|
2217
|
-
if (
|
|
2414
|
+
if (this.syntax.has("continue") || !hasOwnJump(body.statements, "ContinueStatement")) return body;
|
|
2218
2415
|
const flag = hasOwnJump(body.statements, "BreakStatement") ? this.names.fresh("broke") : void 0;
|
|
2219
2416
|
const once = repeatUntil(rewriteOwnJumps(body.statements, flag), boolean(true));
|
|
2220
2417
|
if (!flag) return block([once]);
|
|
@@ -2266,7 +2463,7 @@ end
|
|
|
2266
2463
|
* underscores and `0b1010` becomes the decimal it means. A hex literal
|
|
2267
2464
|
* keeps its base — 5.1 reads those. */
|
|
2268
2465
|
numberRaw(node) {
|
|
2269
|
-
if (
|
|
2466
|
+
if (this.syntax.has("numberLiterals")) return node.raw;
|
|
2270
2467
|
if (/^0[bB]/.test(node.raw)) return String(node.value);
|
|
2271
2468
|
return node.raw.replace(/_/g, "");
|
|
2272
2469
|
}
|
|
@@ -2390,6 +2587,7 @@ function usesVararg(node) {
|
|
|
2390
2587
|
return Object.values(record).some(usesVararg);
|
|
2391
2588
|
}
|
|
2392
2589
|
function calleePath(path) {
|
|
2590
|
+
if (!/^[A-Za-z_]\w*(\.[A-Za-z_]\w*)*$/.test(path)) return (0, import_luau_parser.parseExpressionFromSource)(path);
|
|
2393
2591
|
const [head, ...rest] = path.split(".");
|
|
2394
2592
|
return rest.reduce((value, name) => member(value, name), identifier(head));
|
|
2395
2593
|
}
|
|
@@ -2519,10 +2717,10 @@ function declaredNames(statements) {
|
|
|
2519
2717
|
}
|
|
2520
2718
|
function mentions(expression, name) {
|
|
2521
2719
|
let found = false;
|
|
2522
|
-
const
|
|
2720
|
+
const walk2 = (value) => {
|
|
2523
2721
|
if (found || !value || typeof value !== "object") return;
|
|
2524
2722
|
if (Array.isArray(value)) {
|
|
2525
|
-
for (const item of value)
|
|
2723
|
+
for (const item of value) walk2(item);
|
|
2526
2724
|
return;
|
|
2527
2725
|
}
|
|
2528
2726
|
const node = value;
|
|
@@ -2531,10 +2729,10 @@ function mentions(expression, name) {
|
|
|
2531
2729
|
return;
|
|
2532
2730
|
}
|
|
2533
2731
|
for (const [key, child] of Object.entries(value)) {
|
|
2534
|
-
if (key !== "line" && key !== "column")
|
|
2732
|
+
if (key !== "line" && key !== "column") walk2(child);
|
|
2535
2733
|
}
|
|
2536
2734
|
};
|
|
2537
|
-
|
|
2735
|
+
walk2(expression);
|
|
2538
2736
|
return found;
|
|
2539
2737
|
}
|
|
2540
2738
|
function allNodes(root) {
|
|
@@ -2570,6 +2768,269 @@ var CLASS_METAMETHODS = [
|
|
|
2570
2768
|
"__iter"
|
|
2571
2769
|
];
|
|
2572
2770
|
|
|
2771
|
+
// src/treeshake.ts
|
|
2772
|
+
function walk(node, visit, parent) {
|
|
2773
|
+
if (!node || typeof node !== "object") return;
|
|
2774
|
+
if (Array.isArray(node)) {
|
|
2775
|
+
for (const item of node) walk(item, visit, parent);
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
const n = node;
|
|
2779
|
+
if (typeof n.type === "string" && visit(n, parent) === false) return;
|
|
2780
|
+
for (const [key, child] of Object.entries(n)) {
|
|
2781
|
+
if (key === "line" || key === "column") continue;
|
|
2782
|
+
walk(child, visit, typeof n.type === "string" ? n : parent);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
function pure(expression) {
|
|
2786
|
+
let ok = true;
|
|
2787
|
+
walk(expression, (node) => {
|
|
2788
|
+
if (!ok) return false;
|
|
2789
|
+
switch (node.type) {
|
|
2790
|
+
case "CallExpression":
|
|
2791
|
+
case "MethodCallExpression":
|
|
2792
|
+
case "ImportExpression":
|
|
2793
|
+
case "SuperExpression":
|
|
2794
|
+
ok = false;
|
|
2795
|
+
return false;
|
|
2796
|
+
case "FunctionExpression":
|
|
2797
|
+
case "FunctionBody":
|
|
2798
|
+
case "ClassMethod":
|
|
2799
|
+
case "ClassAccessor":
|
|
2800
|
+
case "ClassConstructor":
|
|
2801
|
+
return false;
|
|
2802
|
+
case "ClassField":
|
|
2803
|
+
if (!node.isStatic) return false;
|
|
2804
|
+
}
|
|
2805
|
+
});
|
|
2806
|
+
return ok;
|
|
2807
|
+
}
|
|
2808
|
+
function declarationOf(statement) {
|
|
2809
|
+
return statement.type === "ExportStatement" ? statement.declaration : statement;
|
|
2810
|
+
}
|
|
2811
|
+
function removable(statement) {
|
|
2812
|
+
const declaration = declarationOf(statement);
|
|
2813
|
+
switch (declaration.type) {
|
|
2814
|
+
case "FunctionDeclaration":
|
|
2815
|
+
return true;
|
|
2816
|
+
case "ClassDeclaration":
|
|
2817
|
+
return pure(declaration);
|
|
2818
|
+
case "VariableDeclaration":
|
|
2819
|
+
return declaration.init === void 0 || pure(declaration.init);
|
|
2820
|
+
case "ExportDefaultStatement":
|
|
2821
|
+
return pure(declaration.declaration);
|
|
2822
|
+
default:
|
|
2823
|
+
return false;
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
function structural(statement) {
|
|
2827
|
+
switch (statement.type) {
|
|
2828
|
+
case "TypeAliasStatement":
|
|
2829
|
+
case "ExportTypeAliasStatement":
|
|
2830
|
+
case "DeclareStatement":
|
|
2831
|
+
case "DeclareClassStatement":
|
|
2832
|
+
case "DeclareMetatableStatement":
|
|
2833
|
+
case "ImportStatement":
|
|
2834
|
+
case "ExportNamedStatement":
|
|
2835
|
+
case "ExportAllStatement":
|
|
2836
|
+
return true;
|
|
2837
|
+
default:
|
|
2838
|
+
return false;
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
function exportedNames(statement) {
|
|
2842
|
+
switch (statement.type) {
|
|
2843
|
+
case "ExportStatement": {
|
|
2844
|
+
const declaration = statement.declaration;
|
|
2845
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") return [declaration.name.name];
|
|
2846
|
+
const names = [];
|
|
2847
|
+
walk(declaration.name, (node) => {
|
|
2848
|
+
if (node.type === "IdentifierPattern") names.push(node.name);
|
|
2849
|
+
});
|
|
2850
|
+
return names;
|
|
2851
|
+
}
|
|
2852
|
+
case "ExportDefaultStatement":
|
|
2853
|
+
return ["default"];
|
|
2854
|
+
default:
|
|
2855
|
+
return [];
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
function factsOf(module2) {
|
|
2859
|
+
const tops = module2.program.body.statements;
|
|
2860
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
2861
|
+
for (const binding of module2.scopes.bindings.values()) {
|
|
2862
|
+
if (binding.declarationNode) byNode.set(binding.declarationNode, binding.id);
|
|
2863
|
+
}
|
|
2864
|
+
const declaredBy = /* @__PURE__ */ new Map();
|
|
2865
|
+
const imported = /* @__PURE__ */ new Map();
|
|
2866
|
+
for (const statement of tops) {
|
|
2867
|
+
const declaration = declarationOf(statement);
|
|
2868
|
+
const declare = (node) => {
|
|
2869
|
+
const id = node && byNode.get(node);
|
|
2870
|
+
if (id !== void 0) declaredBy.set(id, statement);
|
|
2871
|
+
};
|
|
2872
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") declare(declaration.name);
|
|
2873
|
+
else if (declaration.type === "VariableDeclaration") {
|
|
2874
|
+
walk(declaration.name, (node) => {
|
|
2875
|
+
if (node.type === "IdentifierPattern") declare(node);
|
|
2876
|
+
});
|
|
2877
|
+
} else if (declaration.type === "ImportStatement" && !declaration.isTypeOnly) {
|
|
2878
|
+
const target = module2.resolve(declaration.source.value);
|
|
2879
|
+
if (target === void 0) continue;
|
|
2880
|
+
const add = (node, name) => {
|
|
2881
|
+
const id = node && byNode.get(node);
|
|
2882
|
+
if (id !== void 0) imported.set(id, { target, name });
|
|
2883
|
+
};
|
|
2884
|
+
if (declaration.defaultImport) add(declaration.defaultImport, "default");
|
|
2885
|
+
if (declaration.namespaceImport) add(declaration.namespaceImport, "*");
|
|
2886
|
+
for (const s of declaration.specifiers) add(s.local, s.imported.name);
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
2890
|
+
walk(module2.program.body, (node, parent) => {
|
|
2891
|
+
if (parent) parents.set(node, parent);
|
|
2892
|
+
});
|
|
2893
|
+
const sideEffects = tops.some((s) => !structural(s) && !removable(s));
|
|
2894
|
+
return { module: module2, tops, declaredBy, imported, parents, sideEffects };
|
|
2895
|
+
}
|
|
2896
|
+
function treeShake(modules, entry2) {
|
|
2897
|
+
const facts = new Map(modules.map((m) => [m.file, factsOf(m)]));
|
|
2898
|
+
const used = /* @__PURE__ */ new Map();
|
|
2899
|
+
const live = /* @__PURE__ */ new Map();
|
|
2900
|
+
const required = /* @__PURE__ */ new Set();
|
|
2901
|
+
let changed = true;
|
|
2902
|
+
const require2 = (file) => {
|
|
2903
|
+
if (required.has(file) || !facts.has(file)) return;
|
|
2904
|
+
required.add(file);
|
|
2905
|
+
changed = true;
|
|
2906
|
+
};
|
|
2907
|
+
const read3 = (file, name) => {
|
|
2908
|
+
if (!facts.has(file)) return;
|
|
2909
|
+
require2(file);
|
|
2910
|
+
const now = used.get(file);
|
|
2911
|
+
if (now === "all") return;
|
|
2912
|
+
if (name === "*") {
|
|
2913
|
+
used.set(file, "all");
|
|
2914
|
+
changed = true;
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
const names = now ?? /* @__PURE__ */ new Set();
|
|
2918
|
+
if (!names.has(name)) {
|
|
2919
|
+
names.add(name);
|
|
2920
|
+
used.set(file, names);
|
|
2921
|
+
changed = true;
|
|
2922
|
+
}
|
|
2923
|
+
};
|
|
2924
|
+
const isRead = (file, name) => {
|
|
2925
|
+
const now = used.get(file);
|
|
2926
|
+
return now === "all" || (now?.has(name) ?? false);
|
|
2927
|
+
};
|
|
2928
|
+
require2(entry2);
|
|
2929
|
+
used.set(entry2, "all");
|
|
2930
|
+
while (changed) {
|
|
2931
|
+
changed = false;
|
|
2932
|
+
for (const file of [...required]) {
|
|
2933
|
+
const f = facts.get(file);
|
|
2934
|
+
const kept = live.get(file) ?? /* @__PURE__ */ new Set();
|
|
2935
|
+
live.set(file, kept);
|
|
2936
|
+
const queue = [];
|
|
2937
|
+
const keep = (statement) => {
|
|
2938
|
+
if (!statement || kept.has(statement)) return;
|
|
2939
|
+
kept.add(statement);
|
|
2940
|
+
queue.push(statement);
|
|
2941
|
+
changed = true;
|
|
2942
|
+
};
|
|
2943
|
+
for (const statement of f.tops) {
|
|
2944
|
+
if (!structural(statement) && !removable(statement)) keep(statement);
|
|
2945
|
+
if (exportedNames(statement).some((name) => isRead(file, name))) keep(statement);
|
|
2946
|
+
const declaration = declarationOf(statement);
|
|
2947
|
+
if (declaration.type === "ImportStatement" && !declaration.isTypeOnly && !declaration.defaultImport && !declaration.namespaceImport && !declaration.specifiers.length) {
|
|
2948
|
+
const target = f.module.resolve(declaration.source.value);
|
|
2949
|
+
if (target !== void 0) require2(target);
|
|
2950
|
+
}
|
|
2951
|
+
if (declaration.type === "ExportNamedStatement" && !declaration.typeOnly) {
|
|
2952
|
+
const target = declaration.source ? f.module.resolve(declaration.source.value) : void 0;
|
|
2953
|
+
for (const s of declaration.specifiers) {
|
|
2954
|
+
if (!isRead(file, s.exported.name)) continue;
|
|
2955
|
+
if (declaration.source) {
|
|
2956
|
+
if (target !== void 0) read3(target, s.local.name);
|
|
2957
|
+
continue;
|
|
2958
|
+
}
|
|
2959
|
+
const id = f.module.scopes.bindingOf.get(s.local);
|
|
2960
|
+
const own = [...f.declaredBy].find(([bid, st]) => (id !== void 0 ? bid === id : false) || exportedLocal(st, s.local.name));
|
|
2961
|
+
if (own) keep(own[1]);
|
|
2962
|
+
const from = id !== void 0 ? f.imported.get(id) : void 0;
|
|
2963
|
+
if (from) read3(from.target, from.name);
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (declaration.type === "ExportAllStatement") {
|
|
2967
|
+
const target = f.module.resolve(declaration.source.value);
|
|
2968
|
+
if (target === void 0) continue;
|
|
2969
|
+
const mine = used.get(file);
|
|
2970
|
+
if (mine === "all") read3(target, "*");
|
|
2971
|
+
else for (const name of mine ?? []) if (!ownExport(f, name)) read3(target, name);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
for (const statement of [...kept]) queue.push(statement);
|
|
2975
|
+
while (queue.length) {
|
|
2976
|
+
const statement = queue.pop();
|
|
2977
|
+
walk(statement, (node) => {
|
|
2978
|
+
if (node.type === "ImportExpression") {
|
|
2979
|
+
const source = node.source;
|
|
2980
|
+
const target = source?.type === "StringLiteral" ? f.module.resolve(source.value) : void 0;
|
|
2981
|
+
if (target !== void 0) read3(target, "*");
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
if (node.type !== "Identifier") return;
|
|
2985
|
+
const id = f.module.scopes.bindingOf.get(node);
|
|
2986
|
+
if (id === void 0) return;
|
|
2987
|
+
const declaring = f.declaredBy.get(id);
|
|
2988
|
+
if (declaring && declaring !== statement) keep(declaring);
|
|
2989
|
+
const from = f.imported.get(id);
|
|
2990
|
+
if (!from) return;
|
|
2991
|
+
if (from.name !== "*") return read3(from.target, from.name);
|
|
2992
|
+
const parent = f.parents.get(node);
|
|
2993
|
+
if (parent?.type === "MemberExpression" && parent.object === node) read3(from.target, parent.property.name);
|
|
2994
|
+
else read3(from.target, "*");
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
for (const statement of f.tops) {
|
|
2998
|
+
if (statement.type !== "ImportStatement" || statement.isTypeOnly) continue;
|
|
2999
|
+
const target = f.module.resolve(statement.source.value);
|
|
3000
|
+
if (target !== void 0 && facts.get(target)?.sideEffects) require2(target);
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
const shaken = /* @__PURE__ */ new Map();
|
|
3005
|
+
for (const [file, f] of facts) {
|
|
3006
|
+
const kept = live.get(file) ?? /* @__PURE__ */ new Set();
|
|
3007
|
+
const removed = new Set(f.tops.filter((s) => !kept.has(s) && removable(s)));
|
|
3008
|
+
const dead = /* @__PURE__ */ new Set();
|
|
3009
|
+
for (const statement of removed) walk(statement, (node) => {
|
|
3010
|
+
if (node.type === "Identifier") dead.add(node);
|
|
3011
|
+
});
|
|
3012
|
+
shaken.set(file, { removed, dead });
|
|
3013
|
+
}
|
|
3014
|
+
return {
|
|
3015
|
+
modules: shaken,
|
|
3016
|
+
sideEffects: new Set([...facts].filter(([, f]) => f.sideEffects).map(([file]) => file)),
|
|
3017
|
+
required
|
|
3018
|
+
};
|
|
3019
|
+
}
|
|
3020
|
+
function exportedLocal(statement, name) {
|
|
3021
|
+
const declaration = declarationOf(statement);
|
|
3022
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") return declaration.name.name === name;
|
|
3023
|
+
if (declaration.type !== "VariableDeclaration") return false;
|
|
3024
|
+
let found = false;
|
|
3025
|
+
walk(declaration.name, (node) => {
|
|
3026
|
+
if (node.type === "IdentifierPattern" && node.name === name) found = true;
|
|
3027
|
+
});
|
|
3028
|
+
return found;
|
|
3029
|
+
}
|
|
3030
|
+
function ownExport(f, name) {
|
|
3031
|
+
return f.tops.some((statement) => exportedNames(statement).includes(name) || statement.type === "ExportNamedStatement" && statement.specifiers.some((s) => s.exported.name === name));
|
|
3032
|
+
}
|
|
3033
|
+
|
|
2573
3034
|
// src/linemap.ts
|
|
2574
3035
|
var import_parser6 = require("@tilua/parser");
|
|
2575
3036
|
function statementsOf(node) {
|
|
@@ -2660,8 +3121,8 @@ async function bundle(options) {
|
|
|
2660
3121
|
sources.set(file, { file, name: nameOf(file), text, program: program3, scopes });
|
|
2661
3122
|
const dynamic = (0, import_parser7.importExpressions)(program3).flatMap((node) => node.source.type === "StringLiteral" ? [node.source.value] : []);
|
|
2662
3123
|
for (const specifier of [...importedSpecifiers(program3), ...dynamic]) {
|
|
2663
|
-
const
|
|
2664
|
-
if (
|
|
3124
|
+
const target = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
3125
|
+
if (target && !target.endsWith(".d.tilua")) queue.push(target);
|
|
2665
3126
|
}
|
|
2666
3127
|
}
|
|
2667
3128
|
const analysis = analyzeModules([...sources.values()], config2);
|
|
@@ -2675,9 +3136,16 @@ async function bundle(options) {
|
|
|
2675
3136
|
const requireExpression = member(identifier(G), "require");
|
|
2676
3137
|
const importExpression = member(identifier(G), "import");
|
|
2677
3138
|
const mode = options.output ?? config2?.output ?? "single";
|
|
2678
|
-
const
|
|
3139
|
+
const byPath = syntaxOf(lowerings).has("requireByPath");
|
|
2679
3140
|
const modules = /* @__PURE__ */ new Map();
|
|
2680
3141
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3142
|
+
const shared = new SharedRuntime(names);
|
|
3143
|
+
const shaking = options.treeShaking ?? config2?.treeShaking ?? false;
|
|
3144
|
+
const resolveIn = (file) => (specifier) => {
|
|
3145
|
+
const found = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
3146
|
+
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
3147
|
+
};
|
|
3148
|
+
const shaken = shaking ? treeShake([...sources.values()].map((s) => ({ file: s.file, program: s.program, scopes: s.scopes, resolve: resolveIn(s.file) })), entry2) : void 0;
|
|
2681
3149
|
const pending = [entry2];
|
|
2682
3150
|
while (pending.length) {
|
|
2683
3151
|
const file = pending.shift();
|
|
@@ -2690,10 +3158,21 @@ async function bundle(options) {
|
|
|
2690
3158
|
names,
|
|
2691
3159
|
types: analysis.types.get(file),
|
|
2692
3160
|
lowerings,
|
|
2693
|
-
target,
|
|
2694
3161
|
noLib: config2?.noLib,
|
|
2695
3162
|
source: source.text,
|
|
2696
3163
|
file: shown,
|
|
3164
|
+
shared,
|
|
3165
|
+
shaken: shaken && {
|
|
3166
|
+
...shaken.modules.get(file),
|
|
3167
|
+
runs: (specifier) => {
|
|
3168
|
+
const target = resolveIn(file)(specifier);
|
|
3169
|
+
return target !== void 0 && shaken.sideEffects.has(target);
|
|
3170
|
+
},
|
|
3171
|
+
needed: (specifier) => {
|
|
3172
|
+
const target = resolveIn(file)(specifier);
|
|
3173
|
+
return target !== void 0 && shaken.required.has(target);
|
|
3174
|
+
}
|
|
3175
|
+
},
|
|
2697
3176
|
module: {
|
|
2698
3177
|
name: source.name,
|
|
2699
3178
|
require: requireExpression,
|
|
@@ -2724,6 +3203,7 @@ async function bundle(options) {
|
|
|
2724
3203
|
exportsName: lowered2.exportsName,
|
|
2725
3204
|
info: lowered2.module,
|
|
2726
3205
|
usesScriptArgs: lowered2.usesScriptArgs,
|
|
3206
|
+
shared: lowered2.shared,
|
|
2727
3207
|
imports,
|
|
2728
3208
|
dynamicImports
|
|
2729
3209
|
});
|
|
@@ -2749,16 +3229,17 @@ async function bundle(options) {
|
|
|
2749
3229
|
if (diagnostics.some((d) => d.category === "syntax" || d.category === "scope" || d.category === "module")) {
|
|
2750
3230
|
return { files: [], modules: moduleNames, diagnostics };
|
|
2751
3231
|
}
|
|
3232
|
+
if (shaking) shared.shake(lowered.flatMap((m) => m.statements));
|
|
2752
3233
|
const several = mode !== "single";
|
|
2753
3234
|
const layout = layoutOf(mode, modules.get(entry2), lowered, options.outFile);
|
|
2754
3235
|
const usesScriptArgs = lowered.some((m) => m.usesScriptArgs);
|
|
2755
3236
|
const elsewhere = /* @__PURE__ */ new Map();
|
|
2756
3237
|
for (const file of layout.slice(1)) {
|
|
2757
|
-
for (const module2 of file.modules) elsewhere.set(module2.name, loadPath(layout[0].path, file.path,
|
|
3238
|
+
for (const module2 of file.modules) elsewhere.set(module2.name, loadPath(layout[0].path, file.path, byPath));
|
|
2758
3239
|
}
|
|
2759
3240
|
const program2 = (0, import_luau_parser2.parse)(runtime(G, {
|
|
2760
3241
|
several,
|
|
2761
|
-
|
|
3242
|
+
byPath,
|
|
2762
3243
|
files: elsewhere,
|
|
2763
3244
|
imports: lowered.some((m) => m.dynamicImports.size > 0)
|
|
2764
3245
|
}));
|
|
@@ -2773,6 +3254,8 @@ async function bundle(options) {
|
|
|
2773
3254
|
for (const module2 of layout[0].modules) {
|
|
2774
3255
|
modulesTable.fields.push({ type: "TableFieldComputed", key: string(module2.name), value: moduleTable(module2) });
|
|
2775
3256
|
}
|
|
3257
|
+
const helpers = shared.chunk(new Set(layout[0].modules.flatMap((m) => m.shared)));
|
|
3258
|
+
program2.body.statements.unshift(...helpers.declare);
|
|
2776
3259
|
const ok = names.fresh("ok");
|
|
2777
3260
|
const result2 = names.fresh("result");
|
|
2778
3261
|
const entryStatements = (0, import_luau_parser2.parse)(`
|
|
@@ -2794,9 +3277,11 @@ ${modules.get(entry2).info.exports ? `return ${result2}` : ""}
|
|
|
2794
3277
|
if (several) mapStatements.push(...mapRegistration(G, layout[0], `${G}.lines`));
|
|
2795
3278
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
2796
3279
|
}
|
|
3280
|
+
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...helpers.define);
|
|
2797
3281
|
const files = [{ path: layout[0].path, code: (0, import_luau_parser2.print)(program2) + "\n", modules: layout[0].modules.map((m) => m.name) }];
|
|
2798
3282
|
for (const file of layout.slice(1)) {
|
|
2799
|
-
const
|
|
3283
|
+
const fileHelpers = shared.chunk(new Set(file.modules.flatMap((m) => m.shared)));
|
|
3284
|
+
const body = [...fileHelpers.declare];
|
|
2800
3285
|
if (file.modules.some((m) => m.usesScriptArgs)) body.push(...(0, import_luau_parser2.parse)(`local scriptArgs = ${G}.scriptArgs`).body.statements);
|
|
2801
3286
|
for (const module2 of file.modules) {
|
|
2802
3287
|
body.push(assign(
|
|
@@ -2806,7 +3291,7 @@ ${modules.get(entry2).info.exports ? `return ${result2}` : ""}
|
|
|
2806
3291
|
}
|
|
2807
3292
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
2808
3293
|
const lines = buildLineMap(chunk, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(chunk)), origins);
|
|
2809
|
-
body.push(...mapRegistration(G, file, lineMapSource(lines)));
|
|
3294
|
+
body.push(...mapRegistration(G, file, lineMapSource(lines)), ...fileHelpers.define);
|
|
2810
3295
|
files.push({ path: file.path, code: (0, import_luau_parser2.print)(chunk) + "\n", modules: file.modules.map((m) => m.name) });
|
|
2811
3296
|
}
|
|
2812
3297
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
@@ -2868,9 +3353,9 @@ function layoutOf(mode, entry2, modules, outFile) {
|
|
|
2868
3353
|
}
|
|
2869
3354
|
return files;
|
|
2870
3355
|
}
|
|
2871
|
-
function loadPath(entryPath, file,
|
|
3356
|
+
function loadPath(entryPath, file, byPath) {
|
|
2872
3357
|
const path = import_node_path2.posix.relative(import_node_path2.posix.dirname(entryPath), file);
|
|
2873
|
-
if (
|
|
3358
|
+
if (!byPath) return path;
|
|
2874
3359
|
const bare = path.slice(0, path.length - import_node_path2.posix.extname(path).length);
|
|
2875
3360
|
return bare.startsWith("../") ? bare : `./${bare}`;
|
|
2876
3361
|
}
|
|
@@ -2883,8 +3368,8 @@ function mapRegistration(G, file, map) {
|
|
|
2883
3368
|
...file.modules.map((module2) => `${G}.maps[${(0, import_parser7.luauString)(module2.name)}] = ${G}.sources[#${G}.sources][2]`)
|
|
2884
3369
|
].join("\n")).body.statements;
|
|
2885
3370
|
}
|
|
2886
|
-
function loader(G,
|
|
2887
|
-
if (
|
|
3371
|
+
function loader(G, byPath) {
|
|
3372
|
+
if (!byPath) {
|
|
2888
3373
|
return `
|
|
2889
3374
|
-- From beside this file, wherever that is: its own path says where.
|
|
2890
3375
|
local folder = ""
|
|
@@ -3092,7 +3577,7 @@ ${several ? `
|
|
|
3092
3577
|
if ${G}.loaded[file] then
|
|
3093
3578
|
return
|
|
3094
3579
|
end
|
|
3095
|
-
${G}.loaded[file] = true${loader(G, options.
|
|
3580
|
+
${G}.loaded[file] = true${loader(G, options.byPath)}
|
|
3096
3581
|
end,` : ""}${options.imports ? `
|
|
3097
3582
|
-- \`import("./x")\`: the module's exports, asked for where the code runs
|
|
3098
3583
|
-- rather than before its module does. \`require\` does the rest \u2014 and
|
|
@@ -3327,13 +3812,12 @@ function allStatements(statements) {
|
|
|
3327
3812
|
}
|
|
3328
3813
|
|
|
3329
3814
|
// src/cli.ts
|
|
3330
|
-
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]
|
|
3815
|
+
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]";
|
|
3331
3816
|
var args = process.argv.slice(2);
|
|
3332
3817
|
var entry;
|
|
3333
3818
|
var out;
|
|
3334
3819
|
var config;
|
|
3335
3820
|
var typeCheck = true;
|
|
3336
|
-
var buildTarget;
|
|
3337
3821
|
var output;
|
|
3338
3822
|
for (let i = 0; i < args.length; i++) {
|
|
3339
3823
|
const arg = args[i];
|
|
@@ -3341,12 +3825,8 @@ for (let i = 0; i < args.length; i++) {
|
|
|
3341
3825
|
else if (arg === "--config") config = args[++i];
|
|
3342
3826
|
else if (arg === "--noCheck") typeCheck = false;
|
|
3343
3827
|
else if (arg === "--target") {
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
console.error(`--target must be 'luau' or 'lua51', not '${value}'`);
|
|
3347
|
-
process.exit(2);
|
|
3348
|
-
}
|
|
3349
|
-
buildTarget = value;
|
|
3828
|
+
console.error(`--target is gone: the output runs on Lua 5.1 to 5.4, LuaJIT and Luau, and a library says what more its Lua has \u2014 add "luau" to the config's 'types'`);
|
|
3829
|
+
process.exit(2);
|
|
3350
3830
|
} else if (arg === "--output") {
|
|
3351
3831
|
const value = args[++i];
|
|
3352
3832
|
if (value !== "single" && value !== "chunks" && value !== "modules") {
|
|
@@ -3372,7 +3852,6 @@ async function main(from) {
|
|
|
3372
3852
|
entry: from,
|
|
3373
3853
|
config,
|
|
3374
3854
|
typeCheck,
|
|
3375
|
-
target: buildTarget,
|
|
3376
3855
|
output: mode,
|
|
3377
3856
|
outFile: entryFile !== void 0 ? (0, import_node_path3.basename)(entryFile) : void 0
|
|
3378
3857
|
});
|