summaryrefslogtreecommitdiff
path: root/library/assumptions.ml
diff options
context:
space:
mode:
Diffstat (limited to 'library/assumptions.ml')
-rw-r--r--library/assumptions.ml151
1 files changed, 63 insertions, 88 deletions
diff --git a/library/assumptions.ml b/library/assumptions.ml
index 04ee14fb..62645b23 100644
--- a/library/assumptions.ml
+++ b/library/assumptions.ml
@@ -21,6 +21,7 @@ open Names
open Term
open Declarations
open Mod_subst
+open Globnames
type context_object =
| Variable of Id.t (* A section variable or a Let definition *)
@@ -158,93 +159,67 @@ let lookup_constant cst =
else lookup_constant_in_impl cst (Some cb)
with Not_found -> lookup_constant_in_impl cst None
-let assumptions ?(add_opaque=false) ?(add_transparent=false) st (* t *) =
- modcache := MPmap.empty;
- let (idts,knst) = st in
- (* Infix definition for chaining function that accumulate
- on a and a ContextObjectSet, ContextObjectMap. *)
- let ( ** ) f1 f2 s m = let (s',m') = f1 s m in f2 s' m' in
- (* This function eases memoization, by checking if an object is already
- stored before trying and applying a function.
- If the object is there, the function is not fired (we are in a
- particular case where memoized object don't need a treatment at all).
- If the object isn't there, it is stored and the function is fired*)
- let try_and_go o f s m =
- if ContextObjectSet.mem o s then
- (s,m)
- else
- f (ContextObjectSet.add o s) m
- in
- let identity2 s m = (s,m)
+(** Graph traversal of an object, collecting on the way the dependencies of
+ traversed objects *)
+let rec traverse accu t = match kind_of_term t with
+| Var id ->
+ let body () = match Global.lookup_named id with (_, body, _) -> body in
+ traverse_object accu body (VarRef id)
+| Const (kn, _) ->
+ let body () = Global.body_of_constant_body (lookup_constant kn) in
+ traverse_object accu body (ConstRef kn)
+| Ind (ind, _) ->
+ traverse_object accu (fun () -> None) (IndRef ind)
+| Construct (cst, _) ->
+ traverse_object accu (fun () -> None) (ConstructRef cst)
+| Meta _ | Evar _ -> assert false
+| _ -> Constr.fold traverse accu t
+
+and traverse_object (curr, data) body obj =
+ let data =
+ if Refmap.mem obj data then data
+ else match body () with
+ | None -> Refmap.add obj Refset.empty data
+ | Some body ->
+ let (contents, data) = traverse (Refset.empty, data) body in
+ Refmap.add obj contents data
in
- (* Goes recursively into the term to see if it depends on assumptions.
- The 3 important cases are :
- - Const _ where we need to first unfold the constant and return
- the needed assumptions of its body in the environment,
- - Rel _ which means the term is a variable which has been bound
- earlier by a Lambda or a Prod (returns [] ),
- - Var _ which means that the term refers to a section variable or
- a "Let" definition, in the former it is an assumption of [t],
- in the latter is must be unfolded like a Const.
- The other cases are straightforward recursion.
- Calls to the environment are memoized, thus avoiding exploration of
- the DAG of the environment as if it was a tree (can cause
- exponential behavior and prevent the algorithm from terminating
- in reasonable time). [s] is a set of [context_object], representing
- the object already visited.*)
- let rec do_constr t s acc =
- let rec iter t =
- match kind_of_term t with
- | Var id -> do_memoize_id id
- | Meta _ | Evar _ -> assert false
- | Cast (e1,_,e2) | Prod (_,e1,e2) | Lambda (_,e1,e2) ->
- (iter e1)**(iter e2)
- | LetIn (_,e1,e2,e3) -> (iter e1)**(iter e2)**(iter e3)
- | App (e1, e_array) -> (iter e1)**(iter_array e_array)
- | Case (_,e1,e2,e_array) -> (iter e1)**(iter e2)**(iter_array e_array)
- | Fix (_,(_, e1_array, e2_array)) | CoFix (_,(_,e1_array, e2_array)) ->
- (iter_array e1_array) ** (iter_array e2_array)
- | Const (kn,_) -> do_memoize_kn kn
- | _ -> identity2 (* closed atomic types + rel *)
- and iter_array a = Array.fold_right (fun e f -> (iter e)**f) a identity2
- in iter t s acc
-
- and add_id id s acc =
- (* a Var can be either a variable, or a "Let" definition.*)
- match Global.lookup_named id with
- | (_,None,t) ->
- (s,ContextObjectMap.add (Variable id) t acc)
- | (_,Some bdy,_) -> do_constr bdy s acc
-
- and do_memoize_id id =
- try_and_go (Variable id) (add_id id)
-
- and add_kn kn s acc =
+ (Refset.add obj curr, data)
+
+let traverse t =
+ let () = modcache := MPmap.empty in
+ traverse (Refset.empty, Refmap.empty) t
+
+(** Hopefully bullet-proof function to recover the type of a constant. It just
+ ignores all the universe stuff. There are many issues that can arise when
+ considering terms out of any valid environment, so use with caution. *)
+let type_of_constant cb = match cb.Declarations.const_type with
+| Declarations.RegularArity ty -> ty
+| Declarations.TemplateArity (ctx, arity) ->
+ Term.mkArity (ctx, Sorts.sort_of_univ arity.Declarations.template_level)
+
+let assumptions ?(add_opaque=false) ?(add_transparent=false) st t =
+ let (idts, knst) = st in
+ (** Only keep the transitive dependencies *)
+ let (_, graph) = traverse t in
+ let fold obj _ accu = match obj with
+ | VarRef id ->
+ let (_, body, t) = Global.lookup_named id in
+ if Option.is_empty body then ContextObjectMap.add (Variable id) t accu
+ else accu
+ | ConstRef kn ->
let cb = lookup_constant kn in
- let do_type cst =
- let ctype = Global.type_of_global_unsafe (Globnames.ConstRef kn) in
- (s,ContextObjectMap.add cst ctype acc)
- in
- let (s,acc) =
- if Declareops.constant_has_body cb then
- if Declareops.is_opaque cb || not (Cpred.mem kn knst) then
- (** it is opaque *)
- if add_opaque then do_type (Opaque kn)
- else (s, acc)
- else
- if add_transparent then do_type (Transparent kn)
- else (s, acc)
- else (s, acc)
- in
- match Global.body_of_constant_body cb with
- | None -> do_type (Axiom kn)
- | Some body -> do_constr body s acc
-
- and do_memoize_kn kn =
- try_and_go (Axiom kn) (add_kn kn)
-
- in
- fun t ->
- snd (do_constr t
- (ContextObjectSet.empty)
- (ContextObjectMap.empty))
+ if not (Declareops.constant_has_body cb) then
+ let t = type_of_constant cb in
+ ContextObjectMap.add (Axiom kn) t accu
+ else if add_opaque && (Declareops.is_opaque cb || not (Cpred.mem kn knst)) then
+ let t = type_of_constant cb in
+ ContextObjectMap.add (Opaque kn) t accu
+ else if add_transparent then
+ let t = type_of_constant cb in
+ ContextObjectMap.add (Transparent kn) t accu
+ else
+ accu
+ | IndRef _ | ConstructRef _ -> accu
+ in
+ Refmap.fold fold graph ContextObjectMap.empty