+(** create a pattern from a term and a list of subterms.
+* the pattern is granted to have a ? for every subterm that has no selected
+* subterms
+* @param equality equality function used while walking the term. Defaults to
+* physical equality (==) *)
+let pattern_of ?(equality=(==)) ~term terms =
+ let (===) x y = equality x y in
+ let not_found = false, Cic.Implicit None in
+ let rec aux t =
+ match t with
+ | t when List.exists (fun t' -> t === t') terms ->
+ true,Cic.Implicit (Some `Hole)
+ | Cic.Var (uri, subst) ->
+ let b,subst = aux_subst subst in
+ if b then
+ true,Cic.Var (uri, subst)
+ else
+ not_found
+ | Cic.Meta (i, ctxt) ->
+ let b,ctxt =
+ List.fold_right
+ (fun e (b,ctxt) ->
+ match e with
+ None -> b,None::ctxt
+ | Some t -> let bt,t = aux t in b||bt ,Some t::ctxt
+ ) ctxt (false,[])
+ in
+ if b then
+ true,Cic.Meta (i, ctxt)
+ else
+ not_found
+ | Cic.Cast (te, ty) ->
+ let b1,te = aux te in
+ let b2,ty = aux ty in
+ if b1||b2 then true,Cic.Cast (te, ty)
+ else
+ not_found
+ | Cic.Prod (name, s, t) ->
+ let b1,s = aux s in
+ let b2,t = aux t in
+ if b1||b2 then
+ true, Cic.Prod (name, s, t)
+ else
+ not_found
+ | Cic.Lambda (name, s, t) ->
+ let b1,s = aux s in
+ let b2,t = aux t in
+ if b1||b2 then
+ true, Cic.Lambda (name, s, t)
+ else
+ not_found
+ | Cic.LetIn (name, s, t) ->
+ let b1,s = aux s in
+ let b2,t = aux t in
+ if b1||b2 then
+ true, Cic.LetIn (name, s, t)
+ else
+ not_found
+ | Cic.Appl terms ->
+ let b,terms =
+ List.fold_right
+ (fun t (b,terms) ->
+ let bt,t = aux t in
+ b||bt,t::terms
+ ) terms (false,[])
+ in
+ if b then
+ true,Cic.Appl terms
+ else
+ not_found
+ | Cic.Const (uri, subst) ->
+ let b,subst = aux_subst subst in
+ if b then
+ true, Cic.Const (uri, subst)
+ else
+ not_found
+ | Cic.MutInd (uri, tyno, subst) ->
+ let b,subst = aux_subst subst in
+ if b then
+ true, Cic.MutInd (uri, tyno, subst)
+ else
+ not_found
+ | Cic.MutConstruct (uri, tyno, consno, subst) ->
+ let b,subst = aux_subst subst in
+ if b then
+ true, Cic.MutConstruct (uri, tyno, consno, subst)
+ else
+ not_found
+ | Cic.MutCase (uri, tyno, outty, t, pat) ->
+ let b1,outty = aux outty in
+ let b2,t = aux t in
+ let b3,pat =
+ List.fold_right
+ (fun t (b,pat) ->
+ let bt,t = aux t in
+ bt||b,t::pat
+ ) pat (false,[])
+ in
+ if b1 || b2 || b3 then
+ true, Cic.MutCase (uri, tyno, outty, t, pat)
+ else
+ not_found
+ | Cic.Fix (funno, funs) ->
+ let b,funs =
+ List.fold_right
+ (fun (name, i, ty, bo) (b,funs) ->
+ let b1,ty = aux ty in
+ let b2,bo = aux bo in
+ b||b1||b2, (name, i, ty, bo)::funs) funs (false,[])
+ in
+ if b then
+ true, Cic.Fix (funno, funs)
+ else
+ not_found
+ | Cic.CoFix (funno, funs) ->
+ let b,funs =
+ List.fold_right
+ (fun (name, ty, bo) (b,funs) ->
+ let b1,ty = aux ty in
+ let b2,bo = aux bo in
+ b||b1||b2, (name, ty, bo)::funs) funs (false,[])
+ in
+ if b then
+ true, Cic.CoFix (funno, funs)
+ else
+ not_found
+ | Cic.Rel _
+ | Cic.Sort _
+ | Cic.Implicit _ -> not_found
+ and aux_subst subst =
+ List.fold_right
+ (fun (uri, t) (b,subst) ->
+ let b1,t = aux t in
+ b||b1,(uri, t)::subst) subst (false,[])
+ in
+ snd (aux term)
+