Library MetaRocq.Utils.ByteCompareSpec

From Stdlib Require Import Strings.Byte NArith Eqdep_dec.
From MetaRocq.Utils Require Import ReflectEq ByteCompare.
From Equations Require Import Equations.

Derive NoConfusion for comparison.

Section ByteNoConf.
  Local Ltac solve_noconf ::= idtac.
The NoConfusion definition is quite large, so we define a much more compact version of it that is nevertheless convertible
  Definition eta_byte {A} (f : b : byte, A b) (b : byte) : A b
    := Eval cbv in
      ltac:(pose (f b) as v; destruct b; let val := (eval cbv in v) in exact val).
  Definition uneta_byte {A f b} : @eta_byte A f b = f b
    := match b with x00 | _eq_refl end.
  Definition NoConfusion_byte_alt : byte byte Prop
    := eta_byte ( b1 b2eta_byte ( b2if Byte.eqb then True else False) ).
  Derive NoConfusion for byte.
  Next Obligation.
    change (NoConfusion_byte a b) with (NoConfusion_byte_alt a b) in ×.
    cbv [NoConfusion_byte_alt] in *; apply byte_dec_bl.
    rewrite !uneta_byte in ×.
    destruct Byte.eqb; [ reflexivity | exfalso; assumption ].
  Qed.
  Next Obligation.
    destruct b; cbn; exact I.
  Defined.
  Next Obligation.
    lazymatch goal with |- ?f _ _ ?g = ?egeneralize g; revert e end; intros e g; subst; revert e.
    destruct b; vm_compute; intros []; reflexivity.
  Qed.
  Next Obligation.
    apply UIP_dec, byte_eq_dec.
  Qed.
End ByteNoConf.

Lemma reflect_equiv P Q b : P Q Bool.reflect P b Bool.reflect Q b.
Proof.
  intros eq r. destruct r.
  - now constructor; apply eq.
  - constructor. now rewrite eq.
Qed.


From MetaRocq Require Import MRCompare.

Definition lt x y := compare x y = Lt.

Lemma compare_equiv x y : compare x y = N.compare (Byte.to_N x) (Byte.to_N y).
Proof.
  reflexivity.
Qed.

(*
Proof.
  destruct x; abstract (destruct y; exact eq_refl).
Qed. *)


Lemma compare_opp x y : compare x y = CompOpp (compare y x).
Proof.
  rewrite !compare_equiv.
  apply N.compare_antisym.
Qed.


Lemma compare_eq x y : compare x y = Eq x = y.
Proof.
  rewrite compare_equiv.
  intros Hcomp.
  eapply N.compare_eq in Hcomp.
  eapply (f_equal of_N) in Hcomp.
  rewrite !of_to_N in Hcomp. now noconf Hcomp.
Qed.


Lemma compare_spec x y : CompareSpec (x = y) (lt x y) (lt y x) (compare x y).
Proof.
  destruct (compare x y) eqn:comp.
  - constructor. now apply compare_eq in comp.
  - constructor. exact comp.
  - constructor. red. now rewrite compare_opp, comp.
Qed.


From Stdlib Require Import Lia.

Lemma lt_trans x y z : lt x y lt y z lt x z.
Proof.
  unfold lt.
  rewrite !compare_equiv.
  rewrite !N.compare_lt_iff. .
Qed.


Lemma lt_not_eq x y : lt x y x y.
Proof.
  unfold lt.
  rewrite !compare_equiv.
  rewrite !N.compare_lt_iff. intros Hlt Heq. subst. .
Qed.


Lemma compare_eq_refl x : compare x x = Eq.
Proof.
  rewrite compare_equiv.
  eapply N.compare_refl.
Qed.


Definition eqb_compare x y : eqb x y = match compare x y with Eqtrue | _false end.
Proof.
  unfold eqb.
  apply N.eqb_compare.
  (* destruct x; cbn; abstract (destruct y; cbn; exact eq_refl). *)
Qed.


Global Program Instance byte_reflect_eq : ReflectEq byte :=
  {| ReflectEq.eqb := eqb |}.
Next Obligation.
  rewrite eqb_compare.
  destruct (compare_spec x y); constructor; auto.
  all:apply lt_not_eq in H.
  - assumption.
  - now apply not_eq_sym.
Qed.