@tilua/compiler 7.0.1 → 8.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/README.md CHANGED
@@ -74,9 +74,10 @@ JavaScript module the build loads.
74
74
  | `const` / `let` | `local` |
75
75
  | `class C { … }` | one table for the class, one per instance — see below |
76
76
  | `return [a, b]` | `return { a, b }` — several results are an array |
77
- | `for (const item in xs)` | `for _, item in xs do … end` — an array or a table walked for its values |
78
- | `for (const item in step)` | `for item in step do … end` — an iterator function |
79
- | `for (const [k, v] in pairs(t))` | `for item in unpack(pairs(t), 1, 3) do local k, v = item[1], item[2] … end` — an iteration is `[step, state, first]` |
77
+ | `for (const item of xs)` | `for _, item in xs do … end` — an array or a table walked for its values |
78
+ | `for (const item of step)` | `for item in step do … end` — an iterator function |
79
+ | `for (const [k, v] of pairs(t))` | `for item in unpack(pairs(t), 1, 3) do local k, v = item[1], item[2] … end` — an iteration is `[step, state, first]` |
80
+ | `for (const key in t)` | `for key in pairs(t) do … end` — a table's keys, as in TypeScript |
80
81
  | `t ??= v` | `if t == nil then t = v end` — what addresses `t` read once, into locals |
81
82
  | `{ m() { … } }` | `{ m = function(this) … end }` — called with `:` |
82
83
  | `break outer` from a loop inside `outer` | a flag `outer` declares, raised, and a `break`; after each loop on the way out, a check that breaks again — or, at `outer`, does the `break` or `continue` |
@@ -117,7 +118,7 @@ Luau without asking:
117
118
  | `a += b`, `a // b` | `a = a + (b)`, `math.floor(a / (b))` | as written |
118
119
  | `continue` | a `break` out of a one-pass `repeat` | as written |
119
120
  | `c ? a : b`, `a?.b`, `a ?? b` | `and`/`or` where neither arm can be `false`, else a function called on the spot | `if c then a else b` |
120
- | `for (const x in xs)` | `ipairs(xs)` where `xs` is an array by its type; otherwise `tilua_each(xs)`, which walks a table as Luau would — its `__iter` if it has one, `next` if not | `for _, x in xs do` |
121
+ | `for (const x of xs)` | `ipairs(xs)` where `xs` is an array by its type; otherwise `tilua_each(xs)`, which walks a table as Luau would — its `__iter` if it has one, `next` if not | `for _, x in xs do` |
121
122
  | `1_000`, `0b101` | plain numbers | as written |
122
123
  | `@native` and other attributes | dropped | kept |
123
124
  | another file of the bundle | `loadfile` | `require` by path |
@@ -433,12 +434,12 @@ entry's.
433
434
  <!-- compatibility:start -->
434
435
  ## Compatibility
435
436
 
436
- `@tilua/compiler@7.0.1` works with these tilua packages. *Released with* is the
437
+ `@tilua/compiler@8.0.0` works with these tilua packages. *Released with* is the
437
438
  version it was built and tested against.
438
439
 
439
440
  | Package | Range | Released with | |
440
441
  | --- | --- | --- | --- |
441
- | `@tilua/parser` | `^7.0.0` | 7.0.0 | dependency |
442
+ | `@tilua/parser` | `^8.0.0` | 8.0.0 | dependency |
442
443
  <!-- compatibility:end -->
443
444
 
444
445
  ## Development
@@ -1448,8 +1448,15 @@ end`).body.statements, out);
1448
1448
  item = this.names.fresh("item");
1449
1449
  prelude.push(...this.destructure(variable, identifier(item), "declare"));
1450
1450
  }
1451
- const form = this.options.types?.loops.get(node) ?? { walks: "values", viaIter: false };
1451
+ const form = this.options.types?.loops.get(node) ?? { walks: node.over === "keys" ? "keys" : "values", viaIter: false };
1452
1452
  let source = this.expression(node.iterator);
1453
+ if (form.walks === "keys") {
1454
+ return [genericFor(
1455
+ [item],
1456
+ [call(this.builtin("pairs"), [source])],
1457
+ this.loopBody51(this.block(node.body, prelude)).statements
1458
+ )];
1459
+ }
1453
1460
  if (form.viaIter) source = methodCall(source, "__iter", []);
1454
1461
  const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
1455
1462
  let iterators = form.walks === "iteration" ? [call(this.helper("unpack"), [source, number(1), number(3)])] : [source];
@@ -2792,6 +2799,7 @@ import {
2792
2799
  directivesOf,
2793
2800
  applyDirectives,
2794
2801
  UNUSED_EXPECT_ERROR,
2802
+ UNUSED_EXPECT_WARNING,
2795
2803
  ParseError,
2796
2804
  LexError,
2797
2805
  luauString as luauString4
@@ -3213,7 +3221,7 @@ async function bundle(options) {
3213
3221
  }
3214
3222
  for (const [file, fileDirectives] of directives) {
3215
3223
  const semantic = diagnostics.filter((d) => d.file === file && (d.category === "scope" || d.category === "type"));
3216
- const { kept, unusedExpectErrors } = applyDirectives(fileDirectives, semantic, (d) => d.line);
3224
+ const { kept, unusedExpectErrors, unusedExpectWarnings } = applyDirectives(fileDirectives, semantic, (d) => d.line, (d) => d.severity === "warning");
3217
3225
  const suppressed = new Set(semantic.filter((d) => !kept.includes(d)));
3218
3226
  const remaining = diagnostics.filter((d) => !suppressed.has(d));
3219
3227
  diagnostics.length = 0;
@@ -3222,6 +3230,9 @@ async function bundle(options) {
3222
3230
  for (const d of unusedExpectErrors) {
3223
3231
  diagnostics.push({ file, message: UNUSED_EXPECT_ERROR, line: d.line, column: d.column, category: "type" });
3224
3232
  }
3233
+ for (const d of unusedExpectWarnings) {
3234
+ diagnostics.push({ file, message: UNUSED_EXPECT_WARNING, line: d.line, column: d.column, category: "type", severity: "warning" });
3235
+ }
3225
3236
  }
3226
3237
  const moduleProblems = new Set(diagnostics.filter((d) => d.category === "module").map((d) => `${d.file}:${d.line}:${d.column}:${d.message}`));
3227
3238
  const reported = diagnostics.filter((d) => d.category !== "type" || !moduleProblems.has(`${d.file}:${d.line}:${d.column}:${d.message}`));
package/dist/cli.cjs CHANGED
@@ -1465,8 +1465,15 @@ end`).body.statements, out2);
1465
1465
  item = this.names.fresh("item");
1466
1466
  prelude.push(...this.destructure(variable, identifier(item), "declare"));
1467
1467
  }
1468
- const form = this.options.types?.loops.get(node) ?? { walks: "values", viaIter: false };
1468
+ const form = this.options.types?.loops.get(node) ?? { walks: node.over === "keys" ? "keys" : "values", viaIter: false };
1469
1469
  let source = this.expression(node.iterator);
1470
+ if (form.walks === "keys") {
1471
+ return [genericFor(
1472
+ [item],
1473
+ [call(this.builtin("pairs"), [source])],
1474
+ this.loopBody51(this.block(node.body, prelude)).statements
1475
+ )];
1476
+ }
1470
1477
  if (form.viaIter) source = methodCall(source, "__iter", []);
1471
1478
  const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
1472
1479
  let iterators = form.walks === "iteration" ? [call(this.helper("unpack"), [source, number(1), number(3)])] : [source];
@@ -3210,7 +3217,7 @@ async function bundle(options) {
3210
3217
  }
3211
3218
  for (const [file, fileDirectives] of directives) {
3212
3219
  const semantic = diagnostics.filter((d) => d.file === file && (d.category === "scope" || d.category === "type"));
3213
- const { kept, unusedExpectErrors } = (0, import_parser7.applyDirectives)(fileDirectives, semantic, (d) => d.line);
3220
+ const { kept, unusedExpectErrors, unusedExpectWarnings } = (0, import_parser7.applyDirectives)(fileDirectives, semantic, (d) => d.line, (d) => d.severity === "warning");
3214
3221
  const suppressed = new Set(semantic.filter((d) => !kept.includes(d)));
3215
3222
  const remaining = diagnostics.filter((d) => !suppressed.has(d));
3216
3223
  diagnostics.length = 0;
@@ -3219,6 +3226,9 @@ async function bundle(options) {
3219
3226
  for (const d of unusedExpectErrors) {
3220
3227
  diagnostics.push({ file, message: import_parser7.UNUSED_EXPECT_ERROR, line: d.line, column: d.column, category: "type" });
3221
3228
  }
3229
+ for (const d of unusedExpectWarnings) {
3230
+ diagnostics.push({ file, message: import_parser7.UNUSED_EXPECT_WARNING, line: d.line, column: d.column, category: "type", severity: "warning" });
3231
+ }
3222
3232
  }
3223
3233
  const moduleProblems = new Set(diagnostics.filter((d) => d.category === "module").map((d) => `${d.file}:${d.line}:${d.column}:${d.message}`));
3224
3234
  const reported = diagnostics.filter((d) => d.category !== "type" || !moduleProblems.has(`${d.file}:${d.line}:${d.column}:${d.message}`));
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  bundle,
4
4
  resolveConfig
5
- } from "./chunk-WGXXYKEU.js";
5
+ } from "./chunk-TOP7NC3Z.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { mkdirSync, writeFileSync } from "fs";
package/dist/index.cjs CHANGED
@@ -1488,8 +1488,15 @@ end`).body.statements, out);
1488
1488
  item = this.names.fresh("item");
1489
1489
  prelude.push(...this.destructure(variable, identifier(item), "declare"));
1490
1490
  }
1491
- const form = this.options.types?.loops.get(node) ?? { walks: "values", viaIter: false };
1491
+ const form = this.options.types?.loops.get(node) ?? { walks: node.over === "keys" ? "keys" : "values", viaIter: false };
1492
1492
  let source = this.expression(node.iterator);
1493
+ if (form.walks === "keys") {
1494
+ return [genericFor(
1495
+ [item],
1496
+ [call(this.builtin("pairs"), [source])],
1497
+ this.loopBody51(this.block(node.body, prelude)).statements
1498
+ )];
1499
+ }
1493
1500
  if (form.viaIter) source = methodCall(source, "__iter", []);
1494
1501
  const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
1495
1502
  let iterators = form.walks === "iteration" ? [call(this.helper("unpack"), [source, number(1), number(3)])] : [source];
@@ -3233,7 +3240,7 @@ async function bundle(options) {
3233
3240
  }
3234
3241
  for (const [file, fileDirectives] of directives) {
3235
3242
  const semantic = diagnostics.filter((d) => d.file === file && (d.category === "scope" || d.category === "type"));
3236
- const { kept, unusedExpectErrors } = (0, import_parser7.applyDirectives)(fileDirectives, semantic, (d) => d.line);
3243
+ const { kept, unusedExpectErrors, unusedExpectWarnings } = (0, import_parser7.applyDirectives)(fileDirectives, semantic, (d) => d.line, (d) => d.severity === "warning");
3237
3244
  const suppressed = new Set(semantic.filter((d) => !kept.includes(d)));
3238
3245
  const remaining = diagnostics.filter((d) => !suppressed.has(d));
3239
3246
  diagnostics.length = 0;
@@ -3242,6 +3249,9 @@ async function bundle(options) {
3242
3249
  for (const d of unusedExpectErrors) {
3243
3250
  diagnostics.push({ file, message: import_parser7.UNUSED_EXPECT_ERROR, line: d.line, column: d.column, category: "type" });
3244
3251
  }
3252
+ for (const d of unusedExpectWarnings) {
3253
+ diagnostics.push({ file, message: import_parser7.UNUSED_EXPECT_WARNING, line: d.line, column: d.column, category: "type", severity: "warning" });
3254
+ }
3245
3255
  }
3246
3256
  const moduleProblems = new Set(diagnostics.filter((d) => d.category === "module").map((d) => `${d.file}:${d.line}:${d.column}:${d.message}`));
3247
3257
  const reported = diagnostics.filter((d) => d.category !== "type" || !moduleProblems.has(`${d.file}:${d.line}:${d.column}:${d.message}`));
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  lower,
5
5
  program,
6
6
  resolveConfig
7
- } from "./chunk-WGXXYKEU.js";
7
+ } from "./chunk-TOP7NC3Z.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": "7.0.1",
3
+ "version": "8.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",
@@ -38,7 +38,7 @@
38
38
  "type": "module",
39
39
  "dependencies": {
40
40
  "luau-parser": "^1.0.3",
41
- "@tilua/parser": "^7.0.0"
41
+ "@tilua/parser": "^8.0.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22.20.2",