(* Generates a branch of the correctness proof for comparison functions
   generated by derive.eq.

   license: GNU Lesser General Public License Version 2.1 or later           
   ------------------------------------------------------------------------- *)
From elpi.apps.derive.elpi Extra Dependency "discriminate.elpi" as discriminate.
From elpi.apps.derive.elpi Extra Dependency "eqK.elpi" as eqK.
From elpi.apps.derive.elpi Extra Dependency "derive_hook.elpi" as derive_hook.
From elpi.apps.derive.elpi Extra Dependency "derive_synterp_hook.elpi" as derive_synterp_hook.

From elpi.core Require Import Bool.  (* remove when requiring Rocq >= 9.0 *)
From elpi Require Import elpi.
From elpi.apps Require Import derive.
From elpi.apps Require Import derive.bcongr derive.eq derive.isK.

Definition eq_axiom T eqb :=
  forall (x y : T), Datatypes.reflect (x = y) (eqb x y).

Definition eq_axiom_at T eqb (x : T) :=
  forall y, Datatypes.reflect (x = y) (eqb x y).

Definition eq_axiom_on T eqb (x y : T) :=
  Datatypes.reflect (x = y) (eqb x y).

Register eq_axiom    as elpi.derive.eq_axiom.
Register eq_axiom_at as elpi.derive.eq_axiom_at.
Register eq_axiom_on as elpi.derive.eq_axiom_on.

Lemma bool_discr : true = false -> forall T : Type, T.
Proof.
exact (fun h T =>
  eq_rect true (fun x => match x with false => T | _ => True end) I false h).
Qed.

Register bool_discr as elpi.bool_discr.

Elpi Db derive.eqK.db lp:{{

func eqK-db constructor -> term.

}}.
#[superglobal] Elpi Accumulate derive.eqK.db lp:{{

:name "eqK-db:fail"
eqK-db K _ :-
  M is "derive.eqK: can't find the eq.axiom for constructor " ^ {std.any->string K},
  stop M.

}}.

(* standalone *)
Elpi Command derive.eqK.
Elpi Accumulate File derive_hook.
Elpi Accumulate Db derive.isK.db.
Elpi Accumulate File discriminate.
Elpi Accumulate Db derive.bcongr.db.
Elpi Accumulate Db derive.eq.db.
Elpi Accumulate Db derive.eqK.db.
Elpi Accumulate File eqK.
Elpi Accumulate lp:{{
  main [str I, str Prefix] :- !, coq.locate I (indt GR), derive.eqK.main GR Prefix _.
  main [str I] :- !, coq.locate I (indt GR), derive.eqK.main GR "eq_axiom_" _.
  main _ :- usage.

  usage :- coq.error "Usage: derive.eqK <inductive type name> [<prefix>]".
}}.


(* hook into derive *)
Elpi Accumulate derive Db derive.eqK.db.
Elpi Accumulate derive File discriminate.
Elpi Accumulate derive File eqK.

#[phases="both"] Elpi Accumulate derive lp:{{
dep1 "eqK" "bcongr".
dep1 "eqK" "isK".
}}.

#[synterp] Elpi Accumulate derive lp:{{
  derivation _ _ (derive "eqK" (cl\ cl = []) true).
}}.

Elpi Accumulate derive lp:{{

derivation (indt T) Prefix ff (derive "eqK" (derive.eqK.main T N) (derive.exists-indc T (K\ eqK-db K _))) :- N is Prefix ^ "eq_axiom_".

}}.
