tsc-ts 0.1.0 → 0.1.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.
Files changed (60) hide show
  1. package/README.md +1 -1
  2. package/dist/api/compiler/ast.d.ts +9 -3
  3. package/dist/api/compiler/ast.js +17 -12
  4. package/dist/api/compiler/checker-classes.js +2 -1
  5. package/dist/api/compiler/checker-contextual.d.ts +20 -0
  6. package/dist/api/compiler/checker-contextual.js +111 -1
  7. package/dist/api/compiler/checker-expressions.js +14 -1
  8. package/dist/api/compiler/checker-jsx.js +2 -1
  9. package/dist/api/compiler/checker-type-factory.js +53 -12
  10. package/dist/api/compiler/checker.d.ts +5 -1
  11. package/dist/api/compiler/checker.js +10 -4
  12. package/dist/api/compiler/compile-program.d.ts +5 -0
  13. package/dist/api/compiler/compile-program.js +8 -0
  14. package/dist/api/compiler/expr-record.d.ts +11 -0
  15. package/dist/api/compiler/expr-record.js +53 -0
  16. package/dist/api/compiler/identifier-name.d.ts +9 -0
  17. package/dist/api/compiler/identifier-name.js +10 -0
  18. package/dist/api/compiler/jsdoc.js +4 -2
  19. package/dist/api/compiler/parser.d.ts +2 -1
  20. package/dist/api/compiler/parser.js +10 -8
  21. package/dist/api/compiler/printer/factory.js +3 -2
  22. package/dist/api/compiler/printer/printer.js +3 -2
  23. package/dist/api/compiler/reparser.js +4 -3
  24. package/dist/api/compiler/scanner.d.ts +8 -0
  25. package/dist/api/compiler/scanner.js +58 -42
  26. package/dist/api/compiler/shared-results.d.ts +376 -143
  27. package/dist/api/compiler/shared-results.js +1550 -773
  28. package/dist/api/compiler/transformers/declarations.js +2 -1
  29. package/package.json +9 -9
  30. package/src/compiler/ast.ts +19 -12
  31. package/src/compiler/cgroup.ts +157 -0
  32. package/src/compiler/checker-classes.ts +2 -1
  33. package/src/compiler/checker-contextual.ts +104 -0
  34. package/src/compiler/checker-expressions.ts +16 -1
  35. package/src/compiler/checker-jsx.ts +2 -1
  36. package/src/compiler/checker-type-factory.ts +53 -14
  37. package/src/compiler/checker.ts +11 -4
  38. package/src/compiler/compile-program.ts +8 -0
  39. package/src/compiler/decoder.ts +2 -1
  40. package/src/compiler/doctor-report.ts +133 -0
  41. package/src/compiler/expr-record.ts +59 -0
  42. package/src/compiler/identifier-name.ts +13 -0
  43. package/src/compiler/jsdoc.ts +4 -2
  44. package/src/compiler/parallel-check.ts +353 -146
  45. package/src/compiler/parallel-emit.ts +3 -3
  46. package/src/compiler/parser.ts +10 -8
  47. package/src/compiler/printer/factory.ts +3 -2
  48. package/src/compiler/printer/printer.ts +4 -2
  49. package/src/compiler/reparser.ts +7 -3
  50. package/src/compiler/run-config.ts +1383 -0
  51. package/src/compiler/run-record-read.ts +87 -0
  52. package/src/compiler/run-records.ts +575 -0
  53. package/src/compiler/scanner.ts +57 -41
  54. package/src/compiler/shared-results.ts +1626 -896
  55. package/src/compiler/thread-entry.ts +3 -1
  56. package/src/compiler/transformers/declarations.ts +2 -1
  57. package/src/compiler/tsc-build.ts +64 -6
  58. package/src/compiler/tsc-cli.ts +33 -4
  59. package/src/compiler/tsc-compile.ts +213 -8
  60. package/src/compiler/tsc-watch.ts +25 -4
@@ -1,11 +1,12 @@
1
1
  import { type Node, type SourceFile } from './ast.js';
2
2
  import type { Checker } from './checker.js';
3
- import { ConditionalType, LiteralType, ObjectType, TupleType, Type, TypeAlias, UnionType, Signature } from './checker-types.js';
3
+ import { Type, Signature } from './checker-types.js';
4
4
  import { type Symbol } from './symbol.js';
5
+ import { LinkTable } from './link-tables.js';
5
6
  declare const enum RecordKind {
6
- /** A type the checker creates when it starts: `num` is its position in `initialTypes`. */
7
+ /** A type the checker creates when it starts: its position in `initialTypes`. */
7
8
  Initial = 0,
8
- /** A regular literal type: `flags`, `text` or `num`. */
9
+ /** A regular literal type: its flags, then its value as a double or its text. */
9
10
  Literal = 1,
10
11
  /** The fresh type of the literal type `refs[0]`. */
11
12
  FreshLiteral = 2,
@@ -23,24 +24,24 @@ declare const enum RecordKind {
23
24
  NodeType = 8,
24
25
  /** A reference to the generic type `refs[0]` with the type arguments `refs[1..]`. */
25
26
  Reference = 9,
26
- /** The tuple target with the element flags `nums`, labeled by `nodes`, readonly when `num` is 1. */
27
+ /** The tuple target: readonly, then the element flags and label nodes. */
27
28
  TupleTarget = 10,
28
29
  /**
29
- * The instantiation of the anonymous, mapped or deferred reference type `refs[0]` with the `num` outer type arguments
30
- * after it, then the return types its signatures had resolved (built after it).
30
+ * The instantiation of the anonymous, mapped or deferred reference type `refs[0]` with the outer type arguments
31
+ * after it, then the return types its signatures had resolved (built after it); the node declares it.
31
32
  */
32
33
  Instantiation = 11,
33
- /** A union of `refs`, with the origin `num` (a record index, or -1). */
34
+ /** A union of `refs` with the origin record, or -1. */
34
35
  Union = 12,
35
36
  /** An intersection of `refs`. */
36
37
  Intersection = 13,
37
- /** `keyof refs[0]` with the index flags `num`. */
38
+ /** `keyof refs[0]` with the index flags. */
38
39
  Index = 14,
39
- /** `refs[0][refs[1]]` with the access flags `num`. */
40
+ /** `refs[0][refs[1]]` with the access flags. */
40
41
  IndexedAccess = 15,
41
- /** The instantiation of the conditional type of `node` with outer type arguments `refs`, for constraints when `num` is 1. */
42
+ /** The instantiation of the conditional type of `node` with outer type arguments `refs`, for constraints when the tag is 1. */
42
43
  Conditional = 16,
43
- /** A template literal type of `texts` and `refs`. */
44
+ /** A template literal type of its texts and `refs`. */
44
45
  Template = 17,
45
46
  /** The string mapping `symbol` of `refs[0]`. */
46
47
  StringMapping = 18,
@@ -50,57 +51,54 @@ declare const enum RecordKind {
50
51
  NoInfer = 20,
51
52
  /**
52
53
  * The member for the constituent `refs[last]` of the distribution of the conditional type of `node` instantiated
53
- * with outer type arguments `refs[0..last)`, for constraints when `num` is 1.
54
+ * with outer type arguments `refs[0..last)`, for constraints when the tag is 1.
54
55
  */
55
56
  DistributedConditional = 21,
56
57
  /**
57
58
  * An anonymous object type of the object literal `symbol` with members resolved when it was created (an object
58
- * literal type, or its regular, widened or spread form), with the object flags `flags`. Its members come with the
59
- * `CompleteObject` record that follows them.
59
+ * literal type, or its regular, widened or spread form): its object flags, then the record of its members.
60
60
  */
61
61
  AnonymousObject = 22,
62
- /** The members of the `AnonymousObject` record `num`: the properties `refs` and the index infos `indexInfos`. */
62
+ /** The members of the `AnonymousObject` record whose index is written first: the properties `refs` and index infos. */
63
63
  CompleteObject = 23,
64
64
  /**
65
- * A property symbol a checker created (`text` its name, `flags` its symbol flags, `num` its check flags): its
66
- * declarations `nodes`, value declaration `node`, type `refs[0]`, name type `refs[1]` (or -1), the symbol it was
67
- * made from `refs[2]` (a property record, or -1 for `symbol`, a symbol of the program) and its parent `aliasSymbol`.
65
+ * A property symbol a checker created: its symbol flags, check flags and name, its declarations, its type
66
+ * `refs[0]`, name type `refs[1]` (or -1), the symbol it was made from `refs[2]` (a property record, or -1 for the
67
+ * symbol of the program written with it) and its parent (its alias).
68
68
  */
69
69
  Property = 24
70
70
  }
71
- /** An index signature of an `AnonymousObject` record. */
72
- export declare class PortableIndexInfo {
73
- readonly keyType: number;
74
- readonly valueType: number;
75
- readonly isReadonly: boolean;
76
- readonly declaration: Node | undefined;
77
- readonly components: readonly Node[];
78
- constructor(keyType: number, valueType: number, isReadonly: boolean, declaration: Node | undefined, components: readonly Node[]);
79
- }
80
- export declare class PortableRecord {
81
- readonly kind: RecordKind;
82
- readonly flags: number;
83
- readonly num: number;
84
- readonly text: string;
85
- symbol: Symbol | undefined;
86
- readonly node: Node | undefined;
87
- readonly refs: readonly number[];
88
- nums: readonly number[];
89
- nodes: readonly (Node | undefined)[];
90
- texts: readonly string[];
91
- /** For a symbol a checker merged: the id of a symbol it merged, which keys every checker's merged symbol. */
92
- mergedId: number;
93
- /** The alias: its symbol and the records of its type arguments. */
94
- aliasSymbol: Symbol | undefined;
95
- aliasMergedId: number;
96
- aliasRefs: readonly number[];
97
- indexInfos: readonly PortableIndexInfo[];
98
- /** The producer's type id, which keys the consumer's translations of the producer's types. */
99
- readonly id: number;
100
- constructor(kind: RecordKind, id: number, flags: number, num: number, text: string, symbol: Symbol | undefined, node: Node | undefined, refs: readonly number[]);
71
+ /**
72
+ * Writes records into a checker's store: int32 words at a cursor, strings into its string log, and each record's
73
+ * offset in its record table. The cursor is the writer's alone until it publishes a result.
74
+ */
75
+ export declare class StoreWriter {
76
+ readonly numbers: Int32Array;
77
+ readonly strings: Uint16Array;
78
+ readonly table: Int32Array;
79
+ readonly fileIndex: Map<SourceFile, number>;
80
+ /** The cursor in the number log, and in the string log. */
81
+ at: number;
82
+ unitAt: number;
83
+ /** Set when a record or a field didn't fit the store's configured capacity. */
84
+ full: boolean;
85
+ constructor(numbers: Int32Array, strings: Uint16Array, table: Int32Array, fileIndex: Map<SourceFile, number>);
86
+ /** Returns to the cursors `at` and `unitAt`. */
87
+ reset(at: number, unitAt: number): void;
88
+ /** Starts record `index` at the cursor: its header, and its offset in the record table. */
89
+ beginRecord(index: number, header: number): void;
90
+ word(value: number): void;
91
+ /** A double as the two int32 halves of its bits. */
92
+ double(value: number): void;
93
+ /** A string as its offset and length in the string log. */
94
+ text(value: string): void;
95
+ /** A node as its file, range and id, or -1 for none. The file must be one `fileIndex` has. */
96
+ node(node: Node | undefined): void;
101
97
  }
102
98
  /** The types every checker creates when it starts, in the same order; marker types are left out. */
103
99
  export declare function initialTypes(c: Checker): Type[];
100
+ /** The reason an export stops at its budget (`Exporter.limit`), which `post` returns: the result is not posted. */
101
+ export declare const budgetFailure = "export budget";
104
102
  /** A checker's `Exporter.mergedOrigins`, kept while its merged symbols stay the same. */
105
103
  export declare class MergedOrigins {
106
104
  origins: Map<Symbol, number>;
@@ -109,98 +107,144 @@ export declare class MergedOrigins {
109
107
  /** Writes a result as records; `failure` names the first part that has no record kind. */
110
108
  export declare class Exporter {
111
109
  readonly c: Checker;
112
- records: PortableRecord[];
113
- readonly indexes: Map<Type, number>;
110
+ readonly writer: StoreWriter;
114
111
  /**
115
- * The index of `records[0]`. A checker's exporter keeps the indexes of the types it exported before
116
- * (`ThreadSharing.post`): their records are in its store already, and a result's records are only the new ones.
112
+ * The index of the first record of the export in progress. A checker's exporter keeps the records of the types it
113
+ * exported before (`ThreadSharing.post`): its store has them already, and a result's records are only the new ones.
117
114
  */
118
115
  base: number;
116
+ /** The number of records the export in progress wrote. */
117
+ count: number;
118
+ /** The record of each type, by type id, and of each property symbol, by symbol id. */
119
+ readonly indexes: Map<number, number>;
120
+ readonly properties: Map<number, number>;
119
121
  /** The types and properties the export in progress gave indexes, which a failed export forgets again. */
120
- readonly addedTypes: Type[];
121
- readonly addedProperties: Symbol[];
122
- /** Appends `record`; its index. */
123
- push(record: PortableRecord): number;
124
- readonly initial: Map<Type, number>;
122
+ readonly addedTypes: number[];
123
+ readonly addedProperties: number[];
124
+ /**
125
+ * The most records the export in progress may add (`ThreadSharing.post` prices it with `kappa`); past it the export
126
+ * fails and the result is not posted.
127
+ */
128
+ limit: number;
129
+ readonly initial: Map<number, number>;
125
130
  failure: string | undefined;
126
131
  /** The ids above which nodes and symbols are the checker thread's own (lazily parsed JSDoc), or Infinity. */
127
132
  nodeLimit: number;
128
133
  symbolLimit: number;
129
- constructor(c: Checker, initial: Map<Type, number>);
130
- /** Whether `node` is one every checker shares; fails if not. */
131
- sharedNode(node: Node | undefined): boolean;
132
134
  /** The ids of the symbols each merged symbol merged (`getMergedSymbol`), built on first use. */
133
135
  mergedOrigins: Map<Symbol, number> | undefined;
134
136
  /** Where the checker keeps `mergedOrigins` between exports. */
135
137
  originsCache: MergedOrigins | undefined;
138
+ /** How the record in progress names its symbol and its alias, and the node it carries. */
139
+ private naming;
140
+ private namingMerged;
141
+ private namingNode;
142
+ private aliasNaming;
143
+ private aliasMerged;
144
+ private aliasNode;
145
+ private aliasRefs;
146
+ private node;
147
+ constructor(c: Checker, initial: Map<number, number>, writer: StoreWriter);
148
+ fail(reason: string): number;
149
+ /** Whether `node` is one every checker shares, and can name; fails if not. */
150
+ sharedNode(node: Node | undefined): boolean;
136
151
  /**
137
- * Sets the symbol of `record`: a symbol of the program, which every checker shares, or a symbol the checker merged,
138
- * by the id of a symbol it merged. Other symbols are the checker's own.
152
+ * The index of the next record of the store, or -1 if the result is over its export budget; the store's table must
153
+ * have room for it.
139
154
  */
140
- symbolOf(record: PortableRecord, symbol: Symbol, alias: boolean): boolean;
141
- /** `new PortableRecord` with the symbol `symbol` (see `symbolOf`); undefined if it is the checker's own. */
142
- withSymbol(kind: RecordKind, t: Type, symbol: Symbol, num: number, refs: readonly number[]): PortableRecord | undefined;
143
- addWithSymbol(kind: RecordKind, t: Type, symbol: Symbol, num: number, refs: readonly number[]): number;
144
- fail(reason: string): number;
145
- add(t: Type, record: PortableRecord): number;
155
+ nextIndex(): number;
156
+ /** Records the type `t` at `index`. */
157
+ private memo;
158
+ /**
159
+ * Sets how the record in progress names `symbol`: a symbol of the program by the node it is the symbol of, or a
160
+ * symbol the checker merged by the id of a symbol it merged. Fails for a symbol of the thread.
161
+ */
162
+ nameSymbol(symbol: Symbol | undefined, alias: boolean): boolean;
163
+ /** The ids of the symbols each merged symbol merged, from the checker's `mergedSymbols`. */
164
+ private buildOrigins;
165
+ /**
166
+ * Names the alias of the record in progress, after its type arguments are exported, and returns the header bits that
167
+ * name it; -1 if it can't be named.
168
+ */
169
+ private aliasBits;
170
+ /**
171
+ * Starts the record at `index`: its header, its refs, its alias, its symbol and its node, all decided by `bits` and
172
+ * the fields set just before. A kind's own fields follow.
173
+ */
174
+ begin(kind: RecordKind, index: number, refs: readonly number[], bits: number): void;
175
+ /** The record of `t` of `kind`, with `refs` and no fields of its own; its index. */
176
+ private plain;
177
+ /** The record of the initial type `t`, which is `num`th in `initialTypes`. */
178
+ private initialType;
179
+ /** The record of the type `t` of `kind` named by `symbol`, with `refs`; its index. */
180
+ private symbolType;
181
+ /** The record of the type `t` of the type node `node`; its index. */
182
+ private nodeType;
146
183
  types(list: readonly Type[]): number[];
147
- aliasOf(record: PortableRecord, alias: TypeAlias | undefined): PortableRecord;
148
184
  type(t: Type): number;
149
- literal(t: LiteralType): number;
150
- union(t: UnionType): number;
151
- object(t: ObjectType): number;
185
+ private literal;
186
+ /** The record of the constituents of a union's or intersection's origin, which is not a type: it has no alias. */
187
+ private originRecord;
188
+ private union;
189
+ private intersection;
190
+ private object;
152
191
  /** An object literal type, or one made from one, with its properties and index infos. */
153
- anonymousObject(t: ObjectType): number;
154
- /** The records of property symbols, by symbol. */
155
- readonly properties: Map<Symbol, number>;
192
+ private anonymousObject;
156
193
  /** A property symbol of an object literal type: a checker's own, made from one of the program or from another. */
157
- property(prop: Symbol): number;
158
- tupleTarget(t: TupleType): number;
194
+ private property;
195
+ private tupleTarget;
159
196
  /** An instantiated anonymous or mapped type, or a deferred type reference: its target and outer type arguments. */
160
- instantiation(t: ObjectType): number;
197
+ private instantiation;
161
198
  /**
162
199
  * Adds to `refs` the return types the checker resolved for the signatures of the instantiation `t`, exported after
163
200
  * it. The consumer then creates them right after `t` and before the types that contain it, as this checker did:
164
201
  * inference stops at references whose type ids grow along its stack (`isDeeplyNestedType`), so a consumer that
165
202
  * created them later, when it resolved them, could stop an inference this checker made.
166
203
  */
167
- resolvedReturnTypes(t: ObjectType, refs: number[]): void;
204
+ private resolvedReturnTypes;
168
205
  /**
169
206
  * The record of `t`, or -1 if it can't be exported; that leaves the export in progress as it was. An export that
170
207
  * failed before stays failed.
171
208
  */
172
209
  optionalType(t: Type): number;
173
- conditional(t: ConditionalType): number;
210
+ /**
211
+ * The record of the conditional type `t`: the conditional type of a type node, or the instantiation of one with
212
+ * outer type arguments; -1 if it can't be exported.
213
+ */
214
+ private conditional;
174
215
  }
175
- /** Translates records into a checker's own types; one translation per producer type. */
216
+ /** Translates the records of another checker's store into this checker's types, reading them where they are. */
176
217
  export declare class Translator {
177
218
  readonly c: Checker;
178
- readonly translated: Map<number, Type>;
219
+ readonly store: StoreReader;
179
220
  readonly initial: Type[];
180
221
  /** Set when a record has no counterpart here; the translation is then abandoned. */
181
222
  failed: boolean;
182
- constructor(c: Checker);
183
- /** A property symbol made as the producer made it. */
184
- property(r: PortableRecord, types: Type[], symbols: (Symbol | undefined)[]): Symbol;
185
- /** Sets the members of the `AnonymousObject` record a `CompleteObject` record completes. */
186
- complete(r: PortableRecord, types: Type[], symbols: (Symbol | undefined)[]): void;
187
- record(r: PortableRecord, types: Type[]): Type;
223
+ constructor(c: Checker, store: StoreReader);
224
+ /**
225
+ * The symbol of `node`, named by `how`: the symbol of the node itself, or its export symbol. The record names
226
+ * symbols of the program this way, and a consumer that hasn't the symbol fails the translation.
227
+ */
228
+ private namedSymbol;
229
+ /** Abandons the record being read: the translation fails, and a later one starts afresh. */
230
+ private abandon;
231
+ /** A property symbol made as the producer made it; undefined if its record can't be read here. */
232
+ property(index: number): Symbol | undefined;
233
+ /** Sets the members of the `AnonymousObject` record a `CompleteObject` record completes; false if it can't read it. */
234
+ complete(index: number): boolean;
188
235
  /**
189
236
  * Resolves the declared type of the type alias whose declaration contains the type node `node`, as resolving its
190
237
  * nodes through the alias does: that records the alias's type parameters, which its variances are measured with.
191
238
  * Sets `failed` if the alias's declared type is being resolved here.
192
239
  */
193
240
  aliasOfNode(node: Node): void;
194
- alias(r: PortableRecord, types: Type[]): TypeAlias | undefined;
195
- symbol(r: PortableRecord): Symbol;
196
- build(r: PortableRecord, types: Type[]): Type;
241
+ /** The type record `index`; undefined if it or a record it needs can't be translated here. */
242
+ record(index: number): Type | undefined;
197
243
  }
198
244
  /** Whether the type of `symbol` is shared: a variable or property declared in the program, other than parameters. */
199
245
  export declare function isSharedValueSymbol(symbol: Symbol): boolean;
200
246
  /** Whether the return type of `sig` is shared: the signature of a declaration, as `getSignatureFromDeclaration` makes it. */
201
247
  export declare function isSharedReturnSignature(c: Checker, sig: Signature): boolean;
202
- /** Whether checker threads share results (TSC_TS_SHARE=1). */
203
- export declare const shareThreads: boolean;
204
248
  /**
205
249
  * What a checker thread needs to share results with the others; posted in its `workerData` (a plain object: class
206
250
  * instances arrive without their class).
@@ -208,6 +252,11 @@ export declare const shareThreads: boolean;
208
252
  export interface ThreadSharingData {
209
253
  readonly index: number;
210
254
  readonly count: number;
255
+ /**
256
+ * Whether this run's posts are cost-bounded (`RunConfig.bounded`): it posts only results another checker demanded
257
+ * and its takes build a bounded number of records. A run with it off keeps Phase 1's rule.
258
+ */
259
+ readonly bounded: boolean;
211
260
  /**
212
261
  * For each file, by file index: -2 if no checker checks it, -1 if checkers check it in statement ranges, 0 until a
213
262
  * checker takes it, and 1 + k once checker k took it.
@@ -218,6 +267,12 @@ export interface ThreadSharingData {
218
267
  * checker took the file: they never check it, and hand its positions on (`handoff`).
219
268
  */
220
269
  readonly forbidden: SharedArrayBuffer;
270
+ /**
271
+ * For each file, by file index, the checkers (one bit each, the same shape as `forbidden`) that looked for a result
272
+ * for one of its declarations and found none. A checker posts a result only for a declaration whose file one of
273
+ * them reads (`ThreadSharing.demanded`).
274
+ */
275
+ readonly wanted: SharedArrayBuffer;
221
276
  /**
222
277
  * Positions of the order a checker handed on: a lock, their number, the number of checkers that may still hand
223
278
  * positions on, then the positions.
@@ -230,16 +285,43 @@ export interface ThreadSharingData {
230
285
  readonly symbolIds: number;
231
286
  /**
232
287
  * Each checker's store of the records of the results it shares, by checker index: their numbers, and the code units
233
- * of their strings. `used` has two counters per checker, how much of each it wrote. (Results go through shared
234
- * memory: a message a worker receives synchronously makes the native build store the number fields of classes as
235
- * doubles.)
288
+ * of their strings. `used` has two counters per checker, `usedStride` int32s apart, how much of each it wrote; a
289
+ * checker keeps its cursors in its own writer and writes them there only for the summary. (Results go through
290
+ * shared memory: a message a worker receives synchronously makes the native build store the number fields of
291
+ * classes as doubles.)
236
292
  */
237
293
  readonly numberLogs: SharedArrayBuffer[];
238
294
  readonly stringLogs: SharedArrayBuffer[];
239
295
  readonly used: SharedArrayBuffer;
240
- /** For each checker, where each record of its store is in its number log, and each object's completion. */
296
+ /** For each checker, where each record of its store is in its number log: a word per record. */
241
297
  readonly recordTables: SharedArrayBuffer[];
298
+ /**
299
+ * One int32, read by every checker before it posts or translates a result: 0 runs, 1 stops posting, 2
300
+ * stops posting and translating. The main thread sets it (`startParallelCheck`'s window) when the
301
+ * results are not worth what they cost; every switch keeps the diagnostics the same, because a
302
+ * checker that does not take a posted result computes it itself.
303
+ */
304
+ readonly control: SharedArrayBuffer;
305
+ /**
306
+ * One row of `shareStatColumns` doubles per checker, for the counters the main thread reads while
307
+ * checking runs (`ThreadSharing.writeStats`).
308
+ */
309
+ readonly stats: SharedArrayBuffer;
242
310
  }
311
+ /**
312
+ * The columns of a checker's row of `ThreadSharingData.stats`: the milliseconds of its outermost
313
+ * computations by kind (0 owned, 1 computed here for a file another checker took, 2 translated, 3
314
+ * other), of exporting, translating and unpacking results, the results it posted and translated, and
315
+ * the milliseconds it saved by translating a result instead of computing it.
316
+ */
317
+ export declare const shareStatColumns = 10;
318
+ export declare const shareStatKinds = 4;
319
+ export declare const shareStatExport = 4;
320
+ export declare const shareStatTranslation = 5;
321
+ export declare const shareStatUnpack = 6;
322
+ export declare const shareStatPosted = 7;
323
+ export declare const shareStatTranslated = 8;
324
+ export declare const shareStatSaved = 9;
243
325
  /**
244
326
  * The size of each checker's logs: numbers (int32s) and string code units (2 bytes each), 8 MB and 2 MB. Only the
245
327
  * pages a checker writes take memory.
@@ -248,6 +330,8 @@ export declare const numberLogSize: number;
248
330
  export declare const stringLogSize: number;
249
331
  /** The number of records each checker's store can hold. */
250
332
  export declare const recordTableSize: number;
333
+ /** The int32s each checker gets in `ThreadSharingData.used`, a cache line each, for two counters. */
334
+ export declare const usedStride = 16;
251
335
  /** The number of entries of each result table: a power of two. */
252
336
  export declare const resultTableSize: number;
253
337
  /**
@@ -265,6 +349,8 @@ export declare function postedOffset(count: number, state: number): number;
265
349
  export declare function forbiddenWords(count: number): number;
266
350
  /** Whether checker `index` of `count` took results for declarations of file `file` before any checker took it. */
267
351
  export declare function isForbidden(forbidden: Int32Array, count: number, file: number, index: number): boolean;
352
+ /** Whether checker `index` of `count` looked for a result for a declaration of file `file` and found none (`wanted`). */
353
+ export declare function isWanted(wanted: Int32Array, count: number, file: number, index: number): boolean;
268
354
  /**
269
355
  * An open-addressing table in a SharedArrayBuffer, from a key (a symbol or node id) to a result's state: 0 until a
270
356
  * checker posts it, then `postedState`.
@@ -280,6 +366,36 @@ export declare class ResultTable {
280
366
  /** Sets the state of `slot` to a posted result's unless one is there already. */
281
367
  publish(slot: number, state: number): void;
282
368
  }
369
+ /**
370
+ * The rule that decides whether a checker posts a result it computed, and how much a consumer may build to take one.
371
+ * The conditions that keep a take exact (the result's diagnostics, `forbidsLast`, the resolution stack) are checked
372
+ * by the callers, as are the stop switch and the demand bits.
373
+ */
374
+ export interface PostingRule {
375
+ /**
376
+ * Whether a checker that just computed the result keyed `key` of a declaration in file `fileIndex` may post it, in
377
+ * `ms`, with `diagnosticFiles` the files its diagnostics are in. The caller checks first that the computation met
378
+ * no resolution cycle, that the stop switch is off, that (when the run is cost-bounded) another checker demanded the
379
+ * file (`demanded`) and that no result for the key is posted.
380
+ */
381
+ posts(sharing: ThreadSharing, key: number, ms: number, diagnosticFiles: readonly number[], fileIndex: number): boolean;
382
+ /**
383
+ * The most records a consumer may build to take a posted result whose producer computed it in `ms` milliseconds: 0
384
+ * admits only takes that build nothing, because every record they need is in the consumer's caches already.
385
+ */
386
+ buildBudget(ms: number): number;
387
+ }
388
+ /**
389
+ * The rule of the design's Phase 2: a result is posted when it took at least the floor (`ThreadSharing.minMs`), and a
390
+ * consumer builds at most `lambda*T/c` records to take one, where `T` is the producer's time for it.
391
+ */
392
+ export declare class CostBoundedRule implements PostingRule {
393
+ readonly bounded: boolean;
394
+ /** `bounded` false is Phase 1's rule: the same floor, and a take that may build any number of records. */
395
+ constructor(bounded: boolean);
396
+ posts(sharing: ThreadSharing, _key: number, ms: number, _diagnosticFiles: readonly number[], _fileIndex: number): boolean;
397
+ buildBudget(ms: number): number;
398
+ }
283
399
  /** Sets the sharing data of this checker thread; its first checker shares with the other threads. */
284
400
  export declare function setThreadSharingData(data: ThreadSharingData | undefined): void;
285
401
  /** Gives `c` the thread's sharing state, if the thread shares and no checker of it has it yet. */
@@ -293,13 +409,14 @@ export declare class IdBits {
293
409
  }
294
410
  /**
295
411
  * The files of the diagnostics of results, by key (a symbol or declaration id), with a bit per key: most results have
296
- * none, and the bit answers that without a lookup.
412
+ * none, and the bit answers that without a lookup. A file is its index in the program (`Checker.fileIndex`), and -1
413
+ * a diagnostic without a file.
297
414
  */
298
415
  export declare class FilesByKey {
299
416
  private readonly files;
300
417
  private readonly keys;
301
- get(key: number): readonly string[] | undefined;
302
- set(key: number, files: readonly string[]): void;
418
+ get(key: number): readonly number[] | undefined;
419
+ set(key: number, files: readonly number[]): void;
303
420
  }
304
421
  export declare class ThreadSharing {
305
422
  readonly c: Checker;
@@ -308,7 +425,19 @@ export declare class ThreadSharing {
308
425
  readonly returns: ResultTable;
309
426
  /** TSC_TS_SHARE_MIN_MS: the shortest computation this checker posts. */
310
427
  readonly minMs: number;
311
- readonly initialIndexes: Map<Type, number>;
428
+ /**
429
+ * Whether this run is cost-bounded, which the run's configuration chose (`RunConfig.bounded`, off by default and
430
+ * learned from the project's records). Without it the run keeps Phase 1's behavior: no demand bits, no export or
431
+ * take budget, the 2-8 ms floor.
432
+ */
433
+ readonly bounded: boolean;
434
+ /**
435
+ * The rule that decides which of this checker's results are posted, and how much a take may build. A small-result
436
+ * tier stacks on it by constructing its own rule here. Built per checker, not once at module evaluation, for the
437
+ * reason the cost model's functions give (`shareKappa`).
438
+ */
439
+ readonly rule: PostingRule;
440
+ readonly initialIndexes: Map<number, number>;
312
441
  readonly initial: Type[];
313
442
  readonly numberLogs: Int32Array[];
314
443
  readonly recordTables: Int32Array[];
@@ -316,15 +445,41 @@ export declare class ThreadSharing {
316
445
  readonly used: Int32Array;
317
446
  readonly takers: Int32Array;
318
447
  readonly forbidden: Int32Array;
448
+ /** The checkers that missed on a key in each file (`ThreadSharingData.wanted`). */
449
+ readonly wanted: Int32Array;
450
+ /** The files this checker noted a miss on, so that each is marked in `wanted` once. */
451
+ private readonly wantedFiles;
452
+ /** The stop switch of every checker (`ThreadSharingData.control`). */
453
+ readonly control: Int32Array;
454
+ /** This checker's row of the counters the main thread reads (`ThreadSharingData.stats`). */
455
+ readonly stats: Float64Array;
456
+ readonly row: number;
319
457
  /** The number of results this checker posted. */
320
458
  posted: number;
321
459
  translated: number;
460
+ /**
461
+ * Set while this checker exports a result into its store. A computation nested in the export walk can reach
462
+ * another shared result: posting it would write its records in the middle of the record being exported, and an
463
+ * export that failed would rewind over the posted result's words.
464
+ */
465
+ exporting: boolean;
466
+ /** Shared results a nested computation left to the checkers that compute them. */
467
+ nested: number;
322
468
  /** Outermost shared-kind computations: nesting depth, the kind of the current one, and the time by kind. */
323
469
  depth: number;
324
470
  kind: number;
325
471
  readonly kindMs: number[];
326
472
  /** Kinds: 0 owned, 1 computed here for a file another checker took, 2 translated, 3 other. */
327
473
  addOutermost(ms: number): void;
474
+ /**
475
+ * Copies this checker's counters into its row of `stats`, the memory the main thread reads them from
476
+ * while checking runs. Called where a counter changes, a few times per result at most.
477
+ */
478
+ writeStats(): void;
479
+ /** Adds to the milliseconds this checker saved by translating results instead of computing them. */
480
+ addSaved(ms: number): void;
481
+ /** Whether the main thread stopped translating posted results (control 2): this checker computes them. */
482
+ stoppedTranslating(): boolean;
328
483
  notShareable: number;
329
484
  notShareableMs: number;
330
485
  /** Whether the outermost computations are timed by kind (TSC_TS_SHARE_SUMMARY). */
@@ -334,17 +489,26 @@ export declare class ThreadSharing {
334
489
  verifiedIdentity: number;
335
490
  belowMin: number;
336
491
  belowMinMs: number;
492
+ /** Results whose export passed the budget `kappa*T`, and translations that stopped at `lambda*T/c`. */
493
+ overBudget: number;
494
+ overBudgetMs: number;
495
+ stoppedTranslations: number;
496
+ /** Results not posted because no checker that may take one missed on a key in the declaration's file. */
497
+ notDemanded: number;
337
498
  exportFailed: number;
338
499
  exportFailedMs: number;
339
500
  readonly exportFailures: Map<string, number>;
340
- packFailed: number;
341
- /** Of `packFailed`, the results that didn't fit in this checker's logs. */
501
+ /** TSC_TS_SHARE_VERIFY=2: records whose translation created types before an earlier record's. */
502
+ orderViolations: number;
503
+ storeFailed: number;
504
+ /** Of `storeFailed`, the results that didn't fit in this checker's logs. */
342
505
  logFull: number;
343
506
  computedPrivately: number;
507
+ /** Results this checker computed and kept because the main thread stopped sharing (control 1 or 2). */
508
+ stopped: number;
344
509
  /** How often a posted result couldn't be taken here; and results for declarations of the checker's own files. */
345
510
  sawDoneUnusable: number;
346
511
  owned: number;
347
- unpackMs: number;
348
512
  /** The program's nodes results named, by id. */
349
513
  readonly nodesById: Map<number, Node>;
350
514
  readonly origins: MergedOrigins;
@@ -363,9 +527,9 @@ export declare class ThreadSharing {
363
527
  readonly typeFiles: FilesByKey;
364
528
  readonly returnFiles: FilesByKey;
365
529
  /** The files of the computations in progress, innermost last. */
366
- readonly fileStack: (Set<string> | undefined)[];
530
+ readonly fileStack: (Set<number> | undefined)[];
367
531
  /** Adds `files` to those of the computation in progress. */
368
- noteFiles(files: readonly string[] | undefined): void;
532
+ noteFiles(files: readonly number[] | undefined): void;
369
533
  /** The last `computeShared`: whether its result can be shared, and how long it took. */
370
534
  lastShareable: boolean;
371
535
  lastMs: number;
@@ -373,6 +537,13 @@ export declare class ThreadSharing {
373
537
  computeShared(files: FilesByKey, key: number, symbol: Symbol | undefined, sig: Signature | undefined): Type;
374
538
  /** Runs `compute`, keeping in `files` under `key` the files of its diagnostics and of the results it used. */
375
539
  tracked(files: FilesByKey, key: number, symbol: Symbol | undefined, sig: Signature | undefined): Type;
540
+ /**
541
+ * The index of the program file named `fileName`, or -1: a diagnostic in a file this checker hasn't is one every
542
+ * checker would report, like a diagnostic without a file.
543
+ */
544
+ fileIndexOfName(fileName: string): number;
545
+ /** The index of each file by name, built on first use. */
546
+ private filesByIndex;
376
547
  constructor(c: Checker, data: ThreadSharingData);
377
548
  summary(): string;
378
549
  /**
@@ -381,18 +552,27 @@ export declare class ThreadSharing {
381
552
  * result for it (`forbid`).
382
553
  */
383
554
  owns(file: SourceFile): boolean;
555
+ /** Whether this checker checks file `index`, or may; -1 names a diagnostic without a file, which it has. */
556
+ ownsIndex(index: number): boolean;
557
+ /**
558
+ * Notes that this checker looked for a result for a declaration in `file` and found none: a checker posts results
559
+ * for that file only then (`demanded`). One `Atomics.or` per file and checker.
560
+ */
561
+ want(file: SourceFile): void;
562
+ /**
563
+ * Whether a checker other than this one and the file's taker missed on a key in file `index`: someone other than
564
+ * the checkers that already compute its declarations would take a result for one of them.
565
+ */
566
+ demanded(index: number): boolean;
384
567
  /** After taking a result for a declaration in `file`: if no checker took the file yet, this one never will. */
385
568
  forbid(file: SourceFile): void;
569
+ forbidIndex(index: number): void;
386
570
  /**
387
571
  * Whether taking a result would leave file `index` to no checker: no checker took it, and every other checker
388
572
  * took results for its declarations already. The main thread would check it, alone.
389
573
  */
390
574
  forbidsLast(index: number): boolean;
391
- forbidsLastNamed(fileName: string): boolean;
392
- forbidNamed(fileName: string): void;
393
- filesByName: Map<string, SourceFile> | undefined;
394
- ownsFileNamed(fileName: string): boolean;
395
- /** The result checker `k` posted at `offset` in its number log. */
575
+ /** The result checker `k` posted at `offset` in its number log: the record of its type, and the files it named. */
396
576
  result(k: number, offset: number): StoredResult;
397
577
  /** The exporter of this checker's store: it exports each type once. */
398
578
  storeExporter: Exporter | undefined;
@@ -401,7 +581,7 @@ export declare class ThreadSharing {
401
581
  * tables, -1 if it doesn't fit in the logs or a node or symbol in it can't be named across threads, or why it can't
402
582
  * be exported.
403
583
  */
404
- post(t: Type, diagnosticFiles: readonly string[]): number | string;
584
+ post(t: Type, diagnosticFiles: readonly number[], computeMs: number): number | string;
405
585
  /** The records this checker stored. */
406
586
  storedRecords: number;
407
587
  /** The readers of the other checkers' stores. */
@@ -412,52 +592,105 @@ export declare class ThreadSharing {
412
592
  /** A result in a checker's store: the record of its type, and the files of its diagnostics. */
413
593
  export declare class StoredResult {
414
594
  readonly root: number;
415
- readonly files: string[];
416
- constructor(root: number, files: string[]);
595
+ readonly files: number[];
596
+ /** How long computing the result took its producer, in milliseconds. */
597
+ readonly computeMs: number;
598
+ constructor(root: number, files: number[], computeMs?: number);
417
599
  }
418
600
  /** Shares the value type of `symbol` with the other checker threads, computing it with `compute` where needed. */
419
601
  export declare function threadTypeOfSymbol(c: Checker, symbol: Symbol): Type;
420
602
  /** Notes that the computation in progress used the cached return type of `sig` (see `ThreadSharing.typeFiles`). */
421
603
  export declare function noteReturnTypeUse(c: Checker, sig: Signature): void;
422
604
  export declare function threadReturnType(c: Checker, sig: Signature): Type;
423
- /** Reads records from a checker's store. */
424
- declare class RecordUnpacker {
425
- readonly c: Checker;
426
- readonly f: Int32Array;
427
- readonly strings: Uint16Array;
428
- at: number;
429
- failed: boolean;
430
- /** The nodes found so far, by id. */
605
+ /** The nodes of the program records name, by id, found by descending from their file through the nodes that contain them. */
606
+ export declare class NodeFinder {
607
+ readonly files: readonly SourceFile[];
431
608
  readonly nodesById: Map<number, Node>;
432
- constructor(c: Checker, numbers: Int32Array, strings: Uint16Array, nodesById: Map<number, Node>);
433
- next(): number;
434
- double(): number;
435
- text(): string;
436
- list(): number[];
609
+ private visitor;
610
+ constructor(files: readonly SourceFile[], nodesById: Map<number, Node>);
611
+ /** The node of file `fileIndex` with the range `pos`-`end` and id `id`; undefined if the program hasn't it. */
612
+ find(fileIndex: number, pos: number, end: number, id: number): Node | undefined;
613
+ }
614
+ /**
615
+ * Reads the records of a checker's store where it wrote them. `begin` starts a record at its offset in the number log
616
+ * and finds its parts without decoding its kind's fields: its refs, its alias, its symbol, its node, then the fields
617
+ * at `fields`.
618
+ */
619
+ export declare class RecordReader {
620
+ readonly numbers: Int32Array;
621
+ readonly strings: Uint16Array;
622
+ readonly table: Int32Array;
623
+ readonly finder: NodeFinder;
624
+ /** The record in progress: its header and kind, and where its refs are. */
625
+ header: number;
626
+ kind: number;
627
+ refAt: number;
628
+ refCount: number;
629
+ /** Where its alias refs are, if it has an alias; -1 if none. */
630
+ aliasRefAt: number;
631
+ aliasRefCount: number;
632
+ /** How its alias is named: `SymbolNaming` and a merged symbol id, or a node at `aliasNodeStart`. */
633
+ aliasNaming: number;
634
+ aliasMergedId: number;
635
+ aliasNodeStart: number;
636
+ /** How its symbol is named: the kind of naming, a merged symbol id, or a node at `symbolNodeStart`. */
637
+ symbolNaming: number;
638
+ symbolMergedId: number;
639
+ symbolNodeStart: number;
640
+ /** Where its node is, if it has one; -1 if none. */
641
+ nodeStart: number;
642
+ /** The offset of its kind's own fields. */
643
+ fields: number;
644
+ /** The records a record names, filled by `scan`. */
645
+ readonly deps: number[];
646
+ constructor(numbers: Int32Array, strings: Uint16Array, table: Int32Array, files: readonly SourceFile[], nodesById: Map<number, Node>);
647
+ /** Starts the record at `index`; false if the store hasn't it. */
648
+ begin(index: number): boolean;
649
+ /** Finds the record's alias refs, its symbol and its node, and the fields that follow them. */
650
+ private locate;
651
+ /** The words a node at `p` takes: its file index, range and id, or one word for no node. */
652
+ nodeWords(p: number): number;
653
+ /** The node at `p`; undefined if it is none or the program hasn't it. */
654
+ readNode(p: number): Node | undefined;
655
+ /** The record's own node; undefined if it has none or the program hasn't it. */
437
656
  node(): Node | undefined;
438
- nodes(): (Node | undefined)[];
439
- symbol(): Symbol | undefined;
657
+ doubleAt(p: number): number;
658
+ textAt(p: number): string;
659
+ /**
660
+ * Collects in `deps` the indexes of the records the record in progress needs: its refs, its alias refs, and the
661
+ * types of its own fields that are records (a union's origin, an object literal's completion, a completed object's
662
+ * members' types). A record is written before the records it needs.
663
+ */
664
+ scan(): void;
440
665
  }
441
666
  /**
442
- * A consumer's translations of another checker's store: each record is read and translated once, when a result
443
- * first needs it, in the order of the store, which is the order the producer exported them in.
667
+ * A consumer's translations of another checker's store: each record is read where it is, and translated once, when a
668
+ * result first needs it, in the order of the store, which is the order the producer exported them in.
444
669
  */
445
670
  declare class StoreReader {
446
671
  readonly sharing: ThreadSharing;
447
672
  readonly producer: number;
448
673
  readonly translator: Translator;
449
- readonly table: Int32Array;
450
- readonly unpacker: RecordUnpacker;
451
- /** By record: the record, its translation and whether it is translated. */
452
- readonly records: (PortableRecord | undefined)[];
453
- readonly types: Type[];
454
- readonly symbols: (Symbol | undefined)[];
455
- readonly built: number[];
674
+ readonly reader: RecordReader;
675
+ /** Whether the last `translate` stopped at its budget, having built nothing. */
676
+ stopped: boolean;
677
+ /** By record: the type it translated to, the symbol a property record makes, and whether a completion is done. */
678
+ readonly types: LinkTable<Type>;
679
+ readonly symbols: LinkTable<Symbol>;
680
+ readonly completed: LinkTable<boolean>;
456
681
  constructor(sharing: ThreadSharing, producer: number);
457
- private ensure;
458
- /** Record `index`, read on first use; undefined if a node or symbol in it isn't in this program. */
459
- private record;
460
- /** The translation of record `root` and the records it needs; undefined if one can't be translated here. */
461
- translate(root: number): Type | undefined;
682
+ /**
683
+ * Whether record `index` is translated: a property record made its symbol, an object literal got its members, a
684
+ * shell whose members come later only counts with them. A translation that fails after it built a shell leaves
685
+ * the empty type behind, and a later translation of the shell alone would take it for the object.
686
+ */
687
+ private isBuilt;
688
+ /** Whether the record in progress names only merged symbols this program has. */
689
+ private present;
690
+ /**
691
+ * The translation of record `root` and the records it needs; undefined if one can't be translated here, or if the
692
+ * records it would build pass `budget`.
693
+ */
694
+ translate(root: number, budget?: number): Type | undefined;
462
695
  }
463
696
  export {};