diff options
Diffstat (limited to 'pretyping/termops.ml')
-rw-r--r-- | pretyping/termops.ml | 521 |
1 files changed, 183 insertions, 338 deletions
diff --git a/pretyping/termops.ml b/pretyping/termops.ml index 4f38fbb3..3e4c5ae5 100644 --- a/pretyping/termops.ml +++ b/pretyping/termops.ml @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: termops.ml 12058 2009-04-08 10:54:59Z herbelin $ *) +(* $Id$ *) open Pp open Util @@ -34,7 +34,7 @@ let pr_name = function | Name id -> pr_id id | Anonymous -> str "_" -let pr_sp sp = str(string_of_kn sp) +let pr_path sp = str(string_of_kn sp) let pr_con sp = str(string_of_con sp) let rec pr_constr c = match kind_of_term c with @@ -42,7 +42,7 @@ let rec pr_constr c = match kind_of_term c with | Meta n -> str "Meta(" ++ int n ++ str ")" | Var id -> pr_id id | Sort s -> print_sort s - | Cast (c,_, t) -> hov 1 + | Cast (c,_, t) -> hov 1 (str"(" ++ pr_constr c ++ cut() ++ str":" ++ pr_constr t ++ str")") | Prod (Name(id),t,c) -> hov 1 @@ -65,9 +65,9 @@ let rec pr_constr c = match kind_of_term c with (str"Evar#" ++ int e ++ str"{" ++ prlist_with_sep spc pr_constr (Array.to_list l) ++str"}") | Const c -> str"Cst(" ++ pr_con c ++ str")" - | Ind (sp,i) -> str"Ind(" ++ pr_sp sp ++ str"," ++ int i ++ str")" + | Ind (sp,i) -> str"Ind(" ++ pr_mind sp ++ str"," ++ int i ++ str")" | Construct ((sp,i),j) -> - str"Constr(" ++ pr_sp sp ++ str"," ++ int i ++ str"," ++ int j ++ str")" + str"Constr(" ++ pr_mind sp ++ str"," ++ int i ++ str"," ++ int j ++ str")" | Case (ci,p,c,bl) -> v 0 (hv 0 (str"<"++pr_constr p++str">"++ cut() ++ str"Case " ++ pr_constr c ++ str"of") ++ cut() ++ @@ -99,7 +99,7 @@ let pr_var_decl env (id,c,typ) = let pbody = match c with | None -> (mt ()) | Some c -> - (* Force evaluation *) + (* Force evaluation *) let pb = print_constr_env env c in (str" := " ++ pb ++ cut () ) in let pt = print_constr_env env typ in @@ -110,7 +110,7 @@ let pr_rel_decl env (na,c,typ) = let pbody = match c with | None -> mt () | Some c -> - (* Force evaluation *) + (* Force evaluation *) let pb = print_constr_env env c in (str":=" ++ spc () ++ pb ++ spc ()) in let ptyp = print_constr_env env typ in @@ -120,39 +120,39 @@ let pr_rel_decl env (na,c,typ) = let print_named_context env = hv 0 (fold_named_context - (fun env d pps -> + (fun env d pps -> pps ++ ws 2 ++ pr_var_decl env d) env ~init:(mt ())) -let print_rel_context env = +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 ()) + 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 + in (sign_env ++ db_env) - + (*let current_module = ref empty_dirpath let set_module m = current_module := m*) -let new_univ = +let new_univ = let univ_gen = ref 0 in (fun sp -> - incr univ_gen; + incr univ_gen; Univ.make_univ (Lib.library_dp(),!univ_gen)) let new_Type () = mkType (new_univ ()) let new_Type_sort () = Type (new_univ ()) @@ -173,26 +173,20 @@ let refresh_universes_gen strict t = let refresh_universes = refresh_universes_gen false let refresh_universes_strict = refresh_universes_gen true -let new_sort_in_family = function +let new_sort_in_family = function | InProp -> prop_sort | InSet -> set_sort | InType -> Type (new_univ ()) -(* prod_it b [xn:Tn;..;x1:T1] = (x1:T1)..(xn:Tn)b *) -let prod_it ~init = List.fold_left (fun c (n,t) -> mkProd (n, t, c)) init - -(* lam_it b [xn:Tn;..;x1:T1] = [x1:T1]..[xn:Tn]b *) -let lam_it ~init = List.fold_left (fun c (n,t) -> mkLambda (n, t, c)) init - (* [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 = +let rel_list n m = + let rec reln l p = if p>m then l else reln (mkRel(n+p)::l) (p+1) - in + in reln [] 1 (* Same as [rel_list] but takes a context as argument and skips let-ins *) @@ -201,7 +195,7 @@ let extended_rel_list n hyps = | (_,None,_) :: hyps -> reln (mkRel (n+p) :: l) (p+1) hyps | (_,Some _,_) :: hyps -> reln l (p+1) hyps | [] -> l - in + in reln [] 1 hyps let extended_rel_vect n hyps = Array.of_list (extended_rel_list n hyps) @@ -224,53 +218,49 @@ let push_named_rec_types (lna,typarray,_) env = Array.fold_left (fun e assum -> push_named assum e) env ctxt -let rec lookup_rel_id id sign = +let rec lookup_rel_id id sign = let rec lookrec = function | (n, (Anonymous,_,_)::l) -> lookrec (n+1,l) - | (n, (Name id',_,t)::l) -> if id' = id then (n,t) else lookrec (n+1,l) + | (n, (Name id',b,t)::l) -> if id' = id then (n,b,t) else lookrec (n+1,l) | (_, []) -> raise Not_found - in + in lookrec (1,sign) -(* Constructs either [(x:t)c] or [[x=b:t]c] *) +(* 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 [(x:t)c] or [c] where [x] is replaced by [b] *) +(* 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_wo_LetIn ~init = - List.fold_left (fun c d -> mkProd_wo_LetIn d c) init - -let it_mkProd_or_LetIn ~init = - List.fold_left (fun c d -> mkProd_or_LetIn d c) init - -let it_mkLambda_or_LetIn ~init = - List.fold_left (fun c d -> mkLambda_or_LetIn d c) init +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 = +let it_named_context_quantifier f ~init = List.fold_left (fun c d -> f d c) init +let it_mkProd_or_LetIn = it_named_context_quantifier mkProd_or_LetIn +let it_mkProd_wo_LetIn = it_named_context_quantifier mkProd_wo_LetIn +let it_mkLambda_or_LetIn = it_named_context_quantifier mkLambda_or_LetIn let it_mkNamedProd_or_LetIn = it_named_context_quantifier mkNamedProd_or_LetIn -let it_mkNamedLambda_or_LetIn = it_named_context_quantifier mkNamedLambda_or_LetIn - let it_mkNamedProd_wo_LetIn = it_named_context_quantifier mkNamedProd_wo_LetIn +let it_mkNamedLambda_or_LetIn = it_named_context_quantifier mkNamedLambda_or_LetIn (* *) (* strips head casts and flattens head applications *) let rec strip_head_cast c = match kind_of_term c with - | App (f,cl) -> + | 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 Array.length cl2 = 0 then f else mkApp (f,cl2) - in + in collapse_rec f cl | Cast (c,_,_) -> strip_head_cast c | _ -> c @@ -358,7 +348,7 @@ let map_constr_with_binders_left_to_right g f l c = match kind_of_term c with 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) -> + | 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') @@ -422,7 +412,7 @@ let fold_constr_with_binders g f n acc c = match kind_of_term c with | App (c,l) -> Array.fold_left (f n) (f n acc c) l | 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)) -> + | Fix (_,(lna,tl,bl)) -> let n' = iterate g (Array.length tl) n 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 @@ -446,7 +436,7 @@ let iter_constr_with_full_binders g f l c = match kind_of_term c with | App (c,args) -> f l c; Array.iter (f l) args | 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)) -> + | 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 @@ -456,7 +446,7 @@ let iter_constr_with_full_binders g f l c = match kind_of_term c with Array.iter (f l') bl (***************************) -(* occurs check functions *) +(* occurs check functions *) (***************************) exception Occur @@ -467,42 +457,43 @@ let occur_meta c = | _ -> iter_constr occrec c in try occrec c; false with Occur -> true -let occur_existential c = +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 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_const s c = +let occur_const s c = let rec occur_rec c = match kind_of_term c with | Const sp when sp=s -> raise Occur | _ -> iter_constr occur_rec c - in + in try occur_rec c; false with Occur -> true -let occur_evar n c = +let occur_evar n c = let rec occur_rec c = match kind_of_term c with | Evar (sp,_) when sp=n -> raise Occur | _ -> iter_constr occur_rec c - in + 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 List.mem id vars then raise Occur -let occur_var env s c = +let occur_var env id c = let rec occur_rec c = - occur_in_global env s c; - iter_constr occur_rec c - in + 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) = @@ -512,25 +503,19 @@ let occur_var_in_decl env hyp (_,c,typ) = occur_var env hyp typ || occur_var env hyp body -(* Tests that t is a subterm of c *) -let occur_term t c = - let eq_constr_fail c = if eq_constr t c then raise Occur - in let rec occur_rec c = eq_constr_fail c; iter_constr occur_rec c - in try occur_rec c; false with Occur -> true - (* returns the list of free debruijn indices in a term *) -let free_rels m = +let free_rels m = let rec frec depth acc c = match kind_of_term c with | Rel n -> if n >= depth then Intset.add (n-depth+1) acc else acc | _ -> fold_constr_with_binders succ frec depth acc c - in + in frec 1 Intset.empty m (* collects all metavar occurences, in left-to-right order, preserving * repetitions and all. *) -let collect_metas c = +let collect_metas c = let rec collrec acc c = match kind_of_term c with | Meta mv -> list_add_set mv acc @@ -538,10 +523,10 @@ let collect_metas c = in List.rev (collrec [] c) -(* (dependent M N) is true iff M is eq_term with a subterm of N - M is appropriately lifted through abstractions of N *) +(* Tests whether [m] is a subterm of [t]: + [m] is appropriately lifted through abstractions of [t] *) -let dependent m t = +let dependent_main noevar m t = let rec deprec m t = if eq_constr m t then raise Occur @@ -550,28 +535,38 @@ let dependent m t = | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt -> deprec m (mkApp (ft,Array.sub lt 0 (Array.length lm))); Array.iter (deprec m) - (Array.sub lt + (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 (lift 1) deprec m t - in + in try deprec m t; false with Occur -> true +let dependent = dependent_main false +let dependent_no_evar = dependent_main true + +(* Synonymous *) +let occur_term = dependent + let pop t = lift (-1) t (***************************) -(* bindings functions *) +(* bindings functions *) (***************************) -type metamap = (metavariable * constr) list +type meta_type_map = (metavariable * types) list + +type meta_value_map = (metavariable * constr) list -let rec subst_meta bl c = +let rec subst_meta bl c = match kind_of_term c with | Meta i -> (try 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 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) -> @@ -580,11 +575,11 @@ let prefix_application eq_fun (k,c) (t : constr) = 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 + else None | _ -> None -let my_prefix_application eq_fun (k,c) (by_c : constr) (t : constr) = +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) -> @@ -593,7 +588,7 @@ let my_prefix_application eq_fun (k,c) (by_c : constr) (t : constr) = 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 + else None | _ -> None @@ -602,7 +597,7 @@ let my_prefix_application eq_fun (k,c) (by_c : constr) (t : constr) = term [c] in a term [t] *) (*i Bizarre : si on cherche un sous terme clos, pourquoi le lifter ? i*) -let subst_term_gen eq_fun c t = +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 @@ -610,7 +605,7 @@ let subst_term_gen eq_fun c t = 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 + in substrec (1,c) t (* Recognizing occurrences of a given (closed) subterm in a term : @@ -618,7 +613,7 @@ let subst_term_gen eq_fun c t = term [c1] in a term [t] *) (*i Meme remarque : a priori [c] n'est pas forcement clos i*) -let replace_term_gen eq_fun c by_c in_t = +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 @@ -626,7 +621,7 @@ let replace_term_gen eq_fun c by_c in_t = (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 + in substrec (0,c) in_t let subst_term = subst_term_gen eq_constr @@ -645,7 +640,7 @@ let no_occurrences_in_set = (true,[]) let error_invalid_occurrence l = let l = list_uniquize (List.sort Pervasives.compare l) in errorlabstrm "" - (str ("Invalid occurrence " ^ plural (List.length l) "number" ^": ") ++ + (str ("Invalid occurrence " ^ plural (List.length l) "number" ^": ") ++ prlist_with_sep spc int l ++ str ".") let subst_term_occ_gen (nowhere_except_in,locs) occ c t = @@ -656,10 +651,10 @@ let subst_term_occ_gen (nowhere_except_in,locs) occ c t = if nowhere_except_in & !pos > maxocc then t else if eq_constr c t then - let r = + let r = if nowhere_except_in then if List.mem !pos locs then (mkRel k) else t - else + else if List.mem !pos locs then t else (mkRel k) in incr pos; r else @@ -670,9 +665,9 @@ let subst_term_occ_gen (nowhere_except_in,locs) occ c t = let t' = substrec (1,c) t in (!pos, t') -let subst_term_occ (nowhere_except_in,locs as plocs) c t = +let subst_term_occ (nowhere_except_in,locs as plocs) c t = if locs = [] then if nowhere_except_in then t else subst_term c t - else + else let (nbocc,t') = subst_term_occ_gen plocs 1 c t in let rest = List.filter (fun o -> o >= nbocc) locs in if rest <> [] then error_invalid_occurrence rest; @@ -693,20 +688,15 @@ let subst_term_occ_decl ((nowhere_except_in,locs as plocs),hloc) c (id,bodyopt,t if locs = [] then if nowhere_except_in then d else (id,Some (subst_term c body),subst_term c typ) - else + else let (nbocc,body') = subst_term_occ_gen plocs 1 c body in let (nbocc',t') = subst_term_occ_gen plocs nbocc c typ in let rest = List.filter (fun o -> o >= nbocc') locs in if rest <> [] then error_invalid_occurrence rest; (id,Some body',t') -(* First character of a constr *) - -let lowercase_first_char id = - lowercase_first_char_utf8 (string_of_id id) - let vars_of_env env = - let s = + let s = Sign.fold_named_context (fun (id,_,_) s -> Idset.add id s) (named_context env) ~init:Idset.empty in Sign.fold_rel_context @@ -717,85 +707,6 @@ let add_vname vars = function Name id -> Idset.add id vars | _ -> vars -let id_of_global = Nametab.id_of_global - -let sort_hdchar = function - | Prop(_) -> "P" - | Type(_) -> "T" - -let hdchar env c = - let rec hdrec k c = - match kind_of_term c with - | Prod (_,_,c) -> hdrec (k+1) c - | Lambda (_,_,c) -> hdrec (k+1) c - | LetIn (_,_,_,c) -> hdrec (k+1) c - | Cast (c,_,_) -> hdrec k c - | App (f,l) -> hdrec k f - | Const kn -> - lowercase_first_char (id_of_label (con_label kn)) - | Ind ((kn,i) as x) -> - if i=0 then - lowercase_first_char (id_of_label (label kn)) - else - lowercase_first_char (id_of_global (IndRef x)) - | Construct ((sp,i) as x) -> - lowercase_first_char (id_of_global (ConstructRef x)) - | Var id -> lowercase_first_char id - | Sort s -> sort_hdchar s - | Rel n -> - (if n<=k then "p" (* the initial term is flexible product/function *) - else - try match Environ.lookup_rel (n-k) env with - | (Name id,_,_) -> lowercase_first_char id - | (Anonymous,_,t) -> hdrec 0 (lift (n-k) t) - with Not_found -> "y") - | Fix ((_,i),(lna,_,_)) -> - let id = match lna.(i) with Name id -> id | _ -> assert false in - lowercase_first_char id - | CoFix (i,(lna,_,_)) -> - let id = match lna.(i) with Name id -> id | _ -> assert false in - lowercase_first_char id - | Meta _|Evar _|Case (_, _, _, _) -> "y" - in - hdrec 0 c - -let id_of_name_using_hdchar env a = function - | Anonymous -> id_of_string (hdchar env a) - | Name id -> id - -let named_hd env a = function - | Anonymous -> Name (id_of_string (hdchar env a)) - | x -> x - -let mkProd_name env (n,a,b) = mkProd (named_hd env a n, a, b) -let mkLambda_name env (n,a,b) = mkLambda (named_hd env a n, a, b) - -let lambda_name = mkLambda_name -let prod_name = mkProd_name - -let prod_create env (a,b) = mkProd (named_hd env a Anonymous, a, b) -let lambda_create env (a,b) = mkLambda (named_hd env a Anonymous, a, b) - -let name_assumption env (na,c,t) = - match c with - | None -> (named_hd env t na, None, t) - | Some body -> (named_hd env body na, c, t) - -let name_context env hyps = - snd - (List.fold_left - (fun (env,hyps) d -> - let d' = name_assumption env d in (push_rel d' env, d' :: hyps)) - (env,[]) (List.rev hyps)) - -let mkProd_or_LetIn_name env b d = mkProd_or_LetIn (name_assumption env d) b -let mkLambda_or_LetIn_name env b d = mkLambda_or_LetIn (name_assumption env d)b - -let it_mkProd_or_LetIn_name env b hyps = - it_mkProd_or_LetIn b (name_context env hyps) -let it_mkLambda_or_LetIn_name env b hyps = - it_mkLambda_or_LetIn b (name_context env hyps) - (*************************) (* Names environments *) (*************************) @@ -804,12 +715,12 @@ 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 rec lookup_rel_of_name id names = +let rec lookup_rel_of_name id names = let rec lookrec n = function | Anonymous :: l -> lookrec (n+1) l | (Name id') :: l -> if id' = id then n else lookrec (n+1) l | [] -> raise Not_found - in + in lookrec 1 names let empty_names_context = [] @@ -821,7 +732,7 @@ let ids_of_rel_context sign = let ids_of_named_context sign = Sign.fold_named_context (fun (id,_,_) idl -> id::idl) sign ~init:[] -let ids_of_context env = +let ids_of_context env = (ids_of_rel_context (rel_context env)) @ (ids_of_named_context (named_context env)) @@ -829,57 +740,11 @@ let ids_of_context env = let names_of_rel_context env = List.map (fun (na,_,_) -> na) (rel_context env) -(**** Globality of identifiers *) - -let rec is_imported_modpath = function - | MPfile dp -> true - | p -> false - -let is_imported_ref = function - | VarRef _ -> false - | IndRef (kn,_) - | ConstructRef ((kn,_),_) -> - let (mp,_,_) = repr_kn kn in is_imported_modpath mp - | ConstRef kn -> - let (mp,_,_) = repr_con kn in is_imported_modpath mp - -let is_global id = - try - let ref = locate (make_short_qualid id) in - not (is_imported_ref ref) - with Not_found -> - false - -let is_constructor id = - try - match locate (make_short_qualid id) with - | ConstructRef _ as ref -> not (is_imported_ref ref) - | _ -> false - with Not_found -> - false - let is_section_variable id = try let _ = Global.lookup_named id in true with Not_found -> false -let next_global_ident_from allow_secvar id avoid = - let rec next_rec id = - let id = next_ident_away_from id avoid in - if (allow_secvar && is_section_variable id) || not (is_global id) then - id - else - next_rec (lift_ident id) - in - next_rec id - -let next_global_ident_away allow_secvar id avoid = - let id = next_ident_away id avoid in - if (allow_secvar && is_section_variable id) || not (is_global id) then - id - else - next_global_ident_from allow_secvar (lift_ident id) avoid - -let isGlobalRef c = +let isGlobalRef c = match kind_of_term c with | Const _ | Ind _ | Construct _ | Var _ -> true | _ -> false @@ -889,68 +754,6 @@ let has_polymorphic_type c = | Declarations.PolymorphicArity _ -> true | _ -> false -(* nouvelle version de renommage des variables (DEC 98) *) -(* This is the algorithm to display distinct bound variables - - - Règle 1 : un nom non anonyme, même non affiché, contribue à la liste - des noms à éviter - - Règle 2 : c'est la dépendance qui décide si on affiche ou pas - - Exemple : - si bool_ind = (P:bool->Prop)(f:(P true))(f:(P false))(b:bool)(P b), alors - il est affiché (P:bool->Prop)(P true)->(P false)->(b:bool)(P b) - mais f et f0 contribue à la liste des variables à éviter (en supposant - que les noms f et f0 ne sont pas déjà pris) - Intérêt : noms homogènes dans un but avant et après Intro -*) - -type used_idents = identifier list - -let occur_rel p env id = - try lookup_name_of_rel p env = Name id - with Not_found -> false (* Unbound indice : may happen in debug *) - -let occur_id nenv id0 c = - let rec occur n c = match kind_of_term c with - | Var id when id=id0 -> raise Occur - | Const kn when id_of_global (ConstRef kn) = id0 -> raise Occur - | Ind ind_sp - when id_of_global (IndRef ind_sp) = id0 -> - raise Occur - | Construct cstr_sp - when id_of_global (ConstructRef cstr_sp) = id0 -> - raise Occur - | Rel p when p>n & occur_rel (p-n) nenv id0 -> raise Occur - | _ -> iter_constr_with_binders succ occur n c - in - try occur 1 c; false - with Occur -> true - | Not_found -> false (* Case when a global is not in the env *) - -type avoid_flags = bool option - -let next_name_not_occuring avoid_flags name l env_names t = - let rec next id = - if List.mem id l or occur_id env_names id t or - (* Further restrictions ? *) - match avoid_flags with None -> false | Some not_only_cstr -> - (if not_only_cstr then - (* To be consistent with the intro mechanism *) - is_global id & not (is_section_variable id) - else - (* To avoid constructors in pattern-matchings *) - is_constructor id) - then next (lift_ident id) - else id - in - match name with - | Name id -> next id - | Anonymous -> - (* Normally, an anonymous name is not dependent and will not be *) - (* taken into account by the function concrete_name; just in case *) - (* invent a valid name *) - next (id_of_string "H") - let base_sort_cmp pb s0 s1 = match (s0,s1) with | (Prop c1, Prop c2) -> c1 = Null or c2 = Pos (* Prop <= Set *) @@ -959,14 +762,77 @@ let base_sort_cmp pb s0 s1 = | _ -> false (* eq_constr extended with universe erasure *) -let rec constr_cmp cv_pb t1 t2 = - (match kind_of_term t1, kind_of_term t2 with +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 - | _ -> false) - || compare_constr (constr_cmp cv_pb) t1 t2 + | Prod (_,t1,c1), Prod (_,t2,c2) -> + f Reduction.CONV t1 t2 & f cv_pb c1 c2 + | _ -> compare_constr (f Reduction.CONV) t1 t2 + +let rec constr_cmp cv_pb t1 t2 = compare_constr_univ constr_cmp cv_pb t1 t2 let eq_constr = constr_cmp Reduction.CONV +(* 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 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 + +let hdtl l = List.hd l, List.tl l + +type subst = (rel_context*constr) Intmap.t + +exception CannotFilter + +let filtering env cv_pb c1 c2 = + let evm = ref Intmap.empty in + let define cv_pb e1 ev c1 = + try let (e2,c2) = Intmap.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 := Intmap.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 + aux env cv_pb l1 l2; if p1=[] & p2=[] then () else + aux env cv_pb (applist (hdtl p1)) (applist (hdtl p2)) + | 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 + (* On reduit une serie d'eta-redex de tete ou rien du tout *) (* [x1:c1;...;xn:cn]@(f;a1...an;x1;...;xn) --> @(f;a1...an) *) (* Remplace 2 versions précédentes buggées *) @@ -976,7 +842,7 @@ let rec eta_reduce_head c = | Lambda (_,c1,c') -> (match kind_of_term (eta_reduce_head c') with | App (f,cl) -> - let lastn = (Array.length cl) - 1 in + let lastn = (Array.length cl) - 1 in if lastn < 1 then anomaly "application without arguments" else (match kind_of_term cl.(lastn) with @@ -1017,7 +883,7 @@ let assums_of_rel_context sign = | None -> (na, t)::l) sign ~init:[] -let fold_map_rel_context f env sign = +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 @@ -1039,6 +905,25 @@ let substl_rel_context l = 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 (List.rev subst) c :: subst) sign' args' + | [], [] -> List.rev subst + | _ -> anomaly "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 @@ -1046,14 +931,11 @@ let rec mem_named_context id = function | _ :: sign -> mem_named_context id sign | [] -> false -let make_all_name_different env = - let avoid = ref (ids_of_named_context (named_context env)) in - process_rel_context - (fun (na,c,t) newenv -> - let id = next_name_away na !avoid in - avoid := id::!avoid; - push_rel (Name id,c,t) newenv) - env +let clear_named_body id env = + let rec aux _ = function + | (id',Some c,t) when 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 = Idset.elements (global_vars_set env ids) @@ -1076,50 +958,13 @@ let dependency_closure env sign hyps = sign in List.rev lh -let default_x = id_of_string "x" - -let rec next_name_away_in_cases_pattern id avoid = - let id = match id with Name id -> id | Anonymous -> default_x in - let rec next id = - if List.mem id avoid or is_constructor id then next (lift_ident id) - else id in - next id - -(* Remark: Anonymous var may be dependent in Evar's contexts *) -let concrete_name avoid_flags l env_names n c = - if n = Anonymous & noccurn 1 c then - (Anonymous,l) - else - let fresh_id = next_name_not_occuring avoid_flags n l env_names c in - let idopt = if noccurn 1 c then Anonymous else Name fresh_id in - (idopt, fresh_id::l) - -let concrete_let_name avoid_flags l env_names n c = - let fresh_id = next_name_not_occuring avoid_flags n l env_names c in - (Name fresh_id, fresh_id::l) - -let rec rename_bound_var env avoid c = - let env_names = names_of_rel_context env in - let rec rename avoid c = - match kind_of_term c with - | Prod (na,c1,c2) -> - let na',avoid' = concrete_name None avoid env_names na c2 in - mkProd (na', c1, rename avoid' c2) - | LetIn (na,c1,t,c2) -> - let na',avoid' = concrete_let_name None avoid env_names na c2 in - mkLetIn (na',c1,t, rename avoid' c2) - | Cast (c,k,t) -> mkCast (rename avoid c, k,t) - | _ -> c - in - rename avoid c - (* 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 +(* Cut a context ctx in 2 parts (ctx1,ctx2) with ctx1 containing k variables *) let context_chop k ctx = let rec chop_aux acc = function |