type exp = Int of int | Add of exp * exp | Var of string let example_exp = Add (Int 3, Add (Var "x", Int 4)) type env = (string * int) list type 'a Effect.t += Unbound : string -> int Effect.t let rec eval : env -> exp -> int = fun env exp -> match exp with | Int n -> n | Add (l,r) -> eval env l + eval env r | Var x -> match List.assoc_opt x env with | Some v -> v | None -> Effect.perform (Unbound x) let eval_fail : env -> exp -> int option = fun env exp -> try Some (eval env exp) with effect Unbound x, k -> None let eval_default : env -> exp -> int = fun env exp -> try eval env exp with effect Unbound x, k -> Effect.Deep.continue k 0 let eval_prompt : env -> exp -> int = fun env exp -> try eval env exp with effect Unbound x, k -> let v = (Printf.printf "Enter a value for %s\n" x; read_int ()) in Effect.Deep.continue k v let saved : (int, int option) continuation option ref = ref None let eval_save : env -> exp -> int option = fun env exp -> try Some (eval env exp) with effect Unbound x, k -> saved := Some k; None