Instance RelDec_expr_beq : RelDec (@eq expr) :=
{ rel_dec := expr_beq }.Instance RelDec_Correct_expr_beq : RelDec_Correct RelDec_expr_beq.Fixpoint statement_beq s1 s2 :=
  match s1, s2 with
  | Sskip, Sskip
  | Sbreak, Sbreak
  | Scontinue, Scontinue => true
  | Sset id1 e1, Sset id2 e2 => andb (BinPos.Pos.eqb id1 id2) (expr_beq e1 e2)
  | Sassign e11 e21, Sassign e12 e22 =>  andb (expr_beq e11 e12) (expr_beq e21 e22)
  | Scall id1 e1 l1, Scall id2 e2 l2 => andb (andb (expr.eqb_option BinPos.Pos.eqb id1 id2) (expr_beq e1 e2)) (List.list_eqb _ l1 l2)
  | Sbuiltin _ _ _ _, Sbuiltin _ _ _ _ => false (*TODO*)
  | Ssequence st1 st2, Ssequence st3 st4
  | Sloop st1 st2, Sloop st3 st4 => andb (statement_beq st1 st3) (statement_beq st2 st4)
  | Sifthenelse e1 st1 st2, Sifthenelse e2 st3 st4 => andb (andb (statement_beq st1 st3) (statement_beq st2 st4)) (expr_beq e1 e2)
  | Sreturn e1, Sreturn e2 => expr.eqb_option expr_beq e1 e2
  | Slabel l1 s1, Slabel l2 s2 => andb (BinPos.Pos.eqb l1 l2) (statement_beq s1 s2)
  | Sgoto l1, Sgoto l2 => BinPos.Pos.eqb l1 l2
  | Sswitch e1 l1, Sswitch e2 l2 => andb (expr_beq e1 e2) (labeled_statements_beq l1 l2)
  | _ , _ => false
end
with labeled_statements_beq a b :=
match a, b with
| LSnil, LSnil => true
| LScons z1 s1 t1, LScons z2 s2 t2 => andb (andb (expr.eqb_option Zbool.Zeq_bool z1 z2) (statement_beq s1 s2)) (labeled_statements_beq t1 t2)
| _, _ => false
end.Ltac destruct_ands :=
repeat rewrite andb_true_iff in *;
repeat
match goal with
| [ H: _ /\ _ |- _] => destruct H
end.

Lemma eqb_option_sound : forall T f a b, (forall (x y : T), f x y = true -> x = y) -> expr.eqb_option f a b = true -> a = b.