let rec eval (t : term) (g : assignment) (s : store) = match t with
Intconstant x -> (Int x, s)
...
- | Variable (var) -> (
+ | Variable (var) -> ((
(* we don't handle cases where g doesn't bind var to any value *)
match List.assoc var g with
| Nonrecursive value -> value
(* we update savedg to bind self_var to rec_closure here *)
let savedg' = (self_var, rec_closure) :: savedg
in Closure (arg_var, body, savedg')
- ), s
+ ), s)
...
| Lambda (arg_var, t2) -> (Closure (arg_var, t2, g), s)
...
...
| Newref (t1) ->
- let (starting_val, s') = eval t1 g s
+ let (value1, s') = eval t1 g s
(* note that s' may be different from s, if t1 itself contained any mutation operations *)
(* now we want to retrieve the next free index in s' *)
in let new_index = List.length s'
- (* now we want to insert starting_val there; the following is an easy but inefficient way to do it *)
- in let s'' = List.append s' [starting_val]
+ (* now we want to insert value1 there; the following is an easy but inefficient way to do it *)
+ in let s'' = List.append s' [value1]
(* now we return a pair of a wrapped new_index, and the new store *)
in (Mutcell new_index, s'')
| Deref (t1) ->
(* we don't handle cases where t1 doesn't evaluate to a Mutcell *)
let (Mutcell index1, s') = eval t1 g s
(* note that s' may be different from s, if t1 itself contained any mutation operations *)
- in let (new_value, s'') = eval t2 g s'
- (* now we create a list which is just like s'' except it has new_value in index1 *)
+ in let (value2, s'') = eval t2 g s'
+ (* now we create a list which is just like s'' except it has value2 in index1 *)
in let rec replace_nth lst m =
match lst with
| [] -> failwith "list too short"
- | x::xs when m = 0 -> new_value :: xs
+ | x::xs when m = 0 -> value2 :: xs
| x::xs -> x :: replace_nth xs (m - 1)
in let s''' = replace_nth s'' index1
(* we'll arbitrarily return Int 42 as the expressed_value of a Setref operation *)
(* we don't handle cases where t1 doesn't evaluate to a Pair *)
let (Pair (index1, index2), s') = eval t1 g s
(* note that s' may be different from s, if t1 itself contained any mutation operations *)
- in let (new_value, s'') = eval t2 g s'
- (* now we create a list which is just like s'' except it has new_value in index1 *)
+ in let (value2, s'') = eval t2 g s'
+ (* now we create a list which is just like s'' except it has value2 in index1 *)
in let rec replace_nth lst m =
match lst with
| [] -> failwith "list too short"
- | x::xs when m = 0 -> new_value :: xs
+ | x::xs when m = 0 -> value2 :: xs
| x::xs -> x :: replace_nth xs (m - 1)
in let s''' = replace_nth s'' index1
in (Int 42, s''')
type store = expressed_value list;;
-Our evaluation function still interacts with a `store` argument in much the same way it did with explicit-style mutation. The clause for `Variable ...` works differently, because all `expressed_value`s now need to be retrieved from the `store`:
+Our evaluation function still interacts with a `store` argument in much the same way it did with explicit-style mutation. The clause for `Variable (...)` works differently, because all `expressed_value`s now need to be retrieved from the `store`:
let rec eval (t : term) (g : assignment) (s : store) = match t with
...
in eval t3 g s''
;;
-Note that because the `savedg` component of a `Closure` keeps track of which `index`es in the store free variables were bound to, the values at those `index`es can later be changed, and later applications of the `Closure` will use the changed values.
+Note that because the `savedg` component of a `Closure` keeps track of which `index`es in the store---rather than which values---free variables were bound to, the values at those `index`es can later be changed, and later applications of the `Closure` will use the changed values.
The complete code is available [here](/code/calculator/calc6.ml).