yukigo-haskell-parser 0.1.3 → 0.2.2

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 (57) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +51 -9
  3. package/README.md +5 -5
  4. package/dist/index.js +21 -13
  5. package/dist/index.js.map +1 -1
  6. package/dist/parser/grammar.cjs +397 -0
  7. package/dist/parser/grammar.cjs.map +1 -0
  8. package/dist/parser/grammar.d.cts +38 -0
  9. package/dist/parser/lexer.d.ts +2 -1
  10. package/dist/parser/lexer.js +6 -1
  11. package/dist/parser/lexer.js.map +1 -1
  12. package/dist/prelude.js +279 -279
  13. package/dist/typechecker/DeclarationCollector.d.ts +2 -0
  14. package/dist/typechecker/DeclarationCollector.js +6 -5
  15. package/dist/typechecker/DeclarationCollector.js.map +1 -1
  16. package/dist/typechecker/TypeBuilder.js +9 -7
  17. package/dist/typechecker/TypeBuilder.js.map +1 -1
  18. package/dist/typechecker/checker.d.ts +9 -4
  19. package/dist/typechecker/checker.js +66 -94
  20. package/dist/typechecker/checker.js.map +1 -1
  21. package/dist/typechecker/core.js +8 -7
  22. package/dist/typechecker/core.js.map +1 -1
  23. package/dist/typechecker/inference.d.ts +4 -1
  24. package/dist/typechecker/inference.js +39 -19
  25. package/dist/typechecker/inference.js.map +1 -1
  26. package/dist/utils/helpers.d.ts +3 -0
  27. package/dist/utils/helpers.js +5 -0
  28. package/dist/utils/helpers.js.map +1 -1
  29. package/dist/utils/types.d.ts +12 -3
  30. package/dist/utils/types.js +34 -22
  31. package/dist/utils/types.js.map +1 -1
  32. package/package.json +6 -9
  33. package/src/index.ts +223 -192
  34. package/src/parser/{grammar.ts → grammar.cjs} +191 -223
  35. package/src/parser/grammar.d.ts +3 -0
  36. package/src/parser/grammar.ne +521 -518
  37. package/src/parser/lexer.ts +357 -353
  38. package/src/prelude.ts +281 -281
  39. package/src/typechecker/DeclarationCollector.ts +160 -157
  40. package/src/typechecker/TypeBuilder.ts +153 -150
  41. package/src/typechecker/checker.ts +487 -501
  42. package/src/typechecker/core.ts +195 -192
  43. package/src/typechecker/inference.ts +1442 -1421
  44. package/src/utils/helpers.ts +34 -29
  45. package/src/utils/types.ts +75 -63
  46. package/tests/hspec.spec.ts +95 -92
  47. package/tests/lexer.spec.ts +175 -175
  48. package/tests/parser.spec.ts +838 -829
  49. package/tests/prelude.spec.ts +17 -17
  50. package/tests/typechecker.spec.ts +326 -327
  51. package/tsconfig.build.json +16 -0
  52. package/tsconfig.build.tsbuildinfo +1 -0
  53. package/tsconfig.json +29 -26
  54. package/tsconfig.tsbuildinfo +1 -1
  55. package/dist/parser/grammar.d.ts +0 -28
  56. package/dist/parser/grammar.js +0 -393
  57. package/dist/parser/grammar.js.map +0 -1
@@ -1,157 +1,160 @@
1
- import {
2
- ASTNode,
3
- Record,
4
- TypeAlias,
5
- TypeSignature,
6
- Visitor,
7
- TestGroup,
8
- Test,
9
- Assert,
10
- TypeClass,
11
- Instance,
12
- Equation,
13
- TypePattern,
14
- SimpleType,
15
- ListType,
16
- } from "yukigo-ast";
17
- import {
18
- functionType,
19
- Type,
20
- TypeConstructor,
21
- TypeScheme,
22
- TypeVar,
23
- } from "./checker.js";
24
- import { CoreHM } from "./core.js";
25
- import { TypeBuilder } from "./TypeBuilder.js";
26
- import { typeMappings } from "../utils/types.js";
27
-
28
- const builder = new TypeBuilder(new CoreHM());
29
-
30
- export class DeclarationCollectorVisitor implements Visitor<void> {
31
- constructor(
32
- private errors: string[],
33
- private typeAliasMap: Map<string, Type>,
34
- private recordMap: Map<string, Type>,
35
- private signatureMap: Map<string, TypeScheme>,
36
- private coreHM: CoreHM
37
- ) {}
38
-
39
- visitTypeAlias(node: TypeAlias) {
40
- const typeAliasIdentifier = node.identifier.value;
41
- if (
42
- this.typeAliasMap.has(typeAliasIdentifier) ||
43
- this.recordMap.has(typeAliasIdentifier)
44
- ) {
45
- this.errors.push(`Multiple declaration of '${typeAliasIdentifier}'.`);
46
- return;
47
- }
48
-
49
- const { type, constraints } = builder.build(node.value);
50
- this.typeAliasMap.set(typeAliasIdentifier, type);
51
- }
52
- visitRecord(node: Record) {
53
- const recordIdentifier = node.name.value;
54
- if (
55
- this.typeAliasMap.has(recordIdentifier) ||
56
- this.recordMap.has(recordIdentifier)
57
- ) {
58
- this.errors.push(`Multiple declaration of '${recordIdentifier}'.`);
59
- return;
60
- }
61
-
62
- // Save the record type itself
63
- const recordType: TypeConstructor = {
64
- type: "TypeConstructor",
65
- name: recordIdentifier,
66
- args: [],
67
- };
68
- this.recordMap.set(recordIdentifier, recordType);
69
-
70
- // Add constructors to signature map as type schemes
71
- for (const cons of node.contents) {
72
- if (this.signatureMap.has(cons.name.value)) {
73
- this.errors.push(`Constructor '${cons.name}' is already defined`);
74
- continue;
75
- }
76
- const paramTypes = cons.fields.map((field) => builder.build(field.value));
77
- const returnType: TypeConstructor = {
78
- type: "TypeConstructor",
79
- name: recordIdentifier,
80
- args: paramTypes.map(() => this.coreHM.freshVar()),
81
- };
82
-
83
- const funcType: Type = paramTypes.reduceRight(
84
- (acc, param) => functionType(param.type, acc),
85
- returnType
86
- );
87
-
88
- // Generalize all free variables in the constructor type
89
- const scheme = this.coreHM.generalize(new Map(), funcType);
90
- this.signatureMap.set(cons.name.value, scheme);
91
- }
92
- }
93
-
94
- visitTypeClass(node: TypeClass) {
95
- const className = node.name.value;
96
- if (!this.coreHM.typeClasses.has(className)) {
97
- this.coreHM.typeClasses.set(className, []);
98
- }
99
-
100
- // Register method signatures
101
- for (const sig of node.signatures) {
102
- this.visitTypeSignature(sig);
103
- }
104
- }
105
-
106
- visitInstance(node: Instance) {
107
- const className = node.className.value;
108
- let yukigoTypeName = "YuUnknown";
109
-
110
- if (node.type instanceof SimpleType) {
111
- yukigoTypeName = typeMappings[node.type.value] || node.type.value;
112
- } else if (node.type instanceof ListType) {
113
- yukigoTypeName = "YuList";
114
- }
115
-
116
- let instances = this.coreHM.typeClasses.get(className);
117
- if (!instances) {
118
- instances = [];
119
- this.coreHM.typeClasses.set(className, instances);
120
- }
121
-
122
- if (!instances.includes(yukigoTypeName)) {
123
- instances.push(yukigoTypeName);
124
- }
125
- }
126
-
127
- visitTypeSignature(node: TypeSignature) {
128
- const functionName = node.identifier.value;
129
- if (this.signatureMap.has(functionName)) {
130
- this.errors.push(
131
- `Function '${functionName}' has multiple type signatures`
132
- );
133
- return;
134
- }
135
- const typeVarMap = new Map<string, TypeVar>();
136
- const { type, constraints } = builder.build(node.body, typeVarMap);
137
- const quantifiers = Array.from(typeVarMap.values()).map((tv) => tv.id);
138
- this.signatureMap.set(functionName, {
139
- type: "TypeScheme",
140
- quantifiers,
141
- body: type,
142
- constraints,
143
- });
144
- }
145
- visitTestGroup(node: TestGroup): void {
146
- node.group.accept(this);
147
- }
148
- visitTest(node: Test): void {
149
- node.body.accept(this);
150
- }
151
- visitAssert(node: Assert): void {
152
- // assertions don't contain declarations
153
- }
154
- visit(node: ASTNode): void {
155
- node.accept(this);
156
- }
157
- }
1
+ import {
2
+ ASTNode,
3
+ Record,
4
+ TypeAlias,
5
+ TypeSignature,
6
+ Visitor,
7
+ TestGroup,
8
+ Test,
9
+ Assert,
10
+ TypeClass,
11
+ Instance,
12
+ Equation,
13
+ TypePattern,
14
+ SimpleType,
15
+ ListType,
16
+ } from "yukigo-ast";
17
+ import {
18
+ functionType,
19
+ Type,
20
+ TypeConstructor,
21
+ TypeScheme,
22
+ TypeVar,
23
+ } from "./checker.js";
24
+ import { CoreHM } from "./core.js";
25
+ import { TypeBuilder } from "./TypeBuilder.js";
26
+ import { typeMappings } from "../utils/types.js";
27
+
28
+ export class DeclarationCollectorVisitor implements Visitor<void> {
29
+ private builder: TypeBuilder;
30
+
31
+ constructor(
32
+ private errors: string[],
33
+ private typeAliasMap: Map<string, Type>,
34
+ private recordMap: Map<string, Type>,
35
+ private signatureMap: Map<string, TypeScheme>,
36
+ private coreHM: CoreHM,
37
+ ) {
38
+ this.builder = new TypeBuilder(this.coreHM);
39
+ }
40
+
41
+ visitTypeAlias(node: TypeAlias) {
42
+ const typeAliasIdentifier = node.identifier.value;
43
+ if (
44
+ this.typeAliasMap.has(typeAliasIdentifier) ||
45
+ this.recordMap.has(typeAliasIdentifier)
46
+ ) {
47
+ this.errors.push(`Multiple declaration of '${typeAliasIdentifier}'.`);
48
+ return;
49
+ }
50
+
51
+ const { type, constraints } = this.builder.build(node.value);
52
+ this.typeAliasMap.set(typeAliasIdentifier, type);
53
+ }
54
+ visitRecord(node: Record) {
55
+ const recordIdentifier = node.name.value;
56
+ if (
57
+ this.typeAliasMap.has(recordIdentifier) ||
58
+ this.recordMap.has(recordIdentifier)
59
+ ) {
60
+ this.errors.push(`Multiple declaration of '${recordIdentifier}'.`);
61
+ return;
62
+ }
63
+
64
+ // Save the record type itself
65
+ const recordType: TypeConstructor = {
66
+ type: "TypeConstructor",
67
+ name: recordIdentifier,
68
+ args: [],
69
+ };
70
+ this.recordMap.set(recordIdentifier, recordType);
71
+
72
+ // Add constructors to signature map as type schemes
73
+ for (const cons of node.contents) {
74
+ if (this.signatureMap.has(cons.name.value)) {
75
+ this.errors.push(`Constructor '${cons.name}' is already defined`);
76
+ continue;
77
+ }
78
+ const paramTypes = cons.fields.map((field) => this.builder.build(field.value));
79
+ const returnType: TypeConstructor = {
80
+ type: "TypeConstructor",
81
+ name: recordIdentifier,
82
+ args: paramTypes.map(() => this.coreHM.freshVar()),
83
+ };
84
+
85
+ const funcType: Type = paramTypes.reduceRight(
86
+ (acc, param) => functionType(param.type, acc),
87
+ returnType,
88
+ );
89
+
90
+ // Generalize all free variables in the constructor type
91
+ const scheme = this.coreHM.generalize(new Map(), funcType);
92
+ this.signatureMap.set(cons.name.value, scheme);
93
+ }
94
+ }
95
+
96
+ visitTypeClass(node: TypeClass) {
97
+ const className = node.name.value;
98
+ if (!this.coreHM.typeClasses.has(className)) {
99
+ this.coreHM.typeClasses.set(className, []);
100
+ }
101
+
102
+ // Register method signatures
103
+ for (const sig of node.signatures) {
104
+ this.visitTypeSignature(sig);
105
+ }
106
+ }
107
+
108
+ visitInstance(node: Instance) {
109
+ const className = node.className.value;
110
+ let yukigoTypeName = "YuUnknown";
111
+
112
+ if (node.type instanceof SimpleType) {
113
+ yukigoTypeName = typeMappings[node.type.value] || node.type.value;
114
+ } else if (node.type instanceof ListType) {
115
+ yukigoTypeName = "YuList";
116
+ }
117
+
118
+ let instances = this.coreHM.typeClasses.get(className);
119
+ if (!instances) {
120
+ instances = [];
121
+ this.coreHM.typeClasses.set(className, instances);
122
+ }
123
+
124
+ if (!instances.includes(yukigoTypeName)) {
125
+ instances.push(yukigoTypeName);
126
+ }
127
+ }
128
+
129
+ visitTypeSignature(node: TypeSignature) {
130
+ const functionName = node.identifier.value;
131
+ if (this.signatureMap.has(functionName)) {
132
+ this.errors.push(
133
+ `Function '${functionName}' has multiple type signatures`,
134
+ );
135
+ return;
136
+ }
137
+ const typeVarMap = new Map<string, TypeVar>();
138
+ const { type, constraints } = this.builder.build(node.body, typeVarMap);
139
+ const quantifiers = Array.from(typeVarMap.values()).map((tv) => tv.id);
140
+ this.signatureMap.set(functionName, {
141
+ type: "TypeScheme",
142
+ quantifiers,
143
+ body: type,
144
+ constraints,
145
+ });
146
+ }
147
+ visitTestGroup(node: TestGroup): void {
148
+ node.group.accept(this);
149
+ }
150
+ visitTest(node: Test): void {
151
+ node.body.accept(this);
152
+ }
153
+ visitAssert(node: Assert): void {
154
+ // assertions don't contain declarations
155
+ }
156
+ visit(node: ASTNode): void {
157
+ node.accept(this);
158
+ }
159
+ fallback(node: ASTNode): void {}
160
+ }
@@ -1,150 +1,153 @@
1
- import {
2
- SimpleType,
3
- TypeVar as ASTTypeVar,
4
- ListType,
5
- TupleType,
6
- ParameterizedType,
7
- TypeApplication,
8
- Constraint,
9
- Type as YukigoType,
10
- ConstrainedType,
11
- ASTNode,
12
- } from "yukigo-ast";
13
- import { typeMappings } from "../utils/types.js";
14
- import { CoreHM } from "./core.js";
15
- import { functionType, Type, TypeConstructor, TypeVar, stringType, charType } from "./checker.js";
16
-
17
- export class TypeBuilder {
18
- constructor(private coreHM: CoreHM) {}
19
-
20
- build(
21
- node: YukigoType,
22
- typeVarMap: Map<string, TypeVar> = new Map()
23
- ): { type: Type; constraints: Map<number, string[]> } {
24
- const constraintsMap = new Map<number, string[]>();
25
-
26
- // Local visitor to walk Yukigo type AST
27
- const visitor = {
28
- visitSimpleType: (n: SimpleType): Type => {
29
- if (/^[a-z]/.test(n.value)) {
30
- // Lowercase = type variable
31
- if (!typeVarMap.has(n.value)) {
32
- typeVarMap.set(n.value, {
33
- type: "TypeVar",
34
- ...this.coreHM.freshVar(),
35
- name: n.value,
36
- });
37
- }
38
- // Collect constraints on this type var
39
- for (const constraint of n.constraints) {
40
- this.processConstraint(constraint, typeVarMap, constraintsMap);
41
- }
42
- return typeVarMap.get(n.value)!;
43
- }
44
-
45
- // Uppercase = type constructor (e.g., Int, Bool, List)
46
- const primitive = typeMappings[n.value] || n.value;
47
- if (primitive === "YuString") return stringType;
48
- if (primitive === "YuChar") return charType;
49
- return {
50
- type: "TypeConstructor",
51
- name: primitive,
52
- args: [],
53
- };
54
- },
55
-
56
- visitTypeVar: (n: ASTTypeVar): Type => {
57
- // Same as SimpleType for type variables
58
- if (!typeVarMap.has(n.value)) {
59
- typeVarMap.set(n.value, {
60
- type: "TypeVar",
61
- ...this.coreHM.freshVar(),
62
- name: n.value,
63
- });
64
- }
65
- for (const constraint of n.constraints) {
66
- this.processConstraint(constraint, typeVarMap, constraintsMap);
67
- }
68
- return typeVarMap.get(n.value)!;
69
- },
70
-
71
- visitListType: (n: ListType): Type => {
72
- const elementType = n.values.accept(visitor);
73
- return {
74
- type: "TypeConstructor",
75
- name: "List",
76
- args: [elementType],
77
- };
78
- },
79
-
80
- visitTupleType: (n: TupleType): Type => {
81
- const elementTypes = n.values.map((v) => v.accept(visitor));
82
- return {
83
- type: "TypeConstructor",
84
- name: "Tuple",
85
- args: elementTypes,
86
- };
87
- },
88
-
89
- visitTypeApplication: (n: TypeApplication): Type => {
90
- return this.coreHM.freshVar();
91
- },
92
-
93
- visitParameterizedType: (n: ParameterizedType): Type => {
94
- // This represents function types with constraints, e.g.:
95
- // (a, b) => c with Eq a
96
- const returnType = n.returnType.accept(visitor);
97
- const paramTypes = n.inputs.map((input) => input.accept(visitor));
98
-
99
- // Build function type: a -> b -> c
100
- const funcType = paramTypes.reduceRight(
101
- (acc, param) => functionType(param, acc),
102
- returnType
103
- );
104
-
105
- // Process constraints
106
- for (const constraint of n.constraints) {
107
- this.processConstraint(constraint, typeVarMap, constraintsMap);
108
- }
109
-
110
- return funcType;
111
- },
112
-
113
- visitConstrainedType: (n: ConstrainedType): Type => {
114
- // This is unusual at top level; usually constraints appear on type vars or signatures
115
- // For now, ignore or throw
116
- throw new Error("ConstrainedType not expected in this context");
117
- },
118
- visit(node: ASTNode): Type {
119
- return node.accept(visitor);
120
- },
121
- };
122
-
123
- const type = node.accept(visitor);
124
- return { type, constraints: constraintsMap };
125
- }
126
-
127
- private processConstraint(
128
- constraint: Constraint,
129
- typeVarMap: Map<string, { type: "TypeVar"; id: number }>,
130
- constraintsMap: Map<number, string[]>
131
- ): void {
132
- // Assume constraint is of form `Eq a`, so first param is a type var
133
- if (constraint.parameters.length === 0) return;
134
-
135
- const firstParam = constraint.parameters[0];
136
- // Only handle if it's a type variable
137
- if (
138
- (firstParam instanceof SimpleType || firstParam instanceof ASTTypeVar) &&
139
- /^[a-z]/.test(firstParam.value)
140
- ) {
141
- const tv = typeVarMap.get(firstParam.value);
142
- if (tv) {
143
- if (!constraintsMap.has(tv.id)) {
144
- constraintsMap.set(tv.id, []);
145
- }
146
- constraintsMap.get(tv.id)!.push(constraint.name);
147
- }
148
- }
149
- }
150
- }
1
+ import {
2
+ SimpleType,
3
+ TypeVar as ASTTypeVar,
4
+ ListType,
5
+ TupleType,
6
+ ParameterizedType,
7
+ TypeApplication,
8
+ Constraint,
9
+ Type as YukigoType,
10
+ ConstrainedType,
11
+ ASTNode,
12
+ Visitor,
13
+ } from "yukigo-ast";
14
+ import { typeMappings, YUTYPES } from "../utils/types.js";
15
+ import { CoreHM } from "./core.js";
16
+ import { functionType, Type, TypeConstructor, TypeVar, stringType, charType } from "./checker.js";
17
+ import { UnexpectedNode } from "../utils/helpers.js";
18
+
19
+ export class TypeBuilder {
20
+ constructor(private coreHM: CoreHM) {}
21
+
22
+ build(
23
+ node: YukigoType,
24
+ typeVarMap: Map<string, TypeVar> = new Map()
25
+ ): { type: Type; constraints: Map<number, string[]> } {
26
+ const constraintsMap = new Map<number, string[]>();
27
+
28
+ // Local visitor to walk Yukigo type AST
29
+ const visitor: Visitor<Type> = {
30
+ visitSimpleType: (n: SimpleType): Type => {
31
+ if (/^[a-z]/.test(n.value)) {
32
+ // Lowercase = type variable
33
+ if (!typeVarMap.has(n.value)) {
34
+ typeVarMap.set(n.value, {
35
+ ...this.coreHM.freshVar(),
36
+ name: n.value,
37
+ });
38
+ }
39
+ // Collect constraints on this type var
40
+ for (const constraint of n.constraints) {
41
+ this.processConstraint(constraint, typeVarMap, constraintsMap);
42
+ }
43
+ return typeVarMap.get(n.value)!;
44
+ }
45
+
46
+ // Uppercase = type constructor (e.g., Int, Bool, List)
47
+ const primitive = typeMappings[n.value] || n.value;
48
+ if (primitive === YUTYPES.YuString) return stringType;
49
+ if (primitive === YUTYPES.YuChar) return charType;
50
+ return {
51
+ type: "TypeConstructor",
52
+ name: primitive,
53
+ args: [],
54
+ };
55
+ },
56
+
57
+ visitTypeVar: (n: ASTTypeVar): Type => {
58
+ // Same as SimpleType for type variables
59
+ if (!typeVarMap.has(n.value)) {
60
+ typeVarMap.set(n.value, {
61
+ ...this.coreHM.freshVar(),
62
+ name: n.value,
63
+ });
64
+ }
65
+ for (const constraint of n.constraints) {
66
+ this.processConstraint(constraint, typeVarMap, constraintsMap);
67
+ }
68
+ return typeVarMap.get(n.value)!;
69
+ },
70
+
71
+ visitListType: (n: ListType): Type => {
72
+ const elementType = n.values.accept(visitor);
73
+ return {
74
+ type: "TypeConstructor",
75
+ name: YUTYPES.List,
76
+ args: [elementType],
77
+ };
78
+ },
79
+
80
+ visitTupleType: (n: TupleType): Type => {
81
+ const elementTypes = n.values.map((v) => v.accept(visitor));
82
+ return {
83
+ type: "TypeConstructor",
84
+ name: YUTYPES.Tuple,
85
+ args: elementTypes,
86
+ };
87
+ },
88
+
89
+ visitTypeApplication: (n: TypeApplication): Type => {
90
+ return this.coreHM.freshVar();
91
+ },
92
+
93
+ visitParameterizedType: (n: ParameterizedType): Type => {
94
+ // This represents function types with constraints, e.g.:
95
+ // (a, b) => c with Eq a
96
+ const returnType = n.returnType.accept(visitor);
97
+ const paramTypes = n.inputs.map((input) => input.accept(visitor));
98
+
99
+ // Build function type: a -> b -> c
100
+ const funcType = paramTypes.reduceRight(
101
+ (acc, param) => functionType(param, acc),
102
+ returnType
103
+ );
104
+
105
+ // Process constraints
106
+ for (const constraint of n.constraints) {
107
+ this.processConstraint(constraint, typeVarMap, constraintsMap);
108
+ }
109
+
110
+ return funcType;
111
+ },
112
+
113
+ visitConstrainedType: (n: ConstrainedType): Type => {
114
+ // This is unusual at top level; usually constraints appear on type vars or signatures
115
+ // For now, ignore or throw
116
+ throw new Error("ConstrainedType not expected in this context");
117
+ },
118
+ visit(node: ASTNode): Type {
119
+ return node.accept(visitor);
120
+ },
121
+ fallback(node: ASTNode): Type {
122
+ throw new UnexpectedNode(node.constructor.toString(), "TypeBuilder")
123
+ }
124
+ };
125
+
126
+ const type = node.accept(visitor);
127
+ return { type, constraints: constraintsMap };
128
+ }
129
+
130
+ private processConstraint(
131
+ constraint: Constraint,
132
+ typeVarMap: Map<string, { type: "TypeVar"; id: number }>,
133
+ constraintsMap: Map<number, string[]>
134
+ ): void {
135
+ // Assume constraint is of form `Eq a`, so first param is a type var
136
+ if (constraint.parameters.length === 0) return;
137
+
138
+ const firstParam = constraint.parameters[0];
139
+ // Only handle if it's a type variable
140
+ if (
141
+ (firstParam instanceof SimpleType || firstParam instanceof ASTTypeVar) &&
142
+ /^[a-z]/.test(firstParam.value)
143
+ ) {
144
+ const tv = typeVarMap.get(firstParam.value);
145
+ if (tv) {
146
+ if (!constraintsMap.has(tv.id)) {
147
+ constraintsMap.set(tv.id, []);
148
+ }
149
+ constraintsMap.get(tv.id)!.push(constraint.name);
150
+ }
151
+ }
152
+ }
153
+ }