summaryrefslogtreecommitdiff
path: root/pretyping/matching.ml
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping/matching.ml')
-rw-r--r--pretyping/matching.ml357
1 files changed, 0 insertions, 357 deletions
diff --git a/pretyping/matching.ml b/pretyping/matching.ml
deleted file mode 100644
index b86f3e45..00000000
--- a/pretyping/matching.ml
+++ /dev/null
@@ -1,357 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2014 *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-(*i*)
-open Pp
-open Util
-open Names
-open Libnames
-open Nameops
-open Termops
-open Reductionops
-open Term
-open Glob_term
-open Sign
-open Environ
-open Pattern
-(*i*)
-
-(* Given a term with second-order variables in it,
- represented by Meta's, and possibly applied using [SOAPP] to
- terms, this function will perform second-order, binding-preserving,
- matching, in the case where the pattern is a pattern in the sense
- of Dale Miller.
-
- ALGORITHM:
-
- Given a pattern, we decompose it, flattening Cast's and apply's,
- recursing on all operators, and pushing the name of the binder each
- time we descend a binder.
-
- When we reach a first-order variable, we ask that the corresponding
- term's free-rels all be higher than the depth of the current stack.
-
- When we reach a second-order application, we ask that the
- intersection of the free-rels of the term and the current stack be
- contained in the arguments of the application, and in that case, we
- construct a LAMBDA with the names on the stack.
-
- *)
-
-type bound_ident_map = (identifier * identifier) list
-
-exception PatternMatchingFailure
-
-let constrain (n,(ids,m as x)) (names,terms as subst) =
- try
- let (ids',m') = List.assoc n terms in
- if ids = ids' && eq_constr m m' then subst
- else raise PatternMatchingFailure
- with
- Not_found ->
- if List.mem_assoc n names then
- Flags.if_warn Pp.msg_warning
- (str "Collision between bound variable " ++ pr_id n ++
- str " and a metavariable of same name.");
- (names,(n,x)::terms)
-
-let add_binders na1 na2 (names,terms as subst) =
- match na1, na2 with
- | Name id1, Name id2 ->
- if List.mem_assoc id1 names then
- (Flags.if_warn Pp.msg_warning
- (str "Collision between bound variables of name " ++ pr_id id1);
- (names,terms))
- else
- (if List.mem_assoc id1 terms then
- Flags.if_warn Pp.msg_warning
- (str "Collision between bound variable " ++ pr_id id1 ++
- str " and another bound variable of same name.");
- ((id1,id2)::names,terms));
- | _ -> subst
-
-let build_lambda toabstract stk (m : constr) =
- let rec buildrec m p_0 p_1 = match p_0,p_1 with
- | (_, []) -> m
- | (n, (_,na,t)::tl) ->
- if List.mem n toabstract then
- buildrec (mkLambda (na,t,m)) (n+1) tl
- else
- buildrec (lift (-1) m) (n+1) tl
- in
- buildrec m 1 stk
-
-let rec list_insert f a = function
- | [] -> [a]
- | b::l when f a b -> a::b::l
- | b::l when a = b -> raise PatternMatchingFailure
- | b::l -> b :: list_insert f a l
-
-let extract_bound_vars =
- let rec aux k = function
- | ([],_) -> []
- | (n::l,(na1,na2,_)::stk) when k = n ->
- begin match na1,na2 with
- | Name id1,Name _ -> list_insert (<) id1 (aux (k+1) (l,stk))
- | Name _,Anonymous -> anomaly "Unnamed bound variable"
- | Anonymous,_ -> raise PatternMatchingFailure
- end
- | (l,_::stk) -> aux (k+1) (l,stk)
- | (_,[]) -> assert false
- in aux 1
-
-let dummy_constr = mkProp
-
-let rec make_renaming ids = function
- | (Name id,Name _,_)::stk ->
- let renaming = make_renaming ids stk in
- (try mkRel (list_index id ids) :: renaming
- with Not_found -> dummy_constr :: renaming)
- | (_,_,_)::stk ->
- dummy_constr :: make_renaming ids stk
- | [] ->
- []
-
-let merge_binding allow_bound_rels stk n cT subst =
- let depth = List.length stk in
- let c =
- if depth = 0 then
- (* Optimization *)
- ([],cT)
- else
- let frels = Intset.elements (free_rels cT) in
- let frels = List.filter (fun i -> i <= depth) frels in
- if allow_bound_rels then
- let frels = Sort.list (<) frels in
- let canonically_ordered_vars = extract_bound_vars (frels,stk) in
- let renaming = make_renaming canonically_ordered_vars stk in
- (canonically_ordered_vars, substl renaming cT)
- else if frels = [] then
- ([],lift (-depth) cT)
- else
- raise PatternMatchingFailure in
- constrain (n,c) subst
-
-let matches_core convert allow_partial_app allow_bound_rels pat c =
- let conv = match convert with
- | None -> eq_constr
- | Some (env,sigma) -> is_conv env sigma in
- let rec sorec stk subst p t =
- let cT = strip_outer_cast t in
- match p,kind_of_term cT with
- | PSoApp (n,args),m ->
- let relargs =
- List.map
- (function
- | PRel n -> n
- | _ -> error "Only bound indices allowed in second order pattern matching.")
- args in
- let frels = Intset.elements (free_rels cT) in
- if list_subset frels relargs then
- constrain (n,([],build_lambda relargs stk cT)) subst
- else
- raise PatternMatchingFailure
-
- | PMeta (Some n), m -> merge_binding allow_bound_rels stk n cT subst
-
- | PMeta None, m -> subst
-
- | PRef (VarRef v1), Var v2 when v1 = v2 -> subst
-
- | PVar v1, Var v2 when v1 = v2 -> subst
-
- | PRef ref, _ when conv (constr_of_global ref) cT -> subst
-
- | PRel n1, Rel n2 when n1 = n2 -> subst
-
- | PSort (GProp c1), Sort (Prop c2) when c1 = c2 -> subst
-
- | PSort (GType _), Sort (Type _) -> subst
-
- | PApp (p, [||]), _ -> sorec stk subst p t
-
- | PApp (PApp (h, a1), a2), _ ->
- sorec stk subst (PApp(h,Array.append a1 a2)) t
-
- | PApp (PMeta meta,args1), App (c2,args2) when allow_partial_app ->
- let p = Array.length args2 - Array.length args1 in
- if p>=0 then
- let args21, args22 = array_chop p args2 in
- let c = mkApp(c2,args21) in
- let subst =
- match meta with
- | None -> subst
- | Some n -> merge_binding allow_bound_rels stk n c subst in
- array_fold_left2 (sorec stk) subst args1 args22
- else raise PatternMatchingFailure
-
- | PApp (c1,arg1), App (c2,arg2) ->
- (try array_fold_left2 (sorec stk) (sorec stk subst c1 c2) arg1 arg2
- with Invalid_argument _ -> raise PatternMatchingFailure)
-
- | PProd (na1,c1,d1), Prod(na2,c2,d2) ->
- sorec ((na1,na2,c2)::stk)
- (add_binders na1 na2 (sorec stk subst c1 c2)) d1 d2
-
- | PLambda (na1,c1,d1), Lambda(na2,c2,d2) ->
- sorec ((na1,na2,c2)::stk)
- (add_binders na1 na2 (sorec stk subst c1 c2)) d1 d2
-
- | PLetIn (na1,c1,d1), LetIn(na2,c2,t2,d2) ->
- sorec ((na1,na2,t2)::stk)
- (add_binders na1 na2 (sorec stk subst c1 c2)) d1 d2
-
- | PIf (a1,b1,b1'), Case (ci,_,a2,[|b2;b2'|]) ->
- let ctx,b2 = decompose_lam_n_assum ci.ci_cstr_ndecls.(0) b2 in
- let ctx',b2' = decompose_lam_n_assum ci.ci_cstr_ndecls.(1) b2' in
- let n = rel_context_length ctx in
- let n' = rel_context_length ctx' in
- if noccur_between 1 n b2 & noccur_between 1 n' b2' then
- let s =
- List.fold_left (fun l (na,_,t) -> (Anonymous,na,t)::l) stk ctx in
- let s' =
- List.fold_left (fun l (na,_,t) -> (Anonymous,na,t)::l) stk ctx' in
- let b1 = lift_pattern n b1 and b1' = lift_pattern n' b1' in
- sorec s' (sorec s (sorec stk subst a1 a2) b1 b2) b1' b2'
- else
- raise PatternMatchingFailure
-
- | PCase (ci1,p1,a1,br1), Case (ci2,p2,a2,br2) ->
- let n2 = Array.length br2 in
- if (ci1.cip_ind <> None && ci1.cip_ind <> Some ci2.ci_ind) ||
- (not ci1.cip_extensible && List.length br1 <> n2)
- then raise PatternMatchingFailure;
- let chk_branch subst (j,n,c) =
- (* (ind,j+1) is normally known to be a correct constructor
- and br2 a correct match over the same inductive *)
- assert (j < n2);
- sorec stk subst c br2.(j)
- in
- let chk_head = sorec stk (sorec stk subst a1 a2) p1 p2 in
- List.fold_left chk_branch chk_head br1
-
- | PFix c1, Fix _ when eq_constr (mkFix c1) cT -> subst
- | PCoFix c1, CoFix _ when eq_constr (mkCoFix c1) cT -> subst
- | _ -> raise PatternMatchingFailure
-
- in
- let names,terms = sorec [] ([],[]) pat c in
- (names,Sort.list (fun (a,_) (b,_) -> a<b) terms)
-
-let matches_core_closed convert allow_partial_app pat c =
- let names,subst = matches_core convert allow_partial_app false pat c in
- (names, List.map (fun (a,(_,b)) -> (a,b)) subst)
-
-let extended_matches = matches_core None true true
-
-let matches c p = snd (matches_core_closed None true c p)
-
-let special_meta = (-1)
-
-(* Tells if it is an authorized occurrence and if the instance is closed *)
-let authorized_occ partial_app closed pat c mk_ctx next =
- try
- let sigma = matches_core_closed None partial_app pat c in
- if closed && not (List.for_all (fun (_,c) -> closed0 c) (snd sigma))
- then next ()
- else sigma, mk_ctx (mkMeta special_meta), next
- with
- PatternMatchingFailure -> next ()
-
-(* Tries to match a subterm of [c] with [pat] *)
-let sub_match ?(partial_app=false) ?(closed=true) pat c =
- let rec aux c mk_ctx next =
- match kind_of_term c with
- | Cast (c1,k,c2) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let mk_ctx lc = mk_ctx (mkCast (List.hd lc, k,c2)) in
- try_aux [c1] mk_ctx next)
- | Lambda (x,c1,c2) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let mk_ctx lc = mk_ctx (mkLambda (x,List.hd lc,List.nth lc 1)) in
- try_aux [c1;c2] mk_ctx next)
- | Prod (x,c1,c2) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let mk_ctx lc = mk_ctx (mkProd (x,List.hd lc,List.nth lc 1)) in
- try_aux [c1;c2] mk_ctx next)
- | LetIn (x,c1,t,c2) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let mk_ctx = function [c1;c2] -> mkLetIn (x,c1,t,c2) | _ -> assert false
- in try_aux [c1;c2] mk_ctx next)
- | App (c1,lc) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let topdown = true in
- if partial_app then
- if topdown then
- let lc1 = Array.sub lc 0 (Array.length lc - 1) in
- let app = mkApp (c1,lc1) in
- let mk_ctx = function
- | [app';c] -> mk_ctx (mkApp (app',[|c|]))
- | _ -> assert false in
- try_aux [app;array_last lc] mk_ctx next
- else
- let rec aux2 app args next =
- match args with
- | [] ->
- let mk_ctx le =
- mk_ctx (mkApp (List.hd le, Array.of_list (List.tl le))) in
- try_aux (c1::Array.to_list lc) mk_ctx next
- | arg :: args ->
- let app = mkApp (app,[|arg|]) in
- let next () = aux2 app args next in
- let mk_ctx ce = mk_ctx (mkApp (ce, Array.of_list args)) in
- aux app mk_ctx next in
- aux2 c1 (Array.to_list lc) next
- else
- let mk_ctx le =
- mk_ctx (mkApp (List.hd le, Array.of_list (List.tl le))) in
- try_aux (c1::Array.to_list lc) mk_ctx next)
- | Case (ci,hd,c1,lc) ->
- authorized_occ partial_app closed pat c mk_ctx (fun () ->
- let mk_ctx le =
- mk_ctx (mkCase (ci,hd,List.hd le,Array.of_list (List.tl le))) in
- try_aux (c1::Array.to_list lc) mk_ctx next)
- | Construct _ | Fix _ | Ind _|CoFix _ |Evar _|Const _
- | Rel _|Meta _|Var _|Sort _ ->
- authorized_occ partial_app closed pat c mk_ctx next
-
- (* Tries [sub_match] for all terms in the list *)
- and try_aux lc mk_ctx next =
- let rec try_sub_match_rec lacc = function
- | [] -> next ()
- | c::tl ->
- let mk_ctx ce = mk_ctx (List.rev_append lacc (ce::tl)) in
- let next () = try_sub_match_rec (c::lacc) tl in
- aux c mk_ctx next in
- try_sub_match_rec [] lc in
- aux c (fun x -> x) (fun () -> raise PatternMatchingFailure)
-
-type subterm_matching_result =
- (bound_ident_map * patvar_map) * constr * (unit -> subterm_matching_result)
-
-let match_subterm pat c = sub_match pat c
-
-let match_appsubterm pat c = sub_match ~partial_app:true pat c
-
-let match_subterm_gen app pat c = sub_match ~partial_app:app pat c
-
-let is_matching pat c =
- try let _ = matches pat c in true
- with PatternMatchingFailure -> false
-
-let is_matching_appsubterm ?(closed=true) pat c =
- try let _ = sub_match ~partial_app:true ~closed pat c in true
- with PatternMatchingFailure -> false
-
-let matches_conv env sigma c p =
- snd (matches_core_closed (Some (env,sigma)) false c p)
-
-let is_matching_conv env sigma pat n =
- try let _ = matches_conv env sigma pat n in true
- with PatternMatchingFailure -> false
-