@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/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 import_node_fs = require("fs");
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 = (object, property) => isLuauName(property) ? { type: "MemberExpression", object, property: identifier(property), ...span() } : index(object, string(property));
61
- var index = (object, key) => ({ type: "IndexExpression", object, index: key, ...span() });
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 = (object, method, args) => ({ type: "MethodCallExpression", object, method: identifier(method), arguments: args, ...span() });
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
- /** What a library says `receiver:method(...)` is. The last library
363
- * loaded is asked first, so a project's own library can answer for a
364
- * method an earlier one also claims; no answer leaves an ordinary Luau
365
- * method call, which is what a value that answers to the method itself
366
- * wants (`text:upper()`). */
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.options.lowerings;
369
- if (!lowerings?.some((l) => l.plugin.methodCall)) return void 0;
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 (let i = lowerings.length - 1; i >= 0; i--) {
374
- const plugin = lowerings[i].plugin;
375
- if (!plugin.methodCall) continue;
376
- const answer = plugin.methodCall({
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.options.lowerings;
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 plugin = lowerings[i].plugin;
406
- if (!plugin.globalCall) continue;
407
- const answer = plugin.globalCall({
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.options.lowerings;
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.options.lowerings[index2].from}' lowered this to Luau that does not parse: ${JSON.stringify(source)} (${error.message})`);
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.options.lowerings[index2];
473
- const source = plugin.runtime?.[runtime2];
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 object = linkObject(node);
1409
- if (node.type === "CallExpression" && object.type === "Identifier") {
1410
- return this.link(node, this.reference(object));
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(object));
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, object) {
1525
+ link(node, object2) {
1452
1526
  switch (node.type) {
1453
1527
  case "MemberExpression":
1454
- return member(object, node.property.name);
1528
+ return member(object2, node.property.name);
1455
1529
  case "IndexExpression":
1456
- return index(object, this.expression(node.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(object, args);
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 ? [object] : [],
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(object, node.method.name, args);
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, object) {
1498
- return segment.reduce((value, link) => this.link(link, value), object);
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 object = this.expression(node.target.object);
1648
+ const object2 = this.expression(node.target.object);
1575
1649
  const objectName = this.names.fresh("target");
1576
- before.push(local([objectName], [object]));
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 plugin = loaded.default;
1995
- if (!plugin || typeof plugin !== "object") {
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, import_node_fs.statSync)(file);
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, import_node_fs.readFileSync)(file, "utf8");
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, import_node_fs.statSync)(file);
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, import_node_fs.readFileSync)(file, "utf8"));
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(([read, stamp]) => stampOf(read) === stamp)) {
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 read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2425
+ const read2 = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2352
2426
  const own = stampOf(file);
2353
- if (own !== void 0) read.set(file, own);
2354
- readWhile.set(file, read);
2355
- if ([...read.values()].every((stamp) => stamp !== void 0)) {
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 read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2366
- readWhile.set(file, read);
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) read.set(target, stamp);
2369
- for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
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, import_node_fs.readFileSync)(target, "utf8"));
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 import_node_fs2 = require("fs");
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, import_node_fs2.readFileSync)(file, "utf8")));
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
@@ -4,7 +4,7 @@ import {
4
4
  lower,
5
5
  program,
6
6
  resolveConfig
7
- } from "./chunk-3ZQ3EITC.js";
7
+ } from "./chunk-X4DM2BX2.js";
8
8
 
9
9
  // src/compile.ts
10
10
  import { readFileSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tilua/compiler",
3
- "version": "2.4.0",
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": "^2.4.0"
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