-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheval.ml
70 lines (62 loc) · 1.95 KB
/
eval.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
open Ast
open Primitive
open Church
open Utils
let fv e =
let rec aux l = function
| Var x -> x :: l
| Abs (x, t) -> List.filter (fun a -> a <> x) (aux l t)
| App (a, b) | Seq (a, b) -> uniq ((aux l a) @ (aux l b))
| Affect (_, t) -> aux l t
| _ -> l
in aux [] e
;;
let rec substitution t x r =
match t with
| Var v when v = x -> r
| App (t1, t2) -> App (substitution t1 x r, substitution t2 x r)
| Abs (p, e) when p <> x && find p (fv r) = false -> Abs (p, substitution e x r)
| _ -> t
;;
let rec perform_beta_reduction env e =
match e with
| App (Abs(x, t), s) -> (substitution t x s) (* beta_reduction *)
| App (Var v, t) when has_key v env -> perform_beta_reduction env (App (get_val v env, t))
| App (v, Var t) when has_key t env -> perform_beta_reduction env (App (v, get_val t env))
| Abs (s, t) -> Abs (s, perform_beta_reduction env t)
| App (a, b) -> App (perform_beta_reduction env a, perform_beta_reduction env b)
| _ -> e
;;
let rec has_beta_redex env = function
| App (Var v, t) ->
if has_key v env then
has_beta_redex env (App (get_val v env, t))
else has_beta_redex env t
| App (Abs(_,_), _) -> true
| App (t1, t2) -> has_beta_redex env t1 || has_beta_redex env t2
| Abs (s, t) -> has_beta_redex env t
| _ -> false
;;
let rec print_expr env t =
match t with
| Var v ->
if has_key v env then
print_expr env (get_val v env)
else failwith ("Error variable " ^ v ^ "not found.")
| _ -> Printf.printf "%d\n" (church_to_num (eval_term env t))
and eval_term env e =
if has_beta_redex env e then
eval_term env (perform_beta_reduction env e)
else e
;;
let rec eval_expr env e =
match e with
| Affect (k, v) -> update env k v
| Seq (a, b) -> let env' = eval_expr env a in eval_expr env' b
| Print t -> print_expr env t; env
| _ -> env
;;
let _ =
let e = (Parser.prgm Lexer.lexer (Lexing.from_channel (open_in Sys.argv.(1))))
in (eval_expr primitive_env e)
;;