> \[[expression]]<sub>g s</sub> = (value, s')
-For expressions we already know how to interpret, `s'` will usually just be `s`. One exception is complex expressions like `let var = expr1 in expr2`. Part of interpreting this will be to interpret the sub-expression `expr1`, and we have to allow that in doing that, the store may have already been updated. We want to use that possibly updated store when interpreting `expr2`. Like this:
+For expressions we already know how to interpret, expect `s'` to just be `s`.
+An exception is complex expressions like `let var = expr1 in expr2`. Part of
+interpreting this will be to interpret the sub-expression `expr1`, and we have
+to allow that in doing that, the store may have already been updated. We want
+to use that possibly updated store when interpreting `expr2`. Like this:
let rec eval expression g s =
match expression with
eval expr2 ((c, value) :: g) s'
...
+Similarly:
+
+ ...
+ | Addition (expr1, expr2) ->
+ let (value1, s') = eval expr1 g s
+ in let (value2, s'') = eval expr2 g s'
+ in (value1 + value2, s'')
+ ...
+
Let's consider how to interpet our new syntactic forms `newref`, `deref`, and `setref`:
in (Index new_index, s'')
...
-2. When `expr` evaluates to a `store_index`, then `deref expr` should evaluate to whatever value is at that index in the current store. (If `expr` evaluates to a value of another type, `deref expr` is undefined.) In this operation, we don't change the store at all; we're just reading from it. So we'll return the same store back unchanged.
+2. When `expr` evaluates to a `store_index`, then `deref expr` should evaluate to whatever value is at that index in the current store. (If `expr` evaluates to a value of another type, `deref expr` is undefined.) In this operation, we don't change the store at all; we're just reading from it. So we'll return the same store back unchanged (assuming it wasn't changed during the evaluation of `expr`).
let rec eval expression g s =
match expression with
...
| Setref (expr1, expr2) ->
let (Index n, s') = eval expr1 g s
- (* note that s' may be different from s, if expr itself contained any mutation operations *)
+ (* note that s' may be different from s, if expr1 itself contained any mutation operations *)
in let (new_value, s'') = eval expr2 g s'
(* now we create a list which is just like s'' except it has new_value in index n *)
in let rec replace_nth lst m =
To handle implicit-style mutation, we'll need to re-implement the way we interpret expressions like `x` and `let x = expr1 in expr2`. We will also have just one new syntactic form, `change x to expr1 then expr2`.
-Here's how to implement these. We'll suppose that our assignment function is list of pairs, as in [week7](/reader_monad_for_variable_binding).
+Here's how to implement these. We'll suppose that our assignment function is list of pairs, as above and as in [week7](/reader_monad_for_variable_binding).
let rec eval expression g s =
match expression with