From mininix Require Export res lambda.operational_props. From stdpp Require Import options. Module Import lambda. Export lambda. Inductive thunk := Thunk { thunk_env : gmap string thunk; thunk_expr : expr }. Add Printing Constructor thunk. Notation env := (gmap string thunk). Inductive val := | VString (s : string) | VClo (x : string) (E : env) (e : expr). Global Instance maybe_VClo : Maybe3 VClo := λ v, if v is VClo x E e then Some (x, E, e) else None. Definition interp1 (interp : env → expr → res val) (E : env) (e : expr) : res val := match e with | EString s => mret (VString s) | EId x => t ← Res (E !! x); interp (thunk_env t) (thunk_expr t) | EAbs x e => mret (VClo x E e) | EApp e1 e2 => v1 ← interp E e1; '(x, E', e') ← Res (maybe3 VClo v1); interp (<[x:=Thunk E e2]> E') e' end. Fixpoint interp (n : nat) (E : env) (e : expr) : res val := match n with | O => NoFuel | S n => interp1 (interp n) E e end. Global Opaque interp. End lambda. Add Printing Constructor lambda.thunk.