diff options
Diffstat (limited to 'tactics/rewrite.ml4')
| -rw-r--r-- | tactics/rewrite.ml4 | 569 |
1 files changed, 393 insertions, 176 deletions
diff --git a/tactics/rewrite.ml4 b/tactics/rewrite.ml4 index 1634468d0f..c48c38ae30 100644 --- a/tactics/rewrite.ml4 +++ b/tactics/rewrite.ml4 @@ -110,6 +110,9 @@ let respectful = lazy (gen_constant ["Classes"; "Morphisms"] "respectful") let equivalence = lazy (gen_constant ["Classes"; "RelationClasses"] "Equivalence") let default_relation = lazy (gen_constant ["Classes"; "SetoidTactics"] "DefaultRelation") +let subrelation = lazy (gen_constant ["Classes"; "RelationClasses"] "subrelation") +let is_subrelation = lazy (gen_constant ["Classes"; "RelationClasses"] "is_subrelation") + let coq_relation = lazy (gen_constant ["Relations";"Relation_Definitions"] "relation") let mk_relation a = mkApp (Lazy.force coq_relation, [| a |]) (* let mk_relation a = mkProd (Anonymous, a, mkProd (Anonymous, a, new_Type ())) *) @@ -223,45 +226,6 @@ let array_find (arr: 'a array) (pred: int -> 'a -> bool): int = raise Not_found with FoundInt i -> i -let resolve_morphism env sigma oldt m ?(fnewt=fun x -> x) args args' cstr evars = - let morph_instance, proj, sigargs, m', args, args' = - let first = try (array_find args' (fun i b -> b <> None)) with Not_found -> raise (Invalid_argument "resolve_morphism") in - let morphargs, morphobjs = array_chop first args in - let morphargs', morphobjs' = array_chop first args' in - let appm = mkApp(m, morphargs) in - let appmtype = Typing.type_of env sigma appm in - let cstrs = List.map (function None -> None | Some (_, (a, r, _, _)) -> Some (a, r)) (Array.to_list morphobjs') in - let appmtype', signature, sigargs = build_signature evars env appmtype cstrs cstr (fun (a, r) -> r) in - let cl_args = [| appmtype' ; signature ; appm |] in - let app = mkApp (Lazy.force morphism_type, cl_args) in - let morph = Evarutil.e_new_evar evars env app in - morph, morph, sigargs, appm, morphobjs, morphobjs' - in - let projargs, respars, typeargs = - array_fold_left2 - (fun (acc, sigargs, typeargs') x y -> - let (carrier, relation), sigargs = split_head sigargs in - match relation with - | Some relation -> - (match y with - | None -> - let proof = morphism_proof env evars carrier relation x in - [ proof ; x ; x ] @ acc, sigargs, x :: typeargs' - | Some (p, (_, _, _, t')) -> - [ p ; t'; x ] @ acc, sigargs, t' :: typeargs') - | None -> - if y <> None then error "Cannot rewrite the argument of a dependent function"; - x :: acc, sigargs, x :: typeargs') - ([], sigargs, []) args args' - in - let proof = applistc proj (List.rev projargs) in - let newt = applistc m' (List.rev typeargs) in - match respars with - [ a, Some r ] -> (proof, (a, r, oldt, fnewt newt)) - | _ -> assert(false) - -(* Adapted from setoid_replace. *) - type hypinfo = { cl : clausenv; prf : constr; @@ -430,131 +394,318 @@ let lift_cstr env sigma evars args cstr = let unlift_cstr env sigma = function | None -> None - | Some codom -> - let cstr () = - let car, rel = Lazy.force codom in - decomp_prod env sigma 1 car, decomp_pointwise 1 rel - in Some (Lazy.lazy_from_fun cstr) + | Some codom -> Some (decomp_pointwise 1 codom) type rewrite_flags = { under_lambdas : bool; on_morphisms : bool } let default_flags = { under_lambdas = true; on_morphisms = true; } -let build_new gl env sigma flags loccs hypinfo concl cstr evars = +type rewrite_result_info = { + rew_car : constr; + rew_rel : constr; + rew_from : constr; + rew_to : constr; + rew_prf : constr; + rew_evars : evar_defs; +} + +type rewrite_result = rewrite_result_info option + +type strategy = Environ.env -> evar_defs -> constr -> types -> + constr option -> evar_defs -> rewrite_result option + +let resolve_morphism env sigma oldt m ?(fnewt=fun x -> x) args args' cstr evars = + let morph_instance, proj, sigargs, m', args, args' = + let first = try (array_find args' (fun i b -> b <> None)) with Not_found -> raise (Invalid_argument "resolve_morphism") in + let morphargs, morphobjs = array_chop first args in + let morphargs', morphobjs' = array_chop first args' in + let appm = mkApp(m, morphargs) in + let appmtype = Typing.type_of env sigma appm in + let cstrs = List.map (function None -> None | Some r -> Some (r.rew_car, r.rew_rel)) (Array.to_list morphobjs') in + let appmtype', signature, sigargs = build_signature evars env appmtype cstrs cstr (fun (a,r) -> r) in + let cl_args = [| appmtype' ; signature ; appm |] in + let app = mkApp (Lazy.force morphism_type, cl_args) in + let morph = Evarutil.e_new_evar evars env app in + morph, morph, sigargs, appm, morphobjs, morphobjs' + in + let projargs, respars, typeargs = + array_fold_left2 + (fun (acc, sigargs, typeargs') x y -> + let (carrier, relation), sigargs = split_head sigargs in + match relation with + | Some relation -> + (match y with + | None -> + let proof = morphism_proof env evars carrier relation x in + [ proof ; x ; x ] @ acc, sigargs, x :: typeargs' + | Some r -> + [ r.rew_prf; r.rew_to; x ] @ acc, sigargs, r.rew_to :: typeargs') + | None -> + if y <> None then error "Cannot rewrite the argument of a dependent function"; + x :: acc, sigargs, x :: typeargs') + ([], sigargs, []) args args' + in + let proof = applistc proj (List.rev projargs) in + let newt = applistc m' (List.rev typeargs) in + match respars with + [ a, Some r ] -> (proof, (a, r, oldt, fnewt newt)) + | _ -> assert(false) + +let resolve_subrelation env sigma car rel rel' res = + if convertible env sigma rel rel' then res + else + let app = mkApp (Lazy.force subrelation, [|car; rel; rel'|]) in + let evars, subrel = Evarutil.new_evar res.rew_evars env app in + { res with + rew_prf = mkApp (subrel, [| res.rew_from ; res.rew_to ; res.rew_prf |]); + rew_rel = rel'; + rew_evars = evars } + +let apply_constraint env sigma car rel cstr res = + match cstr with + | None -> res + | Some r -> resolve_subrelation env sigma car rel r res + +let apply_rule hypinfo loccs : strategy = let (nowhere_except_in,occs) = loccs in let is_occ occ = if nowhere_except_in then List.mem occ occs else not (List.mem occ occs) in - let rec aux env t occ cstr = - let unif = unify_eqn env sigma hypinfo t in - let occ = if unif = None then occ else succ occ in - match unif with - | Some (env', (prf, hypinfo as x)) when is_occ occ -> - begin - evars := Evd.evar_merge !evars - ( (Evd.undefined_evars (Evarutil.nf_evar_defs env'.evd))); - match cstr with - | None -> Some x, occ - | Some _ -> - let (car, r, orig, dest) = hypinfo in - let res = - resolve_morphism env sigma t ~fnewt:unfold_id - (mkApp (Lazy.force coq_id, [| car |])) - [| orig |] [| Some x |] cstr evars - in Some res, occ - end - | _ -> - match kind_of_term t with - | App (m, args) -> - let rewrite_args occ = - let args', occ = - Array.fold_left - (fun (acc, occ) arg -> let res, occ = aux env arg occ None in (res :: acc, occ)) - ([], occ) args - in - let res = - if List.for_all (fun x -> x = None) args' then None - else - let args' = Array.of_list (List.rev args') in - (Some (resolve_morphism env sigma t m args args' cstr evars)) - in res, occ + let occ = ref 0 in + fun env sigma t ty cstr evars -> + let unif = unify_eqn env sigma hypinfo t in + if unif <> None then incr occ; + match unif with + | Some (env', (prf, (car, rel, c1, c2))) when is_occ !occ -> + begin + let evars = Evd.evar_merge evars + (Evd.undefined_evars (Evarutil.nf_evar_defs env'.evd)) in - if flags.on_morphisms then - let m', occ = aux env m occ (lift_cstr env sigma evars args cstr) in - match m' with - | None -> rewrite_args occ (* Standard path, try rewrite on arguments *) - | Some (prf, (car, rel, c1, c2)) -> - (* We rewrote the function and get a proof of pointwise rel for the arguments. - We just apply it. *) - let nargs = Array.length args in - let res = - mkApp (prf, args), - (decomp_prod env ( !evars) nargs car, - decomp_pointwise nargs rel, mkApp(c1, args), mkApp(c2, args)) - in Some res, occ - else rewrite_args occ - - | Prod (n, x, b) when not (dependent (mkRel 1) b) -> - let x', occ = aux env x occ None in -(* if x' = None && flags.under_lambdas then *) -(* let lam = mkLambda (n, x, b) in *) -(* let lam', occ = aux env lam occ None in *) -(* let res = *) -(* match lam' with *) -(* | None -> None *) -(* | Some (prf, (car, rel, c1, c2)) -> *) -(* Some (resolve_morphism env sigma t *) -(* ~fnewt:unfold_all *) -(* (Lazy.force coq_all) [| x ; lam |] [| None; lam' |] *) -(* cstr evars) *) -(* in res, occ *) -(* else *) - let b = subst1 mkProp b in - let b', occ = aux env b occ None in - let res = - if x' = None && b' = None then None - else - Some (resolve_morphism env sigma t - ~fnewt:unfold_impl - (arrow_morphism (Typing.type_of env sigma x) (Typing.type_of env sigma b)) - [| x ; b |] [| x' ; b' |] - cstr evars) - in res, occ - - | Prod (n, ty, b) -> - let lam = mkLambda (n, ty, b) in - let lam', occ = aux env lam occ None in - let res = - match lam' with - | None -> None - | Some (prf, (car, rel, c1, c2)) -> - Some (resolve_morphism env sigma t - ~fnewt:unfold_all - (Lazy.force coq_all) [| ty ; lam |] [| None; lam' |] - cstr evars) - in res, occ - - | Lambda (n, t, b) when flags.under_lambdas -> - let env' = Environ.push_rel (n, None, t) env in - refresh_hypinfo env' sigma hypinfo; - let b', occ = aux env' b occ (unlift_cstr env sigma cstr) in - let res = - match b' with - | None -> None - | Some (prf, (car, rel, c1, c2)) -> - let prf' = mkLambda (n, t, prf) in - let car' = mkProd (n, t, car) in - let rel' = mkApp (Lazy.force pointwise_relation, [| t; car; rel |]) in - let c1' = mkLambda(n, t, c1) and c2' = mkLambda (n, t, c2) in - Some (prf', (car', rel', c1', c2')) - in res, occ - | _ -> None, occ + let res = { rew_car = ty; rew_rel = rel; rew_from = c1; + rew_to = c2; rew_prf = prf; rew_evars = evars } + in Some (Some (apply_constraint env sigma car rel cstr res)) + end + | _ -> None + +let apply_lemma (evm,c) left2right loccs : strategy = + fun env sigma -> + let evars = Evd.merge sigma evm in + let hypinfo = ref (decompose_setoid_eqhyp env evars c left2right) in + apply_rule hypinfo loccs env sigma + +let subterm all flags (s : strategy) : strategy = + let rec aux env sigma t ty cstr evars = + let cstr' = Option.map (fun c -> lazy (ty, c)) cstr in + match kind_of_term t with + | App (m, args) -> + let rewrite_args success = + let args', evars', progress = + Array.fold_left + (fun (acc, evars, progress) arg -> + if progress <> None && not all then (None :: acc, evars, progress) + else + let res = s env sigma arg (Typing.type_of env sigma arg) None evars in + match res with + | Some None -> (None :: acc, evars, Some false) + | Some (Some r) -> (Some r :: acc, r.rew_evars, Some true) + | None -> (None :: acc, evars, progress)) + ([], evars, success) args + in + match progress with + | None -> None + | Some false -> Some None + | Some true -> + let args' = Array.of_list (List.rev args') in + let evarsref = ref evars' in + let (prf, (car, rel, c1, c2)) = resolve_morphism env sigma t m args args' cstr' evarsref in + let res = { rew_car = ty; rew_rel = rel; rew_from = c1; + rew_to = c2; rew_prf = prf; rew_evars = !evarsref } in + Some (Some res) + in + if flags.on_morphisms then + let evarsref = ref evars in + let cstr' = lift_cstr env sigma evarsref args cstr' in + let m' = s env sigma m (Typing.type_of env sigma m) (Option.map (fun c -> snd (Lazy.force c)) cstr') !evarsref in + match m' with + | None -> rewrite_args None (* Standard path, try rewrite on arguments *) + | Some None -> rewrite_args (Some false) + | Some (Some r) -> + (* We rewrote the function and get a proof of pointwise rel for the arguments. + We just apply it. *) + let nargs = Array.length args in + let res = + { rew_car = decomp_prod env r.rew_evars nargs r.rew_car; + rew_rel = decomp_pointwise nargs r.rew_rel; + rew_from = mkApp(r.rew_from, args); rew_to = mkApp(r.rew_to, args); + rew_prf = mkApp (r.rew_prf, args); rew_evars = r.rew_evars } + in Some (Some res) + else rewrite_args None + + | Prod (n, x, b) when not (dependent (mkRel 1) b) -> + let b = subst1 mkProp b in + let tx = Typing.type_of env sigma x and tb = Typing.type_of env sigma b in + let res = aux env sigma (mkApp (arrow_morphism tx tb, [| x; b |])) ty cstr evars in + (match res with + | Some (Some r) -> Some (Some { r with rew_to = unfold_impl r.rew_to }) + | _ -> res) + + (* if x' = None && flags.under_lambdas then *) + (* let lam = mkLambda (n, x, b) in *) + (* let lam', occ = aux env lam occ None in *) + (* let res = *) + (* match lam' with *) + (* | None -> None *) + (* | Some (prf, (car, rel, c1, c2)) -> *) + (* Some (resolve_morphism env sigma t *) + (* ~fnewt:unfold_all *) + (* (Lazy.force coq_all) [| x ; lam |] [| None; lam' |] *) + (* cstr evars) *) + (* in res, occ *) + (* else *) + + | Prod (n, dom, codom) -> + let lam = mkLambda (n, dom, codom) in + let res = aux env sigma (mkApp (Lazy.force coq_all, [| dom; lam |])) ty cstr evars in + (match res with + | Some (Some r) -> Some (Some { r with rew_to = unfold_all r.rew_to }) + | _ -> res) + + | Lambda (n, t, b) when flags.under_lambdas -> + let env' = Environ.push_rel (n, None, t) env in + let b' = aux env' sigma b (Typing.type_of env' sigma b) (unlift_cstr env sigma cstr) evars in + (match b' with + | Some (Some r) -> + Some (Some { r with + rew_prf = mkLambda (n, t, r.rew_prf); + rew_car = mkProd (n, t, r.rew_car); + rew_rel = mkApp (Lazy.force pointwise_relation, [| t; r.rew_car; r.rew_rel |]); + rew_from = mkLambda(n, t, r.rew_from); + rew_to = mkLambda (n, t, r.rew_to) }) + | _ -> b') + + | _ -> None + in aux + +let all_subterms = subterm true default_flags +let one_subterm = subterm false default_flags + +let morphism_proof env evars carrier relation x = + let goal = + mkApp (Lazy.force morphism_proxy_type, [| carrier ; relation; x |]) + in Evarutil.e_new_evar evars env goal + +(** Requires transitivity of the rewrite step, not tail-recursive. *) + +let transitivity env sigma (res : rewrite_result_info) (next : strategy) : rewrite_result option = + match next env sigma res.rew_to res.rew_car (Some res.rew_rel) res.rew_evars with + | None -> None + | Some None -> Some (Some res) + | Some (Some res') -> + let prfty = mkApp (Lazy.force transitive_type, [| res.rew_car ; res.rew_rel |]) in + let evars, prf = Evarutil.new_evar res'.rew_evars env prfty in + let prf = mkApp (prf, [|res.rew_from; res'.rew_from; res'.rew_to; + res.rew_prf; res'.rew_prf |]) + in Some (Some { res' with rew_from = res.rew_from; rew_evars = evars; rew_prf = prf }) + +module Strategies = + struct + + let fail : strategy = + fun env sigma t ty cstr evars -> None + + let id : strategy = + fun env sigma t ty cstr evars -> Some None + + let refl : strategy = + fun env sigma t ty cstr evars -> + let evars, rel = match cstr with + | None -> Evarutil.new_evar evars env (mk_relation ty) + | Some r -> evars, r + in + let evars, proof = + let mty = mkApp (Lazy.force morphism_proxy_type, [| ty ; rel; t |]) in + Evarutil.new_evar evars env mty + in + Some (Some { rew_car = ty; rew_rel = rel; rew_from = t; rew_to = t; + rew_prf = proof; rew_evars = evars }) + + let progress (s : strategy) : strategy = + fun env sigma t ty cstr evars -> + match s env sigma t ty cstr evars with + | None -> None + | Some None -> None + | r -> r + + let seq fst snd : strategy = + fun env sigma t ty cstr evars -> + match fst env sigma t ty cstr evars with + | None -> None + | Some None -> snd env sigma t ty cstr evars + | Some (Some res) -> transitivity env sigma res snd + + let choice fst snd : strategy = + fun env sigma t ty cstr evars -> + match fst env sigma t ty cstr evars with + | None -> snd env sigma t ty cstr evars + | res -> res + + let try_ str : strategy = choice str id + + let fix (f : strategy -> strategy) : strategy = + let rec aux env = f (fun env -> aux env) env in aux + + let any (s : strategy) : strategy = + fix (fun any -> try_ (seq s any)) + + let repeat (s : strategy) : strategy = + seq s (any s) + + let bu (s : strategy) : strategy = + fix (fun s' -> choice (seq (all_subterms s') (try_ s')) s) + + let td (s : strategy) : strategy = + fix (fun s' -> choice s (all_subterms s')) + + let innermost (s : strategy) : strategy = + fix (fun ins -> choice (one_subterm ins) s) + + let outermost (s : strategy) : strategy = + fix (fun out -> choice s (one_subterm out)) + + let hints (db : string) : strategy = + let rules = Autorewrite.find_base db in + List.fold_left (fun tac (b,t,l2r,_) -> + choice tac (apply_lemma (inj_open b) l2r (false,[]))) + fail rules + +end + +(** The strategy for a single rewrite, dealing with occurences. *) + +let rewrite_strat flags occs hyp = + let app = apply_rule hyp occs in + let rec aux () = + Strategies.choice app (subterm true flags (fun env -> aux () env)) + in aux () + +let rewrite_with (evm,c) left2right loccs : strategy = + fun env sigma -> + let evars = Evd.merge sigma evm in + let hypinfo = ref (decompose_setoid_eqhyp env evars c left2right) in + rewrite_strat default_flags loccs hypinfo env sigma + +let apply_strategy (s : strategy) env sigma concl cstr evars = + let res = + s env sigma concl (Typing.type_of env sigma concl) + (Option.map (fun c -> snd (Lazy.force c)) cstr) !evars in - let eq,nbocc_min_1 = aux env concl 0 cstr in - let rest = List.filter (fun o -> o > nbocc_min_1) occs in - if rest <> [] then error_invalid_occurrence rest; - eq - -let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause gl = + match res with + | None -> None + | Some None -> Some None + | Some (Some res) -> + evars := res.rew_evars; + Some (Some (res.rew_prf, (res.rew_car, res.rew_rel, res.rew_from, res.rew_to))) + +let cl_rewrite_clause_aux ?(abs=None) strat goal_meta clause gl = let concl, is_hyp = match clause with Some id -> pf_get_hyp_typ gl id, Some id @@ -570,17 +721,16 @@ let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause g let sigma = project gl in let evars = ref (Evd.create_evar_defs sigma) in let env = pf_env gl in - let eq = build_new gl env sigma flags occs hypinfo concl (Some (Lazy.lazy_from_val cstr)) evars - in + let eq = apply_strategy strat env sigma concl (Some (Lazy.lazy_from_val cstr)) evars in match eq with - | Some (p, (_, _, oldt, newt)) -> + | Some (Some (p, (_, _, oldt, newt))) -> (try evars := Typeclasses.resolve_typeclasses env ~split:false ~fail:true !evars; let p = Evarutil.nf_isevar !evars p in let newt = Evarutil.nf_isevar !evars newt in let undef = Evd.undefined_evars !evars in let abs = Option.map (fun (x, y) -> Evarutil.nf_isevar !evars x, - Evarutil.nf_isevar !evars y) !hypinfo.abs in + Evarutil.nf_isevar !evars y) abs in let rewtac = match is_hyp with | Some id -> @@ -618,25 +768,30 @@ let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause g ++ fnl () ++ Himsg.explain_typeclass_error env e) gl) (* | Not_found -> *) (* tclFAIL 0 (str" setoid rewrite failed: unable to satisfy the rewriting constraints.") gl) *) + | Some None -> + tclFAIL 0 (str"setoid rewrite failed: no progress made") gl | None -> - let {l2r=l2r; c1=x; c2=y} = !hypinfo in - raise (Pretype_errors.PretypeError - (pf_env gl, - Pretype_errors.NoOccurrenceFound ((if l2r then x else y), is_hyp))) - (* tclFAIL 1 (str"setoid rewrite failed") gl *) - -let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause gl = - cl_rewrite_clause_aux ~flags hypinfo goal_meta occs clause gl +(* let {l2r=l2r; c1=x; c2=y} = !hypinfo in *) +(* raise (Pretype_errors.PretypeError *) +(* (pf_env gl, *) +(* Pretype_errors.NoOccurrenceFound ((if l2r then x else y), is_hyp))) *) + tclFAIL 0 (str"setoid rewrite failed") gl -let cl_rewrite_clause (evm,c) left2right occs clause gl = +let cl_rewrite_clause_strat strat clause gl = init_setoid (); let meta = Evarutil.new_meta() in let gl = { gl with sigma = Typeclasses.mark_unresolvables gl.sigma } in - let env = pf_env gl in - let evars = Evd.merge (project gl) evm in - let hypinfo = ref (decompose_setoid_eqhyp env evars c left2right) in - cl_rewrite_clause_aux hypinfo meta occs clause gl + cl_rewrite_clause_aux strat meta clause gl +let cl_rewrite_clause l left2right occs clause gl = + cl_rewrite_clause_strat (rewrite_with l left2right occs) clause gl + +open Pp +open Pcoq +open Names +open Tacexpr +open Tacinterp +open Termops open Genarg open Extraargs @@ -647,12 +802,66 @@ let occurrences_of = function error "Illegal negative occurrence number."; (true,nl) +let pr_gen_strategy pr_id = Pp.mt () +let pr_loc_strategy _ _ _ = Pp.mt () +let pr_strategy _ _ _ (s : strategy) = Pp.str "<strategy>" + +let intern_strategy ist gl c = c +let interp_strategy ist gl c = c +let glob_strategy ist l = l +let subst_strategy evm l = l + +let apply_constr_expr c l2r occs = fun env sigma -> + let c = Constrintern.interp_open_constr sigma env c in + apply_lemma c l2r occs env sigma + +open Pcoq + +let (wit_strategy, globwit_strategy, rawwit_strategy) = + (Genarg.create_arg "strategy" : + ((strategy, Genarg.tlevel) Genarg.abstract_argument_type * + (strategy, Genarg.glevel) Genarg.abstract_argument_type * + (strategy, Genarg.rlevel) Genarg.abstract_argument_type)) + + +ARGUMENT EXTEND rewstrategy TYPED AS strategy + PRINTED BY pr_strategy + INTERPRETED BY interp_strategy + GLOBALIZED BY glob_strategy + SUBSTITUTED BY subst_strategy + + [ constr(c) ] -> [ apply_constr_expr c true all_occurrences ] + | [ "<-" constr(c) ] -> [ apply_constr_expr c false all_occurrences ] + | [ "subterms" rewstrategy(h) ] -> [ all_subterms h ] + | [ "subterm" rewstrategy(h) ] -> [ one_subterm h ] + | [ "innermost" rewstrategy(h) ] -> [ Strategies.innermost h ] + | [ "outermost" rewstrategy(h) ] -> [ Strategies.outermost h ] + | [ "bottomup" rewstrategy(h) ] -> [ Strategies.bu h ] + | [ "topdown" rewstrategy(h) ] -> [ Strategies.td h ] + | [ "id" ] -> [ Strategies.id ] + | [ "refl" ] -> [ Strategies.refl ] + | [ "progress" rewstrategy(h) ] -> [ Strategies.progress h ] + | [ "fail" ] -> [ Strategies.fail ] + | [ "try" rewstrategy(h) ] -> [ Strategies.try_ h ] + | [ "any" rewstrategy(h) ] -> [ Strategies.any h ] + | [ "repeat" rewstrategy(h) ] -> [ Strategies.repeat h ] + | [ rewstrategy(h) ";" rewstrategy(h') ] -> [ Strategies.seq h h' ] + | [ "(" rewstrategy(h) ")" ] -> [ h ] + | [ "choice" rewstrategy(h) rewstrategy(h') ] -> [ Strategies.choice h h' ] + | [ "hints" preident(h) ] -> [ Strategies.hints h ] +END + TACTIC EXTEND class_rewrite | [ "clrewrite" orient(o) open_constr(c) "in" hyp(id) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o (occurrences_of occ) (Some id) ] | [ "clrewrite" orient(o) open_constr(c) "at" occurrences(occ) "in" hyp(id) ] -> [ cl_rewrite_clause c o (occurrences_of occ) (Some id) ] | [ "clrewrite" orient(o) open_constr(c) "in" hyp(id) ] -> [ cl_rewrite_clause c o all_occurrences (Some id) ] | [ "clrewrite" orient(o) open_constr(c) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o (occurrences_of occ) None ] | [ "clrewrite" orient(o) open_constr(c) ] -> [ cl_rewrite_clause c o all_occurrences None ] + END + +TACTIC EXTEND class_rewrite_strat +| [ "clrewrite_strat" rewstrategy(s) ] -> [ cl_rewrite_clause_strat s None ] +(* | [ "clrewrite_strat" strategy(s) "in" hyp(id) ] -> [ cl_rewrite_clause_strat s (Some id) ] *) END @@ -1046,18 +1255,26 @@ let unification_rewrite l2r c1 c2 cl car rel but gl = let cl' = { cl' with templval = mk_freelisted prf ; templtyp = mk_freelisted prfty } in {cl=cl'; prf=(mkRel 1); car=car; rel=rel; l2r=l2r; c1=c1; c2=c2; c=None; abs=Some (prf, prfty)} -let get_hyp gl (evm,c) clause l2r = - let evars = Evd.merge (project gl) evm in +let get_hyp gl evars (evm,c) clause l2r = let hi = decompose_setoid_eqhyp (pf_env gl) evars c l2r in let but = match clause with Some id -> pf_get_hyp_typ gl id | None -> pf_concl gl in unification_rewrite hi.l2r hi.c1 hi.c2 hi.cl hi.car hi.rel but gl let general_rewrite_flags = { under_lambdas = false; on_morphisms = false } +let apply_lemma gl (evm,c) cl l2r occs = + let sigma = project gl in + let evars = Evd.merge sigma evm in + let hypinfo = ref (get_hyp gl evars (evm,c) cl l2r) in + let app = apply_rule hypinfo occs in + let rec aux () = + Strategies.choice app (subterm true general_rewrite_flags (fun env -> aux () env)) + in !hypinfo.abs, aux () + let general_s_rewrite cl l2r occs c ~new_goals gl = let meta = Evarutil.new_meta() in - let hypinfo = ref (get_hyp gl c cl l2r) in - cl_rewrite_clause_aux ~flags:general_rewrite_flags hypinfo meta occs cl gl + let abs, strat = apply_lemma gl c cl l2r occs in + cl_rewrite_clause_aux ~abs strat meta cl gl let general_s_rewrite_clause x = init_setoid (); @@ -1137,7 +1354,7 @@ let setoid_symmetry_in id gl = let he,c1,c2 = mkApp (equiv, Array.of_list others),c1,c2 in let new_hyp' = mkApp (he, [| c2 ; c1 |]) in let new_hyp = it_mkProd_or_LetIn new_hyp' binders in - tclTHENS (cut new_hyp) + tclTHENS (Tactics.cut new_hyp) [ intro_replacing id; tclTHENLIST [ intros; setoid_symmetry; apply (mkVar id); Tactics.assumption ] ] gl |
