(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2023 --  Inria - CNRS - Paris-Saclay University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(*                                                                  *)
(********************************************************************)

(** {2 User-defined strategies} *)

(** A strategy is defined by a program declared under a simple
      assembly-like form: instructions are indexed by integers
      starting from 0 (the initial instruction counter). An
      instruction is either
      1) a call to a prover, with given time and mem limits
      . on success, the program execution ends
      . on any other result, the program execution continues on the next index
      2) a application of a transformation
      . on success, the execution continues to a explicitly given index
      . on failure, execution continues on the next index
      3) a goto instruction.

      the execution halts when reaching a non-existing state
  *)

type instruction =
  | Icall_prover of (Whyconf.prover * float option * int option * int option) list
    (** timelimit (if none use default timelimit),
        memlimit (if none use default memlimit)
        steplimit (if none use no step limit)
     *)
  | Itransform of string * int (** successor state on success *)
  | Igoto of int (** goto state *)

type t = instruction array




type strat =
  | Sdo_nothing
  (* Sapply_trans(trans, trans_args, strats) : execute the transformation with
     the specified args, then for each generated subgoals execute the
     corresponding strat in strats.
     The length of the strat list must match the length of the generated subgoal
     list. *)
  | Sapply_trans of string * string list * strat list
  (* Scont(trans, trans_args, strat_fn) : execute the transformation with
     the specified args, then for each generated subgoals generate a new strat
     by applying strat_fn to the task of the subgoal. The new strat is then
     executed of the subgoal.
     Note that unlike with Sapply_trans, you don't need to know in advance the
     number of subgoals generated by the transformation.
     *)
  | Scont of string * string list * (Env.env -> Task.task -> strat)
  (* Scall_prover((prover, timelimit, memlimit, steplimit) list, strat) :
     Try to prove the goal with the specified provers. If no value is given for
     the limits, the default one is used. If no prover proves the goal, then
     strat is applied on it. *)
  | Scall_prover of
      (Whyconf.prover * float option * int option * int option) list * strat


exception StratFailure of string * exn
exception UnknownStrat of string
exception KnownStrat of string

val register_strat : desc:Pp.formatted -> string -> (Env.env -> Task.task -> strat) -> unit

val lookup_strat  : string -> (Env.env -> Task.task -> strat)

val list_strats : unit -> (string * Pp.formatted) list
