aboutsummaryrefslogtreecommitdiff
path: root/proofs
diff options
context:
space:
mode:
Diffstat (limited to 'proofs')
-rw-r--r--proofs/monads.ml496
-rw-r--r--proofs/proof_errors.ml12
-rw-r--r--proofs/proof_errors.mli18
-rw-r--r--proofs/proofs.mllib4
-rw-r--r--proofs/proofview.ml196
-rw-r--r--proofs/proofview.mli7
-rw-r--r--proofs/proofview_gen.ml377
-rw-r--r--proofs/proofview_monad.ml1
-rw-r--r--proofs/proofview_monad.mli81
9 files changed, 600 insertions, 592 deletions
diff --git a/proofs/monads.ml b/proofs/monads.ml
deleted file mode 100644
index 803715a450..0000000000
--- a/proofs/monads.ml
+++ /dev/null
@@ -1,496 +0,0 @@
-module type Type = sig
- type t
-end
-
-module type S = sig
- type +'a t
-
- val return : 'a -> 'a t
- val bind : 'a t -> ('a -> 'b t) -> 'b t
- val seq : unit t -> 'a t -> 'a t
- val ignore : 'a t -> unit t
-(* spiwack: these will suffice for now, if we would use monads more
- globally, then I would add map/join/List.map and such functions,
- plus default implementations *)
-end
-
-module type State = sig
- type s (* type of the state *)
- include S
-
- val set : s -> unit t
- val get : s t
-end
-
-module type Writer = sig
- type m (* type of the messages *)
- include S
-
- val put : m -> unit t
-end
-
-module type IO = sig
- include S
-
- type 'a ref
-
- val ref : 'a -> 'a ref t
- val (:=) : 'a ref -> 'a -> unit t
- val (!) : 'a ref -> 'a t
-
- val raise : exn -> 'a t
- val catch : 'a t -> (exn -> 'a t) -> 'a t
-
- (** In the basic IO monad, [timeout n x] acts as [x] unless it runs for more than [n]
- seconds in which case it raises [IO.Timeout]. *)
- val timeout : int -> 'a t -> 'a t
-end
-
-module IO : sig
- include IO
-
- (** To help distinguish between exceptions raised by the [IO] monad
- from the one used natively by Coq, the former are wrapped in
- [Exception]. *)
- exception Exception of exn
- (** This exception is used to signal abortion in [timeout] functions. *)
- exception Timeout
- (** runs the suspension for its effects *)
- val run : 'a t -> 'a
-end = struct
- type 'a t = unit -> 'a
-
- let run x = x ()
-
- let return x () = x
- let bind x k () = k (x ()) ()
- let seq x k () = x (); k ()
- let ignore x () = ignore (x ())
-
- type 'a ref = 'a Pervasives.ref
-
- let ref x () = Pervasives.ref x
- let (:=) r x () = Pervasives.(:=) r x
- let (!) r () = Pervasives.(!) r
-
- exception Exception of exn
- let raise e () = raise (Exception e)
- let catch s h () =
- try s ()
- with Exception e -> h e ()
-
- exception Timeout
- let timeout n t () =
- let timeout_handler _ = Pervasives.raise (Exception Timeout) in
- let psh = Sys.signal Sys.sigalrm (Sys.Signal_handle timeout_handler) in
- Pervasives.ignore (Unix.alarm n);
- let restore_timeout () =
- Pervasives.ignore (Unix.alarm 0);
- Sys.set_signal Sys.sigalrm psh
- in
- try
- let res = t () in
- restore_timeout ();
- res
- with
- | e -> restore_timeout (); Pervasives.raise e
-
- let _ = Errors.register_handler begin function
- | Timeout -> Errors.errorlabstrm "Monads.IO.timeout" (Pp.str"Timeout!")
- | Exception e -> Errors.print e
- | _ -> Pervasives.raise Errors.Unhandled
- end
-end
-
-(* State monad transformer, adapted from Haskell's StateT *)
-module State (X:Type) (T:S) : sig
- (* spiwack: it is not essential that both ['a result] and ['a t] be
- private (or either, for that matter). I just hope it will help
- catch more programming errors. *)
- type +'a result = private { result : 'a ; state : X.t }
- include State with type s = X.t and type +'a t = private X.t -> 'a result T.t
- (* a function version of the coercion from the private type ['a t].*)
- val run : 'a t -> s -> 'a result T.t
- val lift : 'a T.t -> 'a t
-end = struct
- type s = X.t
- type 'a result = { result : 'a ; state : s }
- type 'a t = s -> 'a result T.t
-
- let run x = x
- (*spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = T.bind
- let return x s = T.return { result=x ; state=s }
- let bind x k s =
- x s >>= fun { result=a ; state=s } ->
- k a s
- let ignore x s =
- x s >>= fun x' ->
- T.return { x' with result=() }
- let seq x t s =
- (x s) >>= fun x' ->
- t x'.state
- let lift x s =
- x >>= fun a ->
- T.return { result=a ; state=s }
-
- let set s _ =
- T.return { result=() ; state=s }
- let get s =
- T.return { result=s ; state=s }
-end
-
-module type Monoid = sig
- type t
-
- val zero : t
- val ( * ) : t -> t -> t
-end
-
-module Writer (M:Monoid) (T:S) : sig
- include Writer with type +'a t = private ('a*M.t) T.t and type m = M.t
-
- val lift : 'a T.t -> 'a t
- (* The coercion from private ['a t] in function form. *)
- val run : 'a t -> ('a*m) T.t
-end = struct
-
- type 'a t = ('a*M.t) T.t
- type m = M.t
-
- let run x = x
-
- (*spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = T.bind
-
- let bind x k =
- x >>= fun (a,m) ->
- k a >>= fun (r,m') ->
- T.return (r,M.( * ) m m')
-
- let seq x k =
- x >>= fun ((),m) ->
- k >>= fun (r,m') ->
- T.return (r,M.( * ) m m')
-
- let return x =
- T.return (x,M.zero)
-
- let ignore x =
- x >>= fun (_,m) ->
- T.return ((),m)
-
- let lift x =
- x >>= fun r ->
- T.return (r,M.zero)
-
- let put m =
- T.return ((),m)
-end
-
-(* Double-continuation backtracking monads are reasonable folklore for
- "search" implementations (including Tac interactive prover's
- tactics). Yet it's quite hard to wrap your head around these. I
- recommand reading a few times the "Backtracking, Interleaving, and
- Terminating Monad Transformers" paper by O. Kiselyov, C. Chen,
- D. Fridman. The peculiar shape of the monadic type is reminiscent
- of that of the continuation monad transformer.
-
- The paper also contains the rational for the [split] abstraction.
-
- An explanation of how to derive such a monad from mathematical
- principles can be found in "Kan Extensions for Program
- Optimisation" by Ralf Hinze.
-
- One way to think of the [Logic] functor is to imagine ['a
- Logic(X).t] to represent list of ['a] with an exception at the
- bottom (leaving the monad-transforming issues aside, as they don't
- really work well with lists). Each of the element is a valid
- result, sequentialising with a [f:'a -> 'b t] is done by applying
- [f] to each element and then flatten the list, [plus] is
- concatenation, and [split] is pattern-matching. *)
-(* spiwack: I added the primitives from [IO] directly in the [Logic]
- signature for convenience. It doesn't really make sense, strictly
- speaking, as they are somewhat deconnected from the semantics of
- [Logic], but without an appropriate language for composition (some
- kind of mixins?) I would be going nowhere with a gazillion
- functors. *)
-module type Logic = sig
- include IO
-
- (* [zero] is usually argument free, but Coq likes to explain errors,
- hence error messages should be carried around. *)
- val zero : exn -> 'a t
- val plus : 'a t -> (exn -> 'a t) -> 'a t
-(** Writing (+) for plus and (>>=) for bind, we shall require that
-
- x+(y+z) = (x+y)+z
-
- zero+x = x
-
- x+zero = x
-
- (x+y)>>=k = (x>>=k)+(y>>=k) *)
-
- (** [split x] runs [x] until it either fails with [zero e] or finds
- a result [a]. In the former case it returns [Inr e], otherwise
- it returns [Inl (a,y)] where [y] can be run to get more results
- from [x]. It is a variant of prolog's cut. *)
- val split : 'a t -> ('a * (exn -> 'a t) , exn ) Util.union t
-end
-(* The [T] argument represents the "global" effect: it is not
- backtracked when backtracking occurs at a [plus]. *)
-(* spiwack: hence, [T] will not be instanciated with a state monad
- representing the proofs, we will use a surrounding state transformer
- to that effect. In fact at the time I'm writing this comment, I have
- no immediate use for [T]. We might, however, consider instantiating it
- with a "writer" monad around [Pp] to implement [idtac "msg"] for
- instance. *)
-module Logic (T:IO) : sig
- include Logic
-
- (** [run x] raises [e] if [x] is [zero e]. *)
- val run : 'a t -> 'a T.t
-
- val lift : 'a T.t -> 'a t
-end = struct
-(* spiwack: the implementation is an adaptation of the aforementionned
- "Backtracking, Interleaving, and Terminating Monad Transformers"
- paper *)
- (* spiwack: [fk] stands for failure continuation, and [sk] for success
- continuation. *)
- type +'r fk = exn -> 'r
- type (-'a,'r) sk = 'a -> 'r fk -> 'r
- type 'a t = { go : 'r. ('a,'r T.t) sk -> 'r T.t fk -> 'r T.t }
-
- let return x = { go = fun sk fk ->
- sk x fk
- }
- let bind x k = { go = fun sk fk ->
- x.go (fun a fk -> (k a).go sk fk) fk
- }
- let ignore x = { go = fun sk fk ->
- x.go (fun _ fk -> sk () fk) fk
- }
- let seq x t = { go = fun sk fk ->
- x.go (fun () fk -> t.go sk fk) fk
- }
-
- let zero e = { go = fun _ fk -> fk e }
-
- let plus x y = { go = fun sk fk ->
- x.go sk (fun e -> (y e).go sk fk)
- }
-
- let lift x = { go = fun sk fk ->
- T.bind x (fun a -> sk a fk)
- }
-
- let run x =
- let sk a _ = T.return a in
- let fk e = raise e in
- x.go sk fk
-
- (* For [reflect] and [split] see the "Backtracking, Interleaving,
- and Terminating Monad Transformers" paper *)
- let reflect : ('a*(exn -> 'a t) , exn) Util.union -> 'a t = function
- | Util.Inr e -> zero e
- | Util.Inl (a,x) -> plus (return a) x
-
- let lower x =
- let fk e = T.return (Util.Inr e) in
- let sk a fk = T.return (Util.Inl (a,fun e -> bind (lift (fk e)) reflect)) in
- x.go sk fk
-
- let split x =
- lift (lower x)
-
- (*** IO ***)
-
- type 'a ref = 'a T.ref
- let ref x = lift (T.ref x)
- let (:=) r x = lift (T.(:=) r x)
- let (!) r = lift (T.(!) r)
-
- let raise e = lift (T.raise e)
- let catch t h =
- let h' e = lower (h e) in
- bind (lift (T.catch (lower t) h')) reflect
-
- (** [timeout n x] can have several success. It succeeds as long as,
- individually, each of the past successes run in less than [n]
- seconds.
- In case of timeout if fails with [zero Timeout]. *)
- let rec timeout n x =
- (* spiwack: adds a [T.return] in front of [x] in order to force
- [lower] to go into [T] before running [x]. The problem is that
- in a continuation-passing monad transformer, the monadic
- operations don't make use of the underlying ones. Hence, when
- going back to a lower monad, much computation can be done
- before returning (and running the lower monad). It is
- undesirable for timeout, obviously. *)
- let x = seq (lift (T.return ())) x in
- let x' =
- (* spiwack: this could be a [T.map] if provided *)
- T.bind (lower x) begin function
- | Util.Inr _ as e -> T.return e
- | Util.Inl (a,h) -> T.return (Util.Inl (a, fun e -> timeout n (h e)))
- end
- in
- (* spiwack: we report timeouts as resumable failures. *)
- bind (catch (lift (T.timeout n x')) begin function
- | IO.Timeout -> zero IO.Timeout
- | e -> raise e
- end) reflect
-end
-
-
-(* [State(X)(T:Logic)] can be lifted to [Logic] by backtracking on state on [plus].*)
-module StateLogic(X:Type)(T:Logic) : sig
- (* spiwack: some duplication from interfaces as we need ocaml 3.12
- to substitute inside signatures. *)
- type s = X.t
- type +'a result = private { result : 'a ; state : s }
- include Logic with type +'a t = private X.t -> 'a result T.t
-
- val set : s -> unit t
- val get : s t
-
- val lift : 'a T.t -> 'a t
- val run : 'a t -> s -> 'a result T.t
-end = struct
-
- module S = State(X)(T)
- include S
-
- let zero e = lift (T.zero e)
- let plus x y =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- get >>= fun initial ->
- lift begin
- (T.plus (run x initial) (fun e -> run (y e) initial))
- end >>= fun { result = a ; state = final } ->
- set final >>
- return a
- (* spiwack: the definition of [plus] is essentially [plus x y = fun s
- -> T.plus (run x s) (run y s)]. But the [private] annotation
- prevents us from writing that. Maybe I should remove [private]
- around [+'a t] (it would be unnecessary to remove that of ['a
- result]) after all. I'll leave it like that for now. *)
-
- let split x =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- get >>= fun initial ->
- lift (T.split (run x initial)) >>= function
- | Util.Inr _ as e -> return e
- | Util.Inl (a,y) ->
- let y' e =
- lift (y e) >>= fun b ->
- set b.state >>
- return b.result
- in
- set a.state >>
- return (Util.Inl(a.result,y'))
-
-
- (*** IO ***)
-
- type 'a ref = 'a T.ref
- let ref x = lift (T.ref x)
- let (:=) r x = lift (T.(:=) r x)
- let (!) r = lift (T.(!) r)
-
- let raise e = lift (T.raise e)
- let catch t h =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- get >>= fun initial ->
- let h' e = run (h e) initial in
- lift (T.catch (run t initial) h') >>= fun a ->
- set a.state >>
- return a.result
-
- exception Timeout
- let timeout n t =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- get >>= fun initial ->
- lift (T.timeout n (run t initial)) >>= fun a ->
- set a.state >>
- return a.result
-end
-
-(* [Writer(M)(T:Logic)] can be lifted to [Logic] by backtracking on state on [plus].*)
-module WriterLogic(M:Monoid)(T:Logic) : sig
- (* spiwack: some duplication from interfaces as we need ocaml 3.12
- to substitute inside signatures. *)
- type m = M.t
- include Logic with type +'a t = private ('a*m) T.t
-
- val put : m -> unit t
-
- val lift : 'a T.t -> 'a t
- val run : 'a t -> ('a*m) T.t
-end = struct
- module W = Writer(M)(T)
- include W
-
- let zero e = lift (T.zero e)
- let plus x y =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- lift begin
- (T.plus (run x) (fun e -> run (y e)))
- end >>= fun (r,m) ->
- put m >>
- return r
-
- let split x =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- lift (T.split (run x)) >>= function
- | Util.Inr _ as e -> return e
- | Util.Inl ((a,m),y) ->
- let y' e =
- lift (y e) >>= fun (b,m) ->
- put m >>
- return b
- in
- put m >>
- return (Util.Inl(a,y'))
-
-
- (*** IO ***)
-
- type 'a ref = 'a T.ref
- let ref x = lift (T.ref x)
- let (:=) r x = lift (T.(:=) r x)
- let (!) r = lift (T.(!) r)
-
- let raise e = lift (T.raise e)
- let catch t h =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- let h' e = run (h e) in
- lift (T.catch (run t) h') >>= fun (a,m) ->
- put m >>
- return a
-
- exception Timeout
- let timeout n t =
- (* spiwack: convenience notation, waiting for ocaml 3.12 *)
- let (>>=) = bind in
- let (>>) = seq in
- lift (T.timeout n (run t)) >>= fun (a,m) ->
- put m >>
- return a
-end
diff --git a/proofs/proof_errors.ml b/proofs/proof_errors.ml
new file mode 100644
index 0000000000..e543b0c8fd
--- /dev/null
+++ b/proofs/proof_errors.ml
@@ -0,0 +1,12 @@
+exception Exception of exn
+exception Timeout
+exception TacticFailure of exn
+
+let _ = Errors.register_handler begin function
+ | Timeout -> Errors.errorlabstrm "Some timeout function" (Pp.str"Timeout!")
+ | Exception e -> Errors.print e
+ | TacticFailure e -> Errors.print e
+ | _ -> Pervasives.raise Errors.Unhandled
+end
+
+
diff --git a/proofs/proof_errors.mli b/proofs/proof_errors.mli
new file mode 100644
index 0000000000..dd21d539c9
--- /dev/null
+++ b/proofs/proof_errors.mli
@@ -0,0 +1,18 @@
+(** This small files declares the exceptions needed by Proofview_gen,
+ as Coq's extraction cannot produce exception declarations. *)
+
+(** To help distinguish between exceptions raised by the IO monad from
+ the one used natively by Coq, the former are wrapped in
+ [Exception]. It is only used internally so that [catch] blocks of
+ the IO monad would only catch exceptions raised by the [raise]
+ function of the IO monad, and not for instance, by system
+ interrupts. Also used in [Proofview] to avoid capturing exception
+ from the IO monad ([Proofview] catches errors in its compatibility
+ layer, and when lifting goal-level expressions). *)
+exception Exception of exn
+(** This exception is used to signal abortion in [timeout] functions. *)
+exception Timeout
+(** This exception is used by the tactics to signal failure by lack of
+ successes, rather than some other exceptions (like system
+ interrupts). *)
+exception TacticFailure of exn
diff --git a/proofs/proofs.mllib b/proofs/proofs.mllib
index 19f289316f..4a7efb029c 100644
--- a/proofs/proofs.mllib
+++ b/proofs/proofs.mllib
@@ -1,7 +1,9 @@
Goal
Evar_refiner
-Monads
Proof_type
+Proof_errors
+Proofview_gen
+Proofview_monad
Proofview
Proof
Proof_global
diff --git a/proofs/proofview.ml b/proofs/proofview.ml
index eed792fd7f..9496b51ea8 100644
--- a/proofs/proofview.ml
+++ b/proofs/proofview.ml
@@ -23,11 +23,8 @@
open Util
(* Type of proofviews. *)
-type proofview = {
- initial : (Term.constr * Term.types) list;
- solution : Evd.evar_map;
- comb : Goal.goal list;
- }
+type proofview = Proofview_monad.proofview
+open Proofview_monad
let proofview p =
p.comb , p.solution
@@ -188,79 +185,68 @@ let unfocus c sp =
- access the environment,
- access and change the current [proofview]
- backtrack on previous changes of the proofview *)
-(* spiwack: it seems lighter, for now, to deal with the environment here rather than in [Monads]. *)
-
-module ProofState = struct
- type t = proofview
-end
-module MessageType = struct
- type t = bool (* [false] if an unsafe tactic has been used. *)
-
- let zero = true
- let ( * ) s1 s2 = s1 && s2
-end
-module Backtrack = Monads.Logic(Monads.IO)
-module Message = Monads.WriterLogic(MessageType)(Backtrack)
-module Proof = Monads.StateLogic(ProofState)(Message)
-
-type +'a tactic = Environ.env -> 'a Proof.t
+module Proof = Proofview_monad.Logical
+type +'a tactic = 'a Proof.t
(* Applies a tactic to the current proofview. *)
let apply env t sp =
- let (next,status) = Monads.IO.run (Backtrack.run (Message.run (Proof.run (t env) sp))) in
- next.Proof.result , next.Proof.state , status
+ let (((next_r,next_state),status)) = Proofview_monad.NonLogical.run (Proof.run t env sp) in
+ next_r , next_state , status
(*** tacticals ***)
+let rec catchable_exception = function
+ | Proof_errors.Exception _ -> false
+ | e -> Errors.noncritical e
+
+
(* Unit of the tactic monad *)
-let tclUNIT a _ = Proof.return a
+let tclUNIT a = (Proof.ret a:'a Proof.t)
(* Bind operation of the tactic monad *)
-let tclBIND t k env =
- Proof.bind (t env) (fun a -> k a env)
+let tclBIND = Proof.bind
(* Interpretes the ";" (semicolon) of Ltac.
As a monadic operation, it's a specialized "bind"
on unit-returning tactic (meaning "there is no value to bind") *)
-let tclTHEN t1 t2 env =
- Proof.seq (t1 env) (t2 env)
+let tclTHEN = Proof.seq
(* [tclIGNORE t] has the same operational content as [t],
but drops the value at the end. *)
-let tclIGNORE tac env = Proof.ignore (tac env)
+let tclIGNORE = Proof.ignore
(* [tclOR t1 t2 = t1] as long as [t1] succeeds. Whenever the successes
of [t1] have been depleted and it failed with [e], then it behaves
as [t2 e]. No interleaving at this point. *)
-let tclOR t1 t2 env =
- Proof.plus (t1 env) (fun e -> t2 e env)
+let tclOR t1 t2 =
+ Proof.plus t1 t2
(* [tclZERO e] always fails with error message [e]*)
-let tclZERO e _ = Proof.zero e
+let tclZERO = Proof.zero
(* [tclORELSE t1 t2] behaves like [t1] if [t1] succeeds at least once
or [t2] if [t1] fails. *)
-let tclORELSE t1 t2 env =
+let tclORELSE t1 t2 =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
- Proof.split (t1 env) >>= function
- | Util.Inr e -> t2 e env
- | Util.Inl (a,t1') -> Proof.plus (Proof.return a) t1'
+ Proof.split t1 >>= function
+ | Util.Inr e -> t2 e
+ | Util.Inl (a,t1') -> Proof.plus (Proof.ret a) t1'
(* [tclIFCATCH a s f] is a generalisation of [tclORELSE]: if [a]
succeeds at least once then it behaves as [tclBIND a s] otherwise, if [a]
fails with [e], then it behaves as [f e]. *)
-let tclIFCATCH a s f env =
+let tclIFCATCH a s f =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
- Proof.split (a env) >>= function
- | Util.Inr e -> f e env
- | Util.Inl (x,a') -> Proof.plus (s x env) (fun e -> (a' e) >>= fun x' -> (s x' env))
+ Proof.split a >>= function
+ | Util.Inr e -> f e
+ | Util.Inl (x,a') -> Proof.plus (s x) (fun e -> (a' e) >>= fun x' -> (s x'))
(* Focuses a tactic at a range of subgoals, found by their indices. *)
(* arnaud: bug if 0 goals ! *)
-let tclFOCUS i j t env =
+let tclFOCUS i j t =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
let (>>) = Proof.seq in
@@ -268,14 +254,14 @@ let tclFOCUS i j t env =
try
let (focused,context) = focus i j initial in
Proof.set focused >>
- t (env) >>= fun result ->
+ t >>= fun result ->
Proof.get >>= fun next ->
Proof.set (unfocus context next) >>
- Proof.return result
+ Proof.ret result
with e ->
(* spiwack: a priori the only possible exceptions are that of focus,
of course I haven't made them algebraic yet. *)
- tclZERO e env
+ tclZERO e
(* Dispatch tacticals are used to apply a different tactic to each goal under
consideration. They come in two flavours:
@@ -299,27 +285,27 @@ end
both lists are being concatenated.
[join] and [null] need be some sort of comutative monoid. *)
-let rec tclDISPATCHGEN null join tacs env =
+let rec tclDISPATCHGEN null join tacs =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
let (>>) = Proof.seq in
Proof.get >>= fun initial ->
match tacs,initial.comb with
- | [], [] -> tclUNIT null env
+ | [], [] -> tclUNIT null
| t::tacs , first::goals ->
begin match Goal.advance initial.solution first with
- | None -> Proof.return null (* If [first] has been solved by side effect: do nothing. *)
+ | None -> Proof.ret null (* If [first] has been solved by side effect: do nothing. *)
| Some first ->
Proof.set {initial with comb=[first]} >>
- t env
+ t
end >>= fun y ->
Proof.get >>= fun step ->
Proof.set {step with comb=goals} >>
- tclDISPATCHGEN null join tacs env >>= fun x ->
+ tclDISPATCHGEN null join tacs >>= fun x ->
Proof.get >>= fun step' ->
Proof.set {step' with comb=step.comb@step'.comb} >>
- Proof.return (join y x)
- | _ , _ -> tclZERO SizeMismatch env
+ Proof.ret (join y x)
+ | _ , _ -> tclZERO SizeMismatch
let unitK () () = ()
let tclDISPATCH = tclDISPATCHGEN () unitK
@@ -343,12 +329,12 @@ let extend_to_list =
let ne = List.length endxs in
let n = List.length l in
startxs@(copy (n-ne-ns) rx endxs)
-let tclEXTEND tacs1 rtac tacs2 env =
+let tclEXTEND tacs1 rtac tacs2 =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
Proof.get >>= fun step ->
let tacs = extend_to_list tacs1 rtac tacs2 step.comb in
- tclDISPATCH tacs env
+ tclDISPATCH tacs
(* No backtracking can happen here, hence, as opposed to the dispatch tacticals,
@@ -367,44 +353,79 @@ let sensitive_on_proofview s env step =
{ step with
solution = new_defs;
comb = List.flatten combed_subgoals; }
- let tclSENSITIVE s env =
+let tclSENSITIVE s =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
+ Proof.current >>= fun env ->
Proof.get >>= fun step ->
try
let next = sensitive_on_proofview s env step in
Proof.set next
- with e when Errors.noncritical e ->
- tclZERO e env
+ with e when catchable_exception e ->
+ tclZERO e
-let tclPROGRESS t env =
+let tclPROGRESS t =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
Proof.get >>= fun initial ->
- t env >>= fun res ->
+ t >>= fun res ->
Proof.get >>= fun final ->
let test =
Evd.progress_evar_map initial.solution final.solution &&
not (Util.List.for_all2eq (fun i f -> Goal.equal initial.solution i final.solution f) initial.comb final.comb)
in
if test then
- tclUNIT res env
+ tclUNIT res
else
- tclZERO (Errors.UserError ("Proofview.tclPROGRESS" , Pp.str"Failed to progress.")) env
+ tclZERO (Errors.UserError ("Proofview.tclPROGRESS" , Pp.str"Failed to progress."))
-let tclEVARMAP _ =
+let tclEVARMAP =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
Proof.get >>= fun initial ->
- Proof.return (initial.solution)
+ Proof.ret (initial.solution)
-let tclENV env =
- Proof.return env
+let tclENV = Proof.current
-let tclTIMEOUT n t env = Proof.timeout n (t env)
+exception Timeout
+let _ = Errors.register_handler begin function
+ | Timeout -> Errors.errorlabstrm "Proofview.tclTIMEOUT" (Pp.str"Tactic timeout!")
+ | _ -> Pervasives.raise Errors.Unhandled
+end
-let mark_as_unsafe env =
- Proof.lift (Message.put false)
+let tclTIMEOUT n t =
+ (* spiwack: convenience notations, waiting for ocaml 3.12 *)
+ let (>>=) = Proof.bind in
+ let (>>) = Proof.seq in
+ (* spiwack: as one of the monad is a continuation passing monad, it
+ doesn't force the computation to be threaded inside the underlying
+ (IO) monad. Hence I force it myself by asking for the evaluation of
+ a dummy value first, lest [timeout] be called when everything has
+ already been computed. *)
+ let t = Proof.lift (Proofview_monad.NonLogical.ret ()) >> t in
+ Proof.current >>= fun env ->
+ Proof.get >>= fun initial ->
+ Proof.lift begin
+ Proofview_monad.NonLogical.catch
+ begin
+ Proofview_monad.NonLogical.bind
+ (Proofview_monad.NonLogical.timeout n (Proof.run t env initial))
+ (fun r -> Proofview_monad.NonLogical.ret (Util.Inl r))
+ end
+ begin function
+ | Proof_errors.Timeout -> Proofview_monad.NonLogical.ret (Util.Inr Timeout)
+ | Proof_errors.TacticFailure e -> Proofview_monad.NonLogical.ret (Util.Inr e)
+ | e -> Proofview_monad.NonLogical.raise e
+ end
+ end >>= function
+ | Util.Inl ((res,s),m) ->
+ Proof.set s >>
+ Proof.put m >>
+ Proof.ret res
+ | Util.Inr e -> tclZERO e
+
+let mark_as_unsafe =
+ Proof.put false
(*** Commands ***)
@@ -430,7 +451,7 @@ module Notations = struct
end >= fun l' ->
tclUNIT (List.flatten l')
let (<*>) = tclTHEN
- let (<+>) t1 t2 = tclOR t2 (fun _ -> t2)
+ let (<+>) t1 t2 = tclOR t1 (fun _ -> t2)
end
open Notations
@@ -446,7 +467,7 @@ let rec list_map f = function
module V82 = struct
type tac = Goal.goal Evd.sigma -> Goal.goal list Evd.sigma
- let tactic tac env =
+ let tactic tac =
(* spiwack: we ignore the dependencies between goals here, expectingly
preserving the semantics of <= 8.2 tactics *)
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
@@ -467,8 +488,8 @@ module V82 = struct
let (goalss,evd) = Goal.list_map tac initgoals initevd in
let sgs = List.flatten goalss in
Proof.set { ps with solution=evd ; comb=sgs; }
- with e when Errors.noncritical e ->
- tclZERO e env
+ with e when catchable_exception e ->
+ tclZERO e
let has_unresolved_evar pv =
Evd.has_undefined pv.solution
@@ -515,14 +536,16 @@ module V82 = struct
solution = Evar_refiner.instantiate_pf_com evk com pv.solution }
let of_tactic t gls =
- let init = { solution = gls.Evd.sigma ; comb = [gls.Evd.it] ; initial = [] } in
- let (_,final,_) = apply (Goal.V82.env gls.Evd.sigma gls.Evd.it) t init in
- { Evd.sigma = final.solution ; it = final.comb }
+ try
+ let init = { solution = gls.Evd.sigma ; comb = [gls.Evd.it] ; initial = [] } in
+ let (_,final,_) = apply (Goal.V82.env gls.Evd.sigma gls.Evd.it) t init in
+ { Evd.sigma = final.solution ; it = final.comb }
+ with Proof_errors.TacticFailure e -> raise e
- let put_status b _env =
- Proof.lift (Message.put b)
+ let put_status b =
+ Proof.put b
- let catchable_exception = Errors.noncritical
+ let catchable_exception = catchable_exception
end
@@ -530,10 +553,11 @@ module Goal = struct
type 'a u = 'a list
- let lift s env =
+ let lift s =
(* spiwack: convenience notations, waiting for ocaml 3.12 *)
let (>>=) = Proof.bind in
let (>>) = Proof.seq in
+ Proof.current >>= fun env ->
Proof.get >>= fun step ->
try
let (res,sigma) =
@@ -542,22 +566,12 @@ module Goal = struct
end step.comb step.solution
in
Proof.set { step with solution=sigma } >>
- Proof.return res
- with e when Errors.noncritical e ->
- tclZERO e env
+ Proof.ret res
+ with e when catchable_exception e ->
+ tclZERO e
let return x = lift (Goal.return x)
let concl = lift Goal.concl
let hyps = lift Goal.hyps
let env = lift Goal.env
end
-
-
-
-
-
-
-
-
-
-
diff --git a/proofs/proofview.mli b/proofs/proofview.mli
index a2a5746933..136a44332e 100644
--- a/proofs/proofview.mli
+++ b/proofs/proofview.mli
@@ -194,10 +194,9 @@ val tclEVARMAP : Evd.evar_map tactic
environment is returned by {!Proofview.Goal.env}. *)
val tclENV : Environ.env tactic
-(** [tclTIMEOUT n t] can have several success. It succeeds as long as,
- individually, each of the past successes run in less than [n]
- seconds.
- In case of timeout if fails with [tclZERO Timeout]. *)
+exception Timeout
+(** [tclTIMEOUT n t] can have only one success.
+ In case of timeout if fails with [tclZERO Timeout]. *)
val tclTIMEOUT : int -> 'a tactic -> 'a tactic
(** [mark_as_unsafe] signals that the current tactic is unsafe. *)
diff --git a/proofs/proofview_gen.ml b/proofs/proofview_gen.ml
new file mode 100644
index 0000000000..577aa2ddb0
--- /dev/null
+++ b/proofs/proofview_gen.ml
@@ -0,0 +1,377 @@
+(* This file has been generated by extraction
+ of bootstrap/Monad.v. It shouldn't be
+ modified directly. To regenerate it run
+ coqtop -batch -impredicative-set
+ bootstrap/Monad.v in Coq's source
+ directory. *)
+
+type __ = Obj.t
+let __ = let rec f _ = Obj.repr f in Obj.repr f
+
+module IOBase =
+ struct
+ type 'a coq_T = unit -> 'a
+
+ type 'a coq_Ref = 'a Pervasives.ref
+
+ (** val ret : 'a1 -> 'a1 coq_T **)
+
+ let ret = fun a () -> a
+
+ (** val bind :
+ 'a1 coq_T -> ('a1 -> 'a2 coq_T) -> 'a2
+ coq_T **)
+
+ let bind = fun a k () -> k (a ()) ()
+
+ (** val ignore :
+ 'a1 coq_T -> unit coq_T **)
+
+ let ignore = fun a () -> ignore (a ())
+
+ (** val seq :
+ unit coq_T -> 'a1 coq_T -> 'a1 coq_T **)
+
+ let seq = fun a k () -> a (); k ()
+
+ (** val ref : 'a1 -> 'a1 coq_Ref coq_T **)
+
+ let ref = fun a () -> Pervasives.ref a
+
+ (** val set :
+ 'a1 coq_Ref -> 'a1 -> unit coq_T **)
+
+ let set = fun r a () -> Pervasives.(:=) r a
+
+ (** val get : 'a1 coq_Ref -> 'a1 coq_T **)
+
+ let get = fun r () -> Pervasives.(!) r
+
+ (** val raise : exn -> 'a1 coq_T **)
+
+ let raise = fun e () -> raise (Proof_errors.Exception e)
+
+ (** val catch :
+ 'a1 coq_T -> (exn -> 'a1 coq_T) -> 'a1
+ coq_T **)
+
+ let catch = fun s h () -> try s () with Proof_errors.Exception e -> h e ()
+
+ type coq_Int = int
+
+ (** val timeout :
+ coq_Int -> 'a1 coq_T -> 'a1 coq_T **)
+
+ let timeout = fun n t () ->
+ let timeout_handler _ = Pervasives.raise (Proof_errors.Exception Proof_errors.Timeout) in
+ let psh = Sys.signal Sys.sigalrm (Sys.Signal_handle timeout_handler) in
+ Pervasives.ignore (Unix.alarm n);
+ let restore_timeout () =
+ Pervasives.ignore (Unix.alarm 0);
+ Sys.set_signal Sys.sigalrm psh
+ in
+ try
+ let res = t () in
+ restore_timeout ();
+ res
+ with
+ | e -> restore_timeout (); Pervasives.raise e
+
+ end
+
+type proofview = { initial : (Term.constr*Term.types)
+ list;
+ solution : Evd.evar_map;
+ comb : Goal.goal list }
+
+type logicalState = proofview
+
+type logicalMessageType = bool
+
+type logicalEnvironment = Environ.env
+
+module NonLogical =
+ struct
+ type 'a t = 'a IOBase.coq_T
+
+ type 'a ref = 'a IOBase.coq_Ref
+
+ (** val ret : 'a1 -> 'a1 t **)
+
+ let ret x =
+ IOBase.ret x
+
+ (** val bind :
+ 'a1 t -> ('a1 -> 'a2 t) -> 'a2 t **)
+
+ let bind x k =
+ IOBase.bind x k
+
+ (** val ignore : 'a1 t -> unit t **)
+
+ let ignore x =
+ IOBase.ignore x
+
+ (** val seq : unit t -> 'a1 t -> 'a1 t **)
+
+ let seq x k =
+ IOBase.seq x k
+
+ (** val new_ref : 'a1 -> 'a1 ref t **)
+
+ let new_ref x =
+ IOBase.ref x
+
+ (** val set : 'a1 ref -> 'a1 -> unit t **)
+
+ let set r x =
+ IOBase.set r x
+
+ (** val get : 'a1 ref -> 'a1 t **)
+
+ let get r =
+ IOBase.get r
+
+ (** val raise : exn -> 'a1 t **)
+
+ let raise e =
+ IOBase.raise e
+
+ (** val catch :
+ 'a1 t -> (exn -> 'a1 t) -> 'a1 t **)
+
+ let catch s h =
+ IOBase.catch s h
+
+ (** val timeout :
+ IOBase.coq_Int -> 'a1 t -> 'a1 t **)
+
+ let timeout n x =
+ IOBase.timeout n x
+
+ (** val run : 'a1 t -> 'a1 **)
+
+ let run = fun x -> try x () with Proof_errors.Exception e -> Pervasives.raise e
+ end
+
+module Logical =
+ struct
+ type 'a t =
+ proofview -> Environ.env -> __ ->
+ ((('a*proofview)*bool) -> (exn -> __
+ IOBase.coq_T) -> __ IOBase.coq_T) -> (exn
+ -> __ IOBase.coq_T) -> __ IOBase.coq_T
+
+ (** val ret :
+ 'a1 -> proofview -> Environ.env -> __
+ -> ((('a1*proofview)*bool) -> (exn ->
+ 'a2 IOBase.coq_T) -> 'a2 IOBase.coq_T)
+ -> (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let ret x s e r sk fk =
+ sk ((x,s),true) fk
+
+ (** val bind :
+ 'a1 t -> ('a1 -> 'a2 t) -> proofview ->
+ Environ.env -> __ ->
+ ((('a2*proofview)*bool) -> (exn -> 'a3
+ IOBase.coq_T) -> 'a3 IOBase.coq_T) ->
+ (exn -> 'a3 IOBase.coq_T) -> 'a3
+ IOBase.coq_T **)
+
+ let bind x k s e r sk fk =
+ Obj.magic x s e __ (fun a fk0 ->
+ let x0,c = a in
+ let x1,s0 = x0 in
+ Obj.magic k x1 s0 e __ (fun a0 fk1 ->
+ let y,c' = a0 in
+ sk (y,(if c then c' else false)) fk1)
+ fk0) fk
+
+ (** val ignore :
+ 'a1 t -> proofview -> Environ.env -> __
+ -> (((unit*proofview)*bool) -> (exn ->
+ 'a2 IOBase.coq_T) -> 'a2 IOBase.coq_T)
+ -> (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let ignore x s e r sk fk =
+ Obj.magic x s e __ (fun a fk0 ->
+ let x0,c = a in
+ let sk0 = fun a0 fk1 ->
+ let y,c' = a0 in
+ sk (y,(if c then c' else false)) fk1
+ in
+ let a0,s0 = x0 in
+ sk0 (((),s0),true) fk0) fk
+
+ (** val seq :
+ unit t -> 'a1 t -> proofview ->
+ Environ.env -> __ ->
+ ((('a1*proofview)*bool) -> (exn -> 'a2
+ IOBase.coq_T) -> 'a2 IOBase.coq_T) ->
+ (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let seq x k s e r sk fk =
+ Obj.magic x s e __ (fun a fk0 ->
+ let x0,c = a in
+ let u,s0 = x0 in
+ Obj.magic k s0 e __ (fun a0 fk1 ->
+ let y,c' = a0 in
+ sk (y,(if c then c' else false)) fk1)
+ fk0) fk
+
+ (** val set :
+ logicalState -> proofview ->
+ Environ.env -> __ ->
+ (((unit*proofview)*bool) -> (exn -> 'a1
+ IOBase.coq_T) -> 'a1 IOBase.coq_T) ->
+ (exn -> 'a1 IOBase.coq_T) -> 'a1
+ IOBase.coq_T **)
+
+ let set s s0 e r sk fk =
+ sk (((),s),true) fk
+
+ (** val get :
+ proofview -> Environ.env -> __ ->
+ (((logicalState*proofview)*bool) ->
+ (exn -> 'a1 IOBase.coq_T) -> 'a1
+ IOBase.coq_T) -> (exn -> 'a1
+ IOBase.coq_T) -> 'a1 IOBase.coq_T **)
+
+ let get s e r sk fk =
+ sk ((s,s),true) fk
+
+ (** val put :
+ logicalMessageType -> proofview ->
+ Environ.env -> __ ->
+ (((unit*proofview)*bool) -> (exn -> 'a1
+ IOBase.coq_T) -> 'a1 IOBase.coq_T) ->
+ (exn -> 'a1 IOBase.coq_T) -> 'a1
+ IOBase.coq_T **)
+
+ let put m s e r sk fk =
+ sk (((),s),m) fk
+
+ (** val current :
+ proofview -> Environ.env -> __ ->
+ (((logicalEnvironment*proofview)*bool)
+ -> (exn -> 'a1 IOBase.coq_T) -> 'a1
+ IOBase.coq_T) -> (exn -> 'a1
+ IOBase.coq_T) -> 'a1 IOBase.coq_T **)
+
+ let current s e r sk fk =
+ sk ((e,s),true) fk
+
+ (** val zero :
+ exn -> proofview -> Environ.env -> __
+ -> ((('a1*proofview)*bool) -> (exn ->
+ 'a2 IOBase.coq_T) -> 'a2 IOBase.coq_T)
+ -> (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let zero e s e0 r sk fk =
+ fk e
+
+ (** val plus :
+ 'a1 t -> (exn -> 'a1 t) -> proofview ->
+ Environ.env -> __ ->
+ ((('a1*proofview)*bool) -> (exn -> 'a2
+ IOBase.coq_T) -> 'a2 IOBase.coq_T) ->
+ (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let plus x y s env r sk fk =
+ Obj.magic x s env __ sk (fun e ->
+ Obj.magic y e s env __ sk fk)
+
+ (** val split :
+ 'a1 t -> proofview -> Environ.env -> __
+ -> (((('a1*(exn -> 'a1 t), exn)
+ Util.union*proofview)*bool) -> (exn ->
+ 'a2 IOBase.coq_T) -> 'a2 IOBase.coq_T)
+ -> (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let split x s e r sk fk =
+ IOBase.bind
+ (Obj.magic x s e __ (fun a fk0 ->
+ IOBase.ret (Util.Inl
+ (a,(fun e0 _ sk0 fk1 ->
+ IOBase.bind (fk0 e0) (fun x0 ->
+ match x0 with
+ | Util.Inl p ->
+ let a0,x1 = p in
+ sk0 a0 (fun e1 ->
+ x1 e1 __ sk0 fk1)
+ | Util.Inr e1 -> fk1 e1)))))
+ (fun e0 -> IOBase.ret (Util.Inr e0)))
+ (fun x0 ->
+ let sk0 = fun a fk0 ->
+ let sk0 = fun a0 fk1 ->
+ let x1,c = a0 in
+ let sk0 = fun a1 fk2 ->
+ let y,c' = a1 in
+ sk (y,(if c then c' else false))
+ fk2
+ in
+ (match x1 with
+ | Util.Inl p ->
+ let p0,y = p in
+ let a1,s0 = p0 in
+ sk0 (((Util.Inl
+ (a1,(fun e0 x2 ->
+ y e0))),s0),true) fk1
+ | Util.Inr e0 ->
+ sk0 (((Util.Inr e0),s),true) fk1)
+ in
+ let x1,c = a in
+ let sk1 = fun a0 fk1 ->
+ let y,c' = a0 in
+ sk0 (y,(if c then c' else false))
+ fk1
+ in
+ (match x1 with
+ | Util.Inl p ->
+ let a0,y = p in
+ sk1 ((Util.Inl (a0,(fun e0 x2 ->
+ y e0))),true) fk0
+ | Util.Inr e0 ->
+ sk1 ((Util.Inr e0),true) fk0)
+ in
+ (match x0 with
+ | Util.Inl p ->
+ let p0,y = p in
+ let a,c = p0 in
+ sk0 ((Util.Inl (a,y)),c) fk
+ | Util.Inr e0 ->
+ sk0 ((Util.Inr e0),true) fk))
+
+ (** val lift :
+ 'a1 NonLogical.t -> proofview ->
+ Environ.env -> __ ->
+ ((('a1*proofview)*bool) -> (exn -> 'a2
+ IOBase.coq_T) -> 'a2 IOBase.coq_T) ->
+ (exn -> 'a2 IOBase.coq_T) -> 'a2
+ IOBase.coq_T **)
+
+ let lift x s e r sk fk =
+ IOBase.bind x (fun x0 ->
+ sk ((x0,s),true) fk)
+
+ (** val run :
+ 'a1 t -> logicalEnvironment ->
+ logicalState ->
+ (('a1*logicalState)*logicalMessageType)
+ NonLogical.t **)
+
+ let run x e s =
+ Obj.magic x s e __ (fun a x0 ->
+ IOBase.ret a) (fun e0 ->
+ IOBase.raise
+ ((fun e -> Proof_errors.TacticFailure e)
+ e0))
+ end
+
diff --git a/proofs/proofview_monad.ml b/proofs/proofview_monad.ml
new file mode 100644
index 0000000000..ebbb040877
--- /dev/null
+++ b/proofs/proofview_monad.ml
@@ -0,0 +1 @@
+include Proofview_gen
diff --git a/proofs/proofview_monad.mli b/proofs/proofview_monad.mli
new file mode 100644
index 0000000000..02550aebc0
--- /dev/null
+++ b/proofs/proofview_monad.mli
@@ -0,0 +1,81 @@
+(* This is an interface for the code extracted from bootstrap/Monad.v.
+ The relevant comments are overthere. *)
+
+
+type proofview = { initial : (Term.constr * Term.types) list;
+ solution : Evd.evar_map; comb : Goal.goal list }
+
+type logicalState = proofview
+
+type logicalEnvironment = Environ.env
+
+type logicalMessageType = bool
+
+
+
+module NonLogical : sig
+
+ type +'a t
+ type 'a ref
+
+ val ret : 'a -> 'a t
+ val bind : 'a t -> ('a -> 'b t) -> 'b t
+ val ignore : 'a t -> unit t
+ val seq : unit t -> 'a t -> 'a t
+
+ val new_ref : 'a -> 'a ref t
+ val set : 'a ref -> 'a -> unit t
+ val get : 'a ref -> 'a t
+
+ val raise : exn -> 'a t
+ val catch : 'a t -> (exn -> 'a t) -> 'a t
+ val timeout : int -> 'a t -> 'a t
+
+
+ (* [run] performs effects. *)
+ val run : 'a t -> 'a
+
+end
+
+
+module Logical : sig
+
+ type +'a t
+
+ val ret : 'a -> 'a t
+ val bind : 'a t -> ('a -> 'b t) -> 'b t
+ val ignore : 'a t -> unit t
+ val seq : unit t -> 'a t -> 'a t
+
+ val set : logicalState -> unit t
+ val get : logicalState t
+ val put : logicalMessageType -> unit t
+ val current : logicalEnvironment t
+
+ val zero : exn -> 'a t
+ val plus : 'a t -> (exn -> 'a t) -> 'a t
+ val split : 'a t -> (('a*(exn->'a t),exn) Util.union) t
+
+ val lift : 'a NonLogical.t -> 'a t
+
+ val run : 'a t -> logicalEnvironment -> logicalState -> (('a*logicalState)*logicalMessageType) NonLogical.t
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+