Definition binopDenote (op : binop) (v1 v2 : val) :=
match op, v1, v2 with
| BAdd, (Vint n), (Vint m) => Vint (n+m)%nat
| BAdd, (Vptr p), (Vint n) => Vptr (p+n)%nat
| _, _, _ => Vundef
end.
Fixpoint expr_wellformed (e : expr) : Prop :=
match e with
| EVal _ => True
| EUnop _ e => expr_wellformed e
| EBinop _ e1 e2 => expr_wellformed e1 /\ expr_wellformed e2
| EPrim f => G f
end.
Fixpoint exprEval' (e : expr) : W -> option val := fun w =>
match e with
| EVal v => Some v
| EUnop op e' =>
let v := exprEval' e' w in
match v with
| Some v' => Some (unopDenote op v')
| None => None
end
| EBinop op e1 e2 =>
let v1 := exprEval' e1 w in
let v2 := exprEval' e2 w in
match v1, v2 with
| Some v1', Some v2' => Some (binopDenote op v1' v2')
| _, _ => None
end
| EPrim f => f w
end.
Definition exprEval (e : expr) (w : W) (v : val) :=
expr_wellformed e /\ exprEval' e w = Some v.
Fixpoint pure_expr (e : expr) :=
match e with
| EVal v => True
| EUnop op e' => pure_expr e'
| EBinop op e1 e2 => pure_expr e1 /\ pure_expr e2
| EPrim _ => False
end.

Lemma pure_expr_safe : forall e w,
pure_expr e
-> exists b, exprEval e w b.