Section Expressions.
Variables
(W : Type)
(G : pfunc W val -> Prop) (* Primitive expressions *).
Inductive unop := UNeg.
Inductive binop := BAdd.
Inductive expr : Type :=
| EVal : forall (v : val), expr
| EUnop : forall (op : unop) (e : expr), expr
| EBinop : forall (op : binop) (e1 e2 : expr), expr
| EPrim : forall (f : pfunc W val), expr.
Definition is_true (v : val) :=
exists n, (v = Vint n \/ v = Vptr n) /\ n <> O.
Definition unopDenote (op : unop) (v : val) : val :=
match op, is_true_dec v with
| UNeg, left _ => Vint 0
| UNeg, right _ => Vint 1
end.
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_dec : forall e, {pure_expr e} + {~ pure_expr e}.