From elpi Require Import elpi.
From Corelib Require Import PrimInt63 PrimFloat.
From elpi.apps.derive Require Import PrimStringEqb.
From elpi.apps Require Export derive.

From elpi.apps.derive.elpi Extra Dependency "eqType.elpi" as eqType.
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.

Elpi Db derive.eqType.db lp:{{

kind eqb.arguments type.
kind eqb.trm type.
kind eqb.eqType type.
kind eqb.constructor type.

type eqb.app    gref -> eqb.trm -> list eqb.trm -> eqb.trm.
type eqb.global gref -> eqb.trm.

type eqb.regular    eqb.trm -> eqb.arguments -> eqb.arguments.
type eqb.irrelevant eqb.trm -> eqb.arguments -> eqb.arguments.
type eqb.dependent  eqb.trm -> (eqb.trm -> eqb.arguments) -> eqb.arguments.
type eqb.stop       eqb.trm -> eqb.arguments.

type eqb.type-param  (eqb.trm -> eqb.eqType) -> eqb.eqType.
type eqb.value-param eqb.trm -> (eqb.trm -> eqb.eqType) -> eqb.eqType.
type eqb.inductive   inductive -> (eqb.trm -> list eqb.constructor) -> eqb.eqType.
type eqb.axiom       eqb.eqType.

type eqb.constructor constructor -> eqb.arguments -> eqb.constructor.

pred eqType i:gref, o:eqb.eqType.
eqType {{:gref PrimInt63.int }} eqb.axiom :- !.
eqType {{:gref lib:elpi.pstring }} eqb.axiom :- !.

}}.

Definition arrow T1 T2 := T1 -> T2.
Register arrow as elpi.derive.arrow.
Definition apply {T1 T2} (f : T1 -> T2) x := f x.
Register apply as elpi.derive.apply.

(* standalone *)
Elpi Command derive.eqType.ast.
Elpi Accumulate File derive_hook.
Elpi Accumulate Db derive.eqType.db.
Elpi Accumulate File eqType.
Elpi Accumulate lp:{{

main [str S] :-
  std.assert! (coq.locate S (indt I)) "derive.eqType.ast: not an inductive",
  derive.eqType.ast.main I _.

}}.


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

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

Elpi Accumulate derive lp:{{
  
derivation (indt T) _ ff (derive "eqType_ast" (derive.eqType.ast.main T) (eqType (indt T) _)).

}}.
