Fixpoint ptree_cmp {T : Type} (p1 p2: Maps.PTree.tree T)
(e : T -> T -> bool) :=
match p1, p2 with
| Maps.PTree.Leaf, Maps.PTree.Leaf => true
| Maps.PTree.Node l1 i1 r1, Maps.PTree.Node l2 i2 r2 =>
match i1, i2 with
| Some v1, Some v2 => andb (e v1 v2)
(andb (ptree_cmp l1 l2 e)
(ptree_cmp r1 r2 e))
| None, None => (andb (ptree_cmp l1 l2 e)
(ptree_cmp r1 r2 e))
| _, _ => false
end
| _, _ => false
end.
Definition const_beq a b :=
match a, b with
| fN c1, fN c2 => beq_nat c1 c2
| fZ c1, fZ c2 => Zbool.Zeq_bool c1 c2
| fPos c1, fPos c2 =>  BinPos.Pos.eqb c1 c2
| fCtype c1, fCtype c2 => expr.eqb_type c1 c2
| fCexpr c1, fCexpr c2 => expr_beq c1 c2
| fenv c1, fenv c2 => ptree_cmp c1 c2 expr.eqb_type
| fllrr c1, fllrr c2 => match c1, c2 with | efield_lemmas.LLLL, efield_lemmas.LLLL | efield_lemmas.RRRR, efield_lemmas.RRRR => true | _, _ => false end
| _, _ => false
end.
Instance const_rel_dec : RelDec (@eq const) := { rel_dec := const_beq }.
Definition beq_z_true : forall a b, Zbool.Zeq_bool a b = true -> a = b.
Hint Resolve beq_nat_true : expr_beq.
Hint Resolve beq_z_true : expr_beq.
Hint Resolve const_beq_sound : expr_beq.
Definition z_op_beq a b : bool :=
match a, b with
| fZ_lt, fZ_lt
| fZ_le, fZ_le
| fZ_gt, fZ_gt
| fZ_ge, fZ_ge
| fZ_add, fZ_add
| fZ_sub, fZ_sub
| fZ_mul, fZ_mul
| fZ_div, fZ_div
| fZ_mod, fZ_mod
| fZ_land, fZ_land
| fZ_max, fZ_max
| fZ_opp, fZ_opp  => true
| _, _ => false
end.
Hint Resolve beq_nat_true : expr_beq.
Hint Resolve z_op_beq_sound : expr_beq.
Definition int_op_beq a b : bool :=
match a, b with
| fint_add, fint_add
| fint_and, fint_and
| fint_lt, fint_lt
| fint_ltu, fint_ltu
| fint_mul, fint_mul
| fint_neg, fint_neg
| fint_sub, fint_sub
| fint_cmp, fint_cmp
| fint_cmpu, fint_cmpu
| fint_repr, fint_repr
| fint_signed, fint_signed
| fint_unsigned, fint_unsigned
| fint_max_unsigned, fint_max_unsigned
| fint64_repr, fint64_repr => true
| _, _ => false
end.
Hint Resolve int_op_beq_sound : expr_beq.
Definition values_beq a b:=
match a, b with
| fVint, fVint
| fVfloat, fVfloat
| fVlong, fVlong
| fVptr, fVptr
| fVundef, fVundef => true
| _, _ => false
end.
Hint Resolve values_beq_sound : expr_beq.
Definition eval_beq a b :=
match a,b with
| feval_cast t1_1 t2_1 , feval_cast t1_2 t2_2 => andb (expr.eqb_type t1_1 t1_2)
(expr.eqb_type t2_1 t2_2)
| fderef_noload t1, fderef_noload t2 => expr.eqb_type t1 t2
| feval_field t1 id1 , feval_field t2 id2 =>  andb (expr.eqb_type t1 t2)
(BinPos.Pos.eqb id1 id2)
| feval_binop op1 t1_1 t2_1, feval_binop op2 t1_2 t2_2 =>
andb (andb (binary_op_beq op1 op2)
(expr.eqb_type t1_1 t1_2))
(expr.eqb_type t2_1 t2_2)
| feval_unop op1 t1 , feval_unop op2 t2 =>
andb (unary_op_beq op1 op2)
(expr.eqb_type t1 t2)
| feval_id id1, feval_id id2 => BinPos.Pos.eqb id1 id2
| _, _ => false
end.

Lemma eval_beq_sound : forall a b, eval_beq a b = true -> a = b.