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     ;;