gofront 0.0.9 → 1.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.
Files changed (53) hide show
  1. package/README.md +5 -5
  2. package/package.json +7 -4
  3. package/src/cli-core.js +65 -0
  4. package/src/codegen/expressions.js +523 -1717
  5. package/src/codegen/index.js +576 -0
  6. package/src/codegen/runtime.js +151 -0
  7. package/src/codegen/statements.js +308 -296
  8. package/src/codegen/stdlib/builder.js +39 -0
  9. package/src/codegen/stdlib/bytes.js +65 -0
  10. package/src/codegen/stdlib/errors.js +20 -0
  11. package/src/codegen/stdlib/fmt.js +104 -0
  12. package/src/codegen/stdlib/gom.js +155 -0
  13. package/src/codegen/stdlib/html.js +20 -0
  14. package/src/codegen/stdlib/index.js +98 -0
  15. package/src/codegen/stdlib/io.js +36 -0
  16. package/src/codegen/stdlib/maps.js +45 -0
  17. package/src/codegen/stdlib/math.js +56 -0
  18. package/src/codegen/stdlib/os.js +13 -0
  19. package/src/codegen/stdlib/path.js +34 -0
  20. package/src/codegen/stdlib/rand.js +27 -0
  21. package/src/codegen/stdlib/regexp.js +54 -0
  22. package/src/codegen/stdlib/slices.js +51 -0
  23. package/src/codegen/stdlib/sort.js +31 -0
  24. package/src/codegen/stdlib/strconv.js +33 -0
  25. package/src/codegen/stdlib/strings.js +86 -0
  26. package/src/codegen/stdlib/time.js +57 -0
  27. package/src/codegen/stdlib/unicode.js +25 -0
  28. package/src/codegen/stdlib/utf8.js +26 -0
  29. package/src/codegen/templ.js +284 -0
  30. package/src/compiler.js +142 -77
  31. package/src/dts-parser.js +355 -371
  32. package/src/index.js +32 -162
  33. package/src/lexer.js +186 -272
  34. package/src/minifier.js +305 -318
  35. package/src/{parser.js → parser/declarations.js} +18 -175
  36. package/src/parser/expressions.js +51 -34
  37. package/src/parser/index.js +161 -0
  38. package/src/parser/statements.js +24 -34
  39. package/src/parser/types.js +31 -29
  40. package/src/templ-parser.js +2 -2
  41. package/src/tokens.js +109 -0
  42. package/src/typechecker/assignability.js +261 -0
  43. package/src/typechecker/expressions.js +568 -549
  44. package/src/typechecker/index.js +556 -0
  45. package/src/typechecker/resolve.js +428 -0
  46. package/src/typechecker/statements.js +270 -280
  47. package/src/typechecker/stdlib/core.js +592 -0
  48. package/src/typechecker/stdlib/extended.js +332 -0
  49. package/src/typechecker/stdlib.js +9 -1060
  50. package/src/typechecker/termination.js +86 -0
  51. package/src/typechecker/types.js +1 -0
  52. package/src/codegen.js +0 -882
  53. package/src/typechecker.js +0 -1299
@@ -0,0 +1,556 @@
1
+ // Type checker: walks the AST, resolves types for all expressions,
2
+ // and reports type errors at compile time.
3
+ //
4
+ // Split into sub-modules under typechecker/:
5
+ // types.js — shared type constants, predicates, Scope
6
+ // stdlib.js — browser globals + all built-in package registrations
7
+ // statements.js — checkBlock, checkStmt
8
+ // expressions.js — checkExpr, checkCall, checkBuiltin, checkCompositeLit
9
+ // termination.js — _isTerminating* family
10
+ // resolve.js — resolveTypeNode, fieldType, generics
11
+ // assignability.js — assertAssignable, binaryResultType, implements
12
+
13
+ import { assignabilityMethods } from "./assignability.js";
14
+ import { expressionCheckMethods } from "./expressions.js";
15
+ import { resolveMethods } from "./resolve.js";
16
+ import { statementCheckMethods } from "./statements.js";
17
+ import { setupGlobals } from "./stdlib.js";
18
+ import { terminationMethods } from "./termination.js";
19
+ import {
20
+ ANY,
21
+ defaultType,
22
+ ERROR,
23
+ isVoid,
24
+ Scope,
25
+ TAINTED_ANY,
26
+ TypeCheckError,
27
+ typeStr,
28
+ VOID,
29
+ } from "./types.js";
30
+
31
+ // Re-export for consumers that import from typechecker.js
32
+ export { TypeCheckError, typeStr };
33
+
34
+ export class TypeChecker {
35
+ constructor() {
36
+ this.types = new Map(); // named types
37
+ this.globals = new Scope();
38
+ this.errors = [];
39
+ this._currentFile = null; // filename of file currently being checked
40
+ this._currentSource = null;
41
+ this._loopDepth = 0; // for break/continue validation
42
+ this._switchDepth = 0; // for break/fallthrough validation
43
+ this._typeSwitchDepth = 0; // for rejecting fallthrough in type switch
44
+ this._deferCount = 0; // tracks defer usage in current function body
45
+ this._imports = []; // tracked imports for unused-import detection
46
+ this._setupGlobals();
47
+ // Register error as a named type (interface)
48
+ this.types.set("error", ERROR);
49
+ }
50
+
51
+ _setupGlobals() {
52
+ setupGlobals(this.globals, this.types);
53
+ }
54
+
55
+ addDefinitions(types, values) {
56
+ for (const [name, type] of types) {
57
+ this.types.set(name, type);
58
+ }
59
+ for (const [name, type] of values) {
60
+ this.globals.define(name, type);
61
+ }
62
+ }
63
+
64
+ // Add an imported GoFront package as a qualified namespace.
65
+ // e.g. addPackageNamespace('utils', symbolsMap, typesMap)
66
+ // lets callers type-check `utils.Foo` via SelectorExpr.
67
+ addPackageNamespace(pkgName, symbols, types) {
68
+ const members = {};
69
+ for (const [name, type] of symbols) members[name] = type;
70
+ // _gofront: true marks this as a GoFront package — exported identifier rules apply
71
+ this.globals.define(pkgName, {
72
+ kind: "namespace",
73
+ name: pkgName,
74
+ members,
75
+ _gofront: true,
76
+ });
77
+ for (const [name, type] of types) {
78
+ this.types.set(name, type);
79
+ this.types.set(`${pkgName}.${name}`, type);
80
+ }
81
+ }
82
+
83
+ // Register an import for unused-import detection.
84
+ // `name` is the package name or alias used in code.
85
+ // `node` carries _line for error reporting.
86
+ // `filename` / `source` identify the file containing the import.
87
+ trackImport(name, node, filename, source) {
88
+ this._imports.push({ name, node, filename, source });
89
+ }
90
+
91
+ // Report any tracked imports whose package name was never referenced.
92
+ reportUnusedImports() {
93
+ for (const { name, node, filename, source } of this._imports) {
94
+ if (!this.globals._used.has(name)) {
95
+ const saved = [this._currentFile, this._currentSource];
96
+ this._currentFile = filename;
97
+ this._currentSource = source;
98
+ this.err(`'${name}' imported and not used`, node);
99
+ [this._currentFile, this._currentSource] = saved;
100
+ }
101
+ }
102
+ }
103
+
104
+ // Return a snapshot of all user-defined globals (excludes built-ins).
105
+ // Used by the compiler to expose a package's exports to importers.
106
+ getExportedSymbols() {
107
+ const out = new Map();
108
+ for (const [name, type] of this.globals.symbols) {
109
+ if (type?.kind === "builtin") continue; // skip built-ins
110
+ if (type === ANY && !name[0].match(/[A-Z]/)) continue; // skip browser globals
111
+ out.set(name, type);
112
+ }
113
+ return out;
114
+ }
115
+
116
+ getExportedTypes() {
117
+ return new Map(this.types);
118
+ }
119
+
120
+ err(msg, node) {
121
+ const e = new TypeCheckError(
122
+ msg,
123
+ node,
124
+ this._currentFile,
125
+ this._currentSource,
126
+ );
127
+ this.errors.push(e);
128
+ return TAINTED_ANY; // tainted recovery type — suppresses downstream cascade errors
129
+ }
130
+
131
+ _reportUnused(scope, node) {
132
+ for (const name of scope.unusedLocals()) {
133
+ this.err(`'${name}' declared and not used`, node);
134
+ }
135
+ }
136
+
137
+ _setCurrentFile(p) {
138
+ this._currentFile = p._filename ?? null;
139
+ this._currentSource = p._source ?? null;
140
+ }
141
+
142
+ check(program) {
143
+ this._setCurrentFile(program);
144
+ // Pass 1: collect type declarations
145
+ for (const decl of program.decls) {
146
+ if (decl.kind === "TypeDecl") this.collectType(decl);
147
+ }
148
+ // Pass 2: collect function / method signatures
149
+ for (const decl of program.decls) {
150
+ if (decl.kind === "FuncDecl" || decl.kind === "MethodDecl") {
151
+ this.collectFunc(decl);
152
+ } else if (decl.kind === "TemplDecl") {
153
+ this._collectTemplDecl(decl);
154
+ }
155
+ }
156
+ // Pass 2.1: Promote embedded methods
157
+ this._promoteEmbeddedMethods();
158
+ // Pass 3: check bodies
159
+ for (const decl of program.decls) {
160
+ this.checkTopDecl(decl, this.globals);
161
+ }
162
+ return this.errors;
163
+ }
164
+
165
+ // Pre-declare a package-level var so other files can reference its name
166
+ // before we've type-checked its initializer. Called in pass 2.5.
167
+ collectVar(decl) {
168
+ for (const spec of decl.decls) {
169
+ const type = spec.type
170
+ ? this.resolveTypeNode(spec.type, this.globals)
171
+ : ANY;
172
+ for (const name of spec.names) this.globals.define(name, type);
173
+ }
174
+ }
175
+
176
+ collectConst(decl) {
177
+ for (const spec of decl.decls) {
178
+ const type = spec.type
179
+ ? this.resolveTypeNode(spec.type, this.globals)
180
+ : ANY;
181
+ for (const name of spec.names) this.globals.defineConst(name, type);
182
+ }
183
+ }
184
+
185
+ // Like check() but operates over multiple programs (same-package multi-file).
186
+ // All passes run across all files before moving to the next pass,
187
+ // so every file sees every other file's declarations.
188
+ checkAll(programs) {
189
+ this._collectTypesPass(programs);
190
+ this._collectFuncsPass(programs);
191
+ this._promoteEmbeddedMethods();
192
+ this._collectVarsConstsPass(programs);
193
+ this._checkTopDeclsPass(programs);
194
+ return this.errors;
195
+ }
196
+
197
+ _collectTypesPass(programs) {
198
+ for (const p of programs) {
199
+ this._setCurrentFile(p);
200
+ for (const d of p.decls) if (d.kind === "TypeDecl") this.collectType(d);
201
+ }
202
+ }
203
+
204
+ _collectFuncsPass(programs) {
205
+ for (const p of programs) {
206
+ this._setCurrentFile(p);
207
+ for (const d of p.decls) {
208
+ if (d.kind === "FuncDecl" || d.kind === "MethodDecl")
209
+ this.collectFunc(d);
210
+ else if (d.kind === "TemplDecl") this._collectTemplDecl(d);
211
+ }
212
+ }
213
+ }
214
+
215
+ _collectVarsConstsPass(programs) {
216
+ for (const p of programs) {
217
+ this._setCurrentFile(p);
218
+ for (const d of p.decls) {
219
+ if (d.kind === "VarDecl") this.collectVar(d);
220
+ if (d.kind === "ConstDecl") this.collectConst(d);
221
+ }
222
+ }
223
+ }
224
+
225
+ _checkTopDeclsPass(programs) {
226
+ for (const p of programs) {
227
+ this._setCurrentFile(p);
228
+ for (const d of p.decls) this.checkTopDecl(d, this.globals);
229
+ }
230
+ }
231
+
232
+ // ── Shared pass helpers ──────────────────────────────────────
233
+
234
+ _promoteEmbeddedMethods() {
235
+ for (const type of this.types.values()) {
236
+ const struct = type.underlying;
237
+ if (struct?.kind === "struct" && struct._embeds) {
238
+ for (const embed of struct._embeds) {
239
+ const base = embed.kind === "named" ? embed.underlying : embed;
240
+ if (base?.kind !== "struct" || !base.methods) continue;
241
+ for (const [mName, mType] of base.methods.entries()) {
242
+ if (!struct.methods.has(mName)) struct.methods.set(mName, mType);
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ // ── Type collection ──────────────────────────────────────────
250
+
251
+ collectType(decl) {
252
+ if (decl.typeParams) {
253
+ // Generic type — resolve underlying with type params as ANY for struct fields
254
+ const typeScope = new Scope(this.globals);
255
+ const typeParamTypes = decl.typeParams.map((tp) => {
256
+ const t = {
257
+ kind: "typeParam",
258
+ name: tp.name,
259
+ constraint: tp.constraint,
260
+ };
261
+ typeScope.define(tp.name, t);
262
+ return t;
263
+ });
264
+ const underlying = this.resolveTypeNode(decl.type, typeScope);
265
+ const named = {
266
+ kind: "named",
267
+ name: decl.name,
268
+ underlying,
269
+ _generic: {
270
+ typeParams: typeParamTypes,
271
+ declNode: decl,
272
+ },
273
+ };
274
+ if (underlying.kind === "struct") {
275
+ underlying.name = decl.name;
276
+ underlying.methods = new Map();
277
+ }
278
+ this.types.set(decl.name, named);
279
+ this.globals.define(decl.name, named);
280
+ return;
281
+ }
282
+ const underlying = this.resolveTypeNode(decl.type, this.globals);
283
+ if (decl.isAlias) {
284
+ // type A = B — transparent alias, A and B are identical types
285
+ this.types.set(decl.name, underlying);
286
+ this.globals.define(decl.name, underlying);
287
+ return;
288
+ }
289
+ const named = { kind: "named", name: decl.name, underlying };
290
+ if (underlying.kind === "struct") {
291
+ underlying.name = decl.name;
292
+ underlying.methods = new Map();
293
+ } else if (underlying.kind !== "interface") {
294
+ named.methods = new Map();
295
+ }
296
+ if (underlying.kind === "interface") {
297
+ underlying.name = decl.name;
298
+ }
299
+ this.types.set(decl.name, named);
300
+ this.globals.define(decl.name, named);
301
+ }
302
+
303
+ _buildCollectFuncScope(decl) {
304
+ let resolveScope = this.globals;
305
+ let typeParamTypes = null;
306
+ if (decl.typeParams) {
307
+ resolveScope = new Scope(this.globals);
308
+ typeParamTypes = decl.typeParams.map((tp) => {
309
+ const t = {
310
+ kind: "typeParam",
311
+ name: tp.name,
312
+ constraint: tp.constraint,
313
+ };
314
+ resolveScope.define(tp.name, t);
315
+ return t;
316
+ });
317
+ }
318
+ if (decl.kind === "MethodDecl") {
319
+ const recvNamedType = this.types.get(decl.recvType.name);
320
+ if (recvNamedType?._generic) {
321
+ resolveScope = new Scope(this.globals);
322
+ for (const tp of recvNamedType._generic.typeParams)
323
+ resolveScope.define(tp.name, tp);
324
+ }
325
+ }
326
+ return { resolveScope, typeParamTypes };
327
+ }
328
+
329
+ _registerFuncDecl(decl, funcType, typeParamTypes) {
330
+ if (this.globals.symbols.has(decl.name) && decl.name !== "init")
331
+ this.err(`${decl.name} redeclared in this block`, decl);
332
+ if (typeParamTypes) {
333
+ this.globals.define(decl.name, {
334
+ kind: "generic",
335
+ name: decl.name,
336
+ typeParams: typeParamTypes,
337
+ underlying: funcType,
338
+ });
339
+ } else {
340
+ this.globals.define(decl.name, funcType);
341
+ }
342
+ }
343
+
344
+ collectFunc(decl) {
345
+ const { resolveScope, typeParamTypes } = this._buildCollectFuncScope(decl);
346
+ const paramTypes = decl.params.map((p) =>
347
+ this.resolveTypeNode(p.type, resolveScope),
348
+ );
349
+ const returnType = decl.returnType
350
+ ? this.resolveTypeNode(decl.returnType, resolveScope)
351
+ : VOID;
352
+ const isVariadic =
353
+ decl.params.length > 0 && decl.params[decl.params.length - 1].variadic;
354
+ const funcType = {
355
+ kind: "func",
356
+ params: paramTypes,
357
+ returns: [returnType],
358
+ variadic: isVariadic,
359
+ async: decl.async ?? false,
360
+ };
361
+ if (decl.kind === "FuncDecl")
362
+ this._registerFuncDecl(decl, funcType, typeParamTypes);
363
+ else this._attachMethod(decl, funcType);
364
+ }
365
+
366
+ _attachGenericMethod(recvNamedType, decl, funcType) {
367
+ if (!recvNamedType._generic.methods)
368
+ recvNamedType._generic.methods = new Map();
369
+ recvNamedType._generic.methods.set(decl.name, funcType);
370
+ const base = recvNamedType.underlying;
371
+ if (base?.kind === "struct") base.methods.set(decl.name, funcType);
372
+ }
373
+
374
+ _attachNonGenericMethod(decl, funcType) {
375
+ const recvType = this.resolveTypeNodeName(decl.recvType, this.globals);
376
+ const base = recvType?.underlying ?? recvType;
377
+ if (base?.kind === "struct") {
378
+ base.methods.set(decl.name, funcType);
379
+ } else if (recvType?.kind === "named" && recvType.methods) {
380
+ recvType.methods.set(decl.name, funcType);
381
+ }
382
+ }
383
+
384
+ _attachMethod(decl, funcType) {
385
+ const recvNamedType = this.types.get(decl.recvType.name);
386
+ if (recvNamedType?._generic)
387
+ this._attachGenericMethod(recvNamedType, decl, funcType);
388
+ else this._attachNonGenericMethod(decl, funcType);
389
+ }
390
+
391
+ // ── Top-level checker ────────────────────────────────────────
392
+
393
+ checkTopDecl(decl, scope) {
394
+ switch (decl.kind) {
395
+ case "FuncDecl":
396
+ this.checkFuncDecl(decl, scope);
397
+ break;
398
+ case "MethodDecl":
399
+ this.checkMethodDecl(decl, scope);
400
+ break;
401
+ case "VarDecl":
402
+ this.checkVarDecl(decl, scope);
403
+ break;
404
+ case "ConstDecl":
405
+ this.checkConstDecl(decl, scope);
406
+ break;
407
+ case "TypeDecl":
408
+ case "TemplDecl":
409
+ break; // already collected / no body to check
410
+ }
411
+ }
412
+
413
+ _collectTemplDecl(decl) {
414
+ const paramTypes = decl.params.map((p) =>
415
+ this.resolveTypeNode(p.type, this.globals),
416
+ );
417
+ const gomNodeType = this.types.get("gom.Node") ?? {
418
+ kind: "basic",
419
+ name: "any",
420
+ };
421
+ const isVariadic =
422
+ decl.params.length > 0 && decl.params[decl.params.length - 1].variadic;
423
+ const funcType = {
424
+ kind: "func",
425
+ params: paramTypes,
426
+ returns: [gomNodeType],
427
+ variadic: isVariadic,
428
+ async: false,
429
+ };
430
+ if (this.globals.symbols.has(decl.name) && decl.name !== "init") {
431
+ this.err(`${decl.name} redeclared in this block`, decl);
432
+ }
433
+ this.globals.define(decl.name, funcType);
434
+ }
435
+
436
+ checkFuncDecl(decl, outer) {
437
+ const inner = new Scope(outer);
438
+ this._injectTypeParams(decl, inner, outer);
439
+ for (const p of decl.params) {
440
+ inner.define(p.name, this.resolveTypeNode(p.type, inner));
441
+ }
442
+ const returnType = this._setupFuncReturnType(decl, inner, outer);
443
+ this._runFuncBody(decl, inner, returnType);
444
+ this._checkMissingReturn(decl, returnType, "function");
445
+ }
446
+
447
+ checkMethodDecl(decl, outer) {
448
+ const inner = new Scope(outer);
449
+ const recvTypeName =
450
+ decl.recvType.kind === "GenericTypeName"
451
+ ? decl.recvType.name
452
+ : decl.recvType.name;
453
+ const recvNamedType = this.types.get(recvTypeName);
454
+ this._injectGenericReceiverTypeParams(inner, recvNamedType);
455
+ const recvType = this.resolveTypeNodeName(decl.recvType, outer);
456
+ inner.define(decl.recvName, recvType);
457
+ for (const p of decl.params) {
458
+ inner.define(p.name, this.resolveTypeNode(p.type, inner));
459
+ }
460
+ const returnType = this._setupFuncReturnType(decl, inner, inner);
461
+ this._runFuncBody(decl, inner, returnType);
462
+ this._checkMissingReturn(decl, returnType, "method");
463
+ }
464
+
465
+ _injectTypeParams(decl, inner, outer) {
466
+ if (!decl.typeParams) return;
467
+ for (const tp of decl.typeParams) {
468
+ const constraint = tp.constraint
469
+ ? this.resolveTypeNode(tp.constraint, outer)
470
+ : ANY;
471
+ inner.define(tp.name, { kind: "typeParam", name: tp.name, constraint });
472
+ }
473
+ }
474
+
475
+ _injectGenericReceiverTypeParams(inner, recvNamedType) {
476
+ if (!recvNamedType?._generic) return;
477
+ for (const tp of recvNamedType._generic.typeParams) {
478
+ inner.define(tp.name, tp);
479
+ }
480
+ }
481
+
482
+ _setupFuncReturnType(decl, inner, outer) {
483
+ let returnType = decl.returnType
484
+ ? this.resolveTypeNode(decl.returnType, inner)
485
+ : VOID;
486
+ const hasNamedReturns = this._injectNamedReturns(
487
+ decl.returnType,
488
+ inner,
489
+ outer,
490
+ );
491
+ if (hasNamedReturns && returnType)
492
+ returnType = { ...returnType, _hasNamedReturns: true };
493
+ return returnType;
494
+ }
495
+
496
+ _runFuncBody(decl, inner, returnType) {
497
+ const savedDefer = this._deferCount;
498
+ this._deferCount = 0;
499
+ this.checkBlock(decl.body, inner, returnType);
500
+ this._reportUnused(inner, decl);
501
+ if (this._deferCount > 0) decl.body._hasDefer = true;
502
+ this._deferCount = savedDefer;
503
+ decl._returnType = returnType;
504
+ }
505
+
506
+ _checkMissingReturn(decl, returnType, kind) {
507
+ if (!isVoid(returnType) && !returnType._hasNamedReturns) {
508
+ if (!this._isTerminating(decl.body)) {
509
+ this.err(`missing return at end of ${kind} '${decl.name}'`, decl);
510
+ }
511
+ }
512
+ }
513
+
514
+ _injectNamedReturns(returnTypeNode, scope, outer) {
515
+ if (!returnTypeNode?._namedReturns) return false;
516
+ for (const { name, type } of returnTypeNode._namedReturns) {
517
+ if (name) scope.define(name, this.resolveTypeNode(type, outer));
518
+ }
519
+ return true;
520
+ }
521
+
522
+ checkVarDecl(decl, scope) {
523
+ for (const spec of decl.decls) {
524
+ let type = spec.type ? this.resolveTypeNode(spec.type, scope) : null;
525
+ if (spec.value) {
526
+ const valTypes = spec.value.map((v) => this.checkExpr(v, scope));
527
+ if (!type) type = defaultType(valTypes[0]) ?? ANY;
528
+ for (let i = 0; i < spec.names.length; i++) {
529
+ const vt = valTypes[i] ?? ANY;
530
+ this.assertAssignable(type, vt, spec.value[i]);
531
+ }
532
+ }
533
+ if (!type) type = ANY;
534
+ for (const name of spec.names) scope.defineLocal(name, type);
535
+ }
536
+ }
537
+
538
+ checkConstDecl(decl, scope) {
539
+ for (const spec of decl.decls) {
540
+ const valTypes = spec.value.map((v) => this.checkExpr(v, scope));
541
+ // Explicit type annotation → typed constant; otherwise preserve untyped
542
+ const type = spec.type
543
+ ? this.resolveTypeNode(spec.type, scope)
544
+ : (valTypes[0] ?? ANY);
545
+ for (const name of spec.names) scope.defineConst(name, type);
546
+ }
547
+ }
548
+
549
+ // ── Statement checking ───────────────────────────────────────
550
+ }
551
+
552
+ Object.assign(TypeChecker.prototype, statementCheckMethods);
553
+ Object.assign(TypeChecker.prototype, expressionCheckMethods);
554
+ Object.assign(TypeChecker.prototype, terminationMethods);
555
+ Object.assign(TypeChecker.prototype, resolveMethods);
556
+ Object.assign(TypeChecker.prototype, assignabilityMethods);