@tilua/parser 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/README.md CHANGED
@@ -96,10 +96,14 @@ npm i -D @tilua-types/roblox # Luau + Roblox; or @tilua-types/lua on its
96
96
  - **Which config applies** — the nearest one in the file's folder or above.
97
97
  `tilua.config.json` and `tilua.config.jsonc` in the same folder is an error.
98
98
  Both forms accept comments and trailing commas.
99
- - **`types`** — any name, looked up as the package `@tilua-types/<name>` in
100
- `node_modules` from the config upward; one that is not installed is an
101
- error. A relative path (`"./types"`, `"./defs.d.tilua"`) loads the project's
102
- own definitions. A type library's own type-library dependencies load first.
99
+ - **`types`** — packages are looked for in `node_modules` from the config
100
+ upward. A bare name is `@tilua-types/<name>` first, then the package of that
101
+ name, so a library published under any name works: `"roblox"`,
102
+ `"my-types"`. A scoped name is taken as written (`"@me/types"`), and a `*`
103
+ matches every installed type library it fits (`"@tilua-types/*"`), in name
104
+ order. A relative path (`"./types"`, `"./defs.d.tilua"`) loads the project's
105
+ own definitions. A type library's own type-library dependencies load first;
106
+ one that is not installed is an error.
103
107
  - **`paths`** — tsconfig rules: an exact pattern wins, then the `*` pattern
104
108
  with the longest prefix; targets resolve from `baseUrl` (default: the
105
109
  config's folder).
@@ -147,7 +151,7 @@ if (n < 0) {
147
151
 
148
152
  while (going) { step() }
149
153
  for (i = 1, 10) { total += i }
150
- for (name, value in pairs(t)) { print(name, value) }
154
+ for (const [name, value] in pairs(t)) { print(name, value) }
151
155
  repeat { step() } until (done)
152
156
  do { ... }
153
157
 
@@ -175,7 +179,7 @@ if (n < 0) return "negative"
175
179
  elseif (n == 0) return "zero"
176
180
  else return "positive"
177
181
 
178
- for (_, item in items) if (item) print(item)
182
+ for (const item in items) if (item) print(item)
179
183
  while (queued > 0) queued -= 1
180
184
  ```
181
185
 
@@ -337,9 +341,11 @@ name: T | nil -- must be written, but may be nil
337
341
  Omitting an argument requires `?` (or a default), as in TypeScript — a
338
342
  parameter typed `T | nil` still has to be passed something.
339
343
 
340
- **Optional chaining** — `a?.b` and `a?:m(x)` are nil when `a` is, and then
341
- nothing further along the chain runs, arguments included: `folder?:FindFirstChild("A")?.Name`
342
- is a `string | nil`. The `?` must touch the `.` or `:`; `c ? a : b` stays a
344
+ **Optional chaining** — `a?.b`, `a?.[k]`, `a?.(x)` and `a?:m(x)` are nil when
345
+ `a` is, and then nothing further along the chain runs, arguments and the key
346
+ included: `folder?:FindFirstChild("A")?.Name` is a `string | nil`, and
347
+ `maps?.[key]?.label` reads the key only when `maps` is there. The `?` must
348
+ touch the `.` or `:`; `c ? a : b` stays a
343
349
  ternary. Parentheses end a chain. A chain cannot be assigned to (`a?.b = 1` is
344
350
  an error). A chain that got through narrows what it tested: inside
345
351
  `if (part?.Parent)`, and `if (part?.Name == "Door")`, `part` is not nil.
@@ -407,7 +413,7 @@ class Dog extends Animal {
407
413
  }
408
414
  }
409
415
 
410
- const rex = new Dog("Rex", "shiba")
416
+ const rex = Dog.new("Rex", "shiba")
411
417
  rex:speak() -- the receiver is `this`
412
418
  rex.label = "Max" -- the setter
413
419
  Dog.made() -- a static, inherited from Animal
@@ -415,22 +421,98 @@ Dog.made() -- a static, inherited from Animal
415
421
 
416
422
  The receiver is written `this`, and it is an ordinary first parameter: a
417
423
  method's type is `(this: Dog, ...) => R`, so `rex:speak()` supplies it the way
418
- `function T:m()` supplies `self`. `new Dog(x)` *is* `Dog.new(x)` — the same
419
- function, callable by hand and passable as a value.
424
+ `function T:m()` supplies `self`. An instance is built the way Luau builds
425
+ one, with the class's own function: `Dog.new(x)` — callable like any other,
426
+ and passable as a value. There is no `new Dog(x)`; writing it is a syntax
427
+ error that says so.
428
+
429
+ **`public`, `private` and `protected`** go before a member — `private
430
+ balance = 0`, `private static function check()`, `public get size()`. Leaving
431
+ it out means public. A private member can be reached only inside the body of
432
+ the class that declared it, including functions nested in its methods; a
433
+ subclass is outside, as in TypeScript. A protected one is reachable from the
434
+ classes extending it too. It is a type check and nothing more: the member is
435
+ an ordinary key at runtime.
436
+
437
+ **`readonly`** fields are assigned where they are declared or in the
438
+ constructor of their own class, and nowhere else: `readonly id: number`.
439
+
440
+ The modifiers can come in any order — `static private readonly count = 0` —
441
+ and each stays an ordinary name where no member follows it, so
442
+ `private: boolean` and `readonly = 1` are still fields.
443
+
444
+ **`abstract`** — an `abstract class` has no `new`: it is built only as part of
445
+ a class extending it. It may declare `abstract function area(): number`, a
446
+ head with no body, and a class extending it that is not abstract itself has to
447
+ write every such member. Calling an abstract method through `super` is an
448
+ error, as is `Shape.new`.
449
+
450
+ **`override`** says a member replaces one of the class it extends, and is an
451
+ error on a member that does not. Whether or not it is written, a member that
452
+ replaces one has to fit it: its type, `this` aside, is checked against the
453
+ base's.
454
+
455
+ **`implements`** — `class Person implements Named, Greeter` checks that the
456
+ instances have every member each shape names, of a type that fits. Nothing
457
+ happens at runtime.
420
458
 
421
- **`public` and `private`** go before a member — `private balance = 0`,
422
- `private static function check()`, `public get size()`. Leaving it out means
423
- public. A private member can be reached only inside the body of the class that
424
- declared it, including functions nested in its methods; a subclass is outside,
425
- as in TypeScript. It is a type check and nothing more: the member is an
426
- ordinary key at runtime. `public` and `private` stay ordinary names elsewhere,
427
- so `private: boolean` is still a field.
459
+ ```luau
460
+ abstract class Shape implements Named {
461
+ readonly name: string
462
+ protected sides = 0
463
+ constructor(name: string) {
464
+ this.name = name
465
+ }
466
+ abstract function area(): number
467
+ }
468
+
469
+ class Square extends Shape {
470
+ side = 1
471
+ constructor() {
472
+ super("square")
473
+ this.sides = 4 -- protected: reachable from here
474
+ }
475
+ override function area(): number {
476
+ return this.side * this.side
477
+ }
478
+ }
479
+ ```
480
+
481
+ **Metamethods** are methods with their Luau names. The class table *is* its
482
+ instances' metatable, so `function __add(other: Vec): Vec` in a class is the
483
+ `+` of its instances — and the type checker reads it the same way: `a + b`
484
+ between two `Vec`s is a `Vec`. `__sub`, `__mul`, `__div`, `__idiv`, `__mod`,
485
+ `__pow`, `__unm`, `__concat`, `__len` (`#v`), `__eq`, `__lt` and `__le` (`<`,
486
+ `>`, `<=`, `>=`), `__call` (calling an instance), `__iter` (`for a, b in v`)
487
+ and `__tostring` all work this way, and a class extending another inherits
488
+ them. Each is checked: it takes the operands Luau hands it, returns what Luau
489
+ expects of it (`__tostring` a string, `__eq`/`__lt`/`__le` a boolean), and is
490
+ not `static`. Comparing two instances whose class has no `__lt` is an error,
491
+ as it is at runtime.
492
+
493
+ ```luau
494
+ class Vec {
495
+ x: number
496
+ constructor(x: number) {
497
+ this.x = x
498
+ }
499
+ function __add(other: Vec): Vec {
500
+ return Vec.new(this.x + other.x)
501
+ }
502
+ function __tostring(): string {
503
+ return `Vec(${this.x})`
504
+ }
505
+ }
506
+
507
+ const v = Vec.new(1) + Vec.new(2) -- Vec
508
+ print(tostring(v)) -- Vec(3)
509
+ ```
428
510
 
429
511
  A declaration names two things. As a **type**, `Dog` is the type of its
430
512
  instances, nominal the same way a `declare class` is: a table with the same
431
513
  members is not one, and only `Dog` and what extends it are assignable to it.
432
514
  As a **value**, `Dog` is the class table — its statics, and the `new` that
433
- builds an instance. `export class` exports both.
515
+ builds an instance (`Dog.new(...)`). `export class` exports both.
434
516
 
435
517
  Two links are always there, and they are what the memory model promises:
436
518
 
@@ -455,12 +537,12 @@ class Box<T> {
455
537
  return this.value
456
538
  }
457
539
  function map<R>(f: (value: T) => R): Box<R> {
458
- return new Box(f(this.value))
540
+ return Box.new(f(this.value))
459
541
  }
460
542
  }
461
543
 
462
- const n = new Box(1) -- Box<number>, read off the argument
463
- const s = new Box<string>("a") -- or written out
544
+ const n = Box.new(1) -- Box<number>, read off the argument
545
+ const s = Box.new<string>("a") -- or written out
464
546
  const held: number = n:get()
465
547
 
466
548
  class Ints extends Box<number> { -- extending one fixes its argument
@@ -482,24 +564,65 @@ it, as TypeScript's does, and importing it brings in the type too:
482
564
 
483
565
  ```luau
484
566
  import Box from "./box" -- `Box` is the class *and* the type
485
- const held: Box<number> = new Box(1)
567
+ const held: Box<number> = Box.new(1)
486
568
  ```
487
569
 
488
570
  Reported: a field with a type that nothing gives a value (`name: string` that
489
- the constructor never assigns), a derived constructor that does not call
571
+ the constructor does not assign on every way through it — both arms of an
572
+ `if`, not in a loop or a function written inside), a derived constructor that does not call
490
573
  `super(...)`, `extends` naming something that is not a class, a chain that
491
574
  closes on itself, a member written twice, and a member named one of the words
492
575
  the compiler builds the class table out of (`new`, `ClassObject`,
493
576
  `ParentClass`, `__init`, `__index`, `__newindex`, `__getters`, `__setters`,
494
577
  `__dynamic`).
495
578
 
496
- **Varargs** — `...` is Lua's pack, and every name on the left reads one of
497
- it: with `...: number`, `const a, b = ...` gives two numbers. `[...]` puts the
498
- whole pack in an array.
579
+ **One value, and arrays** — tilua has no packs. A function returns one value;
580
+ several are an array, and a tuple type says how many and of what:
581
+
582
+ ```luau
583
+ function divide(a: number, b: number): [number, number] {
584
+ return [a // b, a % b]
585
+ }
586
+
587
+ const [quotient, remainder] = divide(7, 2) -- taken apart
588
+ const both = divide(7, 2) -- or kept: [number, number]
589
+ ```
590
+
591
+ An array is a table, at runtime as much as in the types: `return [a, b]` is
592
+ `return { a, b }`. Where Luau answers several values — `pcall`, `string.find`,
593
+ a Roblox method such as `FindPartOnRay` — the type library puts a function of
594
+ its own in place of that global or method, which answers one value, as its
595
+ type says. A tuple may end in a rest,
596
+ `[string, ...number[]]`: that many, then any number more. `const a, b = 1, 2`
597
+ still pairs names with values one each; `const a, b = f()` is a name short,
598
+ and says to write `const [a, b] = f()`.
599
+
600
+ **A loop takes one value too** — `for (const item in source)`, and several are
601
+ an array the pattern takes apart:
602
+
603
+ ```luau
604
+ for (const name in names) { print(name) }
605
+ for (const [i, name] in ipairs(names)) { print(i, name) }
606
+ for (const [key, score] in pairs(scores)) { print(key, score) }
607
+ ```
608
+
609
+ The name is `const`, or `let` where the body assigns to it, as anywhere else.
610
+ A source is an array or a table, walked for its values; an iterator function,
611
+ called until it answers `nil`; or an iteration — `[step, state, first]`, what
612
+ `pairs(t)` answers — whose `step` is called with the state and the item before
613
+ it. An object says how it is walked with `__iter`, which answers one of those
614
+ two. `for (k, v in ...)` and `for (x in f, s, v)` are Luau's packs, and are
615
+ syntax errors.
616
+
617
+ A function that returns nothing returns `nil`: `() => nil`, not `() => ()`.
618
+ Bare `...` is gone — a
619
+ function takes a rest parameter, and what the script was started with is
620
+ `scriptArgs: unknown[]`. `()`, `(A, B)` as a type, `T...`, `...: T` and
621
+ `return a, b` are syntax errors that say what to write instead.
499
622
 
500
623
  **Rest parameters** — `...name: T[]` is JavaScript's: every argument from that
501
- position on, as an array. It is last, and the call signature is the same one
502
- `...: T` describes — the difference is only what the body sees.
624
+ position on, as an array. It is last, and it is the one way a function takes a
625
+ varying number of arguments.
503
626
 
504
627
  ```luau
505
628
  function join(separator: string, ...parts: string[]): string {
@@ -517,24 +640,28 @@ firstOf(1, 2) -- number | nil: the arguments say what `T` is
517
640
  ```
518
641
 
519
642
  A type is written the same way: `type Reporter = (level: string, ...lines:
520
- string[]) => ()` describes the same calls as `(level: string, ...string) =>
521
- ()`. Without an annotation a rest parameter is `unknown[]`; annotated with
522
- something that is not an array, it is reported.
643
+ string[]) => nil`. Without an annotation a rest parameter is `unknown[]`. A rest
644
+ parameter may also be a tuple, or a type parameter standing for one — then the
645
+ arguments are exactly its elements, which is how a function says it forwards
646
+ another's:
523
647
 
524
- **Spreads** — `...xs` puts what an array holds into any list of values, as
525
- JavaScript does: a call's arguments, a `return`, a declaration, an assignment.
526
- Bare `...` is unchanged, and is still the pack.
648
+ ```luau
649
+ declare function spawn<A extends unknown[]>(f: (...args: A) => nil, ...args: A): thread
650
+
651
+ spawn(function(n: number) { print(n) }, 1) -- ok
652
+ spawn(function(n: number) { print(n) }, "no") -- '"no"' is not a number
653
+ ```
654
+
655
+ **Spreads** — `...xs` puts what an array holds into a call's arguments or an
656
+ array literal, as JavaScript does. A list of values — a declaration's, an
657
+ assignment's — takes one value per name; take an array apart with a
658
+ destructuring instead.
527
659
 
528
660
  ```luau
529
661
  join("-", ...names) -- every name
530
662
  join("-", ...names, "z") -- and one more after them
531
663
  add3(...nums) -- however many `nums` turns out to hold
532
-
533
- function three(): (number, number, number) {
534
- return ...nums
535
- }
536
-
537
- const first, second = ...names -- one each, as far as the names go
664
+ const both = [...names, "z"]
538
665
  ```
539
666
 
540
667
  What the array holds is checked against what it fills. How many it holds is
@@ -570,9 +697,10 @@ its parameter types from it: in `signal:Connect(player => ... )`,
570
697
  `player` is typed from `Connect`. The same applies to an annotated `const`
571
698
  and to an assignment such as `remote.OnServerInvoke = function(player) { ... }`.
572
699
 
573
- **Type packs** — `type Signal<T... = ...any> = { Connect: (self, cb: (T...) => ()) => () }`.
574
- A pack parameter takes every type argument from its position on:
575
- `Signal<Player, string>`, `Signal<()>` for none.
700
+ **Signals and other variadic generics** — a type parameter can stand for a
701
+ list of arguments: `type Signal<T extends unknown[] = any[]> = { Connect:
702
+ (self, cb: (...args: T) => nil) => Connection }`, given as a tuple —
703
+ `Signal<[Player, string]>`, `Signal<[]>` for none.
576
704
 
577
705
  **Operators** — on a type that declares metamethods (`__add`, `__mul`,
578
706
  `__unm`, ...), an operator has the metamethod's result, tried on the left
@@ -617,8 +745,19 @@ non-nil part.
617
745
 
618
746
  Only `nil` and `false` are falsy — `0` and `""` are truthy, unlike JavaScript.
619
747
 
620
- **Types** — unions, intersections, tuples `[A, B]`, type packs `(A, B)` (the
621
- several values a function returns), `keyof`, `T[K]`, conditional types with
748
+ **What Luau raises on is said first.** An operator no metamethod answers takes
749
+ numbers — `..` a string or a number, `#` a string or a table — so `n * 2` with
750
+ `n` a `number | nil` is an error where it is written rather than where it runs.
751
+ A comparison two types can never settle (`s == "c"` with `s` a `"a" | "b"`) is
752
+ one too; a test against `nil` never is, since a map's value and an array's
753
+ element are read as what they hold. A name holds nothing until its line has
754
+ run, a list is indexed by position (`xs["a"]` is not a read), `readonly T[]`
755
+ rules out writing to the list as well as passing it where a `number[]` is
756
+ wanted, a key written twice in one table is reported, and a parameter with no
757
+ type says so — it is `any`, and `any` turns off every check made of it.
758
+
759
+ **Types** — unions, intersections, tuples `[A, B]` (with a rest, `[A,
760
+ ...B[]]`), `keyof`, `T[K]`, conditional types with
622
761
  `infer`, mapped types with `as` remapping, template literal types
623
762
  (`` `on${Event}` ``), and set difference `A - B`. The utility types
624
763
  (`Partial`, `Pick`, `Omit`, `ReturnType`, `Parameters`, `Exclude`, …) are