-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.ts
104 lines (95 loc) · 2.57 KB
/
utils.ts
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
100
101
102
103
104
import { typeCheck } from "./typechecker.ts";
import { evaluate } from "./interpreter.ts";
export type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T extends
Record<K, V> ? T : never;
export function assertNever(x: never): never {
throw new Error();
}
export function prettyPrint(obj: any) {
function removeInfo(arg: any): any {
if (!arg) {
return arg;
}
if (Array.isArray(arg)) {
return arg.map((el) => removeInfo(el));
}
if ("info" in arg) {
const { info, ...result } = arg;
if (Object.keys(result).length === 1) {
return removeInfo(result[Object.keys(result)[0]]);
}
return removeInfo(result);
}
const result: any = {};
for (const [k, v] of Object.entries(arg)) {
if (typeof v === "object") {
result[k] = removeInfo(v);
} else {
result[k] = v;
}
}
return result;
}
return JSON.stringify(removeInfo(obj), null, 2);
}
// export const genUniqTypeVar = Symbol;
// For debugging...easier to console log than symbols
let i = 0;
export const genUniqTypeVar = (): symbol => {
i++;
return `?X_${i}` as any;
};
export function printValue(v: ReturnType<typeof evaluate>): string {
switch (v.tag) {
case "TmBool":
return v.val ? `#t` : `#f`;
case "TmInt":
return `${v.val}`;
case "TmStr":
return `"${v.val}"`;
case "TmClosure":
return `[CLOSURE]`; // TODO ?
case "TmStdlibFun":
return `[STD_LIB]`; // TODO ?
default:
return assertNever(v);
}
}
export function printType(t: ReturnType<typeof typeCheck>) {
// produces stream of identifiers like
// 'a 'b 'c ... 'z 'aa 'ab 'ac ... 'az 'ba 'bb 'bc ... 'bz 'ca 'cb 'cc ...
const nextFreeGenerator = () => {
let i = 0;
return () => {
let n = i;
let result = "'";
while (n >= 26) {
const multiple = Math.floor(n / 26);
result += String.fromCharCode(97 + multiple - 1);
n -= (26 * multiple);
}
result += String.fromCharCode(97 + (n % 26));
i += 1;
return result;
};
};
const nextFree = nextFreeGenerator();
const symbolToPrettyType: Map<unknown, string> = new Map();
function helper(t: ReturnType<typeof typeCheck>): string {
switch (t.tag) {
case "TyBool":
return "bool";
case "TyInt":
return "int";
case "TyStr":
return "str";
case "TyArrow":
return `(-> ${(t.paramTypes.map((p) => helper(p))).join(" ")} ${
helper(t.returnType)
})`;
default:
return assertNever(t);
}
}
return helper(t);
}