(* Baseline: untyped lambda calculus with closures over a Hashtbl env *) type term = | Var of string | Abs of string * term | App of term * term | Num of int ;; type value = | VNum of int | VClos of string * term * (string * value) list ;; let rec lookup name env = match env with | [] -> failwith "unbound" | (n, v) :: t -> if n = name then v else lookup name t ;; let rec eval env t = match t with | Num n -> VNum n | Var x -> lookup x env | Abs (x, body) -> VClos (x, body, env) | App (f, a) -> let fv = eval env f in let av = eval env a in (match fv with | VClos (param, body, captured) -> eval ((param, av) :: captured) body | _ -> failwith "not a function") ;; let unwrap v = match v with VNum n -> n | _ -> failwith "not a number" ;; (* (\x. \y. x) 7 99 = 7 *) let term = App (App (Abs ("x", Abs ("y", Var "x")), Num 7), Num 99) ;; unwrap (eval [] term)