@tilua/parser 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 +8 -2
- package/dist/index.cjs +47 -12
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +47 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -353,7 +353,9 @@ than -1 — and `push`, `pop`, `shift`, `unshift`, `sort` and `reverse` change
|
|
|
353
353
|
the array. Looking for a value is not adding one, so `includes` and `indexOf`
|
|
354
354
|
take any value, not only one the array's type already holds — and `includes`
|
|
355
355
|
is a guard: `if (modes:includes(s))` narrows `s` to a mode. `concat` may join
|
|
356
|
-
arrays of other types (`(T | U)[]`).
|
|
356
|
+
arrays of other types (`(T | U)[]`). `keys`, `values` and `entries` answer
|
|
357
|
+
arrays rather than JavaScript's iterators — `for (const [i, v] in
|
|
358
|
+
xs:entries())` — counting from 1. The ones that only read take a read-only
|
|
357
359
|
list too (`readonly T[]`, what `as const` makes), as TypeScript's
|
|
358
360
|
`ReadonlyArray` does; the ones that change it do not. A table's are `keys`, `values` and `entries`, which answer a tuple
|
|
359
361
|
in the order the table's type wrote its members, not `string[]` as
|
|
@@ -693,7 +695,11 @@ Dog.ParentClass == Animal -- a class names the one it extends
|
|
|
693
695
|
Animal.ParentClass == nil -- and a root class extends nothing
|
|
694
696
|
```
|
|
695
697
|
|
|
696
|
-
Both live on the class table, so an instance carries neither.
|
|
698
|
+
Both live on the class table, so an instance carries neither. So does its
|
|
699
|
+
name, as a JavaScript class's `name`: `Dog.name` is `"Dog"`, and a class
|
|
700
|
+
written as a value takes the name of what holds it (`const Counter = class
|
|
701
|
+
{ ... }` is `"Counter"`). A static, a method or an accessor cannot be called
|
|
702
|
+
`name`; an instance field can, and lives on the instance.
|
|
697
703
|
|
|
698
704
|
**Generic classes** — `class Box<T> { ... }`. The name is then a generic type,
|
|
699
705
|
and `Box<number>` and `Box<string>` are both `Box` but neither is the other:
|
package/dist/index.cjs
CHANGED
|
@@ -226,6 +226,14 @@ function isAlphaNumeric(ch) {
|
|
|
226
226
|
return isAlpha(ch) || isDigit(ch);
|
|
227
227
|
}
|
|
228
228
|
var KeywordSet = new Set(Keywords);
|
|
229
|
+
var TS_SPELLINGS = [
|
|
230
|
+
["!==", "~=", "Operator"],
|
|
231
|
+
["===", "==", "Operator"],
|
|
232
|
+
["!=", "~=", "Operator"],
|
|
233
|
+
["&&", "and", "Keyword"],
|
|
234
|
+
["||", "or", "Keyword"],
|
|
235
|
+
["!", "not", "Keyword"]
|
|
236
|
+
];
|
|
229
237
|
var OperatorSet = new Set(Operators);
|
|
230
238
|
var SortedSymbols = [...Operators, ...Punctuators].sort((a, b) => b.length - a.length);
|
|
231
239
|
var LexError = class extends Error {
|
|
@@ -686,6 +694,15 @@ function tokenize(source, options = {}) {
|
|
|
686
694
|
tokens.push(readIdentifierOrKeyword());
|
|
687
695
|
continue;
|
|
688
696
|
}
|
|
697
|
+
const spelled = TS_SPELLINGS.find(([written]) => source.startsWith(written, cursor));
|
|
698
|
+
if (spelled) {
|
|
699
|
+
const [written, meant, kind] = spelled;
|
|
700
|
+
const startLine = line, startColumn = column;
|
|
701
|
+
fail(`tilua writes '${meant}', not '${written}'`, startLine, startColumn);
|
|
702
|
+
for (let k = 0; k < written.length; k++) advance();
|
|
703
|
+
tokens.push(kind === "Keyword" ? { type: "Keyword", value: meant, ...makeBase(startLine, startColumn) } : { type: "Operator", value: meant, ...makeBase(startLine, startColumn) });
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
689
706
|
const symbol = readOperatorOrPunctuator();
|
|
690
707
|
if (symbol) tokens.push(symbol);
|
|
691
708
|
}
|
|
@@ -4494,7 +4511,7 @@ declare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler:
|
|
|
4494
4511
|
declare function select(n: "#", ...args: unknown[]): number
|
|
4495
4512
|
declare function select<T>(n: number, ...args: T[]): T[]
|
|
4496
4513
|
-- A copy of the list, or of part of it.
|
|
4497
|
-
declare function unpack<V>(list: V[], i?: number, j?: number): V[]
|
|
4514
|
+
declare function unpack<V>(list: readonly V[], i?: number, j?: number): V[]
|
|
4498
4515
|
declare function rawget(t: unknown, key: unknown): unknown
|
|
4499
4516
|
declare function rawset<T>(t: T, key: unknown, value: unknown): T
|
|
4500
4517
|
declare function rawequal(a: unknown, b: unknown): boolean
|
|
@@ -4513,10 +4530,11 @@ type Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]
|
|
|
4513
4530
|
-- \`for (const [k, v] in pairs(t))\` / \`ipairs(t)\`: each item is one \`[key,
|
|
4514
4531
|
-- value]\` \u2014 a table, as every array is. The analyzer types it from \`t\` itself
|
|
4515
4532
|
-- (a record's keys as literals, an array's elements); these declare the
|
|
4516
|
-
-- names, and their shape for any other use.
|
|
4517
|
-
|
|
4533
|
+
-- names, and their shape for any other use. Walking a list only reads it, so
|
|
4534
|
+
-- a read-only one (\`as const\`, \`readonly T[]\`) is walked as well.
|
|
4535
|
+
declare function pairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>
|
|
4518
4536
|
declare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>
|
|
4519
|
-
declare function ipairs<V>(t: V[]): Iteration<V[], [number, V]>
|
|
4537
|
+
declare function ipairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>
|
|
4520
4538
|
|
|
4521
4539
|
declare function collectgarbage(option: "count"): number
|
|
4522
4540
|
declare function gcinfo(): number
|
|
@@ -4590,14 +4608,14 @@ declare table: {
|
|
|
4590
4608
|
-- \`insert(t, v)\` appends; \`insert(t, pos, v)\` puts it there.
|
|
4591
4609
|
insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),
|
|
4592
4610
|
remove: <T>(t: T[], pos?: number) => T | nil,
|
|
4593
|
-
concat: (t: (string | number)[], sep?: string, i?: number, j?: number) => string,
|
|
4611
|
+
concat: (t: readonly (string | number)[], sep?: string, i?: number, j?: number) => string,
|
|
4594
4612
|
sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,
|
|
4595
4613
|
-- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau
|
|
4596
4614
|
-- still answers to them, so code being ported still type-checks.
|
|
4597
|
-
getn: <T>(t: T[]) => number,
|
|
4598
|
-
maxn: <T>(t: T[]) => number,
|
|
4615
|
+
getn: <T>(t: readonly T[]) => number,
|
|
4616
|
+
maxn: <T>(t: readonly T[]) => number,
|
|
4599
4617
|
foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,
|
|
4600
|
-
foreachi: <V, R>(t: V[], f: (index: number, value: V) => R) => R | nil,
|
|
4618
|
+
foreachi: <V, R>(t: readonly V[], f: (index: number, value: V) => R) => R | nil,
|
|
4601
4619
|
}
|
|
4602
4620
|
|
|
4603
4621
|
declare os: {
|
|
@@ -5490,6 +5508,11 @@ declare metatable<T> T[]: {
|
|
|
5490
5508
|
concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],
|
|
5491
5509
|
slice: (self: readonly T[], start?: number, stop?: number) => T[],
|
|
5492
5510
|
flat: (self: readonly T[]) => T[],
|
|
5511
|
+
-- JavaScript's, as arrays rather than iterators: \`for (const [i, v] in
|
|
5512
|
+
-- xs:entries())\` walks positions and values, counting from 1.
|
|
5513
|
+
keys: (self: readonly T[]) => number[],
|
|
5514
|
+
values: (self: readonly T[]) => T[],
|
|
5515
|
+
entries: (self: readonly T[]) => [number, T][],
|
|
5493
5516
|
reverse: (self: T[]) => T[],
|
|
5494
5517
|
sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],
|
|
5495
5518
|
push: (self: T[], ...args: T[]) => number,
|
|
@@ -7277,7 +7300,7 @@ function keepsLiterals(paramType) {
|
|
|
7277
7300
|
const members = paramType.constraint.kind === "union" ? paramType.constraint.types : [paramType.constraint];
|
|
7278
7301
|
return members.some((m) => m.kind === "literal" || m.kind === "primitive" && (m.name === "string" || m.name === "number"));
|
|
7279
7302
|
}
|
|
7280
|
-
var CLASS_LINKS = /* @__PURE__ */ new Set(["new", "ClassObject", "ParentClass"]);
|
|
7303
|
+
var CLASS_LINKS = /* @__PURE__ */ new Set(["new", "ClassObject", "ParentClass", "name"]);
|
|
7281
7304
|
var CLASS_RESERVED = /* @__PURE__ */ new Set([
|
|
7282
7305
|
"new",
|
|
7283
7306
|
"ClassObject",
|
|
@@ -8035,6 +8058,7 @@ var TypeAnalyzer = class {
|
|
|
8035
8058
|
});
|
|
8036
8059
|
type.properties.set("new", construct);
|
|
8037
8060
|
type.properties.set("ParentClass", { type: parent ?? nilType, optional: false, readonly: true });
|
|
8061
|
+
type.properties.set("name", { type: stmt.name ? literal(stmt.name.name) : stringType, optional: false, readonly: true });
|
|
8038
8062
|
return type;
|
|
8039
8063
|
}
|
|
8040
8064
|
/** The value side of the class `superclass` names when it is not
|
|
@@ -8294,6 +8318,9 @@ var TypeAnalyzer = class {
|
|
|
8294
8318
|
if (CLASS_RESERVED.has(member.name.name)) {
|
|
8295
8319
|
report(member.name, `'${member.name.name}' is what the compiler calls part of a class; a member cannot be named that`);
|
|
8296
8320
|
}
|
|
8321
|
+
if (member.name.name === "name" && !(member.type === "ClassField" && !member.isStatic)) {
|
|
8322
|
+
report(member.name, "'name' is the class's own name, `Dog.name`: a static, a method or an accessor cannot be called that \u2014 an instance field can");
|
|
8323
|
+
}
|
|
8297
8324
|
}
|
|
8298
8325
|
const seen = /* @__PURE__ */ new Map();
|
|
8299
8326
|
for (const member of stmt.members) {
|
|
@@ -9134,6 +9161,13 @@ var TypeAnalyzer = class {
|
|
|
9134
9161
|
case "array":
|
|
9135
9162
|
case "tuple":
|
|
9136
9163
|
return union([numberType, literal("length")]);
|
|
9164
|
+
// A string is not indexed by position in Lua (`s[1]` is nil), so
|
|
9165
|
+
// of its keys only `length` is there.
|
|
9166
|
+
case "primitive":
|
|
9167
|
+
return t.name === "string" ? literal("length") : neverType;
|
|
9168
|
+
case "literal":
|
|
9169
|
+
case "templateLiteral":
|
|
9170
|
+
return t.kind === "templateLiteral" || t.base === "string" ? literal("length") : neverType;
|
|
9137
9171
|
case "union": {
|
|
9138
9172
|
const sets = t.types.map((m) => {
|
|
9139
9173
|
const keys = this.keysOf(m);
|
|
@@ -9604,7 +9638,7 @@ var TypeAnalyzer = class {
|
|
|
9604
9638
|
this.loops.set(stmt, { walks: "iteration", viaIter: false });
|
|
9605
9639
|
} else {
|
|
9606
9640
|
const [item, form] = this.iterationOf(stmt.iterator, sourceType);
|
|
9607
|
-
this.bindPattern(stmt.variable, item, bodyEnv, "widen");
|
|
9641
|
+
this.bindPattern(stmt.variable, item, bodyEnv, stmt.kind === "const" ? "keep" : "widen");
|
|
9608
9642
|
this.loops.set(stmt, form);
|
|
9609
9643
|
}
|
|
9610
9644
|
this.visitBlock(stmt.body, bodyEnv);
|
|
@@ -11060,7 +11094,8 @@ var TypeAnalyzer = class {
|
|
|
11060
11094
|
const name = source.callee.name;
|
|
11061
11095
|
const src = this.expand(this.typeOf.get(source.arguments[0]) ?? unknownType);
|
|
11062
11096
|
const iteration = { walks: "iteration", viaIter: false };
|
|
11063
|
-
|
|
11097
|
+
const element = src.kind === "array" ? src.element : src.kind === "tuple" ? union(tupleMembers(src).map((m) => m.kind === "spread" ? this.spreadElement(m.type) ?? unknownType : m)) : void 0;
|
|
11098
|
+
if (name === "ipairs") return [tuple([numberType, element ?? this.elementType(src, 0)]), iteration];
|
|
11064
11099
|
if (name === "pairs") {
|
|
11065
11100
|
if (src.kind === "object") {
|
|
11066
11101
|
return [tuple([
|
|
@@ -11068,7 +11103,7 @@ var TypeAnalyzer = class {
|
|
|
11068
11103
|
src.indexer?.value ?? union([...src.properties.values()].map((p) => p.type))
|
|
11069
11104
|
]), iteration];
|
|
11070
11105
|
}
|
|
11071
|
-
if (
|
|
11106
|
+
if (element) return [tuple([numberType, element]), iteration];
|
|
11072
11107
|
}
|
|
11073
11108
|
}
|
|
11074
11109
|
const handsOut = (t2, viaIter) => {
|
package/dist/index.d.cts
CHANGED
|
@@ -1756,7 +1756,7 @@ resolveModule?: (specifier: string) => ModuleExports | undefined): ModuleExports
|
|
|
1756
1756
|
* `ObjectValues<T>` and `ObjectEntries<T>`, an object's members as tuples in
|
|
1757
1757
|
* the order they were written.
|
|
1758
1758
|
*/
|
|
1759
|
-
declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = Exclude<T, Falsy>\n\n-- `Exclude<T, U>` is the analyzer's own: what of `T` is not a `U`. Over a\n-- union it drops the members it takes whole; over `unknown`, `any`, a\n-- primitive or an unresolved parameter it is kept \u2014 `Exclude<string, \"a\">` is\n-- a string that is not `\"a\"` \u2014 unlike TypeScript's.\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = Exclude<T, nil>\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n-- A class table builds with `new`: `InstanceType<typeof Dog>` is a `Dog`.\ntype InstanceType<T> = T extends { new: (...args: any[]) => infer R } ? R : never\ntype ConstructorParameters<T> = T extends { new: (...args: infer P) => any } ? P : never\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- The ones that only read take a `readonly T[]` too \u2014 `as const` lists, and\n-- what a function promised not to change \u2014 as TypeScript's `ReadonlyArray`.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: readonly T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: readonly T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: readonly T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: readonly T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: readonly T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: readonly T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: readonly T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n -- Asking is not adding: any value may be looked for, and finding it\n -- says it is one of the array's \u2014 `if (names:includes(s))` narrows `s`.\n includes: (self: readonly T[], value: unknown) => value is T,\n indexOf: (self: readonly T[], value: unknown, start?: number) => number | nil,\n join: (self: readonly T[], separator?: string) => string,\n concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],\n slice: (self: readonly T[], start?: number, stop?: number) => T[],\n flat: (self: readonly T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
|
|
1759
|
+
declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = Exclude<T, Falsy>\n\n-- `Exclude<T, U>` is the analyzer's own: what of `T` is not a `U`. Over a\n-- union it drops the members it takes whole; over `unknown`, `any`, a\n-- primitive or an unresolved parameter it is kept \u2014 `Exclude<string, \"a\">` is\n-- a string that is not `\"a\"` \u2014 unlike TypeScript's.\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = Exclude<T, nil>\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n-- A class table builds with `new`: `InstanceType<typeof Dog>` is a `Dog`.\ntype InstanceType<T> = T extends { new: (...args: any[]) => infer R } ? R : never\ntype ConstructorParameters<T> = T extends { new: (...args: infer P) => any } ? P : never\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- The ones that only read take a `readonly T[]` too \u2014 `as const` lists, and\n-- what a function promised not to change \u2014 as TypeScript's `ReadonlyArray`.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: readonly T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: readonly T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: readonly T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: readonly T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: readonly T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: readonly T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: readonly T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n -- Asking is not adding: any value may be looked for, and finding it\n -- says it is one of the array's \u2014 `if (names:includes(s))` narrows `s`.\n includes: (self: readonly T[], value: unknown) => value is T,\n indexOf: (self: readonly T[], value: unknown, start?: number) => number | nil,\n join: (self: readonly T[], separator?: string) => string,\n concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],\n slice: (self: readonly T[], start?: number, stop?: number) => T[],\n flat: (self: readonly T[]) => T[],\n -- JavaScript's, as arrays rather than iterators: `for (const [i, v] in\n -- xs:entries())` walks positions and values, counting from 1.\n keys: (self: readonly T[]) => number[],\n values: (self: readonly T[]) => T[],\n entries: (self: readonly T[]) => [number, T][],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
|
|
1760
1760
|
|
|
1761
1761
|
/**
|
|
1762
1762
|
* The Lua 5.1 standard library, always there — as TypeScript always has
|
|
@@ -1773,7 +1773,7 @@ declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `
|
|
|
1773
1773
|
* `@tilua-types/lua`, where this used to live, is not loaded when a project
|
|
1774
1774
|
* still names it: it would declare everything twice.
|
|
1775
1775
|
*/
|
|
1776
|
-
declare const STANDARD_LIBRARY_SOURCE = "\n-- The Lua 5.1 standard library, written in tilua.\n--\n-- This is the floor every tilua project stands on, the way TypeScript stands\n-- on JavaScript's: the functions and libraries Lua itself defines, there in\n-- every file without being asked for. Nothing here is Luau's or Roblox's \u2014\n-- `buffer`, `table.create` and the rest live one layer up in\n-- `@tilua-types/roblox`, which adds to it.\n--\n-- Lua's `type()` is not here: what a value is, is asked with the language's\n-- own `typeof v`, which also tells an array from an object.\n--\n-- Adding to it is literal: a name declared again in a later file keeps what\n-- earlier files gave it. `declare table: { find: ... }` in `@tilua-types/roblox` does\n-- not replace this `table`, it extends it, and overloads of a function\n-- accumulate the same way. So the layers really are layers.\n\n-- ============================================================\n-- Base library\n-- ============================================================\n\ndeclare _G: { [string]: unknown }\ndeclare _VERSION: string\n\ndeclare function require(module: unknown): unknown\ndeclare function tostring(value: unknown): string\ndeclare function tonumber(value: unknown, base?: number): number | nil\ndeclare function print(...args: unknown[]): nil\n-- `error` never returns, which is what lets\n-- `if v == nil then error(\"...\") end` narrow the rest of the block.\ndeclare function error(message: unknown, level?: number): never\n\n-- `asserts value` \u2014 narrows the *rest of the enclosing block*, the way\n-- TypeScript's assertion signatures do:\n--\n-- const part = workspace:FindFirstChild(\"Part\") -- Instance | nil\n-- assert(part)\n-- part.Name -- Instance, no `?`\n\ndeclare function assert<T>(value: T, message?: string): asserts value\n\n-- `pcall` and `xpcall` answer the way a JavaScript result object does:\n--\n-- const { success, data, error } = pcall(load, \"config\")\n-- if (success) { use(data) } else { warn(error) }\n--\n-- `data` is what the function returned. These are not Luau's own `pcall`:\n-- where Luau answers several values, tilua has one, and the compiler puts its\n-- own functions in place of those globals (runtime/result.luau) \u2014 for calls,\n-- and for the global read as a value alike. The same goes for `string.find`,\n-- `string.match`, `string.gsub`, `string.byte`, `math.modf`, `math.frexp`,\n-- `next`, `select`, `unpack`, `loadstring`, `pairs`, `ipairs` and\n-- `string.gmatch` below.\ntype PcallResult<T> = { success: true, data: T, error: nil } | { success: false, data: nil, error: unknown }\n\ndeclare function pcall<A extends unknown[], T>(fn: (...args: A) => T, ...args: A): PcallResult<T>\ndeclare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler: (err: unknown) => unknown, ...args: A): PcallResult<T>\n-- `select(\"#\", ...args)` counts; `select(n, ...args)` is what follows the\n-- n-th, as an array.\ndeclare function select(n: \"#\", ...args: unknown[]): number\ndeclare function select<T>(n: number, ...args: T[]): T[]\n-- A copy of the list, or of part of it.\ndeclare function unpack<V>(list: V[], i?: number, j?: number): V[]\ndeclare function rawget(t: unknown, key: unknown): unknown\ndeclare function rawset<T>(t: T, key: unknown, value: unknown): T\ndeclare function rawequal(a: unknown, b: unknown): boolean\ndeclare function setmetatable<T>(t: T, mt: unknown): T\ndeclare function getmetatable(t: unknown): unknown\ndeclare function newproxy(addMeta?: boolean): unknown\n-- The entry after `key` \u2014 or nil, past the last one.\ndeclare function next<K, V>(t: { [K]: V }, key?: K): [K, V] | nil\n\n-- What `for (const item in source)` walks: `step` is called with the state\n-- and the item before it \u2014 `first` the first time \u2014 until it answers nil.\n-- An array, a table and an iterator function are walked too, so this is only\n-- what a source such as `pairs(t)` hands over.\ntype Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]\n\n-- `for (const [k, v] in pairs(t))` / `ipairs(t)`: each item is one `[key,\n-- value]` \u2014 a table, as every array is. The analyzer types it from `t` itself\n-- (a record's keys as literals, an array's elements); these declare the\n-- names, and their shape for any other use.\ndeclare function pairs<V>(t: V[]): Iteration<V[], [number, V]>\ndeclare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>\ndeclare function ipairs<V>(t: V[]): Iteration<V[], [number, V]>\n\ndeclare function collectgarbage(option: \"count\"): number\ndeclare function gcinfo(): number\ndeclare function getfenv(target?: unknown): { [string]: unknown }\ndeclare function setfenv<T>(target: T, env: { [string]: unknown }): T\ndeclare function loadstring(source: string, chunkname?: string): [((...args: unknown[]) => unknown) | nil, string | nil]\n\ndeclare debug: {\n traceback: (message?: string, level?: number) => string,\n}\n\ndeclare string: {\n format: (fmt: string, ...args: unknown[]) => string,\n sub: (s: string, i: number, j?: number) => string,\n len: (s: string) => number,\n upper: (s: string) => string,\n lower: (s: string) => string,\n rep: (s: string, n: number, sep?: string) => string,\n reverse: (s: string) => string,\n -- Where the pattern is, then what it captured \u2014 or nil.\n find: (s: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n -- What it captured (the whole match when there are no captures), as\n -- JavaScript's `match` answers \u2014 or nil.\n match: (s: string, pattern: string, init?: number) => [...string[]] | nil,\n -- Each match's captures (the whole match when there are none), one\n -- array at a time: `for (const [word] in s:gmatch(\"%a+\"))`.\n gmatch: (s: string, pattern: string) => () => [string, ...string[]] | nil,\n -- The new string, as JavaScript's `replace` answers; Luau's count of\n -- replacements is left behind.\n gsub: (s: string, pattern: string, repl: unknown, n?: number) => string,\n -- One code for one position; an array of them for a range.\n byte: ((s: string, i?: number) => number) & ((s: string, i: number, j: number) => number[]),\n char: (...args: number[]) => string,\n}\n\ndeclare math: {\n abs: (x: number) => number,\n floor: (x: number) => number,\n ceil: (x: number) => number,\n fmod: (x: number, y: number) => number,\n modf: (x: number) => [number, number],\n sqrt: (x: number) => number,\n pow: (x: number, y: number) => number,\n exp: (x: number) => number,\n log: (x: number, base?: number) => number,\n log10: (x: number) => number,\n frexp: (x: number) => [number, number],\n ldexp: (m: number, e: number) => number,\n min: (...args: number[]) => number,\n max: (...args: number[]) => number, \n sin: (x: number) => number,\n cos: (x: number) => number,\n tan: (x: number) => number,\n asin: (x: number) => number,\n acos: (x: number) => number,\n atan: (x: number) => number,\n atan2: (y: number, x: number) => number,\n sinh: (x: number) => number,\n cosh: (x: number) => number,\n tanh: (x: number) => number,\n rad: (deg: number) => number,\n deg: (rad: number) => number,\n random: (m?: number, n?: number) => number,\n randomseed: (x: number) => nil,\n huge: number,\n pi: number,\n}\n\n\ndeclare table: {\n -- `insert(t, v)` appends; `insert(t, pos, v)` puts it there.\n insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),\n remove: <T>(t: T[], pos?: number) => T | nil,\n concat: (t: (string | number)[], sep?: string, i?: number, j?: number) => string,\n sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,\n -- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau\n -- still answers to them, so code being ported still type-checks.\n getn: <T>(t: T[]) => number,\n maxn: <T>(t: T[]) => number,\n foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,\n foreachi: <V, R>(t: V[], f: (index: number, value: V) => R) => R | nil,\n}\n\ndeclare os: {\n time: (t?: unknown) => number,\n clock: () => number,\n date: (format?: string, time?: number) => unknown,\n difftime: (a: number, b: number) => number,\n}\n\ndeclare coroutine: {\n create: (fn: (...args: unknown[]) => unknown) => thread,\n -- Answers like `pcall`: `{ success, data, error }`, `data` what the\n -- coroutine yielded or returned.\n resume: (co: thread, ...args: unknown[]) => PcallResult<unknown>,\n yield: (...args: unknown[]) => unknown,\n wrap: (fn: (...args: unknown[]) => unknown) => (...args: unknown[]) => unknown,\n status: (co: thread) => string,\n running: () => thread,\n}\n\n-- A string's, an array's and a table's methods \u2014 `text:trim()`,\n-- `names:filter(f)`, `point:keys()` \u2014 are the language's: their metatables\n-- are declared in @tilua/parser's prelude, and the compiler runs them. A\n-- library adds to one with `declare metatable` of the same target, as\n-- `@tilua-types/roblox` gives a string Luau's `split`.\n\n-- The console. Written with `:` \u2014 `console:log(value)` \u2014 and lowered by the\n-- compiler (standard.ts) into runtime/console.luau, not into `print`.\n--\n-- Every line starts with the place that called it: `[src/main:12]: ...`.\n-- `print` and `warn` are left as written; `error` puts `src/main.tilua:12:` in\n-- its message, as Lua does.\n--\n-- `log` expands what it is given the way a browser console does: a table is\n-- printed as its contents, not as an address. A function prints as the type it\n-- was inferred to have *and* the code it was written as, both of which the\n-- compiler passes along, since neither exists once the code is running.\n--\n-- `error` reports in the project's own files: a bundle is one Luau file, so\n-- Luau's own line numbers name a file nobody wrote. It does not raise on the\n-- calling thread \u2014 the error goes to `task.spawn`, so reporting a problem\n-- never becomes one.\ntype Console = {\n log: (self: Console, ...args: unknown[]) => nil,\n warn: (self: Console, ...args: unknown[]) => nil,\n error: (self: Console, ...args: unknown[]) => nil,\n}\n\ndeclare console: Console\n";
|
|
1776
|
+
declare const STANDARD_LIBRARY_SOURCE = "\n-- The Lua 5.1 standard library, written in tilua.\n--\n-- This is the floor every tilua project stands on, the way TypeScript stands\n-- on JavaScript's: the functions and libraries Lua itself defines, there in\n-- every file without being asked for. Nothing here is Luau's or Roblox's \u2014\n-- `buffer`, `table.create` and the rest live one layer up in\n-- `@tilua-types/roblox`, which adds to it.\n--\n-- Lua's `type()` is not here: what a value is, is asked with the language's\n-- own `typeof v`, which also tells an array from an object.\n--\n-- Adding to it is literal: a name declared again in a later file keeps what\n-- earlier files gave it. `declare table: { find: ... }` in `@tilua-types/roblox` does\n-- not replace this `table`, it extends it, and overloads of a function\n-- accumulate the same way. So the layers really are layers.\n\n-- ============================================================\n-- Base library\n-- ============================================================\n\ndeclare _G: { [string]: unknown }\ndeclare _VERSION: string\n\ndeclare function require(module: unknown): unknown\ndeclare function tostring(value: unknown): string\ndeclare function tonumber(value: unknown, base?: number): number | nil\ndeclare function print(...args: unknown[]): nil\n-- `error` never returns, which is what lets\n-- `if v == nil then error(\"...\") end` narrow the rest of the block.\ndeclare function error(message: unknown, level?: number): never\n\n-- `asserts value` \u2014 narrows the *rest of the enclosing block*, the way\n-- TypeScript's assertion signatures do:\n--\n-- const part = workspace:FindFirstChild(\"Part\") -- Instance | nil\n-- assert(part)\n-- part.Name -- Instance, no `?`\n\ndeclare function assert<T>(value: T, message?: string): asserts value\n\n-- `pcall` and `xpcall` answer the way a JavaScript result object does:\n--\n-- const { success, data, error } = pcall(load, \"config\")\n-- if (success) { use(data) } else { warn(error) }\n--\n-- `data` is what the function returned. These are not Luau's own `pcall`:\n-- where Luau answers several values, tilua has one, and the compiler puts its\n-- own functions in place of those globals (runtime/result.luau) \u2014 for calls,\n-- and for the global read as a value alike. The same goes for `string.find`,\n-- `string.match`, `string.gsub`, `string.byte`, `math.modf`, `math.frexp`,\n-- `next`, `select`, `unpack`, `loadstring`, `pairs`, `ipairs` and\n-- `string.gmatch` below.\ntype PcallResult<T> = { success: true, data: T, error: nil } | { success: false, data: nil, error: unknown }\n\ndeclare function pcall<A extends unknown[], T>(fn: (...args: A) => T, ...args: A): PcallResult<T>\ndeclare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler: (err: unknown) => unknown, ...args: A): PcallResult<T>\n-- `select(\"#\", ...args)` counts; `select(n, ...args)` is what follows the\n-- n-th, as an array.\ndeclare function select(n: \"#\", ...args: unknown[]): number\ndeclare function select<T>(n: number, ...args: T[]): T[]\n-- A copy of the list, or of part of it.\ndeclare function unpack<V>(list: readonly V[], i?: number, j?: number): V[]\ndeclare function rawget(t: unknown, key: unknown): unknown\ndeclare function rawset<T>(t: T, key: unknown, value: unknown): T\ndeclare function rawequal(a: unknown, b: unknown): boolean\ndeclare function setmetatable<T>(t: T, mt: unknown): T\ndeclare function getmetatable(t: unknown): unknown\ndeclare function newproxy(addMeta?: boolean): unknown\n-- The entry after `key` \u2014 or nil, past the last one.\ndeclare function next<K, V>(t: { [K]: V }, key?: K): [K, V] | nil\n\n-- What `for (const item in source)` walks: `step` is called with the state\n-- and the item before it \u2014 `first` the first time \u2014 until it answers nil.\n-- An array, a table and an iterator function are walked too, so this is only\n-- what a source such as `pairs(t)` hands over.\ntype Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]\n\n-- `for (const [k, v] in pairs(t))` / `ipairs(t)`: each item is one `[key,\n-- value]` \u2014 a table, as every array is. The analyzer types it from `t` itself\n-- (a record's keys as literals, an array's elements); these declare the\n-- names, and their shape for any other use. Walking a list only reads it, so\n-- a read-only one (`as const`, `readonly T[]`) is walked as well.\ndeclare function pairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>\ndeclare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>\ndeclare function ipairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>\n\ndeclare function collectgarbage(option: \"count\"): number\ndeclare function gcinfo(): number\ndeclare function getfenv(target?: unknown): { [string]: unknown }\ndeclare function setfenv<T>(target: T, env: { [string]: unknown }): T\ndeclare function loadstring(source: string, chunkname?: string): [((...args: unknown[]) => unknown) | nil, string | nil]\n\ndeclare debug: {\n traceback: (message?: string, level?: number) => string,\n}\n\ndeclare string: {\n format: (fmt: string, ...args: unknown[]) => string,\n sub: (s: string, i: number, j?: number) => string,\n len: (s: string) => number,\n upper: (s: string) => string,\n lower: (s: string) => string,\n rep: (s: string, n: number, sep?: string) => string,\n reverse: (s: string) => string,\n -- Where the pattern is, then what it captured \u2014 or nil.\n find: (s: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n -- What it captured (the whole match when there are no captures), as\n -- JavaScript's `match` answers \u2014 or nil.\n match: (s: string, pattern: string, init?: number) => [...string[]] | nil,\n -- Each match's captures (the whole match when there are none), one\n -- array at a time: `for (const [word] in s:gmatch(\"%a+\"))`.\n gmatch: (s: string, pattern: string) => () => [string, ...string[]] | nil,\n -- The new string, as JavaScript's `replace` answers; Luau's count of\n -- replacements is left behind.\n gsub: (s: string, pattern: string, repl: unknown, n?: number) => string,\n -- One code for one position; an array of them for a range.\n byte: ((s: string, i?: number) => number) & ((s: string, i: number, j: number) => number[]),\n char: (...args: number[]) => string,\n}\n\ndeclare math: {\n abs: (x: number) => number,\n floor: (x: number) => number,\n ceil: (x: number) => number,\n fmod: (x: number, y: number) => number,\n modf: (x: number) => [number, number],\n sqrt: (x: number) => number,\n pow: (x: number, y: number) => number,\n exp: (x: number) => number,\n log: (x: number, base?: number) => number,\n log10: (x: number) => number,\n frexp: (x: number) => [number, number],\n ldexp: (m: number, e: number) => number,\n min: (...args: number[]) => number,\n max: (...args: number[]) => number, \n sin: (x: number) => number,\n cos: (x: number) => number,\n tan: (x: number) => number,\n asin: (x: number) => number,\n acos: (x: number) => number,\n atan: (x: number) => number,\n atan2: (y: number, x: number) => number,\n sinh: (x: number) => number,\n cosh: (x: number) => number,\n tanh: (x: number) => number,\n rad: (deg: number) => number,\n deg: (rad: number) => number,\n random: (m?: number, n?: number) => number,\n randomseed: (x: number) => nil,\n huge: number,\n pi: number,\n}\n\n\ndeclare table: {\n -- `insert(t, v)` appends; `insert(t, pos, v)` puts it there.\n insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),\n remove: <T>(t: T[], pos?: number) => T | nil,\n concat: (t: readonly (string | number)[], sep?: string, i?: number, j?: number) => string,\n sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,\n -- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau\n -- still answers to them, so code being ported still type-checks.\n getn: <T>(t: readonly T[]) => number,\n maxn: <T>(t: readonly T[]) => number,\n foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,\n foreachi: <V, R>(t: readonly V[], f: (index: number, value: V) => R) => R | nil,\n}\n\ndeclare os: {\n time: (t?: unknown) => number,\n clock: () => number,\n date: (format?: string, time?: number) => unknown,\n difftime: (a: number, b: number) => number,\n}\n\ndeclare coroutine: {\n create: (fn: (...args: unknown[]) => unknown) => thread,\n -- Answers like `pcall`: `{ success, data, error }`, `data` what the\n -- coroutine yielded or returned.\n resume: (co: thread, ...args: unknown[]) => PcallResult<unknown>,\n yield: (...args: unknown[]) => unknown,\n wrap: (fn: (...args: unknown[]) => unknown) => (...args: unknown[]) => unknown,\n status: (co: thread) => string,\n running: () => thread,\n}\n\n-- A string's, an array's and a table's methods \u2014 `text:trim()`,\n-- `names:filter(f)`, `point:keys()` \u2014 are the language's: their metatables\n-- are declared in @tilua/parser's prelude, and the compiler runs them. A\n-- library adds to one with `declare metatable` of the same target, as\n-- `@tilua-types/roblox` gives a string Luau's `split`.\n\n-- The console. Written with `:` \u2014 `console:log(value)` \u2014 and lowered by the\n-- compiler (standard.ts) into runtime/console.luau, not into `print`.\n--\n-- Every line starts with the place that called it: `[src/main:12]: ...`.\n-- `print` and `warn` are left as written; `error` puts `src/main.tilua:12:` in\n-- its message, as Lua does.\n--\n-- `log` expands what it is given the way a browser console does: a table is\n-- printed as its contents, not as an address. A function prints as the type it\n-- was inferred to have *and* the code it was written as, both of which the\n-- compiler passes along, since neither exists once the code is running.\n--\n-- `error` reports in the project's own files: a bundle is one Luau file, so\n-- Luau's own line numbers name a file nobody wrote. It does not raise on the\n-- calling thread \u2014 the error goes to `task.spawn`, so reporting a problem\n-- never becomes one.\ntype Console = {\n log: (self: Console, ...args: unknown[]) => nil,\n warn: (self: Console, ...args: unknown[]) => nil,\n error: (self: Console, ...args: unknown[]) => nil,\n}\n\ndeclare console: Console\n";
|
|
1777
1777
|
/** The standard library, parsed once. */
|
|
1778
1778
|
declare function standardLibrary(): Program;
|
|
1779
1779
|
/** The globals the standard library declares: `print`, `string`, ... */
|
package/dist/index.d.ts
CHANGED
|
@@ -1756,7 +1756,7 @@ resolveModule?: (specifier: string) => ModuleExports | undefined): ModuleExports
|
|
|
1756
1756
|
* `ObjectValues<T>` and `ObjectEntries<T>`, an object's members as tuples in
|
|
1757
1757
|
* the order they were written.
|
|
1758
1758
|
*/
|
|
1759
|
-
declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = Exclude<T, Falsy>\n\n-- `Exclude<T, U>` is the analyzer's own: what of `T` is not a `U`. Over a\n-- union it drops the members it takes whole; over `unknown`, `any`, a\n-- primitive or an unresolved parameter it is kept \u2014 `Exclude<string, \"a\">` is\n-- a string that is not `\"a\"` \u2014 unlike TypeScript's.\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = Exclude<T, nil>\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n-- A class table builds with `new`: `InstanceType<typeof Dog>` is a `Dog`.\ntype InstanceType<T> = T extends { new: (...args: any[]) => infer R } ? R : never\ntype ConstructorParameters<T> = T extends { new: (...args: infer P) => any } ? P : never\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- The ones that only read take a `readonly T[]` too \u2014 `as const` lists, and\n-- what a function promised not to change \u2014 as TypeScript's `ReadonlyArray`.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: readonly T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: readonly T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: readonly T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: readonly T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: readonly T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: readonly T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: readonly T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n -- Asking is not adding: any value may be looked for, and finding it\n -- says it is one of the array's \u2014 `if (names:includes(s))` narrows `s`.\n includes: (self: readonly T[], value: unknown) => value is T,\n indexOf: (self: readonly T[], value: unknown, start?: number) => number | nil,\n join: (self: readonly T[], separator?: string) => string,\n concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],\n slice: (self: readonly T[], start?: number, stop?: number) => T[],\n flat: (self: readonly T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
|
|
1759
|
+
declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = Exclude<T, Falsy>\n\n-- `Exclude<T, U>` is the analyzer's own: what of `T` is not a `U`. Over a\n-- union it drops the members it takes whole; over `unknown`, `any`, a\n-- primitive or an unresolved parameter it is kept \u2014 `Exclude<string, \"a\">` is\n-- a string that is not `\"a\"` \u2014 unlike TypeScript's.\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = Exclude<T, nil>\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n-- A class table builds with `new`: `InstanceType<typeof Dog>` is a `Dog`.\ntype InstanceType<T> = T extends { new: (...args: any[]) => infer R } ? R : never\ntype ConstructorParameters<T> = T extends { new: (...args: infer P) => any } ? P : never\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- The ones that only read take a `readonly T[]` too \u2014 `as const` lists, and\n-- what a function promised not to change \u2014 as TypeScript's `ReadonlyArray`.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: readonly T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: readonly T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: readonly T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: readonly T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: readonly T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: readonly T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: readonly T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: readonly T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n -- Asking is not adding: any value may be looked for, and finding it\n -- says it is one of the array's \u2014 `if (names:includes(s))` narrows `s`.\n includes: (self: readonly T[], value: unknown) => value is T,\n indexOf: (self: readonly T[], value: unknown, start?: number) => number | nil,\n join: (self: readonly T[], separator?: string) => string,\n concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],\n slice: (self: readonly T[], start?: number, stop?: number) => T[],\n flat: (self: readonly T[]) => T[],\n -- JavaScript's, as arrays rather than iterators: `for (const [i, v] in\n -- xs:entries())` walks positions and values, counting from 1.\n keys: (self: readonly T[]) => number[],\n values: (self: readonly T[]) => T[],\n entries: (self: readonly T[]) => [number, T][],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
|
|
1760
1760
|
|
|
1761
1761
|
/**
|
|
1762
1762
|
* The Lua 5.1 standard library, always there — as TypeScript always has
|
|
@@ -1773,7 +1773,7 @@ declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `
|
|
|
1773
1773
|
* `@tilua-types/lua`, where this used to live, is not loaded when a project
|
|
1774
1774
|
* still names it: it would declare everything twice.
|
|
1775
1775
|
*/
|
|
1776
|
-
declare const STANDARD_LIBRARY_SOURCE = "\n-- The Lua 5.1 standard library, written in tilua.\n--\n-- This is the floor every tilua project stands on, the way TypeScript stands\n-- on JavaScript's: the functions and libraries Lua itself defines, there in\n-- every file without being asked for. Nothing here is Luau's or Roblox's \u2014\n-- `buffer`, `table.create` and the rest live one layer up in\n-- `@tilua-types/roblox`, which adds to it.\n--\n-- Lua's `type()` is not here: what a value is, is asked with the language's\n-- own `typeof v`, which also tells an array from an object.\n--\n-- Adding to it is literal: a name declared again in a later file keeps what\n-- earlier files gave it. `declare table: { find: ... }` in `@tilua-types/roblox` does\n-- not replace this `table`, it extends it, and overloads of a function\n-- accumulate the same way. So the layers really are layers.\n\n-- ============================================================\n-- Base library\n-- ============================================================\n\ndeclare _G: { [string]: unknown }\ndeclare _VERSION: string\n\ndeclare function require(module: unknown): unknown\ndeclare function tostring(value: unknown): string\ndeclare function tonumber(value: unknown, base?: number): number | nil\ndeclare function print(...args: unknown[]): nil\n-- `error` never returns, which is what lets\n-- `if v == nil then error(\"...\") end` narrow the rest of the block.\ndeclare function error(message: unknown, level?: number): never\n\n-- `asserts value` \u2014 narrows the *rest of the enclosing block*, the way\n-- TypeScript's assertion signatures do:\n--\n-- const part = workspace:FindFirstChild(\"Part\") -- Instance | nil\n-- assert(part)\n-- part.Name -- Instance, no `?`\n\ndeclare function assert<T>(value: T, message?: string): asserts value\n\n-- `pcall` and `xpcall` answer the way a JavaScript result object does:\n--\n-- const { success, data, error } = pcall(load, \"config\")\n-- if (success) { use(data) } else { warn(error) }\n--\n-- `data` is what the function returned. These are not Luau's own `pcall`:\n-- where Luau answers several values, tilua has one, and the compiler puts its\n-- own functions in place of those globals (runtime/result.luau) \u2014 for calls,\n-- and for the global read as a value alike. The same goes for `string.find`,\n-- `string.match`, `string.gsub`, `string.byte`, `math.modf`, `math.frexp`,\n-- `next`, `select`, `unpack`, `loadstring`, `pairs`, `ipairs` and\n-- `string.gmatch` below.\ntype PcallResult<T> = { success: true, data: T, error: nil } | { success: false, data: nil, error: unknown }\n\ndeclare function pcall<A extends unknown[], T>(fn: (...args: A) => T, ...args: A): PcallResult<T>\ndeclare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler: (err: unknown) => unknown, ...args: A): PcallResult<T>\n-- `select(\"#\", ...args)` counts; `select(n, ...args)` is what follows the\n-- n-th, as an array.\ndeclare function select(n: \"#\", ...args: unknown[]): number\ndeclare function select<T>(n: number, ...args: T[]): T[]\n-- A copy of the list, or of part of it.\ndeclare function unpack<V>(list: V[], i?: number, j?: number): V[]\ndeclare function rawget(t: unknown, key: unknown): unknown\ndeclare function rawset<T>(t: T, key: unknown, value: unknown): T\ndeclare function rawequal(a: unknown, b: unknown): boolean\ndeclare function setmetatable<T>(t: T, mt: unknown): T\ndeclare function getmetatable(t: unknown): unknown\ndeclare function newproxy(addMeta?: boolean): unknown\n-- The entry after `key` \u2014 or nil, past the last one.\ndeclare function next<K, V>(t: { [K]: V }, key?: K): [K, V] | nil\n\n-- What `for (const item in source)` walks: `step` is called with the state\n-- and the item before it \u2014 `first` the first time \u2014 until it answers nil.\n-- An array, a table and an iterator function are walked too, so this is only\n-- what a source such as `pairs(t)` hands over.\ntype Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]\n\n-- `for (const [k, v] in pairs(t))` / `ipairs(t)`: each item is one `[key,\n-- value]` \u2014 a table, as every array is. The analyzer types it from `t` itself\n-- (a record's keys as literals, an array's elements); these declare the\n-- names, and their shape for any other use.\ndeclare function pairs<V>(t: V[]): Iteration<V[], [number, V]>\ndeclare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>\ndeclare function ipairs<V>(t: V[]): Iteration<V[], [number, V]>\n\ndeclare function collectgarbage(option: \"count\"): number\ndeclare function gcinfo(): number\ndeclare function getfenv(target?: unknown): { [string]: unknown }\ndeclare function setfenv<T>(target: T, env: { [string]: unknown }): T\ndeclare function loadstring(source: string, chunkname?: string): [((...args: unknown[]) => unknown) | nil, string | nil]\n\ndeclare debug: {\n traceback: (message?: string, level?: number) => string,\n}\n\ndeclare string: {\n format: (fmt: string, ...args: unknown[]) => string,\n sub: (s: string, i: number, j?: number) => string,\n len: (s: string) => number,\n upper: (s: string) => string,\n lower: (s: string) => string,\n rep: (s: string, n: number, sep?: string) => string,\n reverse: (s: string) => string,\n -- Where the pattern is, then what it captured \u2014 or nil.\n find: (s: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n -- What it captured (the whole match when there are no captures), as\n -- JavaScript's `match` answers \u2014 or nil.\n match: (s: string, pattern: string, init?: number) => [...string[]] | nil,\n -- Each match's captures (the whole match when there are none), one\n -- array at a time: `for (const [word] in s:gmatch(\"%a+\"))`.\n gmatch: (s: string, pattern: string) => () => [string, ...string[]] | nil,\n -- The new string, as JavaScript's `replace` answers; Luau's count of\n -- replacements is left behind.\n gsub: (s: string, pattern: string, repl: unknown, n?: number) => string,\n -- One code for one position; an array of them for a range.\n byte: ((s: string, i?: number) => number) & ((s: string, i: number, j: number) => number[]),\n char: (...args: number[]) => string,\n}\n\ndeclare math: {\n abs: (x: number) => number,\n floor: (x: number) => number,\n ceil: (x: number) => number,\n fmod: (x: number, y: number) => number,\n modf: (x: number) => [number, number],\n sqrt: (x: number) => number,\n pow: (x: number, y: number) => number,\n exp: (x: number) => number,\n log: (x: number, base?: number) => number,\n log10: (x: number) => number,\n frexp: (x: number) => [number, number],\n ldexp: (m: number, e: number) => number,\n min: (...args: number[]) => number,\n max: (...args: number[]) => number, \n sin: (x: number) => number,\n cos: (x: number) => number,\n tan: (x: number) => number,\n asin: (x: number) => number,\n acos: (x: number) => number,\n atan: (x: number) => number,\n atan2: (y: number, x: number) => number,\n sinh: (x: number) => number,\n cosh: (x: number) => number,\n tanh: (x: number) => number,\n rad: (deg: number) => number,\n deg: (rad: number) => number,\n random: (m?: number, n?: number) => number,\n randomseed: (x: number) => nil,\n huge: number,\n pi: number,\n}\n\n\ndeclare table: {\n -- `insert(t, v)` appends; `insert(t, pos, v)` puts it there.\n insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),\n remove: <T>(t: T[], pos?: number) => T | nil,\n concat: (t: (string | number)[], sep?: string, i?: number, j?: number) => string,\n sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,\n -- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau\n -- still answers to them, so code being ported still type-checks.\n getn: <T>(t: T[]) => number,\n maxn: <T>(t: T[]) => number,\n foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,\n foreachi: <V, R>(t: V[], f: (index: number, value: V) => R) => R | nil,\n}\n\ndeclare os: {\n time: (t?: unknown) => number,\n clock: () => number,\n date: (format?: string, time?: number) => unknown,\n difftime: (a: number, b: number) => number,\n}\n\ndeclare coroutine: {\n create: (fn: (...args: unknown[]) => unknown) => thread,\n -- Answers like `pcall`: `{ success, data, error }`, `data` what the\n -- coroutine yielded or returned.\n resume: (co: thread, ...args: unknown[]) => PcallResult<unknown>,\n yield: (...args: unknown[]) => unknown,\n wrap: (fn: (...args: unknown[]) => unknown) => (...args: unknown[]) => unknown,\n status: (co: thread) => string,\n running: () => thread,\n}\n\n-- A string's, an array's and a table's methods \u2014 `text:trim()`,\n-- `names:filter(f)`, `point:keys()` \u2014 are the language's: their metatables\n-- are declared in @tilua/parser's prelude, and the compiler runs them. A\n-- library adds to one with `declare metatable` of the same target, as\n-- `@tilua-types/roblox` gives a string Luau's `split`.\n\n-- The console. Written with `:` \u2014 `console:log(value)` \u2014 and lowered by the\n-- compiler (standard.ts) into runtime/console.luau, not into `print`.\n--\n-- Every line starts with the place that called it: `[src/main:12]: ...`.\n-- `print` and `warn` are left as written; `error` puts `src/main.tilua:12:` in\n-- its message, as Lua does.\n--\n-- `log` expands what it is given the way a browser console does: a table is\n-- printed as its contents, not as an address. A function prints as the type it\n-- was inferred to have *and* the code it was written as, both of which the\n-- compiler passes along, since neither exists once the code is running.\n--\n-- `error` reports in the project's own files: a bundle is one Luau file, so\n-- Luau's own line numbers name a file nobody wrote. It does not raise on the\n-- calling thread \u2014 the error goes to `task.spawn`, so reporting a problem\n-- never becomes one.\ntype Console = {\n log: (self: Console, ...args: unknown[]) => nil,\n warn: (self: Console, ...args: unknown[]) => nil,\n error: (self: Console, ...args: unknown[]) => nil,\n}\n\ndeclare console: Console\n";
|
|
1776
|
+
declare const STANDARD_LIBRARY_SOURCE = "\n-- The Lua 5.1 standard library, written in tilua.\n--\n-- This is the floor every tilua project stands on, the way TypeScript stands\n-- on JavaScript's: the functions and libraries Lua itself defines, there in\n-- every file without being asked for. Nothing here is Luau's or Roblox's \u2014\n-- `buffer`, `table.create` and the rest live one layer up in\n-- `@tilua-types/roblox`, which adds to it.\n--\n-- Lua's `type()` is not here: what a value is, is asked with the language's\n-- own `typeof v`, which also tells an array from an object.\n--\n-- Adding to it is literal: a name declared again in a later file keeps what\n-- earlier files gave it. `declare table: { find: ... }` in `@tilua-types/roblox` does\n-- not replace this `table`, it extends it, and overloads of a function\n-- accumulate the same way. So the layers really are layers.\n\n-- ============================================================\n-- Base library\n-- ============================================================\n\ndeclare _G: { [string]: unknown }\ndeclare _VERSION: string\n\ndeclare function require(module: unknown): unknown\ndeclare function tostring(value: unknown): string\ndeclare function tonumber(value: unknown, base?: number): number | nil\ndeclare function print(...args: unknown[]): nil\n-- `error` never returns, which is what lets\n-- `if v == nil then error(\"...\") end` narrow the rest of the block.\ndeclare function error(message: unknown, level?: number): never\n\n-- `asserts value` \u2014 narrows the *rest of the enclosing block*, the way\n-- TypeScript's assertion signatures do:\n--\n-- const part = workspace:FindFirstChild(\"Part\") -- Instance | nil\n-- assert(part)\n-- part.Name -- Instance, no `?`\n\ndeclare function assert<T>(value: T, message?: string): asserts value\n\n-- `pcall` and `xpcall` answer the way a JavaScript result object does:\n--\n-- const { success, data, error } = pcall(load, \"config\")\n-- if (success) { use(data) } else { warn(error) }\n--\n-- `data` is what the function returned. These are not Luau's own `pcall`:\n-- where Luau answers several values, tilua has one, and the compiler puts its\n-- own functions in place of those globals (runtime/result.luau) \u2014 for calls,\n-- and for the global read as a value alike. The same goes for `string.find`,\n-- `string.match`, `string.gsub`, `string.byte`, `math.modf`, `math.frexp`,\n-- `next`, `select`, `unpack`, `loadstring`, `pairs`, `ipairs` and\n-- `string.gmatch` below.\ntype PcallResult<T> = { success: true, data: T, error: nil } | { success: false, data: nil, error: unknown }\n\ndeclare function pcall<A extends unknown[], T>(fn: (...args: A) => T, ...args: A): PcallResult<T>\ndeclare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler: (err: unknown) => unknown, ...args: A): PcallResult<T>\n-- `select(\"#\", ...args)` counts; `select(n, ...args)` is what follows the\n-- n-th, as an array.\ndeclare function select(n: \"#\", ...args: unknown[]): number\ndeclare function select<T>(n: number, ...args: T[]): T[]\n-- A copy of the list, or of part of it.\ndeclare function unpack<V>(list: readonly V[], i?: number, j?: number): V[]\ndeclare function rawget(t: unknown, key: unknown): unknown\ndeclare function rawset<T>(t: T, key: unknown, value: unknown): T\ndeclare function rawequal(a: unknown, b: unknown): boolean\ndeclare function setmetatable<T>(t: T, mt: unknown): T\ndeclare function getmetatable(t: unknown): unknown\ndeclare function newproxy(addMeta?: boolean): unknown\n-- The entry after `key` \u2014 or nil, past the last one.\ndeclare function next<K, V>(t: { [K]: V }, key?: K): [K, V] | nil\n\n-- What `for (const item in source)` walks: `step` is called with the state\n-- and the item before it \u2014 `first` the first time \u2014 until it answers nil.\n-- An array, a table and an iterator function are walked too, so this is only\n-- what a source such as `pairs(t)` hands over.\ntype Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]\n\n-- `for (const [k, v] in pairs(t))` / `ipairs(t)`: each item is one `[key,\n-- value]` \u2014 a table, as every array is. The analyzer types it from `t` itself\n-- (a record's keys as literals, an array's elements); these declare the\n-- names, and their shape for any other use. Walking a list only reads it, so\n-- a read-only one (`as const`, `readonly T[]`) is walked as well.\ndeclare function pairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>\ndeclare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>\ndeclare function ipairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>\n\ndeclare function collectgarbage(option: \"count\"): number\ndeclare function gcinfo(): number\ndeclare function getfenv(target?: unknown): { [string]: unknown }\ndeclare function setfenv<T>(target: T, env: { [string]: unknown }): T\ndeclare function loadstring(source: string, chunkname?: string): [((...args: unknown[]) => unknown) | nil, string | nil]\n\ndeclare debug: {\n traceback: (message?: string, level?: number) => string,\n}\n\ndeclare string: {\n format: (fmt: string, ...args: unknown[]) => string,\n sub: (s: string, i: number, j?: number) => string,\n len: (s: string) => number,\n upper: (s: string) => string,\n lower: (s: string) => string,\n rep: (s: string, n: number, sep?: string) => string,\n reverse: (s: string) => string,\n -- Where the pattern is, then what it captured \u2014 or nil.\n find: (s: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n -- What it captured (the whole match when there are no captures), as\n -- JavaScript's `match` answers \u2014 or nil.\n match: (s: string, pattern: string, init?: number) => [...string[]] | nil,\n -- Each match's captures (the whole match when there are none), one\n -- array at a time: `for (const [word] in s:gmatch(\"%a+\"))`.\n gmatch: (s: string, pattern: string) => () => [string, ...string[]] | nil,\n -- The new string, as JavaScript's `replace` answers; Luau's count of\n -- replacements is left behind.\n gsub: (s: string, pattern: string, repl: unknown, n?: number) => string,\n -- One code for one position; an array of them for a range.\n byte: ((s: string, i?: number) => number) & ((s: string, i: number, j: number) => number[]),\n char: (...args: number[]) => string,\n}\n\ndeclare math: {\n abs: (x: number) => number,\n floor: (x: number) => number,\n ceil: (x: number) => number,\n fmod: (x: number, y: number) => number,\n modf: (x: number) => [number, number],\n sqrt: (x: number) => number,\n pow: (x: number, y: number) => number,\n exp: (x: number) => number,\n log: (x: number, base?: number) => number,\n log10: (x: number) => number,\n frexp: (x: number) => [number, number],\n ldexp: (m: number, e: number) => number,\n min: (...args: number[]) => number,\n max: (...args: number[]) => number, \n sin: (x: number) => number,\n cos: (x: number) => number,\n tan: (x: number) => number,\n asin: (x: number) => number,\n acos: (x: number) => number,\n atan: (x: number) => number,\n atan2: (y: number, x: number) => number,\n sinh: (x: number) => number,\n cosh: (x: number) => number,\n tanh: (x: number) => number,\n rad: (deg: number) => number,\n deg: (rad: number) => number,\n random: (m?: number, n?: number) => number,\n randomseed: (x: number) => nil,\n huge: number,\n pi: number,\n}\n\n\ndeclare table: {\n -- `insert(t, v)` appends; `insert(t, pos, v)` puts it there.\n insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),\n remove: <T>(t: T[], pos?: number) => T | nil,\n concat: (t: readonly (string | number)[], sep?: string, i?: number, j?: number) => string,\n sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,\n -- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau\n -- still answers to them, so code being ported still type-checks.\n getn: <T>(t: readonly T[]) => number,\n maxn: <T>(t: readonly T[]) => number,\n foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,\n foreachi: <V, R>(t: readonly V[], f: (index: number, value: V) => R) => R | nil,\n}\n\ndeclare os: {\n time: (t?: unknown) => number,\n clock: () => number,\n date: (format?: string, time?: number) => unknown,\n difftime: (a: number, b: number) => number,\n}\n\ndeclare coroutine: {\n create: (fn: (...args: unknown[]) => unknown) => thread,\n -- Answers like `pcall`: `{ success, data, error }`, `data` what the\n -- coroutine yielded or returned.\n resume: (co: thread, ...args: unknown[]) => PcallResult<unknown>,\n yield: (...args: unknown[]) => unknown,\n wrap: (fn: (...args: unknown[]) => unknown) => (...args: unknown[]) => unknown,\n status: (co: thread) => string,\n running: () => thread,\n}\n\n-- A string's, an array's and a table's methods \u2014 `text:trim()`,\n-- `names:filter(f)`, `point:keys()` \u2014 are the language's: their metatables\n-- are declared in @tilua/parser's prelude, and the compiler runs them. A\n-- library adds to one with `declare metatable` of the same target, as\n-- `@tilua-types/roblox` gives a string Luau's `split`.\n\n-- The console. Written with `:` \u2014 `console:log(value)` \u2014 and lowered by the\n-- compiler (standard.ts) into runtime/console.luau, not into `print`.\n--\n-- Every line starts with the place that called it: `[src/main:12]: ...`.\n-- `print` and `warn` are left as written; `error` puts `src/main.tilua:12:` in\n-- its message, as Lua does.\n--\n-- `log` expands what it is given the way a browser console does: a table is\n-- printed as its contents, not as an address. A function prints as the type it\n-- was inferred to have *and* the code it was written as, both of which the\n-- compiler passes along, since neither exists once the code is running.\n--\n-- `error` reports in the project's own files: a bundle is one Luau file, so\n-- Luau's own line numbers name a file nobody wrote. It does not raise on the\n-- calling thread \u2014 the error goes to `task.spawn`, so reporting a problem\n-- never becomes one.\ntype Console = {\n log: (self: Console, ...args: unknown[]) => nil,\n warn: (self: Console, ...args: unknown[]) => nil,\n error: (self: Console, ...args: unknown[]) => nil,\n}\n\ndeclare console: Console\n";
|
|
1777
1777
|
/** The standard library, parsed once. */
|
|
1778
1778
|
declare function standardLibrary(): Program;
|
|
1779
1779
|
/** The globals the standard library declares: `print`, `string`, ... */
|
package/dist/index.js
CHANGED
|
@@ -94,6 +94,14 @@ function isAlphaNumeric(ch) {
|
|
|
94
94
|
return isAlpha(ch) || isDigit(ch);
|
|
95
95
|
}
|
|
96
96
|
var KeywordSet = new Set(Keywords);
|
|
97
|
+
var TS_SPELLINGS = [
|
|
98
|
+
["!==", "~=", "Operator"],
|
|
99
|
+
["===", "==", "Operator"],
|
|
100
|
+
["!=", "~=", "Operator"],
|
|
101
|
+
["&&", "and", "Keyword"],
|
|
102
|
+
["||", "or", "Keyword"],
|
|
103
|
+
["!", "not", "Keyword"]
|
|
104
|
+
];
|
|
97
105
|
var OperatorSet = new Set(Operators);
|
|
98
106
|
var SortedSymbols = [...Operators, ...Punctuators].sort((a, b) => b.length - a.length);
|
|
99
107
|
var LexError = class extends Error {
|
|
@@ -554,6 +562,15 @@ function tokenize(source, options = {}) {
|
|
|
554
562
|
tokens.push(readIdentifierOrKeyword());
|
|
555
563
|
continue;
|
|
556
564
|
}
|
|
565
|
+
const spelled = TS_SPELLINGS.find(([written]) => source.startsWith(written, cursor));
|
|
566
|
+
if (spelled) {
|
|
567
|
+
const [written, meant, kind] = spelled;
|
|
568
|
+
const startLine = line, startColumn = column;
|
|
569
|
+
fail(`tilua writes '${meant}', not '${written}'`, startLine, startColumn);
|
|
570
|
+
for (let k = 0; k < written.length; k++) advance();
|
|
571
|
+
tokens.push(kind === "Keyword" ? { type: "Keyword", value: meant, ...makeBase(startLine, startColumn) } : { type: "Operator", value: meant, ...makeBase(startLine, startColumn) });
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
557
574
|
const symbol = readOperatorOrPunctuator();
|
|
558
575
|
if (symbol) tokens.push(symbol);
|
|
559
576
|
}
|
|
@@ -4362,7 +4379,7 @@ declare function xpcall<A extends unknown[], T>(fn: (...args: A) => T, handler:
|
|
|
4362
4379
|
declare function select(n: "#", ...args: unknown[]): number
|
|
4363
4380
|
declare function select<T>(n: number, ...args: T[]): T[]
|
|
4364
4381
|
-- A copy of the list, or of part of it.
|
|
4365
|
-
declare function unpack<V>(list: V[], i?: number, j?: number): V[]
|
|
4382
|
+
declare function unpack<V>(list: readonly V[], i?: number, j?: number): V[]
|
|
4366
4383
|
declare function rawget(t: unknown, key: unknown): unknown
|
|
4367
4384
|
declare function rawset<T>(t: T, key: unknown, value: unknown): T
|
|
4368
4385
|
declare function rawequal(a: unknown, b: unknown): boolean
|
|
@@ -4381,10 +4398,11 @@ type Iteration<S, T> = [(state: S, previous: T | nil) => T | nil, S, T | nil]
|
|
|
4381
4398
|
-- \`for (const [k, v] in pairs(t))\` / \`ipairs(t)\`: each item is one \`[key,
|
|
4382
4399
|
-- value]\` \u2014 a table, as every array is. The analyzer types it from \`t\` itself
|
|
4383
4400
|
-- (a record's keys as literals, an array's elements); these declare the
|
|
4384
|
-
-- names, and their shape for any other use.
|
|
4385
|
-
|
|
4401
|
+
-- names, and their shape for any other use. Walking a list only reads it, so
|
|
4402
|
+
-- a read-only one (\`as const\`, \`readonly T[]\`) is walked as well.
|
|
4403
|
+
declare function pairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>
|
|
4386
4404
|
declare function pairs<K, V>(t: { [K]: V }): Iteration<{ [K]: V }, [K, V]>
|
|
4387
|
-
declare function ipairs<V>(t: V[]): Iteration<V[], [number, V]>
|
|
4405
|
+
declare function ipairs<V>(t: readonly V[]): Iteration<readonly V[], [number, V]>
|
|
4388
4406
|
|
|
4389
4407
|
declare function collectgarbage(option: "count"): number
|
|
4390
4408
|
declare function gcinfo(): number
|
|
@@ -4458,14 +4476,14 @@ declare table: {
|
|
|
4458
4476
|
-- \`insert(t, v)\` appends; \`insert(t, pos, v)\` puts it there.
|
|
4459
4477
|
insert: (<T>(t: T[], value: T) => nil) & (<T>(t: T[], pos: number, value: T) => nil),
|
|
4460
4478
|
remove: <T>(t: T[], pos?: number) => T | nil,
|
|
4461
|
-
concat: (t: (string | number)[], sep?: string, i?: number, j?: number) => string,
|
|
4479
|
+
concat: (t: readonly (string | number)[], sep?: string, i?: number, j?: number) => string,
|
|
4462
4480
|
sort: <T>(t: T[], compare?: (a: T, b: T) => boolean) => nil,
|
|
4463
4481
|
-- Lua 5.1's originals. Deprecated there and gone from 5.2 on, but Luau
|
|
4464
4482
|
-- still answers to them, so code being ported still type-checks.
|
|
4465
|
-
getn: <T>(t: T[]) => number,
|
|
4466
|
-
maxn: <T>(t: T[]) => number,
|
|
4483
|
+
getn: <T>(t: readonly T[]) => number,
|
|
4484
|
+
maxn: <T>(t: readonly T[]) => number,
|
|
4467
4485
|
foreach: <K, V, R>(t: { [K]: V }, f: (key: K, value: V) => R) => R | nil,
|
|
4468
|
-
foreachi: <V, R>(t: V[], f: (index: number, value: V) => R) => R | nil,
|
|
4486
|
+
foreachi: <V, R>(t: readonly V[], f: (index: number, value: V) => R) => R | nil,
|
|
4469
4487
|
}
|
|
4470
4488
|
|
|
4471
4489
|
declare os: {
|
|
@@ -5358,6 +5376,11 @@ declare metatable<T> T[]: {
|
|
|
5358
5376
|
concat: <U>(self: readonly T[], ...others: (readonly U[])[]) => (T | U)[],
|
|
5359
5377
|
slice: (self: readonly T[], start?: number, stop?: number) => T[],
|
|
5360
5378
|
flat: (self: readonly T[]) => T[],
|
|
5379
|
+
-- JavaScript's, as arrays rather than iterators: \`for (const [i, v] in
|
|
5380
|
+
-- xs:entries())\` walks positions and values, counting from 1.
|
|
5381
|
+
keys: (self: readonly T[]) => number[],
|
|
5382
|
+
values: (self: readonly T[]) => T[],
|
|
5383
|
+
entries: (self: readonly T[]) => [number, T][],
|
|
5361
5384
|
reverse: (self: T[]) => T[],
|
|
5362
5385
|
sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],
|
|
5363
5386
|
push: (self: T[], ...args: T[]) => number,
|
|
@@ -7145,7 +7168,7 @@ function keepsLiterals(paramType) {
|
|
|
7145
7168
|
const members = paramType.constraint.kind === "union" ? paramType.constraint.types : [paramType.constraint];
|
|
7146
7169
|
return members.some((m) => m.kind === "literal" || m.kind === "primitive" && (m.name === "string" || m.name === "number"));
|
|
7147
7170
|
}
|
|
7148
|
-
var CLASS_LINKS = /* @__PURE__ */ new Set(["new", "ClassObject", "ParentClass"]);
|
|
7171
|
+
var CLASS_LINKS = /* @__PURE__ */ new Set(["new", "ClassObject", "ParentClass", "name"]);
|
|
7149
7172
|
var CLASS_RESERVED = /* @__PURE__ */ new Set([
|
|
7150
7173
|
"new",
|
|
7151
7174
|
"ClassObject",
|
|
@@ -7903,6 +7926,7 @@ var TypeAnalyzer = class {
|
|
|
7903
7926
|
});
|
|
7904
7927
|
type.properties.set("new", construct);
|
|
7905
7928
|
type.properties.set("ParentClass", { type: parent ?? nilType, optional: false, readonly: true });
|
|
7929
|
+
type.properties.set("name", { type: stmt.name ? literal(stmt.name.name) : stringType, optional: false, readonly: true });
|
|
7906
7930
|
return type;
|
|
7907
7931
|
}
|
|
7908
7932
|
/** The value side of the class `superclass` names when it is not
|
|
@@ -8162,6 +8186,9 @@ var TypeAnalyzer = class {
|
|
|
8162
8186
|
if (CLASS_RESERVED.has(member.name.name)) {
|
|
8163
8187
|
report(member.name, `'${member.name.name}' is what the compiler calls part of a class; a member cannot be named that`);
|
|
8164
8188
|
}
|
|
8189
|
+
if (member.name.name === "name" && !(member.type === "ClassField" && !member.isStatic)) {
|
|
8190
|
+
report(member.name, "'name' is the class's own name, `Dog.name`: a static, a method or an accessor cannot be called that \u2014 an instance field can");
|
|
8191
|
+
}
|
|
8165
8192
|
}
|
|
8166
8193
|
const seen = /* @__PURE__ */ new Map();
|
|
8167
8194
|
for (const member of stmt.members) {
|
|
@@ -9002,6 +9029,13 @@ var TypeAnalyzer = class {
|
|
|
9002
9029
|
case "array":
|
|
9003
9030
|
case "tuple":
|
|
9004
9031
|
return union([numberType, literal("length")]);
|
|
9032
|
+
// A string is not indexed by position in Lua (`s[1]` is nil), so
|
|
9033
|
+
// of its keys only `length` is there.
|
|
9034
|
+
case "primitive":
|
|
9035
|
+
return t.name === "string" ? literal("length") : neverType;
|
|
9036
|
+
case "literal":
|
|
9037
|
+
case "templateLiteral":
|
|
9038
|
+
return t.kind === "templateLiteral" || t.base === "string" ? literal("length") : neverType;
|
|
9005
9039
|
case "union": {
|
|
9006
9040
|
const sets = t.types.map((m) => {
|
|
9007
9041
|
const keys = this.keysOf(m);
|
|
@@ -9472,7 +9506,7 @@ var TypeAnalyzer = class {
|
|
|
9472
9506
|
this.loops.set(stmt, { walks: "iteration", viaIter: false });
|
|
9473
9507
|
} else {
|
|
9474
9508
|
const [item, form] = this.iterationOf(stmt.iterator, sourceType);
|
|
9475
|
-
this.bindPattern(stmt.variable, item, bodyEnv, "widen");
|
|
9509
|
+
this.bindPattern(stmt.variable, item, bodyEnv, stmt.kind === "const" ? "keep" : "widen");
|
|
9476
9510
|
this.loops.set(stmt, form);
|
|
9477
9511
|
}
|
|
9478
9512
|
this.visitBlock(stmt.body, bodyEnv);
|
|
@@ -10928,7 +10962,8 @@ var TypeAnalyzer = class {
|
|
|
10928
10962
|
const name = source.callee.name;
|
|
10929
10963
|
const src = this.expand(this.typeOf.get(source.arguments[0]) ?? unknownType);
|
|
10930
10964
|
const iteration = { walks: "iteration", viaIter: false };
|
|
10931
|
-
|
|
10965
|
+
const element = src.kind === "array" ? src.element : src.kind === "tuple" ? union(tupleMembers(src).map((m) => m.kind === "spread" ? this.spreadElement(m.type) ?? unknownType : m)) : void 0;
|
|
10966
|
+
if (name === "ipairs") return [tuple([numberType, element ?? this.elementType(src, 0)]), iteration];
|
|
10932
10967
|
if (name === "pairs") {
|
|
10933
10968
|
if (src.kind === "object") {
|
|
10934
10969
|
return [tuple([
|
|
@@ -10936,7 +10971,7 @@ var TypeAnalyzer = class {
|
|
|
10936
10971
|
src.indexer?.value ?? union([...src.properties.values()].map((p) => p.type))
|
|
10937
10972
|
]), iteration];
|
|
10938
10973
|
}
|
|
10939
|
-
if (
|
|
10974
|
+
if (element) return [tuple([numberType, element]), iteration];
|
|
10940
10975
|
}
|
|
10941
10976
|
}
|
|
10942
10977
|
const handsOut = (t2, viaIter) => {
|