@tilua/compiler 1.1.0 → 2.1.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
@@ -216,14 +216,18 @@ var Lowerer = class {
216
216
  const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
217
217
  const helpers = this.helperDefinitions();
218
218
  const captured = [...this.builtins].map(([global, local2]) => local([local2], [identifier(global)]));
219
+ const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [table([{ type: "TableFieldPositional", value: vararg() }])])] : [];
219
220
  return {
220
- statements: [...captured, ...helpers, ...this.classRuntimeStatements(), ...body],
221
+ statements: [...scriptArgs, ...captured, ...helpers, ...this.classRuntimeStatements(), ...body],
221
222
  exportsName: this.exportsName,
222
223
  module: this.info,
223
224
  diagnostics: this.diagnostics,
224
- origins: this.origins
225
+ origins: this.origins,
226
+ usesScriptArgs: this.usesScriptArgs
225
227
  };
226
228
  }
229
+ /** Whether the file reads `scriptArgs`, the language's own global. */
230
+ usesScriptArgs = false;
227
231
  report(node, message) {
228
232
  this.diagnostics.push({ message, line: node.line.start, column: node.column.start });
229
233
  }
@@ -348,6 +352,10 @@ var Lowerer = class {
348
352
  /** The name a global is read by at `node`, or `undefined` when `node` is
349
353
  * not a global — a local of the same name is the author's. */
350
354
  globalName(node) {
355
+ if (node.type === "MemberExpression" && !node.optional) {
356
+ const base = this.globalName(node.object);
357
+ return base === void 0 ? void 0 : `${base}.${node.property.name}`;
358
+ }
351
359
  if (node.type !== "Identifier") return void 0;
352
360
  const id = this.scopes.bindingOf.get(node);
353
361
  if (id === void 0) return node.name;
@@ -644,7 +652,7 @@ var Lowerer = class {
644
652
  break;
645
653
  }
646
654
  case "ReturnStatement":
647
- if (declaration.arguments.length) this.report(declaration, "A module cannot return a value; export it instead");
655
+ if (declaration.argument) this.report(declaration, "A module cannot return a value; export it instead");
648
656
  body.push(returns([]));
649
657
  break;
650
658
  case "ImportStatement":
@@ -823,7 +831,7 @@ var Lowerer = class {
823
831
  case "CallStatement": {
824
832
  const chain = optionalChain(node.expression);
825
833
  if (chain) return [this.optionalCallStatement(chain)];
826
- const expression = this.expression(node.expression);
834
+ const expression = this.callValues(node.expression);
827
835
  if (expression.type !== "CallExpression" && expression.type !== "MethodCallExpression") {
828
836
  this.report(node, "A statement must be a call");
829
837
  return [];
@@ -876,23 +884,26 @@ var Lowerer = class {
876
884
  }];
877
885
  case "GenericForStatement": {
878
886
  const prelude = [];
879
- const variables = node.variables.map((target) => {
880
- if (target.type === "IdentifierPattern") return this.name(target.name);
881
- const temp = this.names.fresh("item");
882
- prelude.push(...this.destructure(target, identifier(temp), "declare"));
883
- return temp;
884
- });
885
- if (variables.length === 1 && this.options.types?.iteratesValues.has(node)) {
886
- variables.unshift(this.names.fresh("_"));
887
+ let item;
888
+ if (node.variable.type === "IdentifierPattern") {
889
+ item = this.name(node.variable.name);
890
+ } else {
891
+ item = this.names.fresh("item");
892
+ prelude.push(...this.destructure(node.variable, identifier(item), "declare"));
887
893
  }
894
+ const form = this.options.types?.loops.get(node) ?? { walks: "values", viaIter: false };
895
+ let source = this.expression(node.iterator);
896
+ if (form.viaIter) source = methodCall(source, "__iter", []);
897
+ const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
898
+ const iterators = form.walks === "iteration" ? [call(this.builtin("unpack"), [source, number(1), number(3)])] : [source];
888
899
  return [genericFor(
889
900
  variables,
890
- node.iterators.map((e) => this.expression(e)),
901
+ iterators,
891
902
  this.loopBody51(this.block(node.body, prelude)).statements
892
903
  )];
893
904
  }
894
905
  case "ReturnStatement":
895
- return [returns(this.values(node.arguments))];
906
+ return [returns(node.argument ? [this.expression(node.argument)] : [])];
896
907
  case "BreakStatement":
897
908
  return [{ type: "BreakStatement", ...spanOf(node) }];
898
909
  case "ContinueStatement":
@@ -936,7 +947,7 @@ var Lowerer = class {
936
947
  // end
937
948
  // function Dog.speak(this) ... end
938
949
  //
939
- // `new Dog(x)` is `Dog.new(x)`, `dog:speak()` passes the instance
950
+ // `Dog.new(x)` builds one, `dog:speak()` passes the instance
940
951
  // as `this`, and `super.speak()` is `Animal.speak(this)` — the
941
952
  // base's own function, run on this instance.
942
953
  // ============================================================
@@ -962,6 +973,7 @@ var Lowerer = class {
962
973
  classRuntimeStatements() {
963
974
  if (!this.classHelpers) return [];
964
975
  const { build, accessors } = this.classHelpers;
976
+ const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
965
977
  return (0, import_luau_parser.parse)(`
966
978
  local function ${build}(base)
967
979
  local class = { __getters = {}, __setters = {} }
@@ -972,6 +984,9 @@ local function ${build}(base)
972
984
  setmetatable(class, { __index = base })
973
985
  setmetatable(class.__getters, { __index = base.__getters })
974
986
  setmetatable(class.__setters, { __index = base.__setters })
987
+ for _, key in ipairs(${metamethods}) do
988
+ class[key] = base[key]
989
+ end
975
990
  end
976
991
  return class
977
992
  end
@@ -1034,6 +1049,7 @@ end
1034
1049
  }
1035
1050
  break;
1036
1051
  case "ClassMethod":
1052
+ if (member2.isAbstract) break;
1037
1053
  out.push(this.functionStatement(
1038
1054
  member(self, member2.name.name),
1039
1055
  member2,
@@ -1055,7 +1071,7 @@ end
1055
1071
  }
1056
1072
  }
1057
1073
  out.push(this.classInit(node, self));
1058
- out.push(this.classNew(node, self));
1074
+ if (!node.isAbstract) out.push(this.classNew(node, self));
1059
1075
  out.push(callStatement(call(identifier(accessors), [self])));
1060
1076
  } finally {
1061
1077
  this.classContext = previous;
@@ -1333,6 +1349,10 @@ end
1333
1349
  }
1334
1350
  switch (node.type) {
1335
1351
  case "Identifier":
1352
+ if (node.name === "scriptArgs" && this.isLanguageGlobal(node)) {
1353
+ this.usesScriptArgs = true;
1354
+ return identifier("scriptArgs");
1355
+ }
1336
1356
  return this.loweredGlobalValue(node) ?? this.reference(node);
1337
1357
  case "NilLiteral":
1338
1358
  return nil();
@@ -1342,8 +1362,6 @@ end
1342
1362
  return number(node.value, this.numberRaw(node));
1343
1363
  case "StringLiteral":
1344
1364
  return string(node.value);
1345
- case "VarargExpression":
1346
- return vararg();
1347
1365
  // Only a recovering parse makes one, and a syntax error stops the build.
1348
1366
  case "ErrorExpression":
1349
1367
  this.report(node, "Syntax error");
@@ -1364,11 +1382,6 @@ end
1364
1382
  }
1365
1383
  case "UnaryExpression":
1366
1384
  return unary(node.operator, this.expression(node.argument));
1367
- case "NewExpression":
1368
- return call(
1369
- member(this.expression(node.callee), "new"),
1370
- this.values(node.arguments)
1371
- );
1372
1385
  case "SuperExpression":
1373
1386
  return this.superClassReference(node);
1374
1387
  case "SpreadElement":
@@ -1376,17 +1389,16 @@ end
1376
1389
  return nil();
1377
1390
  case "ClassExpression":
1378
1391
  return this.classExpression(node);
1379
- case "MemberExpression":
1380
- case "IndexExpression":
1381
1392
  case "CallExpression":
1382
- case "MethodCallExpression": {
1393
+ case "MethodCallExpression":
1394
+ return this.callValues(node);
1395
+ case "MemberExpression":
1396
+ case "IndexExpression": {
1383
1397
  const chain = optionalChain(node);
1384
1398
  if (chain) return this.optionalChainExpression(chain);
1385
- const object = linkObject(node);
1386
- if (node.type === "CallExpression" && object.type === "Identifier") {
1387
- return this.link(node, this.reference(object));
1388
- }
1389
- return this.link(node, this.expression(object));
1399
+ const global = node.type === "MemberExpression" ? this.loweredGlobalValue(node) : void 0;
1400
+ if (global) return global;
1401
+ return this.link(node, this.expression(linkObject(node)));
1390
1402
  }
1391
1403
  case "ParenthesizedExpression":
1392
1404
  return parenthesized(this.expression(node.expression));
@@ -1405,14 +1417,47 @@ end
1405
1417
  };
1406
1418
  }
1407
1419
  }
1420
+ /** A call. */
1421
+ callValues(node) {
1422
+ const chain = optionalChain(node);
1423
+ if (chain) return this.optionalChainExpression(chain);
1424
+ const object = linkObject(node);
1425
+ if (node.type === "CallExpression" && object.type === "Identifier") {
1426
+ return this.link(node, this.reference(object));
1427
+ }
1428
+ return this.link(node, this.expression(object));
1429
+ }
1430
+ /** A call is one value in tilua, and Luau would hand on every value one
1431
+ * in the last place of an argument list or an array returns. Types say
1432
+ * how many a call returns; where a type says nothing — `any`, `unknown`
1433
+ * — the call is kept to one: `f((g()))`. */
1434
+ keptToOne(nodes, values) {
1435
+ const node = nodes[nodes.length - 1];
1436
+ const last = values[values.length - 1];
1437
+ if (!node || !last || !expandsToMany(last)) return values;
1438
+ const type = this.options.types?.typeOf.get(node);
1439
+ if (type && type.kind !== "any" && type.kind !== "unknown") return values;
1440
+ return [...values.slice(0, -1), parenthesized(last)];
1441
+ }
1442
+ /** Is this `scriptArgs` the language's own, not a name the file declared? */
1443
+ isLanguageGlobal(node) {
1444
+ const id = this.bindingIdOf(node);
1445
+ return id === void 0 || this.scopes.bindings.get(id)?.kind === "global";
1446
+ }
1408
1447
  /** A list of values — a call's arguments, a `return`'s, a declaration's,
1409
1448
  * an assignment's. `f(a, ...xs)` is Lua's own last-value expansion,
1410
1449
  * `f(a, table.unpack(xs))`; a spread anywhere else cannot be, since only
1411
1450
  * the last value of a list expands, so the whole list is built as an
1412
- * array first and that is what expands. */
1413
- values(list) {
1451
+ * array first and that is what expands.
1452
+ *
1453
+ * `arguments` is set for a call's arguments, where Luau hands on every
1454
+ * value the last one returns — see `keptToOne`. */
1455
+ values(list, asArguments = false) {
1414
1456
  const spreads = list.filter((a) => a.type === "SpreadElement");
1415
- if (!spreads.length) return list.map((a) => this.expression(a));
1457
+ if (!spreads.length) {
1458
+ const lowered = list.map((a) => this.expression(a));
1459
+ return asArguments ? this.keptToOne(list, lowered) : lowered;
1460
+ }
1416
1461
  const unpack = (value) => call(member(this.builtin("table"), "unpack"), [value]);
1417
1462
  const last = list[list.length - 1];
1418
1463
  if (spreads.length === 1 && last.type === "SpreadElement") {
@@ -1433,13 +1478,13 @@ end
1433
1478
  return index(object, this.expression(node.index));
1434
1479
  case "CallExpression": {
1435
1480
  const lowered = this.loweredGlobalCall(node);
1436
- const args = this.values(node.arguments);
1437
- if (lowered) return call(calleePath(lowered.callee), [...lowered.prepend, ...args]);
1438
- return call(object, args);
1481
+ const args = this.values(node.arguments, true);
1482
+ if (!lowered) return call(object, args);
1483
+ return call(calleePath(lowered.callee), [...lowered.prepend, ...args]);
1439
1484
  }
1440
1485
  case "MethodCallExpression": {
1441
1486
  const lowered = this.loweredMethodCall(node);
1442
- const args = this.values(node.arguments);
1487
+ const args = this.values(node.arguments, true);
1443
1488
  if (lowered) {
1444
1489
  return call(calleePath(lowered.callee), [
1445
1490
  ...lowered.prepend,
@@ -1673,7 +1718,8 @@ end
1673
1718
  * runs of plain elements and the spread arrays are joined by `concat`. */
1674
1719
  arrayExpression(node) {
1675
1720
  if (!node.elements.some((e) => e.type === "SpreadElement")) {
1676
- return table(node.elements.map((e) => ({ type: "TableFieldPositional", value: this.expression(e) })));
1721
+ const elements = node.elements;
1722
+ return table(this.keptToOne(elements, elements.map((e) => this.expression(e))).map((value) => ({ type: "TableFieldPositional", value })));
1677
1723
  }
1678
1724
  const parts = [];
1679
1725
  let current = [];
@@ -1872,6 +1918,24 @@ function allNodes(root) {
1872
1918
  visit(root);
1873
1919
  return out;
1874
1920
  }
1921
+ var CLASS_METAMETHODS = [
1922
+ "__add",
1923
+ "__sub",
1924
+ "__mul",
1925
+ "__div",
1926
+ "__idiv",
1927
+ "__mod",
1928
+ "__pow",
1929
+ "__unm",
1930
+ "__concat",
1931
+ "__len",
1932
+ "__eq",
1933
+ "__lt",
1934
+ "__le",
1935
+ "__call",
1936
+ "__tostring",
1937
+ "__iter"
1938
+ ];
1875
1939
 
1876
1940
  // src/linemap.ts
1877
1941
  function statementsOf(node) {
@@ -2011,7 +2075,8 @@ async function bundle(options) {
2011
2075
  name: source.name,
2012
2076
  statements: lowered.statements,
2013
2077
  exportsName: lowered.exportsName,
2014
- info: lowered.module
2078
+ info: lowered.module,
2079
+ usesScriptArgs: lowered.usesScriptArgs
2015
2080
  });
2016
2081
  }
2017
2082
  for (const [file, fileDirectives] of directives) {
@@ -2036,6 +2101,9 @@ async function bundle(options) {
2036
2101
  }
2037
2102
  const program2 = (0, import_luau_parser2.parse)(runtime(G));
2038
2103
  const assignment = program2.body.statements[1];
2104
+ if ([...modules.values()].some((m) => m.usesScriptArgs)) {
2105
+ program2.body.statements.unshift(local(["scriptArgs"], [table([{ type: "TableFieldPositional", value: { type: "VarargExpression" } }])]));
2106
+ }
2039
2107
  const modulesTable = assignment.type === "AssignmentStatement" && assignment.values[0].type === "TableExpression" ? assignment.values[0].fields.find((f) => f.type === "TableFieldNamed" && f.name.name === "modules")?.value : void 0;
2040
2108
  if (!modulesTable) throw new Error("@tilua/compiler: the bundle runtime has no modules table");
2041
2109
  for (const module2 of modules.values()) {
@@ -2172,7 +2240,22 @@ ${G} = {
2172
2240
  }
2173
2241
  `;
2174
2242
  }
2243
+ function stampOf(file) {
2244
+ try {
2245
+ const at = (0, import_node_fs.statSync)(file);
2246
+ return `${at.size}:${at.mtimeMs}`;
2247
+ } catch {
2248
+ return void 0;
2249
+ }
2250
+ }
2251
+ var parsedFiles = /* @__PURE__ */ new Map();
2175
2252
  function parseFile(file, diagnostics, directives) {
2253
+ const stamp = stampOf(file);
2254
+ const cached = stamp !== void 0 ? parsedFiles.get(file) : void 0;
2255
+ if (cached && cached.stamp === stamp) {
2256
+ directives.set(file, cached.directives);
2257
+ return { program: cached.program, text: cached.text };
2258
+ }
2176
2259
  let text;
2177
2260
  try {
2178
2261
  text = (0, import_node_fs.readFileSync)(file, "utf8");
@@ -2182,7 +2265,9 @@ function parseFile(file, diagnostics, directives) {
2182
2265
  }
2183
2266
  try {
2184
2267
  const program2 = (0, import_parser3.parse)(text);
2185
- directives.set(file, (0, import_parser3.directivesOf)(text));
2268
+ const found = (0, import_parser3.directivesOf)(text);
2269
+ directives.set(file, found);
2270
+ if (stamp !== void 0) parsedFiles.set(file, { stamp, program: program2, text, directives: found });
2186
2271
  return { program: program2, text };
2187
2272
  } catch (error) {
2188
2273
  if (error instanceof import_parser3.ParseError || error instanceof import_parser3.LexError) {
@@ -2196,22 +2281,93 @@ function parseFile(file, diagnostics, directives) {
2196
2281
  function importedSpecifiers(program2) {
2197
2282
  return program2.body.statements.flatMap((s) => s.type === "ImportStatement" || s.type === "ExportAllStatement" || s.type === "ExportNamedStatement" && s.source ? [s.source.value] : []);
2198
2283
  }
2284
+ var libraryCache = /* @__PURE__ */ new Map();
2285
+ function parsedLibrary(file) {
2286
+ let stamp;
2287
+ try {
2288
+ const at = (0, import_node_fs.statSync)(file);
2289
+ stamp = `${at.size}:${at.mtimeMs}`;
2290
+ } catch {
2291
+ stamp = "";
2292
+ }
2293
+ const cached = libraryCache.get(file);
2294
+ if (cached && cached.stamp === stamp) return cached.program;
2295
+ const program2 = (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8"));
2296
+ libraryCache.set(file, { stamp, program: program2 });
2297
+ return program2;
2298
+ }
2299
+ var moduleAnalyses = /* @__PURE__ */ new Map();
2199
2300
  function analyzeModules(modules, config) {
2200
2301
  const out = [];
2201
2302
  const analyses = /* @__PURE__ */ new Map();
2202
2303
  const libraries = config ? (0, import_parser3.resolveTypeLibraries)(config) : { files: [], lowerings: [], problems: [] };
2203
2304
  for (const p of libraries.problems) out.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
2204
- const libs = libraries.files.map((file) => (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8")));
2305
+ const libs = libraries.files.map(parsedLibrary);
2205
2306
  const globals = libs.flatMap((lib) => lib.body.statements.flatMap((s) => s.type === "DeclareStatement" ? [s.name] : []));
2206
2307
  const byFile = new Map(modules.map((m) => [m.file, m]));
2207
2308
  const exportsCache = /* @__PURE__ */ new Map();
2208
2309
  const inProgress = /* @__PURE__ */ new Set();
2310
+ const analyzed = /* @__PURE__ */ new Map();
2311
+ let partials = 0;
2312
+ const readWhile = /* @__PURE__ */ new Map();
2313
+ const settingFor = `${libraries.files.join("|")}#${config?.directory ?? ""}#${JSON.stringify(config?.paths ?? {})}`;
2314
+ const analyzeModule = (file, program2) => {
2315
+ const done = analyzed.get(file);
2316
+ if (done) return done;
2317
+ const remembered = moduleAnalyses.get(file);
2318
+ 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)) {
2319
+ analyzed.set(file, remembered.result);
2320
+ readWhile.set(file, remembered.read);
2321
+ return remembered.result;
2322
+ }
2323
+ const scopes = (0, import_parser3.analyzeScopes)(program2, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2324
+ const said = [];
2325
+ for (const d of scopes.diagnostics) {
2326
+ if (d.kind !== "undeclared") continue;
2327
+ said.push({ file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2328
+ }
2329
+ const before = partials;
2330
+ const types = (0, import_parser3.analyzeTypes)(program2, scopes, {
2331
+ libs,
2332
+ resolveModule: resolverFor(file),
2333
+ reportUnknownTypes: libs.length > 0
2334
+ });
2335
+ for (const d of types.diagnostics) {
2336
+ const at = d.node;
2337
+ said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2338
+ }
2339
+ const result = { types, diagnostics: said };
2340
+ if (partials === before) {
2341
+ analyzed.set(file, result);
2342
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2343
+ const own = stampOf(file);
2344
+ if (own !== void 0) read.set(file, own);
2345
+ readWhile.set(file, read);
2346
+ if ([...read.values()].every((stamp) => stamp !== void 0)) {
2347
+ moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program: program2, read, result });
2348
+ }
2349
+ }
2350
+ return result;
2351
+ };
2209
2352
  const resolverFor = (file) => (specifier) => {
2210
2353
  const target = (0, import_parser3.resolveModulePath)(file, specifier, config);
2211
2354
  if (!target) return void 0;
2212
- if (inProgress.has(target)) return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2355
+ const noteRead = () => {
2356
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2357
+ readWhile.set(file, read);
2358
+ const stamp = stampOf(target);
2359
+ if (stamp !== void 0) read.set(target, stamp);
2360
+ for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
2361
+ };
2362
+ if (inProgress.has(target)) {
2363
+ partials++;
2364
+ return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2365
+ }
2213
2366
  const cached = exportsCache.get(target);
2214
- if (cached) return cached;
2367
+ if (cached) {
2368
+ noteRead();
2369
+ return cached;
2370
+ }
2215
2371
  let program2 = byFile.get(target)?.program;
2216
2372
  if (!program2) {
2217
2373
  try {
@@ -2223,30 +2379,19 @@ function analyzeModules(modules, config) {
2223
2379
  inProgress.add(target);
2224
2380
  try {
2225
2381
  const scopes = (0, import_parser3.analyzeScopes)(program2, { builtinGlobals: globals });
2226
- const types = (0, import_parser3.analyzeTypes)(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2382
+ const types = byFile.has(target) ? analyzeModule(target, program2).types : (0, import_parser3.analyzeTypes)(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2227
2383
  const exports2 = (0, import_parser3.moduleExports)(program2, scopes, types, resolverFor(target));
2228
2384
  exportsCache.set(target, exports2);
2385
+ noteRead();
2229
2386
  return exports2;
2230
2387
  } finally {
2231
2388
  inProgress.delete(target);
2232
2389
  }
2233
2390
  };
2234
2391
  for (const module2 of modules) {
2235
- const scopes = (0, import_parser3.analyzeScopes)(module2.program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2236
- for (const d of scopes.diagnostics) {
2237
- if (d.kind !== "undeclared") continue;
2238
- out.push({ file: module2.file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2239
- }
2240
- const types = (0, import_parser3.analyzeTypes)(module2.program, scopes, {
2241
- libs,
2242
- resolveModule: resolverFor(module2.file),
2243
- reportUnknownTypes: libs.length > 0
2244
- });
2392
+ const { types, diagnostics } = analyzeModule(module2.file, module2.program);
2245
2393
  analyses.set(module2.file, types);
2246
- for (const d of types.diagnostics) {
2247
- const at = d.node;
2248
- out.push({ file: module2.file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2249
- }
2394
+ out.push(...diagnostics);
2250
2395
  }
2251
2396
  return { types: analyses, diagnostics: out, lowerings: [...libraries.lowerings] };
2252
2397
  }
package/dist/index.d.cts CHANGED
@@ -142,6 +142,9 @@ interface LowerResult {
142
142
  * file it was lowered from, this is what turns a line of the bundle back
143
143
  * into a place someone can open. */
144
144
  readonly origins: WeakMap<L.Statement, number>;
145
+ /** The file reads `scriptArgs`: whatever runs it has to set it up, from
146
+ * the chunk's own `...` — this file, compiled alone, does it itself. */
147
+ readonly usesScriptArgs: boolean;
145
148
  }
146
149
  /** How a module's exports behave at runtime, beyond what its code assigns. */
147
150
  interface ModuleInfo {
package/dist/index.d.ts CHANGED
@@ -142,6 +142,9 @@ interface LowerResult {
142
142
  * file it was lowered from, this is what turns a line of the bundle back
143
143
  * into a place someone can open. */
144
144
  readonly origins: WeakMap<L.Statement, number>;
145
+ /** The file reads `scriptArgs`: whatever runs it has to set it up, from
146
+ * the chunk's own `...` — this file, compiled alone, does it itself. */
147
+ readonly usesScriptArgs: boolean;
145
148
  }
146
149
  /** How a module's exports behave at runtime, beyond what its code assigns. */
147
150
  interface ModuleInfo {
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  lower,
5
5
  program,
6
6
  resolveConfig
7
- } from "./chunk-2IPPO4V3.js";
7
+ } from "./chunk-TBSJRVKA.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": "1.1.0",
3
+ "version": "2.1.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",
@@ -37,7 +37,7 @@
37
37
  "type": "module",
38
38
  "dependencies": {
39
39
  "luau-parser": "^1.0.3",
40
- "@tilua/parser": "^1.1.0"
40
+ "@tilua/parser": "^2.1.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.20.2",