+(* Note: this code is almost identical to change_tac and
+* it could be unified by making the change function a callback *)
+let reduction_tac ~reduction ~pattern (proof,goal) =
+ let curi,metasenv,pbo,pty = proof in
+ let (metano,context,ty) as conjecture = CicUtil.lookup_meta goal metasenv in
+ let change subst where terms metasenv ugraph =
+ if terms = [] then where, metasenv, ugraph
+ else
+ let pairs, metasenv, ugraph =
+ List.fold_left
+ (fun (pairs, metasenv, ugraph) (context, t) ->
+ let reduction, metasenv, ugraph = reduction context metasenv ugraph in
+ ((t, reduction context t) :: pairs), metasenv, ugraph)
+ ([], metasenv, ugraph)
+ terms
+ in
+ let terms, terms' = List.split pairs in
+ let where' =
+ ProofEngineReduction.replace ~equality:(==) ~what:terms ~with_what:terms'
+ ~where:where
+ in
+ CicMetaSubst.apply_subst subst where', metasenv, ugraph
+ in
+ let (subst,metasenv,ugraph,selected_context,selected_ty) =
+ ProofEngineHelpers.select ~metasenv ~ugraph:CicUniv.empty_ugraph
+ ~conjecture ~pattern
+ in
+ let ty', metasenv, ugraph = change subst ty selected_ty metasenv ugraph in
+ let context', metasenv, ugraph =
+ List.fold_right2
+ (fun entry selected_entry (context', metasenv, ugraph) ->
+ match entry,selected_entry with
+ None,None -> None::context', metasenv, ugraph
+ | Some (name,Cic.Decl ty),Some (`Decl selected_ty) ->
+ let ty', metasenv, ugraph =
+ change subst ty selected_ty metasenv ugraph
+ in
+ Some (name,Cic.Decl ty')::context', metasenv, ugraph
+ | Some (name,Cic.Def (bo,ty)),Some (`Def (selected_bo,selected_ty)) ->
+ let bo', metasenv, ugraph =
+ change subst bo selected_bo metasenv ugraph
+ in
+ let ty', metasenv, ugraph =
+ match ty,selected_ty with
+ None,None -> None, metasenv, ugraph
+ | Some ty,Some selected_ty ->
+ let ty', metasenv, ugraph =
+ change subst ty selected_ty metasenv ugraph
+ in
+ Some ty', metasenv, ugraph
+ | _,_ -> assert false
+ in
+ (Some (name,Cic.Def (bo',ty'))::context'), metasenv, ugraph
+ | _,_ -> assert false
+ ) context selected_context ([], metasenv, ugraph) in
+ let metasenv' =
+ List.map (function
+ | (n,_,_) when n = metano -> (metano,context',ty')