summaryrefslogtreecommitdiff
path: root/pretyping/termops.ml
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping/termops.ml')
-rw-r--r--pretyping/termops.ml1026
1 files changed, 0 insertions, 1026 deletions
diff --git a/pretyping/termops.ml b/pretyping/termops.ml
deleted file mode 100644
index 9d469cb7..00000000
--- a/pretyping/termops.ml
+++ /dev/null
@@ -1,1026 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-open Pp
-open Errors
-open Util
-open Names
-open Nameops
-open Term
-open Vars
-open Context
-open Environ
-
-(* Sorts and sort family *)
-
-let print_sort = function
- | Prop Pos -> (str "Set")
- | Prop Null -> (str "Prop")
- | Type u -> (str "Type(" ++ Univ.Universe.pr u ++ str ")")
-
-let pr_sort_family = function
- | InSet -> (str "Set")
- | InProp -> (str "Prop")
- | InType -> (str "Type")
-
-let pr_name = function
- | Name id -> pr_id id
- | Anonymous -> str "_"
-
-let pr_con sp = str(string_of_con sp)
-
-let pr_fix pr_constr ((t,i),(lna,tl,bl)) =
- let fixl = Array.mapi (fun i na -> (na,t.(i),tl.(i),bl.(i))) lna in
- hov 1
- (str"fix " ++ int i ++ spc() ++ str"{" ++
- v 0 (prlist_with_sep spc (fun (na,i,ty,bd) ->
- pr_name na ++ str"/" ++ int i ++ str":" ++ pr_constr ty ++
- cut() ++ str":=" ++ pr_constr bd) (Array.to_list fixl)) ++
- str"}")
-
-let pr_puniverses p u =
- if Univ.Instance.is_empty u then p
- else p ++ str"(*" ++ Univ.Instance.pr Universes.pr_with_global_universes u ++ str"*)"
-
-let rec pr_constr c = match kind_of_term c with
- | Rel n -> str "#"++int n
- | Meta n -> str "Meta(" ++ int n ++ str ")"
- | Var id -> pr_id id
- | Sort s -> print_sort s
- | Cast (c,_, t) -> hov 1
- (str"(" ++ pr_constr c ++ cut() ++
- str":" ++ pr_constr t ++ str")")
- | Prod (Name(id),t,c) -> hov 1
- (str"forall " ++ pr_id id ++ str":" ++ pr_constr t ++ str"," ++
- spc() ++ pr_constr c)
- | Prod (Anonymous,t,c) -> hov 0
- (str"(" ++ pr_constr t ++ str " ->" ++ spc() ++
- pr_constr c ++ str")")
- | Lambda (na,t,c) -> hov 1
- (str"fun " ++ pr_name na ++ str":" ++
- pr_constr t ++ str" =>" ++ spc() ++ pr_constr c)
- | LetIn (na,b,t,c) -> hov 0
- (str"let " ++ pr_name na ++ str":=" ++ pr_constr b ++
- str":" ++ brk(1,2) ++ pr_constr t ++ cut() ++
- pr_constr c)
- | App (c,l) -> hov 1
- (str"(" ++ pr_constr c ++ spc() ++
- prlist_with_sep spc pr_constr (Array.to_list l) ++ str")")
- | Evar (e,l) -> hov 1
- (str"Evar#" ++ int (Evar.repr e) ++ str"{" ++
- prlist_with_sep spc pr_constr (Array.to_list l) ++str"}")
- | Const (c,u) -> str"Cst(" ++ pr_puniverses (pr_con c) u ++ str")"
- | Ind ((sp,i),u) -> str"Ind(" ++ pr_puniverses (pr_mind sp ++ str"," ++ int i) u ++ str")"
- | Construct (((sp,i),j),u) ->
- str"Constr(" ++ pr_puniverses (pr_mind sp ++ str"," ++ int i ++ str"," ++ int j) u ++ str")"
- | Proj (p,c) -> str"Proj(" ++ pr_con (Projection.constant p) ++ str"," ++ bool (Projection.unfolded p) ++ pr_constr c ++ str")"
- | Case (ci,p,c,bl) -> v 0
- (hv 0 (str"<"++pr_constr p++str">"++ cut() ++ str"Case " ++
- pr_constr c ++ str"of") ++ cut() ++
- prlist_with_sep (fun _ -> brk(1,2)) pr_constr (Array.to_list bl) ++
- cut() ++ str"end")
- | Fix f -> pr_fix pr_constr f
- | CoFix(i,(lna,tl,bl)) ->
- let fixl = Array.mapi (fun i na -> (na,tl.(i),bl.(i))) lna in
- hov 1
- (str"cofix " ++ int i ++ spc() ++ str"{" ++
- v 0 (prlist_with_sep spc (fun (na,ty,bd) ->
- pr_name na ++ str":" ++ pr_constr ty ++
- cut() ++ str":=" ++ pr_constr bd) (Array.to_list fixl)) ++
- str"}")
-
-let term_printer = ref (fun _ -> pr_constr)
-let print_constr_env t = !term_printer t
-let print_constr t = !term_printer (Global.env()) t
-let set_print_constr f = term_printer := f
-
-let pr_var_decl env (id,c,typ) =
- let pbody = match c with
- | None -> (mt ())
- | Some c ->
- (* Force evaluation *)
- let pb = print_constr_env env c in
- (str" := " ++ pb ++ cut () ) in
- let pt = print_constr_env env typ in
- let ptyp = (str" : " ++ pt) in
- (pr_id id ++ hov 0 (pbody ++ ptyp))
-
-let pr_rel_decl env (na,c,typ) =
- let pbody = match c with
- | None -> mt ()
- | Some c ->
- (* Force evaluation *)
- let pb = print_constr_env env c in
- (str":=" ++ spc () ++ pb ++ spc ()) in
- let ptyp = print_constr_env env typ in
- match na with
- | Anonymous -> hov 0 (str"<>" ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp)
- | Name id -> hov 0 (pr_id id ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp)
-
-let print_named_context env =
- hv 0 (fold_named_context
- (fun env d pps ->
- pps ++ ws 2 ++ pr_var_decl env d)
- env ~init:(mt ()))
-
-let print_rel_context env =
- hv 0 (fold_rel_context
- (fun env d pps -> pps ++ ws 2 ++ pr_rel_decl env d)
- env ~init:(mt ()))
-
-let print_env env =
- let sign_env =
- fold_named_context
- (fun env d pps ->
- let pidt = pr_var_decl env d in
- (pps ++ fnl () ++ pidt))
- env ~init:(mt ())
- in
- let db_env =
- fold_rel_context
- (fun env d pps ->
- let pnat = pr_rel_decl env d in (pps ++ fnl () ++ pnat))
- env ~init:(mt ())
- in
- (sign_env ++ db_env)
-
-(* [Rel (n+m);...;Rel(n+1)] *)
-let rel_vect n m = Array.init m (fun i -> mkRel(n+m-i))
-
-let rel_list n m =
- let rec reln l p =
- if p>m then l else reln (mkRel(n+p)::l) (p+1)
- in
- reln [] 1
-
-(* Same as [rel_list] but takes a context as argument and skips let-ins *)
-let extended_rel_list n hyps =
- let rec reln l p = function
- | (_,None,_) :: hyps -> reln (mkRel (n+p) :: l) (p+1) hyps
- | (_,Some _,_) :: hyps -> reln l (p+1) hyps
- | [] -> l
- in
- reln [] 1 hyps
-
-let extended_rel_vect n hyps = Array.of_list (extended_rel_list n hyps)
-
-
-
-let push_rel_assum (x,t) env = push_rel (x,None,t) env
-
-let push_rels_assum assums =
- push_rel_context (List.map (fun (x,t) -> (x,None,t)) assums)
-
-let push_named_rec_types (lna,typarray,_) env =
- let ctxt =
- Array.map2_i
- (fun i na t ->
- match na with
- | Name id -> (id, None, lift i t)
- | Anonymous -> anomaly (Pp.str "Fix declarations must be named"))
- lna typarray in
- Array.fold_left
- (fun e assum -> push_named assum e) env ctxt
-
-let lookup_rel_id id sign =
- let rec lookrec n = function
- | [] -> raise Not_found
- | (Anonymous, _, _) :: l -> lookrec (n + 1) l
- | (Name id', b, t) :: l ->
- if Names.Id.equal id' id then (n, b, t) else lookrec (n + 1) l
- in
- lookrec 1 sign
-
-(* Constructs either [forall x:t, c] or [let x:=b:t in c] *)
-let mkProd_or_LetIn (na,body,t) c =
- match body with
- | None -> mkProd (na, t, c)
- | Some b -> mkLetIn (na, b, t, c)
-
-(* Constructs either [forall x:t, c] or [c] in which [x] is replaced by [b] *)
-let mkProd_wo_LetIn (na,body,t) c =
- match body with
- | None -> mkProd (na, t, c)
- | Some b -> subst1 b c
-
-let it_mkProd init = List.fold_left (fun c (n,t) -> mkProd (n, t, c)) init
-let it_mkLambda init = List.fold_left (fun c (n,t) -> mkLambda (n, t, c)) init
-
-let it_named_context_quantifier f ~init =
- List.fold_left (fun c d -> f d c) init
-
-let it_mkProd_or_LetIn init = it_named_context_quantifier mkProd_or_LetIn ~init
-let it_mkProd_wo_LetIn init = it_named_context_quantifier mkProd_wo_LetIn ~init
-let it_mkLambda_or_LetIn init = it_named_context_quantifier mkLambda_or_LetIn ~init
-let it_mkNamedProd_or_LetIn init = it_named_context_quantifier mkNamedProd_or_LetIn ~init
-let it_mkNamedProd_wo_LetIn init = it_named_context_quantifier mkNamedProd_wo_LetIn ~init
-let it_mkNamedLambda_or_LetIn init = it_named_context_quantifier mkNamedLambda_or_LetIn ~init
-
-let it_mkLambda_or_LetIn_from_no_LetIn c decls =
- let rec aux k decls c = match decls with
- | [] -> c
- | (na,Some b,t)::decls -> mkLetIn (na,b,t,aux (k-1) decls (liftn 1 k c))
- | (na,None,t)::decls -> mkLambda (na,t,aux (k-1) decls c)
- in aux (List.length decls) (List.rev decls) c
-
-(* *)
-
-(* strips head casts and flattens head applications *)
-let rec strip_head_cast c = match kind_of_term c with
- | App (f,cl) ->
- let rec collapse_rec f cl2 = match kind_of_term f with
- | App (g,cl1) -> collapse_rec g (Array.append cl1 cl2)
- | Cast (c,_,_) -> collapse_rec c cl2
- | _ -> if Int.equal (Array.length cl2) 0 then f else mkApp (f,cl2)
- in
- collapse_rec f cl
- | Cast (c,_,_) -> strip_head_cast c
- | _ -> c
-
-let rec drop_extra_implicit_args c = match kind_of_term c with
- (* Removed trailing extra implicit arguments, what improves compatibility
- for constants with recently added maximal implicit arguments *)
- | App (f,args) when isEvar (Array.last args) ->
- drop_extra_implicit_args
- (mkApp (f,fst (Array.chop (Array.length args - 1) args)))
- | _ -> c
-
-(* Get the last arg of an application *)
-let last_arg c = match kind_of_term c with
- | App (f,cl) -> Array.last cl
- | _ -> anomaly (Pp.str "last_arg")
-
-(* Get the last arg of an application *)
-let decompose_app_vect c =
- match kind_of_term c with
- | App (f,cl) -> (f, cl)
- | _ -> (c,[||])
-
-let adjust_app_list_size f1 l1 f2 l2 =
- let len1 = List.length l1 and len2 = List.length l2 in
- if Int.equal len1 len2 then (f1,l1,f2,l2)
- else if len1 < len2 then
- let extras,restl2 = List.chop (len2-len1) l2 in
- (f1, l1, applist (f2,extras), restl2)
- else
- let extras,restl1 = List.chop (len1-len2) l1 in
- (applist (f1,extras), restl1, f2, l2)
-
-let adjust_app_array_size f1 l1 f2 l2 =
- let len1 = Array.length l1 and len2 = Array.length l2 in
- if Int.equal len1 len2 then (f1,l1,f2,l2)
- else if len1 < len2 then
- let extras,restl2 = Array.chop (len2-len1) l2 in
- (f1, l1, appvect (f2,extras), restl2)
- else
- let extras,restl1 = Array.chop (len1-len2) l1 in
- (appvect (f1,extras), restl1, f2, l2)
-
-(* [map_constr_with_named_binders g f l c] maps [f l] on the immediate
- subterms of [c]; it carries an extra data [l] (typically a name
- list) which is processed by [g na] (which typically cons [na] to
- [l]) at each binder traversal (with name [na]); it is not recursive
- and the order with which subterms are processed is not specified *)
-
-let map_constr_with_named_binders g f l c = match kind_of_term c with
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c
- | Cast (c,k,t) -> mkCast (f l c, k, f l t)
- | Prod (na,t,c) -> mkProd (na, f l t, f (g na l) c)
- | Lambda (na,t,c) -> mkLambda (na, f l t, f (g na l) c)
- | LetIn (na,b,t,c) -> mkLetIn (na, f l b, f l t, f (g na l) c)
- | App (c,al) -> mkApp (f l c, Array.map (f l) al)
- | Proj (p,c) -> mkProj (p, f l c)
- | Evar (e,al) -> mkEvar (e, Array.map (f l) al)
- | Case (ci,p,c,bl) -> mkCase (ci, f l p, f l c, Array.map (f l) bl)
- | Fix (ln,(lna,tl,bl)) ->
- let l' = Array.fold_left (fun l na -> g na l) l lna in
- mkFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
- | CoFix(ln,(lna,tl,bl)) ->
- let l' = Array.fold_left (fun l na -> g na l) l lna in
- mkCoFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
-
-(* [map_constr_with_binders_left_to_right g f n c] maps [f n] on the
- immediate subterms of [c]; it carries an extra data [n] (typically
- a lift index) which is processed by [g] (which typically add 1 to
- [n]) at each binder traversal; the subterms are processed from left
- to right according to the usual representation of the constructions
- (this may matter if [f] does a side-effect); it is not recursive;
- in fact, the usual representation of the constructions is at the
- time being almost those of the ML representation (except for
- (co-)fixpoint) *)
-
-let fold_rec_types g (lna,typarray,_) e =
- let ctxt = Array.map2_i (fun i na t -> (na, None, lift i t)) lna typarray in
- Array.fold_left (fun e assum -> g assum e) e ctxt
-
-let map_left2 f a g b =
- let l = Array.length a in
- if Int.equal l 0 then [||], [||] else begin
- let r = Array.make l (f a.(0)) in
- let s = Array.make l (g b.(0)) in
- for i = 1 to l - 1 do
- r.(i) <- f a.(i);
- s.(i) <- g b.(i)
- done;
- r, s
- end
-
-let map_constr_with_binders_left_to_right g f l c = match kind_of_term c with
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c
- | Cast (b,k,t) ->
- let b' = f l b in
- let t' = f l t in
- if b' == b && t' == t then c
- else mkCast (b',k,t')
- | Prod (na,t,b) ->
- let t' = f l t in
- let b' = f (g (na,None,t) l) b in
- if t' == t && b' == b then c
- else mkProd (na, t', b')
- | Lambda (na,t,b) ->
- let t' = f l t in
- let b' = f (g (na,None,t) l) b in
- if t' == t && b' == b then c
- else mkLambda (na, t', b')
- | LetIn (na,bo,t,b) ->
- let bo' = f l bo in
- let t' = f l t in
- let b' = f (g (na,Some bo,t) l) b in
- if bo' == bo && t' == t && b' == b then c
- else mkLetIn (na, bo', t', b')
- | App (c,[||]) -> assert false
- | App (t,al) ->
- (*Special treatment to be able to recognize partially applied subterms*)
- let a = al.(Array.length al - 1) in
- let app = (mkApp (t, Array.sub al 0 (Array.length al - 1))) in
- let app' = f l app in
- let a' = f l a in
- if app' == app && a' == a then c
- else mkApp (app', [| a' |])
- | Proj (p,b) ->
- let b' = f l b in
- if b' == b then c
- else mkProj (p, b')
- | Evar (e,al) ->
- let al' = Array.map_left (f l) al in
- if Array.for_all2 (==) al' al then c
- else mkEvar (e, al')
- | Case (ci,p,b,bl) ->
- (* In v8 concrete syntax, predicate is after the term to match! *)
- let b' = f l b in
- let p' = f l p in
- let bl' = Array.map_left (f l) bl in
- if b' == b && p' == p && bl' == bl then c
- else mkCase (ci, p', b', bl')
- | Fix (ln,(lna,tl,bl as fx)) ->
- let l' = fold_rec_types g fx l in
- let (tl', bl') = map_left2 (f l) tl (f l') bl in
- if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
- then c
- else mkFix (ln,(lna,tl',bl'))
- | CoFix(ln,(lna,tl,bl as fx)) ->
- let l' = fold_rec_types g fx l in
- let (tl', bl') = map_left2 (f l) tl (f l') bl in
- if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
- then c
- else mkCoFix (ln,(lna,tl',bl'))
-
-(* strong *)
-let map_constr_with_full_binders g f l cstr = match kind_of_term cstr with
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> cstr
- | Cast (c,k, t) ->
- let c' = f l c in
- let t' = f l t in
- if c==c' && t==t' then cstr else mkCast (c', k, t')
- | Prod (na,t,c) ->
- let t' = f l t in
- let c' = f (g (na,None,t) l) c in
- if t==t' && c==c' then cstr else mkProd (na, t', c')
- | Lambda (na,t,c) ->
- let t' = f l t in
- let c' = f (g (na,None,t) l) c in
- if t==t' && c==c' then cstr else mkLambda (na, t', c')
- | LetIn (na,b,t,c) ->
- let b' = f l b in
- let t' = f l t in
- let c' = f (g (na,Some b,t) l) c in
- if b==b' && t==t' && c==c' then cstr else mkLetIn (na, b', t', c')
- | App (c,al) ->
- let c' = f l c in
- let al' = Array.map (f l) al in
- if c==c' && Array.for_all2 (==) al al' then cstr else mkApp (c', al')
- | Proj (p,c) ->
- let c' = f l c in
- if c' == c then cstr else mkProj (p, c')
- | Evar (e,al) ->
- let al' = Array.map (f l) al in
- if Array.for_all2 (==) al al' then cstr else mkEvar (e, al')
- | Case (ci,p,c,bl) ->
- let p' = f l p in
- let c' = f l c in
- let bl' = Array.map (f l) bl in
- if p==p' && c==c' && Array.for_all2 (==) bl bl' then cstr else
- mkCase (ci, p', c', bl')
- | Fix (ln,(lna,tl,bl)) ->
- let tl' = Array.map (f l) tl in
- let l' =
- Array.fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- let bl' = Array.map (f l') bl in
- if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
- then cstr
- else mkFix (ln,(lna,tl',bl'))
- | CoFix(ln,(lna,tl,bl)) ->
- let tl' = Array.map (f l) tl in
- let l' =
- Array.fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- let bl' = Array.map (f l') bl in
- if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl'
- then cstr
- else mkCoFix (ln,(lna,tl',bl'))
-
-(* [fold_constr_with_binders g f n acc c] folds [f n] on the immediate
- subterms of [c] starting from [acc] and proceeding from left to
- right according to the usual representation of the constructions as
- [fold_constr] but it carries an extra data [n] (typically a lift
- index) which is processed by [g] (which typically add 1 to [n]) at
- each binder traversal; it is not recursive *)
-
-let fold_constr_with_full_binders g f n acc c = match kind_of_term c with
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> acc
- | Cast (c,_, t) -> f n (f n acc c) t
- | Prod (na,t,c) -> f (g (na,None,t) n) (f n acc t) c
- | Lambda (na,t,c) -> f (g (na,None,t) n) (f n acc t) c
- | LetIn (na,b,t,c) -> f (g (na,Some b,t) n) (f n (f n acc b) t) c
- | App (c,l) -> Array.fold_left (f n) (f n acc c) l
- | Proj (p,c) -> f n acc c
- | Evar (_,l) -> Array.fold_left (f n) acc l
- | Case (_,p,c,bl) -> Array.fold_left (f n) (f n (f n acc p) c) bl
- | Fix (_,(lna,tl,bl)) ->
- let n' = CArray.fold_left2 (fun c n t -> g (n,None,t) c) n lna tl in
- let fd = Array.map2 (fun t b -> (t,b)) tl bl in
- Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
- | CoFix (_,(lna,tl,bl)) ->
- let n' = CArray.fold_left2 (fun c n t -> g (n,None,t) c) n lna tl in
- let fd = Array.map2 (fun t b -> (t,b)) tl bl in
- Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
-
-let fold_constr_with_binders g f n acc c =
- fold_constr_with_full_binders (fun _ x -> g x) f n acc c
-
-(* [iter_constr_with_full_binders g f acc c] iters [f acc] on the immediate
- subterms of [c]; it carries an extra data [acc] which is processed by [g] at
- each binder traversal; it is not recursive and the order with which
- subterms are processed is not specified *)
-
-let iter_constr_with_full_binders g f l c = match kind_of_term c with
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> ()
- | Cast (c,_, t) -> f l c; f l t
- | Prod (na,t,c) -> f l t; f (g (na,None,t) l) c
- | Lambda (na,t,c) -> f l t; f (g (na,None,t) l) c
- | LetIn (na,b,t,c) -> f l b; f l t; f (g (na,Some b,t) l) c
- | App (c,args) -> f l c; Array.iter (f l) args
- | Proj (p,c) -> f l c
- | Evar (_,args) -> Array.iter (f l) args
- | Case (_,p,c,bl) -> f l p; f l c; Array.iter (f l) bl
- | Fix (_,(lna,tl,bl)) ->
- let l' = Array.fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- Array.iter (f l) tl;
- Array.iter (f l') bl
- | CoFix (_,(lna,tl,bl)) ->
- let l' = Array.fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- Array.iter (f l) tl;
- Array.iter (f l') bl
-
-(***************************)
-(* occurs check functions *)
-(***************************)
-
-exception Occur
-
-let occur_meta c =
- let rec occrec c = match kind_of_term c with
- | Meta _ -> raise Occur
- | _ -> iter_constr occrec c
- in try occrec c; false with Occur -> true
-
-let occur_existential c =
- let rec occrec c = match kind_of_term c with
- | Evar _ -> raise Occur
- | _ -> iter_constr occrec c
- in try occrec c; false with Occur -> true
-
-let occur_meta_or_existential c =
- let rec occrec c = match kind_of_term c with
- | Evar _ -> raise Occur
- | Meta _ -> raise Occur
- | _ -> iter_constr occrec c
- in try occrec c; false with Occur -> true
-
-let occur_evar n c =
- let rec occur_rec c = match kind_of_term c with
- | Evar (sp,_) when Evar.equal sp n -> raise Occur
- | _ -> iter_constr occur_rec c
- in
- try occur_rec c; false with Occur -> true
-
-let occur_in_global env id constr =
- let vars = vars_of_global env constr in
- if Id.Set.mem id vars then raise Occur
-
-let occur_var env id c =
- let rec occur_rec c =
- match kind_of_term c with
- | Var _ | Const _ | Ind _ | Construct _ -> occur_in_global env id c
- | _ -> iter_constr occur_rec c
- in
- try occur_rec c; false with Occur -> true
-
-let occur_var_in_decl env hyp (_,c,typ) =
- match c with
- | None -> occur_var env hyp typ
- | Some body ->
- occur_var env hyp typ ||
- occur_var env hyp body
-
-(* returns the list of free debruijn indices in a term *)
-
-let free_rels m =
- let rec frec depth acc c = match kind_of_term c with
- | Rel n -> if n >= depth then Int.Set.add (n-depth+1) acc else acc
- | _ -> fold_constr_with_binders succ frec depth acc c
- in
- frec 1 Int.Set.empty m
-
-(* collects all metavar occurrences, in left-to-right order, preserving
- * repetitions and all. *)
-
-let collect_metas c =
- let rec collrec acc c =
- match kind_of_term c with
- | Meta mv -> List.add_set Int.equal mv acc
- | _ -> fold_constr collrec acc c
- in
- List.rev (collrec [] c)
-
-(* collects all vars; warning: this is only visible vars, not dependencies in
- all section variables; for the latter, use global_vars_set *)
-let collect_vars c =
- let rec aux vars c = match kind_of_term c with
- | Var id -> Id.Set.add id vars
- | _ -> fold_constr aux vars c in
- aux Id.Set.empty c
-
-(* Tests whether [m] is a subterm of [t]:
- [m] is appropriately lifted through abstractions of [t] *)
-
-let dependent_main noevar univs m t =
- let eqc x y = if univs then fst (Universes.eq_constr_universes x y) else eq_constr_nounivs x y in
- let rec deprec m t =
- if eqc m t then
- raise Occur
- else
- match kind_of_term m, kind_of_term t with
- | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt ->
- deprec m (mkApp (ft,Array.sub lt 0 (Array.length lm)));
- CArray.Fun1.iter deprec m
- (Array.sub lt
- (Array.length lm) ((Array.length lt) - (Array.length lm)))
- | _, Cast (c,_,_) when noevar && isMeta c -> ()
- | _, Evar _ when noevar -> ()
- | _ -> iter_constr_with_binders (fun c -> lift 1 c) deprec m t
- in
- try deprec m t; false with Occur -> true
-
-let dependent = dependent_main false false
-let dependent_no_evar = dependent_main true false
-
-let dependent_univs = dependent_main false true
-let dependent_univs_no_evar = dependent_main true true
-
-let dependent_in_decl a (_,c,t) =
- match c with
- | None -> dependent a t
- | Some body -> dependent a body || dependent a t
-
-let count_occurrences m t =
- let n = ref 0 in
- let rec countrec m t =
- if eq_constr m t then
- incr n
- else
- match kind_of_term m, kind_of_term t with
- | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt ->
- countrec m (mkApp (ft,Array.sub lt 0 (Array.length lm)));
- Array.iter (countrec m)
- (Array.sub lt
- (Array.length lm) ((Array.length lt) - (Array.length lm)))
- | _, Cast (c,_,_) when isMeta c -> ()
- | _, Evar _ -> ()
- | _ -> iter_constr_with_binders (lift 1) countrec m t
- in
- countrec m t;
- !n
-
-(* Synonymous *)
-let occur_term = dependent
-
-let pop t = lift (-1) t
-
-(***************************)
-(* bindings functions *)
-(***************************)
-
-type meta_type_map = (metavariable * types) list
-
-type meta_value_map = (metavariable * constr) list
-
-let rec subst_meta bl c =
- match kind_of_term c with
- | Meta i -> (try Int.List.assoc i bl with Not_found -> c)
- | _ -> map_constr (subst_meta bl) c
-
-(* First utilities for avoiding telescope computation for subst_term *)
-
-let prefix_application eq_fun (k,c) (t : constr) =
- let c' = collapse_appl c and t' = collapse_appl t in
- match kind_of_term c', kind_of_term t' with
- | App (f1,cl1), App (f2,cl2) ->
- let l1 = Array.length cl1
- and l2 = Array.length cl2 in
- if l1 <= l2
- && eq_fun c' (mkApp (f2, Array.sub cl2 0 l1)) then
- Some (mkApp (mkRel k, Array.sub cl2 l1 (l2 - l1)))
- else
- None
- | _ -> None
-
-let my_prefix_application eq_fun (k,c) (by_c : constr) (t : constr) =
- let c' = collapse_appl c and t' = collapse_appl t in
- match kind_of_term c', kind_of_term t' with
- | App (f1,cl1), App (f2,cl2) ->
- let l1 = Array.length cl1
- and l2 = Array.length cl2 in
- if l1 <= l2
- && eq_fun c' (mkApp (f2, Array.sub cl2 0 l1)) then
- Some (mkApp ((lift k by_c), Array.sub cl2 l1 (l2 - l1)))
- else
- None
- | _ -> None
-
-(* Recognizing occurrences of a given subterm in a term: [subst_term c t]
- substitutes [(Rel 1)] for all occurrences of term [c] in a term [t];
- works if [c] has rels *)
-
-let subst_term_gen eq_fun c t =
- let rec substrec (k,c as kc) t =
- match prefix_application eq_fun kc t with
- | Some x -> x
- | None ->
- if eq_fun c t then mkRel k
- else
- map_constr_with_binders (fun (k,c) -> (k+1,lift 1 c)) substrec kc t
- in
- substrec (1,c) t
-
-let subst_term = subst_term_gen eq_constr
-
-(* Recognizing occurrences of a given subterm in a term :
- [replace_term c1 c2 t] substitutes [c2] for all occurrences of
- term [c1] in a term [t]; works if [c1] and [c2] have rels *)
-
-let replace_term_gen eq_fun c by_c in_t =
- let rec substrec (k,c as kc) t =
- match my_prefix_application eq_fun kc by_c t with
- | Some x -> x
- | None ->
- (if eq_fun c t then (lift k by_c) else
- map_constr_with_binders (fun (k,c) -> (k+1,lift 1 c))
- substrec kc t)
- in
- substrec (0,c) in_t
-
-let replace_term = replace_term_gen eq_constr
-
-let vars_of_env env =
- let s =
- Context.fold_named_context (fun (id,_,_) s -> Id.Set.add id s)
- (named_context env) ~init:Id.Set.empty in
- Context.fold_rel_context
- (fun (na,_,_) s -> match na with Name id -> Id.Set.add id s | _ -> s)
- (rel_context env) ~init:s
-
-let add_vname vars = function
- Name id -> Id.Set.add id vars
- | _ -> vars
-
-(*************************)
-(* Names environments *)
-(*************************)
-type names_context = Name.t list
-let add_name n nl = n::nl
-let lookup_name_of_rel p names =
- try List.nth names (p-1)
- with Invalid_argument _ | Failure _ -> raise Not_found
-let lookup_rel_of_name id names =
- let rec lookrec n = function
- | Anonymous :: l -> lookrec (n+1) l
- | (Name id') :: l -> if Id.equal id' id then n else lookrec (n+1) l
- | [] -> raise Not_found
- in
- lookrec 1 names
-let empty_names_context = []
-
-let ids_of_rel_context sign =
- Context.fold_rel_context
- (fun (na,_,_) l -> match na with Name id -> id::l | Anonymous -> l)
- sign ~init:[]
-
-let ids_of_named_context sign =
- Context.fold_named_context (fun (id,_,_) idl -> id::idl) sign ~init:[]
-
-let ids_of_context env =
- (ids_of_rel_context (rel_context env))
- @ (ids_of_named_context (named_context env))
-
-
-let names_of_rel_context env =
- List.map (fun (na,_,_) -> na) (rel_context env)
-
-let is_section_variable id =
- try let _ = Global.lookup_named id in true
- with Not_found -> false
-
-let isGlobalRef c =
- match kind_of_term c with
- | Const _ | Ind _ | Construct _ | Var _ -> true
- | _ -> false
-
-let is_template_polymorphic env f =
- match kind_of_term f with
- | Ind ind -> Environ.template_polymorphic_pind ind env
- | Const c -> Environ.template_polymorphic_pconstant c env
- | _ -> false
-
-let base_sort_cmp pb s0 s1 =
- match (s0,s1) with
- | (Prop c1, Prop c2) -> c1 == Null || c2 == Pos (* Prop <= Set *)
- | (Prop c1, Type u) -> pb == Reduction.CUMUL
- | (Type u1, Type u2) -> true
- | _ -> false
-
-(* eq_constr extended with universe erasure *)
-let compare_constr_univ f cv_pb t1 t2 =
- match kind_of_term t1, kind_of_term t2 with
- Sort s1, Sort s2 -> base_sort_cmp cv_pb s1 s2
- | Prod (_,t1,c1), Prod (_,t2,c2) ->
- f Reduction.CONV t1 t2 && f cv_pb c1 c2
- | _ -> compare_constr (fun t1 t2 -> f Reduction.CONV t1 t2) t1 t2
-
-let rec constr_cmp cv_pb t1 t2 = compare_constr_univ constr_cmp cv_pb t1 t2
-
-let eq_constr t1 t2 = constr_cmp Reduction.CONV t1 t2
-
-(* App(c,[t1,...tn]) -> ([c,t1,...,tn-1],tn)
- App(c,[||]) -> ([],c) *)
-let split_app c = match kind_of_term c with
- App(c,l) ->
- let len = Array.length l in
- if Int.equal len 0 then ([],c) else
- let last = Array.get l (len-1) in
- let prev = Array.sub l 0 (len-1) in
- c::(Array.to_list prev), last
- | _ -> assert false
-
-type subst = (rel_context*constr) Evar.Map.t
-
-exception CannotFilter
-
-let filtering env cv_pb c1 c2 =
- let evm = ref Evar.Map.empty in
- let define cv_pb e1 ev c1 =
- try let (e2,c2) = Evar.Map.find ev !evm in
- let shift = List.length e1 - List.length e2 in
- if constr_cmp cv_pb c1 (lift shift c2) then () else raise CannotFilter
- with Not_found ->
- evm := Evar.Map.add ev (e1,c1) !evm
- in
- let rec aux env cv_pb c1 c2 =
- match kind_of_term c1, kind_of_term c2 with
- | App _, App _ ->
- let ((p1,l1),(p2,l2)) = (split_app c1),(split_app c2) in
- let () = aux env cv_pb l1 l2 in
- begin match p1, p2 with
- | [], [] -> ()
- | (h1 :: p1), (h2 :: p2) ->
- aux env cv_pb (applistc h1 p1) (applistc h2 p2)
- | _ -> assert false
- end
- | Prod (n,t1,c1), Prod (_,t2,c2) ->
- aux env cv_pb t1 t2;
- aux ((n,None,t1)::env) cv_pb c1 c2
- | _, Evar (ev,_) -> define cv_pb env ev c1
- | Evar (ev,_), _ -> define cv_pb env ev c2
- | _ ->
- if compare_constr_univ
- (fun pb c1 c2 -> aux env pb c1 c2; true) cv_pb c1 c2 then ()
- else raise CannotFilter
- (* TODO: le reste des binders *)
- in
- aux env cv_pb c1 c2; !evm
-
-let decompose_prod_letin : constr -> int * rel_context * constr =
- let rec prodec_rec i l c = match kind_of_term c with
- | Prod (n,t,c) -> prodec_rec (succ i) ((n,None,t)::l) c
- | LetIn (n,d,t,c) -> prodec_rec (succ i) ((n,Some d,t)::l) c
- | Cast (c,_,_) -> prodec_rec i l c
- | _ -> i,l,c in
- prodec_rec 0 []
-
-let align_prod_letin c a : rel_context * constr =
- let (lc,_,_) = decompose_prod_letin c in
- let (la,l,a) = decompose_prod_letin a in
- if not (la >= lc) then invalid_arg "align_prod_letin";
- let (l1,l2) = Util.List.chop lc l in
- l2,it_mkProd_or_LetIn a l1
-
-(* We reduce a series of head eta-redex or nothing at all *)
-(* [x1:c1;...;xn:cn]@(f;a1...an;x1;...;xn) --> @(f;a1...an) *)
-(* Remplace 2 earlier buggish versions *)
-
-let rec eta_reduce_head c =
- match kind_of_term c with
- | Lambda (_,c1,c') ->
- (match kind_of_term (eta_reduce_head c') with
- | App (f,cl) ->
- let lastn = (Array.length cl) - 1 in
- if lastn < 0 then anomaly (Pp.str "application without arguments")
- else
- (match kind_of_term cl.(lastn) with
- | Rel 1 ->
- let c' =
- if Int.equal lastn 0 then f
- else mkApp (f, Array.sub cl 0 lastn)
- in
- if noccurn 1 c'
- then lift (-1) c'
- else c
- | _ -> c)
- | _ -> c)
- | _ -> c
-
-
-(* iterator on rel context *)
-let process_rel_context f env =
- let sign = named_context_val env in
- let rels = rel_context env in
- let env0 = reset_with_named_context sign env in
- Context.fold_rel_context f rels ~init:env0
-
-let assums_of_rel_context sign =
- Context.fold_rel_context
- (fun (na,c,t) l ->
- match c with
- Some _ -> l
- | None -> (na, t)::l)
- sign ~init:[]
-
-let map_rel_context_in_env f env sign =
- let rec aux env acc = function
- | d::sign ->
- aux (push_rel d env) (map_rel_declaration (f env) d :: acc) sign
- | [] ->
- acc
- in
- aux env [] (List.rev sign)
-
-let map_rel_context_with_binders f sign =
- let rec aux k = function
- | d::sign -> map_rel_declaration (f k) d :: aux (k-1) sign
- | [] -> []
- in
- aux (rel_context_length sign) sign
-
-let substl_rel_context l =
- map_rel_context_with_binders (fun k -> substnl l (k-1))
-
-let lift_rel_context n =
- map_rel_context_with_binders (liftn n)
-
-let smash_rel_context sign =
- let rec aux acc = function
- | [] -> acc
- | (_,None,_ as d) :: l -> aux (d::acc) l
- | (_,Some b,_) :: l ->
- (* Quadratic in the number of let but there are probably a few of them *)
- aux (List.rev (substl_rel_context [b] (List.rev acc))) l
- in List.rev (aux [] sign)
-
-let adjust_subst_to_rel_context sign l =
- let rec aux subst sign l =
- match sign, l with
- | (_,None,_)::sign', a::args' -> aux (a::subst) sign' args'
- | (_,Some c,_)::sign', args' ->
- aux (substl subst c :: subst) sign' args'
- | [], [] -> List.rev subst
- | _ -> anomaly (Pp.str "Instance and signature do not match")
- in aux [] (List.rev sign) l
-
-let fold_named_context_both_sides f l ~init = List.fold_right_and_left f l init
-
-let rec mem_named_context id = function
- | (id',_,_) :: _ when Id.equal id id' -> true
- | _ :: sign -> mem_named_context id sign
- | [] -> false
-
-let compact_named_context_reverse sign =
- let compact l (i1,c1,t1) =
- match l with
- | [] -> [[i1],c1,t1]
- | (l2,c2,t2)::q ->
- if Option.equal Constr.equal c1 c2 && Constr.equal t1 t2
- then (i1::l2,c2,t2)::q
- else ([i1],c1,t1)::l
- in Context.fold_named_context_reverse compact ~init:[] sign
-
-let compact_named_context sign = List.rev (compact_named_context_reverse sign)
-
-let clear_named_body id env =
- let aux _ = function
- | (id',Some c,t) when Id.equal id id' -> push_named (id,None,t)
- | d -> push_named d in
- fold_named_context aux env ~init:(reset_context env)
-
-let global_vars env ids = Id.Set.elements (global_vars_set env ids)
-
-let global_vars_set_of_decl env = function
- | (_,None,t) -> global_vars_set env t
- | (_,Some c,t) ->
- Id.Set.union (global_vars_set env t)
- (global_vars_set env c)
-
-let dependency_closure env sign hyps =
- if Id.Set.is_empty hyps then [] else
- let (_,lh) =
- Context.fold_named_context_reverse
- (fun (hs,hl) (x,_,_ as d) ->
- if Id.Set.mem x hs then
- (Id.Set.union (global_vars_set_of_decl env d) (Id.Set.remove x hs),
- x::hl)
- else (hs,hl))
- ~init:(hyps,[])
- sign in
- List.rev lh
-
-(* Combinators on judgments *)
-
-let on_judgment f j = { uj_val = f j.uj_val; uj_type = f j.uj_type }
-let on_judgment_value f j = { j with uj_val = f j.uj_val }
-let on_judgment_type f j = { j with uj_type = f j.uj_type }
-
-(* Cut a context ctx in 2 parts (ctx1,ctx2) with ctx1 containing k
- variables; skips let-in's *)
-let context_chop k ctx =
- let rec chop_aux acc = function
- | (0, l2) -> (List.rev acc, l2)
- | (n, ((_,Some _,_ as h)::t)) -> chop_aux (h::acc) (n, t)
- | (n, (h::t)) -> chop_aux (h::acc) (pred n, t)
- | (_, []) -> anomaly (Pp.str "context_chop")
- in chop_aux [] (k,ctx)
-
-(* Do not skip let-in's *)
-let env_rel_context_chop k env =
- let rels = rel_context env in
- let ctx1,ctx2 = List.chop k rels in
- push_rel_context ctx2 (reset_with_named_context (named_context_val env) env),
- ctx1
-
-(*******************************************)
-(* Functions to deal with impossible cases *)
-(*******************************************)
-let impossible_default_case = ref None
-
-let set_impossible_default_clause c = impossible_default_case := Some c
-
-let coq_unit_judge =
- let na1 = Name (Id.of_string "A") in
- let na2 = Name (Id.of_string "H") in
- fun () ->
- match !impossible_default_case with
- | Some fn ->
- let (id,type_of_id), ctx = fn () in
- make_judge id type_of_id, ctx
- | None ->
- (* In case the constants id/ID are not defined *)
- make_judge (mkLambda (na1,mkProp,mkLambda(na2,mkRel 1,mkRel 1)))
- (mkProd (na1,mkProp,mkArrow (mkRel 1) (mkRel 2))),
- Univ.ContextSet.empty