# Pruviloj.Core

Core tactics for working with Elab reflection. These will be used
by most reasonable scripts, and they may be candidates for
eventual Prelude inclusion.

unproduct : (tm : Raw) -> Elab ()

  Let-bind all results of completely destructuring nested tuples.

  This makes them available to the `hypothesis` tactic, among others.

  tm

    the nested tuple to destructure

try : Alternative f => f a -> f ()

  Attempt to apply a tactic. If it fails, do nothing.

skip : Applicative f => f ()

  Do nothing

simple : m () -> m ()

  Restrict a polymorphic type to () for contexts where it doesn't
  matter. This is nice for sticking `debug` in a context where
  Idris can't solve the type.

repeatUntilFail : Elab () -> Elab ()

  Repeat a given tactic until it fails. Fails if the tactic fails on
  the first attempt; succeeds otherwise.

remember : (n : TTName) -> (ty : Raw) -> Elab TTName

  Remember a term built with elaboration for later use. If the
  current goal is `h`, then `remember n ty` puts a fresh hole at
  the front of the queue, with the old goal `h` second. The
  contents of this hole end up let-bound in the scope of
  `h`. Return the name of the new hole, in case it will be used
  later.

  n

    the name to be used to save the term

  ty

    the type to inhabit

reflexivity : Elab ()

  A special-purpose tactic that attempts to solve a goal using
  `Refl`. This is useful for ensuring that goals in fact are trivial
  when developing or testing other tactics; otherwise, consider
  using `search`.

refine : (tm : Raw) -> Elab (List TTName)

  Refine the current goal using some term, constructing holes for
  all arguments that can't be inferred. Return the list of generated
  holes.

  tm

    the term to apply to some number of goals

newHole : (hint : String) -> (ty : Raw) -> Elab TTName

  Create a new hole with a given type without changing the
  focus. Return the name of the hole.

  hint

    the hint to pass to `gensym`

  ty

    the type of the new hole

nameFrom : TTName -> Elab TTName

  Generate a unique name (using `gensym`) that looks like some
  previous name, for ease of debugging code generators.

intros : Elab (List TTName)

  Introduce as many names as possible, returning them.

inferType : (tac : Elab ()) -> Elab (TT, TT)

  Run a tactic script in a context where the type of the resulting
  expression must be solvable via unification. Return the term and
  its type.

  tac

    a tactic script that will be run with focus on the hole
    whose type is to be inferred.

inHole : TTName -> Elab a -> Elab (Maybe a)

  Run a tactic inside of a particular hole, if it still exists. If
  it has been solved, do nothing.

ignore : Functor f => f a -> f ()

  Run something for effects, throwing away the return value

hypothesis : Elab ()

  Solve the goal using the most recent applicable hypothesis

headName : Raw -> Maybe TTName

  Get the name at the head of the term, if it exists.

goalType : Elab Raw

  Get the goal type as a Raw term. Fails if there are no holes.

forget' : List TTName -> TT -> Elab Raw

  Remove type information from a `TT` term, in a context. Fails if
  de Bruijn indices are out of scope.

forget : TT -> Elab Raw

  Remove type information from a `TT` term. Fails if de Bruijn
  indices are out of scope.

exact : (tm : Raw) -> Elab ()

  Use a term to solve a hole

  tm

    the term that has the right type for the hole

equiv : (newGoal : Raw) -> Elab TTName

  Replace the current goal with one that's definitionally
  equal. Return the name of the new goal, and ensure that it's
  focused.

  newGoal

    A type that is equivalent to the current goal

both : Raw -> TTName -> TTName -> Elab ()

  Split a pair into its projections, binding them in the context
  with the supplied names. A special case of Coq's `inversion`.

bindPat : Elab ()

  If the current goal is a pattern-bound variable, bind it with the
  expected name. Otherwise fail.

andThen : (first : Elab (List TTName)) -> (after : Elab a) -> Elab (List a)

  Given one tactic that produces a list of subgoal names and another
  that produces some result, run the second tactic in each hole
  produced by the first and return the resulting values.

  Elab has no built-in notion of "subgoals", so this simulates the
  Coq or JonPRL semicolon operators.

  first

    run this tactic to produce subgoals

  after

    run this tactic in each subgoal

data Infer : Type

  The underlying implementation type for the inferType operator.

  MkInfer : (a : Type) -> a -> Infer