-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
w.ts
47 lines (41 loc) · 1.22 KB
/
w.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
import { generalise, instantiate, makeSubstitution, newTypeVar, Substitution, unify } from "./helper";
import { Context, Expression, makeContext, MonoType } from "./models";
export const W = (typEnv: Context, expr: Expression): [Substitution, MonoType] => {
if (expr.type === "var") {
const value = typEnv[expr.x];
if (value === undefined) throw new Error(`Undefined variable: ${expr.x}`);
return [makeSubstitution({}), instantiate(value)]
}
if (expr.type === "abs") {
const beta = newTypeVar();
const [s1, t1] = W(makeContext({
...typEnv,
[expr.x]: beta,
}), expr.e)
return [s1, s1({
type: 'ty-app',
C: '->',
mus: [beta, t1]
})]
}
if (expr.type === "app") {
const [s1, t1] = W(typEnv, expr.e1)
const [s2, t2] = W(s1(typEnv), expr.e2)
const beta = newTypeVar()
const s3 = unify(s2(t1), {
type: 'ty-app',
C: '->',
mus: [t2, beta]
})
return [s3(s2(s1)), s3(beta)]
}
if (expr.type === "let") {
const [s1, t1] = W(typEnv, expr.e1)
const [s2, t2] = W(makeContext({
...s1(typEnv),
[expr.x]: generalise(typEnv, t1),
}), expr.e2)
return [s2(s1), t2]
}
throw new Error('Unknown expression type')
}