1 (* Original calculator from Week7, enhanced with Booleans and Immutable Pairs *)
3         type term =
4       Intconstant of int
5     | Multiplication of (term * term)
6     | Addition of (term * term)
7     | Variable of char
8     | Let of (char * term * term)
9     | Iszero of term
10     | If of (term * term * term)
11     | Makepair of (term * term)
12     | First of term
13     ;;
15         type expressed_value = Int of int | Bool of bool | Pair of expressed_value * expressed_value;;
16         type bound_value = expressed_value;;
17         type assignment = (char * bound_value) list;;
19         let rec eval (t : term) (g : assignment) = match t with
20           Intconstant x -> Int x
21         | Multiplication (t1, t2) ->
22                 (* we don't handle cases where the subterms don't evaluate to Ints *)
23                 let Int i1 = eval t1 g
24                 in let Int i2 = eval t2 g
25                 (* Multiplication (t1, t2) should evaluate to an Int *)
26                 in Int (i1 * i2)
27         | Addition (t1, t2) ->
28                 let Int i1 = eval t1 g
29                 in let Int i2 = eval t2 g
30                 in Int (i1 + i2)
31         | Variable (var) ->
32                 (* we don't handle cases where g doesn't bind var to any value *)
33                 List.assoc var g
34         | Let (var_to_bind, t2, t3) ->
35                 (* evaluate t3 under a new assignment where var_to_bind has been bound to
36                    the result of evaluating t2 under the current assignment *)
37                 let value2 = eval t2 g
38                 in let g' = (var_to_bind, value2) :: g
39                 in eval t3 g'
40         | Iszero (t1) ->
41                 (* we don't handle cases where t1 doesn't evaluate to an Int *)
42                 let Int i1 = eval t1 g
43                 (* Iszero t1 should evaluate to a Bool *)
44                 in Bool (i1 = 0)
45         | If (t1, t2, t3) ->
46                 (* we don't handle cases where t1 doesn't evaluate to a boolean *)
47                 let Bool b1 = eval t1 g
48                 in if b1 then eval t2 g
49                 else eval t3 g
50         | Makepair (t1, t2) ->
51                 let value1 = eval t1 g
52                 in let value2 = eval t2 g
53                 in Pair (value1, value2)
54         | First (t1) ->
55                 (* we don't handle cases where t1 doesn't evaluate to a Pair *)
56                 let Pair (value1, value2) = eval t1 g
57                 in value1
58     ;;