@tilua/parser 2.4.0 → 3.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
@@ -260,22 +260,51 @@ brings in names that are types and nothing else: unlike TypeScript, using one
260
260
  as a value is an error, and only type positions — `typeof A` included — may
261
261
  name it. Compiled code keeps no trace of it.
262
262
 
263
- **Array and string methods** — an array and a string answer to methods
264
- written with `:`, the way JavaScript writes them:
263
+ **Methods of strings, arrays and tables** — a value answers to the methods
264
+ its metatable's `__index` has, written with `:`:
265
265
 
266
266
  ```luau
267
267
  const long = names:filter(n => #n > 3):map(string.upper)
268
- const first = names:find(n => n:startsWith("A"))
269
- print(names:join(", "), text:trim(), text:replaceAll(",", ";"))
268
+ print(names:join(", "), text:trim(), text:upper())
269
+ const point = { x: 1, y: "up" }
270
+ const [x, y] = point:values() -- [number, string]
270
271
  ```
271
272
 
272
- Which methods those are is not the language's business. The analyzer looks for
273
- two types by name — `ArrayMethods<T>` and `StringMethods` — and reads an
274
- array's or a string's members out of whichever type library declared them;
275
- without such a library an array has no methods at all.
273
+ Strings, arrays and tables are the language's own, so their metatables are
274
+ too: the prelude declares them, in tilua, and they are there with no type
275
+ library at all. A string's is Lua's (`upper`, `sub`, with one value where Lua
276
+ answers several: `find` is an array) plus the JavaScript-shaped ones (`trim`,
277
+ `startsWith`, ...); an array's is JavaScript's (`filter`, `map`, `join`, ...),
278
+ with Lua's indices — the first element is 1, `indexOf` answers `nil` rather
279
+ than -1 — and `push`, `pop`, `shift`, `unshift`, `sort` and `reverse` change
280
+ the array. A table's are `keys`, `values` and `entries`, which answer a tuple
281
+ in the order the table's type wrote its members, not `string[]` as
282
+ JavaScript's `Object.keys` does; the analyzer supplies that order as
283
+ `ObjectKeys<T>`, `ObjectValues<T>` and `ObjectEntries<T>`. A member of a
284
+ value's own with the same name is what a call reaches, and a class instance,
285
+ which has a metatable of its own, has none of them.
286
+
287
+ No Lua array or table really has these methods, so the compiler lowers each
288
+ call into its own runtime (`names:filter(f)` becomes `array.filter(names, f)`);
289
+ a string's Lua methods stay plain method calls.
290
+
291
+ A library adds to a metatable by declaring the same target again, and a
292
+ metatable can be declared for any type:
276
293
 
277
- Running them is that library's business too. A library points at a JavaScript
278
- module in its package.json, and the compiler asks it what a call becomes:
294
+ ```luau
295
+ declare metatable string: { __index: { split: (self: string, separator?: string) => string[] } }
296
+ declare metatable<T> T[]: { __index: { first: (self: T[]) => T | nil } }
297
+ declare metatable<T extends {}> T: { __index: { size: (self: T) => number } }
298
+ ```
299
+
300
+ `<T> T[]` is every array, `T` what it holds; `<T extends C> T` every value
301
+ that is a `C`, `T` the value itself; a target with no parameters, every value
302
+ of that type. The most specific target a value matches is its metatable.
303
+
304
+ A method a library's metatable gives may be one the value really has, as
305
+ Luau's `split` is. When it is not, the library says how it runs. It points at
306
+ a JavaScript module in its package.json, and the compiler asks it — and only
307
+ it — what a call through a metatable it declared becomes:
279
308
 
280
309
  ```json
281
310
  "tilua": { "types": "index.d.tilua", "lowering": "lowering.mjs" }
@@ -285,11 +314,9 @@ module in its package.json, and the compiler asks it what a call becomes:
285
314
  // @ts-check
286
315
  /** @type {import("@tilua/parser").LoweringPlugin} */ // the contract, declared here
287
316
  const plugin = {
288
- runtime: { array: "local __NAME__ = {}\nfunction __NAME__.filter(t, test) ... end" },
289
- methodCall({ method, receiver, use }) {
290
- if (receiver?.kind === "array" && method === "filter") {
291
- return { callee: `${use("array")}.filter` }
292
- }
317
+ runtime: { array: "local __NAME__ = {}\nfunction __NAME__.first(t) return t[1] end" },
318
+ methodCall({ method, use }) {
319
+ if (method === "first") return { callee: `${use("array")}.first` }
293
320
  return undefined
294
321
  },
295
322
  }
@@ -300,7 +327,9 @@ export default plugin
300
327
  local name that table got — emitted once, at the top of the output, only if a
301
328
  call needed it — and the receiver is passed as the call's first argument. An
302
329
  answer of `undefined` leaves an ordinary Luau method call, which is what
303
- `text:upper()` wants, since a string already answers to it.
330
+ `text:split(",")` wants, since a Luau string already answers to it. A method
331
+ of a value's own (`console:log`, a member of a declared table) is asked of
332
+ every library, the last loaded first.
304
333
 
305
334
  A call can also carry more than was written. Every hook is told `at`, where
306
335
  the call was written (`{ file, line, column }`), and `arguments`: each one's
@@ -314,13 +343,6 @@ hook is asked about it. A runtime can read `__LINES__`, the bundle's line map
314
343
  project. `console:log`, `print` and `error` in `@tilua-types/lua` are built on
315
344
  these hooks.
316
345
 
317
- The compiler lowers the language and nothing else: `filter` appears nowhere in
318
- it.
319
-
320
- `@tilua-types/lua` ships the JavaScript-shaped set; there, indices are Luau's (the
321
- first element is 1, `indexOf` answers `nil` rather than -1) and `push`, `pop`,
322
- `shift`, `unshift`, `sort` and `reverse` change the array they are called on.
323
-
324
346
  **A `(` that starts a line** continues the statement above it, as in Lua and
325
347
  in JavaScript — `const v = map[key]` followed by `("A"):upper()` is one
326
348
  statement, a call of `map[key]`. tilua says so rather than letting it pass: