Staging the interpreter for commands proceeds in a similar manner:
(* interpret2 : Com -> index -> <unit M> *)
fun interpret2 stmt index =
case stmt of
Assign(name,e) =>
let val loc = position name index
in <Do mswo { n <- ~(eval2 e index) ;
write ~(lift loc) n }>
end
| Seq(s1,s2) =>
<Do mswo { x <- ~(interpret2 s1 index);
y <- ~(interpret2 s2 index);
Return mswo () }>
| Cond(e,s1,s2) =>
<Do mswo
{ x <- ~(eval2 e index);
if x=1
then ~(interpret2 s1 index)
else ~(interpret2 s2 index)}>
| While(e,b) =>
<let fun loop () =
Do mswo
{ v <- ~(eval2 e index);
if v=0
then Return mswo ()
else Do mswo
{ q <- ~(interpret2 b index);
loop ()}
}
in loop () end>
| Declare(nm,e,stmt) =>
<Do mswo { x <- ~(eval2 e index) ;
push x ;
~(interpret2 stmt (nm::index)) ;
pop }>
| Print e =>
<Do mswo { x <- ~(eval2 e index) ;
output x }>;