blob: ea1ddfb6caada52b89f106be78d545ce9cefba68 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
import type { Identifier } from '@/parser';
export type UnionDenotableType =
| Array<DenotableType | DenotableFunctionSignature>
| DenotableType
| DenotableFunctionSignature
| Array<UnionDenotableType>;
export type DenotableFunctionSignature = {
arguments: Array<UnionDenotableType>;
return: DenotableType;
};
export type DenotableFunction = {
signatures: Array<DenotableFunctionSignature>;
body: Function;
};
export type DenotableType =
| 'null'
| 'int'
| 'real'
| 'bool'
| 'string'
| 'record'
| 'bytearray'
| 'function';
export type DenotableRecord = {
length: number;
record: Array<Denotable>;
};
export type DenotableValue =
| null
| number
| string
| Uint8Array
| DenotableFunction
| DenotableRecord
| Identifier;
export type Denotable = {
type: DenotableType;
value: DenotableValue;
};
export const denotableTypesEquivalent = (
a: UnionDenotableType,
b: UnionDenotableType,
): boolean => {
if (typeof a !== typeof b) return false;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (!denotableTypesEquivalent(a[i], b[i])) return false;
}
return true;
}
if (
typeof a === 'object' &&
typeof b === 'object' &&
'arguments' in a &&
'arguments' in b
) {
if (a.arguments.length !== b.arguments.length) return false;
if (!denotableTypesEquivalent(a.return, b.return)) return false;
for (let i = 0; i < a.arguments.length; i++) {
if (!denotableTypesEquivalent(a.arguments[i], b.arguments[i])) {
return false;
}
}
return true;
}
if (a === b) return true;
return false;
};
export const matchSignature = (
args: Array<UnionDenotableType>,
signatures: Array<DenotableFunctionSignature>,
): DenotableFunctionSignature | undefined => {
return signatures.find(signature => {
if (args.length !== signature.arguments.length) return false;
return args.every((arg, i) => {
const argSignature = signature.arguments[i];
if (Array.isArray(argSignature)) {
return argSignature.some(a => denotableTypesEquivalent(a, arg));
}
return denotableTypesEquivalent(arg, signature.arguments[i]);
});
});
};
|