-let mk_meta status ?name where bo_or_ty =
- let n,h,metasenv,subst,o = status.pstatus in
- let ctx = match where with `Ctx c -> c | `Term (_,c,_) -> c in
- match bo_or_ty with
- | `Decl ty ->
- let _,_,ty = relocate ctx ty in
- let metasenv, _, instance, _ =
- NCicMetaSubst.mk_meta ?name metasenv ctx (`WithType ty)
- in
- let status = { status with pstatus = n,h,metasenv,subst,o } in
- status, (None,ctx,instance)
- | `Def bo ->
- let _,_,ty = typeof status (`Ctx ctx) bo in
- let metasenv, metano, instance, _ =
- NCicMetaSubst.mk_meta ?name metasenv ctx (`WithType ty)
- in
- let status = { status with pstatus = n,h,metasenv,subst,o } in
- let status = instantiate status metano bo in
- status, (None,ctx,instance)
-;;
-
-let select_term low_status (name,context,term) (wanted,path) =
- let found status ctx t wanted =
- (* we could lift wanted step-by-step *)
- try true, unify status (`Ctx ctx) (None,ctx,t) wanted
- with
- | NCicUnification.UnificationFailure _
- | NCicUnification.Uncertain _ -> false, status
+let find_in_context name context =
+ let rec aux acc = function
+ | [] -> raise Not_found
+ | (hd,_) :: tl when hd = name -> acc
+ | _ :: tl -> aux (acc + 1) tl
+ in
+ aux 1 context
+;;
+
+let clear_tac names =
+ if names = [] then id_tac
+ else
+ distribute_tac (fun status goal ->
+ let goalty = get_goalty status goal in
+ let js =
+ List.map
+ (fun name ->
+ try find_in_context name (ctx_of goalty)
+ with Not_found ->
+ fail (lazy ("hypothesis '" ^ name ^ "' not found")))
+ names
+ in
+ let n,h,metasenv,subst,o = status#obj in
+ let metasenv,subst,_ = NCicMetaSubst.restrict metasenv subst goal js in
+ status#set_obj (n,h,metasenv,subst,o))
+;;
+
+let generalize0_tac args =
+ if args = [] then id_tac
+ else exact_tac ("",0,Ast.Appl (Ast.Implicit `JustOne :: args))
+;;
+
+let select0_tac ~where:(wanted,hyps,where) ~job =
+ let found, postprocess =
+ match job with
+ | `Substexpand argsno -> mk_in_scope, mk_out_scope argsno
+ | `Collect l -> (fun s t -> l := t::!l; mk_in_scope s t), mk_out_scope 1
+ | `ChangeWith f -> f,(fun s t -> s, t)
+ in
+ distribute_tac (fun status goal ->
+ let goalty = get_goalty status goal in
+ let path =
+ match where with None -> NCic.Implicit `Term | Some where -> where
+ in
+ let status, newgoalctx =
+ List.fold_right
+ (fun (name,d as entry) (status,ctx) ->
+ try
+ let path = List.assoc name hyps in
+ match d with
+ NCic.Decl ty ->
+ let status,ty =
+ select_term status ~found ~postprocess (mk_cic_term ctx ty)
+ (wanted,path) in
+ let status,ty = term_of_cic_term status ty ctx in
+ status,(name,NCic.Decl ty)::ctx
+ | NCic.Def (bo,ty) ->
+ let status,bo =
+ select_term status ~found ~postprocess (mk_cic_term ctx bo)
+ (wanted,path) in
+ let status,bo = term_of_cic_term status bo ctx in
+ status,(name,NCic.Def (bo,ty))::ctx
+ with
+ Not_found -> status, entry::ctx
+ ) (ctx_of goalty) (status,[])
+ in
+ let status, newgoalty =
+ select_term status ~found ~postprocess goalty (wanted,path) in
+ (* WARNING: the next two lines simply change the context of newgoalty
+ from the old to the new one. Otherwise mk_meta will do that herself,
+ calling relocate that calls delift. However, newgoalty is now
+ ?[out_scope] and thus the delift would trigger the special unification
+ case, which is wrong now :-( *)
+ let status,newgoalty = term_of_cic_term status newgoalty (ctx_of goalty) in
+ let newgoalty = mk_cic_term newgoalctx newgoalty in
+
+ let status, instance =
+ mk_meta status newgoalctx (`Decl newgoalty)
+ in
+ instantiate status goal instance)
+;;
+
+let select_tac ~where ~job move_down_hyps =
+ let (wanted,hyps,where) = GrafiteDisambiguate.disambiguate_npattern where in
+ let path =
+ match where with None -> NCic.Implicit `Term | Some where -> where in
+ if not move_down_hyps then
+ select0_tac ~where:(wanted,hyps,Some path) ~job
+ else
+ let path =
+ List.fold_left
+ (fun path (name,path_name) -> NCic.Prod ("_",path_name,path))
+ path (List.rev hyps)