Notation "'exists' x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 ',' P" :=
  (exists x1, exists x2, exists x3, exists x4, exists x5, exists x6,
   exists x7, exists x8, exists x9, exists x10, P)
  (at level 200, x1 ident, x2 ident, x3 ident, x4 ident, x5 ident,
   x6 ident, x7 ident, x8 ident, x9 ident, x10 ident,
   right associativity) : type_scope.(* ********************************************************************** *)
(** * Tools for programming with Ltac *)

(* ---------------------------------------------------------------------- *)
(** ** Identity continuation *)

Ltac idcont tt :=
  idtac.(* ---------------------------------------------------------------------- *)
(** ** Untyped arguments for tactics *)

(** Any Coq value can be boxed into the type [Boxer]. This is
    useful to use Coq computations for implementing tactics. *)

Inductive Boxer : Type :=
  | boxer : forall (A:Type), A -> Boxer.(* ---------------------------------------------------------------------- *)
(** ** Untyped arguments for tactics *)

(** Any Coq value can be boxed into the type [Boxer]. This is
    useful to use Coq computations for implementing tactics. *)

Inductive Boxer : Type :=
  | boxer : forall (A:Type), A -> Boxer.(* ---------------------------------------------------------------------- *)
(** ** Optional arguments for tactics  *)

(** [ltac_no_arg] is a constant that can be used to simulate
    optional arguments in tactic definitions.
    Use [mytactic ltac_no_arg] on the tactic invokation,
    and use [match arg with ltac_no_arg => ..] or
    [match type of arg with ltac_No_arg  => ..] to
    test whether an argument was provided. *)

Inductive ltac_No_arg : Set :=
  | ltac_no_arg : ltac_No_arg.(* ---------------------------------------------------------------------- *)
(** ** Optional arguments for tactics  *)

(** [ltac_no_arg] is a constant that can be used to simulate
    optional arguments in tactic definitions.
    Use [mytactic ltac_no_arg] on the tactic invokation,
    and use [match arg with ltac_no_arg => ..] or
    [match type of arg with ltac_No_arg  => ..] to
    test whether an argument was provided. *)

Inductive ltac_No_arg : Set :=
  | ltac_no_arg : ltac_No_arg.(* ---------------------------------------------------------------------- *)
(** ** Wildcard arguments for tactics  *)

(** [ltac_wild] is a constant that can be used to simulate
    wildcard arguments in tactic definitions. Notation is [__]. *)

Inductive ltac_Wild : Set :=
  | ltac_wild : ltac_Wild.(* ---------------------------------------------------------------------- *)
(** ** Wildcard arguments for tactics  *)

(** [ltac_wild] is a constant that can be used to simulate
    wildcard arguments in tactic definitions. Notation is [__]. *)

Inductive ltac_Wild : Set :=
  | ltac_wild : ltac_Wild.Notation "'>>' v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13" :=
  ((boxer v1)::(boxer v2)::(boxer v3)::(boxer v4)::(boxer v5)
   ::(boxer v6)::(boxer v7)::(boxer v8)::(boxer v9)::(boxer v10)
   ::(boxer v11)::(boxer v12)::(boxer v13)::nil)
  (at level 0, v1 at level 0, v2 at level 0, v3 at level 0,
   v4 at level 0, v5 at level 0, v6 at level 0, v7 at level 0,
   v8 at level 0, v9 at level 0, v10 at level 0, v11 at level 0,
   v12 at level 0, v13 at level 0)
  : ltac_scope.(** [ltac_wilds] is another constant that is typically used to
    simulate a sequence of [N] wildcards, with [N] chosen
    appropriately depending on the context. Notation is [___]. *)

Inductive ltac_Wilds : Set :=
  | ltac_wilds : ltac_Wilds.(** [ltac_wilds] is another constant that is typically used to
    simulate a sequence of [N] wildcards, with [N] chosen
    appropriately depending on the context. Notation is [___]. *)

Inductive ltac_Wilds : Set :=
  | ltac_wilds : ltac_Wilds.(* ---------------------------------------------------------------------- *)
(** ** Position markers *)

(** [ltac_Mark] and [ltac_mark] are dummy definitions used as sentinel
    by tactics, to mark a certain position in the context or in the goal. *)

Inductive ltac_Mark : Type :=
  | ltac_mark : ltac_Mark.(* ---------------------------------------------------------------------- *)
(** ** Position markers *)

(** [ltac_Mark] and [ltac_mark] are dummy definitions used as sentinel
    by tactics, to mark a certain position in the context or in the goal. *)

Inductive ltac_Mark : Type :=
  | ltac_mark : ltac_Mark.(** [gen_until_mark] repeats [generalize] on hypotheses from the
    context, starting from the bottom and stopping as soon as reaching
    an hypothesis of type [Mark]. If fails if [Mark] does not
    appear in the context. *)

Ltac gen_until_mark :=
  match goal with H: ?T |- _ =>
  match T with
  | ltac_Mark => clear H
  | _ => generalize H; clear H; gen_until_mark
  end end.(** [intro_until_mark] repeats [intro] until reaching an hypothesis of
    type [Mark]. It throws away the hypothesis [Mark].
    It fails if [Mark] does not appear as an hypothesis in the
    goal. *)

Ltac intro_until_mark :=
  match goal with
  | |- (ltac_Mark -> _) => intros _
  | _ => intro; intro_until_mark
  end.(** The tactic [list_boxer_of] inputs a term [E] and returns a term
    of type "list boxer", according to the following rules:
    - if [E] is already of type "list Boxer", then it returns [E];
    - otherwise, it returns the list [(boxer E)::nil]. *)

Ltac list_boxer_of E :=
  match type of E with
  | List.list Boxer => constr:(E)
  | _ => constr:((boxer E)::nil)
  end.(* ---------------------------------------------------------------------- *)
(** ** Databases of lemmas  *)

(** Use the hint facility to implement a database mapping
    terms to terms. To declare a new database, use a definition:
    [Definition mydatabase := True.]

    Then, to map [mykey] to [myvalue], write the hint:
    [Hint Extern 1 (Register mydatabase mykey) => Provide myvalue.]

    Finally, to query the value associated with a key, run the
    tactic [ltac_database_get mydatabase mykey]. This will leave
    at the head of the goal the term [myvalue]. It can then be
    named and exploited using [intro]. *)

Definition ltac_database (D:Boxer) (T:Boxer) (A:Boxer) := True.Notation "'Something'" :=
  (@ltac_something _ _).

Lemma ltac_database_provide : forall (A:Boxer) (D:Boxer) (T:Boxer), ltac_database D T A.