@tilua/compiler 5.0.0 → 5.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 CHANGED
@@ -180,7 +180,9 @@ another, and one the class writes itself replaces the copy.
180
180
  Two links come with every class, and they cost an instance nothing because
181
181
  they live on the class table: `ClassObject`, which an instance reads through
182
182
  its metatable to reach its own class, and `ParentClass`, which a class reads
183
- to reach the one it extends.
183
+ to reach the one it extends. The class table holds its `name` too
184
+ (`tilua_class(base, "Dog")`), so `rex.ClassObject.name` says what built an
185
+ instance.
184
186
 
185
187
  A class written as a value (`const Counter = class { … }`) is the same code,
186
188
  inside a function that runs where the class is written and hands the table
@@ -258,6 +258,18 @@ var Lowerer = class {
258
258
  for (const binding of scopes.bindings.values()) {
259
259
  if (binding.declarationNode) this.bindingByDeclaration.set(binding.declarationNode, binding);
260
260
  }
261
+ const visit = (value) => {
262
+ if (!value || typeof value !== "object") return;
263
+ if (Array.isArray(value)) return void value.forEach(visit);
264
+ const node = value;
265
+ if (node.type === "VariableDeclaration" && node.name?.type === "IdentifierPattern" && node.name.name) {
266
+ let init = node.init;
267
+ while (init?.type === "ParenthesizedExpression") init = init.expression;
268
+ if (init?.type === "ClassExpression") this.classExpressionNames.set(init, node.name.name);
269
+ }
270
+ for (const [key, child] of Object.entries(value)) if (key !== "line" && key !== "column") visit(child);
271
+ };
272
+ visit(source.body);
261
273
  }
262
274
  source;
263
275
  scopes;
@@ -279,6 +291,8 @@ var Lowerer = class {
279
291
  lua51;
280
292
  /** The source line each emitted statement came from. */
281
293
  origins = /* @__PURE__ */ new WeakMap();
294
+ /** The name each class written as a value is known by. */
295
+ classExpressionNames = /* @__PURE__ */ new WeakMap();
282
296
  run() {
283
297
  const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
284
298
  const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
@@ -660,6 +674,8 @@ end`).body.statements);
660
674
  out.push(...parseLuau(`
661
675
  local function ${accessors}(target, getters, setters)
662
676
  return ${this.builtin("setmetatable").name}(target, {
677
+ -- Read by a spread, which copies what the getters give.
678
+ __tiluaGetters = getters,
663
679
  __index = function(self, key)
664
680
  local get = getters[key]
665
681
  if get ~= nil then
@@ -683,17 +699,25 @@ end`).body.statements);
683
699
  }
684
700
  const assign2 = this.helpers.get("assign");
685
701
  if (assign2) {
686
- out.push(localFunction(assign2, functionBody(["target"], [
687
- numericFor("i", number(1), selectCount(this.builtin("select")), [
688
- local(["source"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
689
- ifThen(binary("~=", identifier("source"), nil()), [
690
- genericFor(["key", "value"], [call(this.builtin("pairs"), [identifier("source")])], [
691
- assign([index(identifier("target"), identifier("key"))], [identifier("value")])
692
- ])
693
- ])
694
- ]),
695
- returns([identifier("target")])
696
- ], true)));
702
+ out.push(...parseLuau(`
703
+ local function ${assign2}(target, ...)
704
+ for i = 1, ${this.builtin("select").name}("#", ...) do
705
+ local source = (${this.builtin("select").name}(i, ...))
706
+ if source ~= nil then
707
+ for key, value in ${this.builtin("pairs").name}(source) do
708
+ target[key] = value
709
+ end
710
+ local meta = ${this.builtin("type").name}(source) == "table" and ${this.builtin("getmetatable").name}(source) or nil
711
+ local getters = ${this.builtin("type").name}(meta) == "table" and ${this.builtin("rawget").name}(meta, "__tiluaGetters") or nil
712
+ if getters ~= nil then
713
+ for key, get in ${this.builtin("pairs").name}(getters) do
714
+ target[key] = get(source)
715
+ end
716
+ end
717
+ end
718
+ end
719
+ return target
720
+ end`).body.statements);
697
721
  }
698
722
  out.push(...runtimes);
699
723
  const concat = this.helpers.get("concat");
@@ -1238,11 +1262,12 @@ end`).body.statements);
1238
1262
  const { build, accessors } = this.classHelpers;
1239
1263
  const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
1240
1264
  return parseLuau(`
1241
- local function ${build}(base)
1265
+ local function ${build}(base, name)
1242
1266
  local class = { __getters = {}, __setters = {} }
1243
1267
  class.__index = class
1244
1268
  class.ClassObject = class
1245
1269
  class.ParentClass = base
1270
+ class.name = name
1246
1271
  if base ~= nil then
1247
1272
  setmetatable(class, { __index = base })
1248
1273
  setmetatable(class.__getters, { __index = base.__getters })
@@ -1296,7 +1321,11 @@ end
1296
1321
  * table is assigned to `self`, which a module has already declared. */
1297
1322
  classStatements(node, self, declare) {
1298
1323
  const { build, accessors } = this.classRuntime();
1299
- const create = call(identifier(build), [node.superclass ? this.reference(node.superclass) : nil()]);
1324
+ const called = node.name?.name ?? (node.type === "ClassExpression" ? this.classExpressionNames.get(node) : void 0) ?? "";
1325
+ const create = call(identifier(build), [
1326
+ node.superclass ? this.reference(node.superclass) : nil(),
1327
+ string(called)
1328
+ ]);
1300
1329
  const out = [declare !== void 0 ? local([declare], [create]) : assign([self], [create])];
1301
1330
  const previous = this.classContext;
1302
1331
  this.classContext = node;
package/dist/cli.cjs CHANGED
@@ -275,6 +275,18 @@ var Lowerer = class {
275
275
  for (const binding of scopes.bindings.values()) {
276
276
  if (binding.declarationNode) this.bindingByDeclaration.set(binding.declarationNode, binding);
277
277
  }
278
+ const visit = (value) => {
279
+ if (!value || typeof value !== "object") return;
280
+ if (Array.isArray(value)) return void value.forEach(visit);
281
+ const node = value;
282
+ if (node.type === "VariableDeclaration" && node.name?.type === "IdentifierPattern" && node.name.name) {
283
+ let init = node.init;
284
+ while (init?.type === "ParenthesizedExpression") init = init.expression;
285
+ if (init?.type === "ClassExpression") this.classExpressionNames.set(init, node.name.name);
286
+ }
287
+ for (const [key, child] of Object.entries(value)) if (key !== "line" && key !== "column") visit(child);
288
+ };
289
+ visit(source.body);
278
290
  }
279
291
  source;
280
292
  scopes;
@@ -296,6 +308,8 @@ var Lowerer = class {
296
308
  lua51;
297
309
  /** The source line each emitted statement came from. */
298
310
  origins = /* @__PURE__ */ new WeakMap();
311
+ /** The name each class written as a value is known by. */
312
+ classExpressionNames = /* @__PURE__ */ new WeakMap();
299
313
  run() {
300
314
  const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
301
315
  const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
@@ -677,6 +691,8 @@ end`).body.statements);
677
691
  out2.push(...(0, import_luau_parser.parse)(`
678
692
  local function ${accessors}(target, getters, setters)
679
693
  return ${this.builtin("setmetatable").name}(target, {
694
+ -- Read by a spread, which copies what the getters give.
695
+ __tiluaGetters = getters,
680
696
  __index = function(self, key)
681
697
  local get = getters[key]
682
698
  if get ~= nil then
@@ -700,17 +716,25 @@ end`).body.statements);
700
716
  }
701
717
  const assign2 = this.helpers.get("assign");
702
718
  if (assign2) {
703
- out2.push(localFunction(assign2, functionBody(["target"], [
704
- numericFor("i", number(1), selectCount(this.builtin("select")), [
705
- local(["source"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
706
- ifThen(binary("~=", identifier("source"), nil()), [
707
- genericFor(["key", "value"], [call(this.builtin("pairs"), [identifier("source")])], [
708
- assign([index(identifier("target"), identifier("key"))], [identifier("value")])
709
- ])
710
- ])
711
- ]),
712
- returns([identifier("target")])
713
- ], true)));
719
+ out2.push(...(0, import_luau_parser.parse)(`
720
+ local function ${assign2}(target, ...)
721
+ for i = 1, ${this.builtin("select").name}("#", ...) do
722
+ local source = (${this.builtin("select").name}(i, ...))
723
+ if source ~= nil then
724
+ for key, value in ${this.builtin("pairs").name}(source) do
725
+ target[key] = value
726
+ end
727
+ local meta = ${this.builtin("type").name}(source) == "table" and ${this.builtin("getmetatable").name}(source) or nil
728
+ local getters = ${this.builtin("type").name}(meta) == "table" and ${this.builtin("rawget").name}(meta, "__tiluaGetters") or nil
729
+ if getters ~= nil then
730
+ for key, get in ${this.builtin("pairs").name}(getters) do
731
+ target[key] = get(source)
732
+ end
733
+ end
734
+ end
735
+ end
736
+ return target
737
+ end`).body.statements);
714
738
  }
715
739
  out2.push(...runtimes);
716
740
  const concat = this.helpers.get("concat");
@@ -1255,11 +1279,12 @@ end`).body.statements);
1255
1279
  const { build, accessors } = this.classHelpers;
1256
1280
  const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
1257
1281
  return (0, import_luau_parser.parse)(`
1258
- local function ${build}(base)
1282
+ local function ${build}(base, name)
1259
1283
  local class = { __getters = {}, __setters = {} }
1260
1284
  class.__index = class
1261
1285
  class.ClassObject = class
1262
1286
  class.ParentClass = base
1287
+ class.name = name
1263
1288
  if base ~= nil then
1264
1289
  setmetatable(class, { __index = base })
1265
1290
  setmetatable(class.__getters, { __index = base.__getters })
@@ -1313,7 +1338,11 @@ end
1313
1338
  * table is assigned to `self`, which a module has already declared. */
1314
1339
  classStatements(node, self, declare) {
1315
1340
  const { build, accessors } = this.classRuntime();
1316
- const create = call(identifier(build), [node.superclass ? this.reference(node.superclass) : nil()]);
1341
+ const called = node.name?.name ?? (node.type === "ClassExpression" ? this.classExpressionNames.get(node) : void 0) ?? "";
1342
+ const create = call(identifier(build), [
1343
+ node.superclass ? this.reference(node.superclass) : nil(),
1344
+ string(called)
1345
+ ]);
1317
1346
  const out2 = [declare !== void 0 ? local([declare], [create]) : assign([self], [create])];
1318
1347
  const previous = this.classContext;
1319
1348
  this.classContext = node;
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  bundle,
4
4
  resolveConfig
5
- } from "./chunk-3J2QMA4W.js";
5
+ } from "./chunk-Y7QGXLCV.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { mkdirSync, writeFileSync } from "fs";
package/dist/index.cjs CHANGED
@@ -298,6 +298,18 @@ var Lowerer = class {
298
298
  for (const binding of scopes.bindings.values()) {
299
299
  if (binding.declarationNode) this.bindingByDeclaration.set(binding.declarationNode, binding);
300
300
  }
301
+ const visit = (value) => {
302
+ if (!value || typeof value !== "object") return;
303
+ if (Array.isArray(value)) return void value.forEach(visit);
304
+ const node = value;
305
+ if (node.type === "VariableDeclaration" && node.name?.type === "IdentifierPattern" && node.name.name) {
306
+ let init = node.init;
307
+ while (init?.type === "ParenthesizedExpression") init = init.expression;
308
+ if (init?.type === "ClassExpression") this.classExpressionNames.set(init, node.name.name);
309
+ }
310
+ for (const [key, child] of Object.entries(value)) if (key !== "line" && key !== "column") visit(child);
311
+ };
312
+ visit(source.body);
301
313
  }
302
314
  source;
303
315
  scopes;
@@ -319,6 +331,8 @@ var Lowerer = class {
319
331
  lua51;
320
332
  /** The source line each emitted statement came from. */
321
333
  origins = /* @__PURE__ */ new WeakMap();
334
+ /** The name each class written as a value is known by. */
335
+ classExpressionNames = /* @__PURE__ */ new WeakMap();
322
336
  run() {
323
337
  const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
324
338
  const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
@@ -700,6 +714,8 @@ end`).body.statements);
700
714
  out.push(...(0, import_luau_parser.parse)(`
701
715
  local function ${accessors}(target, getters, setters)
702
716
  return ${this.builtin("setmetatable").name}(target, {
717
+ -- Read by a spread, which copies what the getters give.
718
+ __tiluaGetters = getters,
703
719
  __index = function(self, key)
704
720
  local get = getters[key]
705
721
  if get ~= nil then
@@ -723,17 +739,25 @@ end`).body.statements);
723
739
  }
724
740
  const assign2 = this.helpers.get("assign");
725
741
  if (assign2) {
726
- out.push(localFunction(assign2, functionBody(["target"], [
727
- numericFor("i", number(1), selectCount(this.builtin("select")), [
728
- local(["source"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
729
- ifThen(binary("~=", identifier("source"), nil()), [
730
- genericFor(["key", "value"], [call(this.builtin("pairs"), [identifier("source")])], [
731
- assign([index(identifier("target"), identifier("key"))], [identifier("value")])
732
- ])
733
- ])
734
- ]),
735
- returns([identifier("target")])
736
- ], true)));
742
+ out.push(...(0, import_luau_parser.parse)(`
743
+ local function ${assign2}(target, ...)
744
+ for i = 1, ${this.builtin("select").name}("#", ...) do
745
+ local source = (${this.builtin("select").name}(i, ...))
746
+ if source ~= nil then
747
+ for key, value in ${this.builtin("pairs").name}(source) do
748
+ target[key] = value
749
+ end
750
+ local meta = ${this.builtin("type").name}(source) == "table" and ${this.builtin("getmetatable").name}(source) or nil
751
+ local getters = ${this.builtin("type").name}(meta) == "table" and ${this.builtin("rawget").name}(meta, "__tiluaGetters") or nil
752
+ if getters ~= nil then
753
+ for key, get in ${this.builtin("pairs").name}(getters) do
754
+ target[key] = get(source)
755
+ end
756
+ end
757
+ end
758
+ end
759
+ return target
760
+ end`).body.statements);
737
761
  }
738
762
  out.push(...runtimes);
739
763
  const concat = this.helpers.get("concat");
@@ -1278,11 +1302,12 @@ end`).body.statements);
1278
1302
  const { build, accessors } = this.classHelpers;
1279
1303
  const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
1280
1304
  return (0, import_luau_parser.parse)(`
1281
- local function ${build}(base)
1305
+ local function ${build}(base, name)
1282
1306
  local class = { __getters = {}, __setters = {} }
1283
1307
  class.__index = class
1284
1308
  class.ClassObject = class
1285
1309
  class.ParentClass = base
1310
+ class.name = name
1286
1311
  if base ~= nil then
1287
1312
  setmetatable(class, { __index = base })
1288
1313
  setmetatable(class.__getters, { __index = base.__getters })
@@ -1336,7 +1361,11 @@ end
1336
1361
  * table is assigned to `self`, which a module has already declared. */
1337
1362
  classStatements(node, self, declare) {
1338
1363
  const { build, accessors } = this.classRuntime();
1339
- const create = call(identifier(build), [node.superclass ? this.reference(node.superclass) : nil()]);
1364
+ const called = node.name?.name ?? (node.type === "ClassExpression" ? this.classExpressionNames.get(node) : void 0) ?? "";
1365
+ const create = call(identifier(build), [
1366
+ node.superclass ? this.reference(node.superclass) : nil(),
1367
+ string(called)
1368
+ ]);
1340
1369
  const out = [declare !== void 0 ? local([declare], [create]) : assign([self], [create])];
1341
1370
  const previous = this.classContext;
1342
1371
  this.classContext = node;
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  lower,
5
5
  program,
6
6
  resolveConfig
7
- } from "./chunk-3J2QMA4W.js";
7
+ } from "./chunk-Y7QGXLCV.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": "5.0.0",
3
+ "version": "5.0.1",
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": "^5.0.0"
41
+ "@tilua/parser": "^5.0.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22.20.2",
@@ -130,6 +130,30 @@ function __NAME__.slice(t, start, stop)
130
130
  end
131
131
 
132
132
  -- One level, as JavaScript's `flat()` does by default.
133
+ function __NAME__.keys(t)
134
+ local out = __ARRAY__({})
135
+ for i = 1, #t do
136
+ out[i] = i
137
+ end
138
+ return out
139
+ end
140
+
141
+ function __NAME__.values(t)
142
+ local out = __ARRAY__({})
143
+ for i = 1, #t do
144
+ out[i] = t[i]
145
+ end
146
+ return out
147
+ end
148
+
149
+ function __NAME__.entries(t)
150
+ local out = __ARRAY__({})
151
+ for i = 1, #t do
152
+ out[i] = __ARRAY__({ i, t[i] })
153
+ end
154
+ return out
155
+ end
156
+
133
157
  function __NAME__.flat(t)
134
158
  local out = __ARRAY__({})
135
159
  for i = 1, #t do