-
Notifications
You must be signed in to change notification settings - Fork 0
/
lambda.ml
122 lines (107 loc) · 3.67 KB
/
lambda.ml
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(*** An extended example of a lambda calculus interpreter written in OCalf ***)
open Ast
open TypedAst
open Printer
(** apply f [e1; e2; e3] is App(App(App(f, e1), e2), e3) *)
let apply = List.fold_left (fun f e -> App (f,e))
let lambda_spec = {
vars = [];
name = "expr";
constructors = [
"Lambda", TStar (TString, TVariant ([], "expr"));
"App", TStar (TVariant ([], "expr"), TVariant ([], "expr"));
"Var", TString;
"Int", TInt;
];
}
let lambda_step_spec = {
vars = [];
name = "step_result";
constructors = [
"Value", TVariant ([], "expr");
"Stuck", TUnit;
"Progress", TVariant ([], "expr");
];
}
let lambda_subst_body =
Fun("e", Fun("v", Fun ("x", Match (Var "e", [
PVariant ("Lambda", PPair (PVar "y", PVar "e")),
If (BinOp (Eq, Var "x", Var "y"),
Variant ("Lambda", Pair (Var "y", Var "e")),
Variant ("Lambda", Pair (Var "y",
apply (Var "subst") [Var "e"; Var "v"; Var "x"])))
;
PVariant ("App", PPair (PVar "e1", PVar "e2")),
Variant ("App", Pair (apply (Var "subst") [Var "e1"; Var "v"; Var "x"],
apply (Var "subst") [Var "e2"; Var "v"; Var "x"]))
;
PVariant ("Var", PVar "y"),
If (BinOp (Eq, Var "x", Var "y"),
Var "v",
Variant ("Var", Var "y"))
;
PVariant ("Int", PVar "n"),
Variant ("Int", Var "n")
]))))
let lambda_subst = LetRec ("subst", lambda_subst_body, Var "subst")
let lambda_step_body = Fun("e", Match (Var "e", [
PVariant ("Lambda", PVar "_"), Variant ("Value", Var "e");
PVariant ("Int", PVar "_"), Variant ("Value", Var "e");
PVariant ("App", PPair (PVariant ("Lambda", PPair (PVar "x", PVar "e1")),
PVar "e2")),
Match (App (Var "step", Var "e2"), [
PVariant ("Value", PVar "v"),
Variant ("Progress", apply (Var "subst") [Var "e1"; Var "v"; Var "x"]);
PVariant ("Stuck", PUnit),
Variant ("Stuck", Unit);
PVariant ("Progress", PVar "e2'"),
Variant ("Progress", Variant ("App", Pair (Variant ("Lambda", Pair (Var "x", Var "e1")),
Var "e2'")));
]);
PVariant ("App", PPair (PVar "e1", PVar "e2")),
Match (App (Var "step", Var "e1"), [
PVariant ("Progress", PVar "e1'"),
Variant ("Progress", Variant ("App", Pair (Var "e1'", Var "e2")));
PVar "_",
Variant ("Stuck", Unit);
]);
PVar "_",
Variant ("Stuck", Unit);
];
))
let lambda_step =
LetRec ("subst", lambda_subst_body,
LetRec ("step", lambda_step_body,
Var "step"))
let lambda_run_body =
Fun ("e", Match (App (Var "step", Var "e"), [
PVariant ("Progress", PVar "e'"),
App (Var "run", Var "e'");
PVar "res",
Var "res";
]))
let lambda_run =
LetRec ("subst", lambda_subst_body,
LetRec ("step", lambda_step_body,
LetRec ("run", lambda_run_body,
Var "run")))
let lambda_expr =
Variant ("App", Pair (Variant ("App", Pair (
Variant ("Lambda", Pair (String "x",
Variant ("Lambda", Pair (String "y",
Variant ("Var", String "x"))))),
Variant ("Int", Int 0))), Variant ("Int", Int 1)))
let lambda_zero =
Variant ("Lambda", Pair (String "f", Variant ("App", Pair (Variant ("Var", String "x"), Variant ("Int", Int 0)))))
let lambda_succ =
Variant ("Lambda", Pair (String "n", Variant ("Lambda", Pair (String "f",
Variant ("App", Pair (Variant ("Var", String "f"),
Variant ("App", Pair (Variant ("Var", String "n"),
Variant ("Var", String "f")))))))))
let lambda_test =
LetRec ("subst", lambda_subst_body,
LetRec ("step", lambda_step_body,
LetRec ("run", lambda_run_body,
Let ("zero", lambda_zero,
Let ("succ", lambda_succ,
App (Var "run", lambda_expr))))))