signature BASIC_RAW_SIMPLIFIER = sig val simp_depth_limit: int Config.T val simp_trace_depth_limit: int Config.T val simp_debug: bool Config.T val simp_trace: bool Config.T type cong_name = bool * string type rrule val mk_rrules: Proof.context -> thm -> rrule list val eq_rrule: rrule * rrule -> bool type proc = Proof.context -> cterm -> thm option type solver val mk_solver: string -> (Proof.context -> int -> tactic) -> solver type simpset val empty_ss: simpset val merge_ss: simpset * simpset -> simpset datatype proc_kind = Simproc | Congproc ofbool type simproc val cert_simproc: theory ->
{name: string, kind: proc_kind, lhss: term list,
proc: proc Morphism.entity, identifier: thm list} -> simproc val transform_simproc: morphism -> simproc -> simproc val trim_context_simproc: simproc -> simproc val simpset_of: Proof.context -> simpset val put_simpset: simpset -> Proof.context -> Proof.context val simpset_map: Proof.context -> (Proof.context -> Proof.context) -> simpset -> simpset val map_theory_simpset: (Proof.context -> Proof.context) -> theory -> theory val empty_simpset: Proof.context -> Proof.context val clear_simpset: Proof.context -> Proof.context
val rewrite_rule: Proof.context -> thm list -> thm -> thm val rewrite_goals_rule: Proof.context -> thm list -> thm -> thm val rewrite_goals_tac: Proof.context -> thm list -> tactic val rewrite_goal_tac: Proof.context -> thm list -> int -> tactic val prune_params_tac: Proof.context -> tactic val fold_rule: Proof.context -> thm list -> thm -> thm val fold_goals_tac: Proof.context -> thm list -> tactic val norm_hhf: Proof.context -> thm -> thm val norm_hhf_protect: Proof.context -> thm -> thm end;
signature RAW_SIMPLIFIER = sig
include BASIC_RAW_SIMPLIFIER
exception SIMPLIFIER ofstring * thm list val dest_simps: simpset -> (Thm_Name.T * thm) list val dest_congs: simpset -> (cong_name * thm) list val dest_ss: simpset ->
{simps: (Thm_Name.T * thm) list,
simprocs: (string * term list) list,
congprocs: (string * {lhss: term list, proc: proc Morphism.entity}) list,
congs: (cong_name * thm) list,
weak_congs: cong_name list,
loopers: stringlist,
unsafe_solvers: stringlist,
safe_solvers: stringlist} val init_simpset: thm list -> Proof.context -> Proof.context type trace_ops val set_trace_ops: trace_ops -> theory -> theory val map_ss: (Proof.context -> Proof.context) -> Context.generic -> Context.generic val mksimps: Proof.context -> thm -> thm list val get_mksimps_context: Proof.context -> (thm -> Proof.context -> thm list * Proof.context) val set_mksimps_context: (thm -> Proof.context -> thm list * Proof.context) ->
Proof.context -> Proof.context val add_simps: thm list -> Proof.context -> Proof.context val add_simp: thm -> Proof.context -> Proof.context val del_simps: thm list -> Proof.context -> Proof.context val del_simp: thm -> Proof.context -> Proof.context val flip_simps: thm list -> Proof.context -> Proof.context val flip_simp: thm -> Proof.context -> Proof.context val mk_cong: Proof.context -> thm -> thm val set_mkcong: (Proof.context -> thm -> thm) -> Proof.context -> Proof.context val add_eqcong: thm -> Proof.context -> Proof.context val del_eqcong: thm -> Proof.context -> Proof.context val add_cong: thm -> Proof.context -> Proof.context val del_cong: thm -> Proof.context -> Proof.context val add_proc: simproc -> Proof.context -> Proof.context val del_proc: simproc -> Proof.context -> Proof.context val set_mksym: (Proof.context -> thm -> thm option) -> Proof.context -> Proof.context val set_mkeqTrue: (Proof.context -> thm -> thm option) -> Proof.context -> Proof.context val set_term_ord: term ord -> Proof.context -> Proof.context val subgoal_tac: Proof.context -> int -> tactic val set_subgoaler: (Proof.context -> int -> tactic) -> Proof.context -> Proof.context val prems_of: Proof.context -> thm list val add_prems: thm list -> Proof.context -> Proof.context val loop_tac: Proof.context -> int -> tactic val set_loop: (Proof.context -> int -> tactic) -> Proof.context -> Proof.context val add_loop: string * (Proof.context -> int -> tactic) -> Proof.context -> Proof.context val del_loop: string -> Proof.context -> Proof.context val solvers: Proof.context -> solver list * solver list val solver: Proof.context -> solver -> int -> tactic val set_safe_solver: solver -> Proof.context -> Proof.context val add_safe_solver: solver -> Proof.context -> Proof.context val set_unsafe_solver: solver -> Proof.context -> Proof.context val add_unsafe_solver: solver -> Proof.context -> Proof.context val set_solvers: solver list -> Proof.context -> Proof.context val default_mk_sym: Proof.context -> thm -> thm option val set_reorient: (Proof.context -> term list -> term -> term -> bool) ->
Proof.context -> Proof.context val rewrite_cterm: bool * bool * bool ->
(Proof.context -> thm -> thm option) -> Proof.context -> conv val rewrite_term: theory -> thm list -> (term -> term option) list -> term -> term val rewrite_thm: bool * bool * bool ->
(Proof.context -> thm -> thm option) -> Proof.context -> thm -> thm val generic_rewrite_goal_tac: bool * bool * bool ->
(Proof.context -> tactic) -> Proof.context -> int -> tactic val rewrite0: Proof.context -> bool -> conv val rewrite_wrt: Proof.context -> bool -> thm list -> conv val rewrite0_rule: Proof.context -> thm -> thm end;
signature LEGACY_RAW_SIMPLIFIER = sig
include RAW_SIMPLIFIER val rewrite: Proof.context -> bool -> thm list -> conv end
(* FIXME: it seems that the conditions on extra variables are too liberal if premsarenonempty:doessolvingthepremsreallyguaranteeinstantiationof allitsVars?Better:adynamiccheckeachtimearuleisapplied.
*) fun rewrite_rule_extra_vars prems elhs erhs = let val elhss = elhs :: prems; val tvars = TVars.build (fold TVars.add_tvars elhss); val vars = Vars.build (fold Vars.add_vars elhss); in
erhs |> Term.exists_type (Term.exists_subtype
(fn TVar v => not (TVars.defined tvars v) | _ => false)) orelse
erhs |> Term.exists_subterm
(fn Var v => not (Vars.defined vars v) | _ => false) end;
fun mk_rrule2 {thm, name, lhs, elhs, perm} = let val t = Thm.term_of elhs; val fo = Pattern.first_order t orelse not (Pattern.pattern t); val extra = rrule_extra_vars elhs thm; in {thm = thm, name = name, lhs = lhs, elhs = elhs, extra = extra, fo = fo, perm = perm} end;
(*simple test for looping rewrite rules and stupid orientations*) fun default_reorient ctxt prems lhs rhs =
rewrite_rule_extra_vars prems lhs rhs
orelse
is_Var (head_of lhs)
orelse (* turns t = x around, which causes a headache if x is a local variable - usuallyitisveryuseful:-( is_Freerhsandalsonot(is_Freelhs)andalsonot(Logic.occs(rhs,lhs)) andalsonot(exists_subtermis_Varlhs) orelse
*) exists (fn t => Logic.occs (lhs, t)) (rhs :: prems)
orelse
null prems andalso Pattern.matches (Proof_Context.theory_of ctxt) (lhs, rhs) (*the condition "null prems" is necessary because conditional rewrites withextravariablesintheconditionsmayterminatealthough
the rhs is an instance of the lhs; example: ?m < ?n \<Longrightarrow> f ?n \<equiv> f ?m *)
orelse
is_Const lhs andalso not (is_Const rhs);
val rules' = Net.merge eq_rrule (rules1, rules2); val prems' = Thm.merge_thms (prems1, prems2); val depth' = if #1 depth1 < #1 depth2 then depth2 else depth1; val congs' = Congtab.merge (K true) (congs1, congs2); val weak' = merge (op =) (weak1, weak2); val simprocs' = Net.merge eq_procedure_id (simprocs1, simprocs2); val congprocs' = Net.merge eq_procedure_id (congprocs1, congprocs2); val loop_tacs' = AList.merge (op =) (K true) (loop_tacs1, loop_tacs2); val unsafe_solvers' = merge eq_solver (unsafe_solvers1, unsafe_solvers2); val solvers' = merge eq_solver (solvers1, solvers2); in
make_simpset ((rules', prems', depth'), ((congs', weak'), (simprocs', congprocs'),
mk_rews, term_ord, subgoal_tac, loop_tacs', (unsafe_solvers', solvers'))) end;
(** context data **)
structure Simpset = Generic_Data
( type T = simpset; val empty = empty_ss; val merge = merge_ss;
);
val simpset_of = Simpset.get o Context.Proof;
fun map_simpset f = Context.proof_map (Simpset.map f); fun map_simpset1 f = map_simpset (fn Simpset (ss1, ss2) => Simpset (map_ss1 f ss1, ss2)); fun map_simpset2 f = map_simpset (fn Simpset (ss1, ss2) => Simpset (ss1, map_ss2 f ss2));
fun put_simpset ss = map_simpset (K ss);
fun simpset_map ctxt f ss = ctxt |> put_simpset ss |> f |> simpset_of;
val empty_simpset = put_simpset empty_ss;
fun map_theory_simpset f thy = let val ctxt' = f (Proof_Context.init_global thy); val thy' = Proof_Context.theory_of ctxt'; in Context.theory_map (Simpset.map (K (simpset_of ctxt'))) thy'end;
fun map_ss f = Context.mapping (map_theory_simpset (f o Context_Position.not_really)) f;
val simp_depth_limit = Config.declare_int ("simp_depth_limit", \<^here>) (K 40); val simp_trace_depth_limit = Config.declare_int ("simp_trace_depth_limit", \<^here>) (K 1);
fun inc_simp_depth ctxt =
ctxt |> map_simpset1 (fn (rules, prems, (depth, exceeded)) =>
(rules, prems,
(depth + 1, if depth = Config.get ctxt simp_trace_depth_limit then Unsynchronized.reffalseelse exceeded)));
fun simp_depth ctxt = letval Simpset ({depth = (depth, _), ...}, _) = simpset_of ctxt in depth end;
(* diagnostics *)
exception SIMPLIFIER ofstring * thm list;
val simp_debug = Config.declare_bool ("simp_debug", \<^here>) (K false); val simp_trace = Config.declare_bool ("simp_trace", \<^here>) (K false);
fun cond_warning ctxt msg = if Context_Position.is_really_visible ctxt then warning (msg ()) else ();
fun cond_tracing' ctxt flag msg = if Config.get ctxt flag then let val Simpset ({depth = (depth, exceeded), ...}, _) = simpset_of ctxt; val depth_limit = Config.get ctxt simp_trace_depth_limit; in if depth > depth_limit then if ! exceeded then () else (tracing "simp_trace_depth_limit exceeded!"; exceeded := true) else (tracing (enclose "[""]" (string_of_int depth) ^ msg ()); exceeded := false) end else ();
fun cond_tracing ctxt = cond_tracing' ctxt simp_trace;
fun print_term ctxt s t =
s ^ "\n" ^ Syntax.string_of_term ctxt t;
fun print_thm ctxt msg (name, th) = let val sffx = if Thm_Name.is_empty name then"" else" " ^ quote (Global_Theory.print_thm_name ctxt name) ^ ":"; in print_term ctxt (msg ^ sffx) (Thm.full_prop_of th) end;
fun decomp_simp thm = let val prop = Thm.prop_of thm; val prems = Logic.strip_imp_prems prop; val concl = Drule.strip_imp_concl (Thm.cprop_of thm); val (lhs, rhs) = Thm.dest_equals concl handle TERM _ => raise SIMPLIFIER ("Rewrite rule not a meta-equality", [thm]); val elhs = Thm.dest_arg (Thm.cprop_of (Thm.eta_conversion lhs)); val erhs = Envir.eta_contract (Thm.term_of rhs); val perm =
var_perm (Thm.term_of elhs, erhs) andalso not (Thm.term_of elhs aconv erhs) andalso not (is_Var (Thm.term_of elhs)); in (prems, Thm.term_of lhs, elhs, Thm.term_of rhs, perm) end;
end;
fun decomp_simp' thm = letval (_, lhs, _, rhs, _) = decomp_simp thm in if Thm.nprems_of thm > 0thenraise SIMPLIFIER ("Bad conditional rewrite rule", [thm]) else (lhs, rhs) end;
fun mk_eq_True ctxt (thm, name) =
(case #mk_eq_True (get_mk_rews ctxt) ctxt thm of
NONE => []
| SOME eq_True => letval (_, lhs, elhs, _, _) = decomp_simp eq_True; in [{thm = eq_True, name = name, lhs = lhs, elhs = elhs, perm = false}] end);
(*create the rewrite rule and possibly also the eq_True variant,
in case there are extra vars on the rhs*) fun rrule_eq_True ctxt thm name lhs elhs rhs thm2 = letval rrule = {thm = thm, name = name, lhs = lhs, elhs = elhs, perm = false} in if rewrite_rule_extra_vars [] lhs rhs then
mk_eq_True ctxt (thm2, name) @ [rrule] else [rrule] end;
fun mk_rrule ctxt (thm, name) = letval (prems, lhs, elhs, rhs, perm) = decomp_simp thm in if perm then [{thm = thm, name = name, lhs = lhs, elhs = elhs, perm = true}] else (*weak test for loops*) if rewrite_rule_extra_vars prems lhs rhs orelse is_Var (Thm.term_of elhs) then mk_eq_True ctxt (thm, name) else rrule_eq_True ctxt thm name lhs elhs rhs thm end |> map (fn {thm, name, lhs, elhs, perm} =>
{thm = Thm.trim_context thm, name = name, lhs = lhs,
elhs = Thm.trim_context_cterm elhs, perm = perm});
fun orient_rrule ctxt (thm, name) = let val (prems, lhs, elhs, rhs, perm) = decomp_simp thm; val {reorient, mk_sym, ...} = get_mk_rews ctxt; in if perm then [{thm = thm, name = name, lhs = lhs, elhs = elhs, perm = true}] elseif reorient ctxt prems lhs rhs then if reorient ctxt prems rhs lhs then mk_eq_True ctxt (thm, name) else
(case mk_sym ctxt thm of
NONE => []
| SOME thm' => letval (_, lhs', elhs', rhs', _) = decomp_simp thm' in rrule_eq_True ctxt thm' name lhs' elhs' rhs' thm end) else rrule_eq_True ctxt thm name lhs elhs rhs thm end;
fun extract_rews {sym} thm ctxt = let val mk = #mk (get_mk_rews ctxt); val (rews, ctxt') = mk thm ctxt; val rews' = if sym then rews RL [Drule.symmetric_thm] else rews; in (map (rpair (Thm.get_name_hint thm)) rews', ctxt') end;
fun is_full_cong_prems [] [] = true
| is_full_cong_prems [] _ = false
| is_full_cong_prems (p :: prems) varpairs =
(case Logic.strip_assums_concl p of Const ("Pure.eq", _) $ lhs $ rhs => letval (x, xs) = strip_comb lhs and (y, ys) = strip_comb rhs in
is_Var x andalso forall is_Bound xs andalso not (has_duplicates (op =) xs) andalso xs = ys andalso
member (op =) varpairs (x, y) andalso
is_full_cong_prems prems (remove (op =) (x, y) varpairs) end
| _ => false);
fun is_full_cong thm = let val prems = Thm.prems_of thm and concl = Thm.concl_of thm; val (lhs, rhs) = Logic.dest_equals concl; val (f, xs) = strip_comb lhs and (g, ys) = strip_comb rhs; in
f = g andalso not (has_duplicates (op =) (xs @ ys)) andalso length xs = length ys andalso
is_full_cong_prems prems (xs ~~ ys) end;
in
fun mk_cong ctxt = #mk_cong (get_mk_rews ctxt) ctxt;
fun add_eqcong thm ctxt = ctxt |> map_simpset2
(fn (congs, procs, mk_rews, term_ord, subgoal_tac, loop_tacs, solvers) => let val (lhs, _) = Logic.dest_equals (Thm.concl_of thm) handle TERM _ => raise SIMPLIFIER ("Congruence not a meta-equality", [thm]); (*val lhs = Envir.eta_contract lhs;*) val a = the (cong_name (head_of lhs)) handleOption.Option => raise SIMPLIFIER ("Congruence must start with a constant or free variable", [thm]); val (xs, weak) = congs; val xs' = Congtab.update (a, Thm.trim_context thm) xs; val weak' = if is_full_cong thm then weak else a :: weak; in ((xs', weak'), procs, mk_rews, term_ord, subgoal_tac, loop_tacs, solvers) end);
fun del_eqcong thm ctxt = ctxt |> map_simpset2
(fn (congs, procs, mk_rews, term_ord, subgoal_tac, loop_tacs, solvers) => let val (lhs, _) = Logic.dest_equals (Thm.concl_of thm) handle TERM _ => raise SIMPLIFIER ("Congruence not a meta-equality", [thm]); (*val lhs = Envir.eta_contract lhs;*) val a = the (cong_name (head_of lhs)) handleOption.Option => raise SIMPLIFIER ("Congruence must start with a constant", [thm]); val (xs, _) = congs; val xs' = Congtab.delete_safe a xs; val weak' = Congtab.fold (fn (a, th) => if is_full_cong th then I else insert (op =) a) xs' []; in ((xs', weak'), procs, mk_rews, term_ord, subgoal_tac, loop_tacs, solvers) end);
fun add_cong thm ctxt = add_eqcong (mk_cong ctxt thm) ctxt; fun del_cong thm ctxt = del_eqcong (mk_cong ctxt thm) ctxt;
fun check_conv ctxt msg thm thm' = let val thm'' = Thm.transitive thm thm' handle THM _ => let val nthm' =
Thm.transitive (Thm.symmetric (Drule.beta_eta_conversion (Thm.lhs_of thm'))) thm' in Thm.transitive thm nthm' handle THM _ => let val nthm =
Thm.transitive thm (Drule.beta_eta_conversion (Thm.rhs_of thm)) in Thm.transitive nthm nthm' end end val _ = if msg then cond_tracing ctxt (fn () => print_thm0 ctxt "SUCCEEDED" thm') else (); in SOME thm''end handle THM _ => let val _ $ _ $ prop0 = Thm.prop_of thm; val _ =
cond_tracing ctxt (fn () =>
print_thm0 ctxt "Proved wrong theorem (bad subgoaler?)" thm' ^ "\n" ^
print_term ctxt "Should have proved:" prop0); in NONE end;
(* mk_procrule *)
fun mk_procrule ctxt thm = let val (prems, lhs, elhs, rhs, _) = decomp_simp thm val thm' = Thm.close_derivation \<^here> thm; in if rewrite_rule_extra_vars prems lhs rhs then (cond_warning ctxt (fn () => print_thm0 ctxt "Extra vars on rhs:" thm); []) else [mk_rrule2 {thm = thm', name = Thm_Name.empty, lhs = lhs, elhs = elhs, perm = false}] end;
(* rewritec: conversion to apply the meta simpset to a term *)
(*Since the rewriting strategy is bottom-up, we avoid re-normalizing already normalizedtermsbycarryingaroundtherhsoftherewriterulejust applied.Thisiscalledthe`skeleton'.Itisdecomposedinparallel withtheterm.OnceaVarisencountered,thecorrespondingtermis alreadyinnormalform.
skel0 is a dummy skeleton that is to enforce complete normalization.*)
(*Use rhs as skeleton only if the lhs does not contain unnormalized bits. Thelattermayhappeniffthereareweakcongruencerulesforconstants
in the lhs.*)
fun weak_cong weak lhs = if null weak thenfalse(*optimization*) else exists_subterm
(fn Const (a, _) => member (op =) weak (true, a)
| Free (a, _) => member (op =) weak (false, a)
| _ => false) lhs
fun uncond_skel ((_, weak), congprocs, (lhs, rhs)) = if weak_cong weak lhs then skel0 elseif Net.is_empty congprocs then rhs (*optimization*) elseifexists (is_weak_congproc o procedure_kind) (Net.match_term congprocs lhs) then skel0 else rhs;
(*Behaves like unconditional rule if rhs does not contain vars not in the lhs. Otherwisethosevarsmaybecomeinstantiatedwithunnormalizedterms
while the premises are solved.*)
fun cond_skel (args as (_, _, (lhs, rhs))) = if Vars.subset (vars_set rhs, vars_set lhs) then uncond_skel args else skel0;
fun pattern_order thy = let fun matches arg = can (Pattern.match thy arg) (Vartab.empty, Vartab.empty); in
fn (p1, p2) => if matches (p1, p2) then if matches (p2, p1) then EQUAL else GREATER else if matches (p2, p1) then LESS else EQUAL end;
fun app_congprocs ctxt ct = let val thy = Proof_Context.theory_of ctxt; val Simpset (_, {procs = (_, congprocs), ...}) = simpset_of ctxt;
val eta_ct = Thm.rhs_of (Thm.eta_conversion ct);
fun proc_congs [] = NONE
| proc_congs (Procedure {name, lhs, proc, ...} :: ps) = if Pattern.matches thy (lhs, Thm.term_of ct) then let val _ =
cond_tracing' ctxt simp_debug (fn () =>
print_term ctxt ("Trying procedure " ^ quote name ^ " on:") (Thm.term_of eta_ct));
val ctxt' = Config.put simp_trace (Config.get ctxt simp_debug) ctxt; val res =
trace_simproc {name = name, cterm = eta_ct} ctxt'
(fn ctxt'' => Morphism.form_context' ctxt'' proc eta_ct); in
(case res of
NONE => (cond_tracing' ctxt simp_debug (fn () => "FAILED"); proc_congs ps)
| SOME raw_thm =>
(cond_tracing ctxt (fn () =>
print_thm0 ctxt ("Procedure " ^ quote name ^ " produced congruence rule:")
raw_thm);
SOME (raw_thm, skel0))) end else proc_congs ps; in
Net.match_term congprocs (Thm.term_of eta_ct)
|> sort (pattern_order thy o apply2 procedure_lhs)
|> proc_congs end;
(* conversion to apply a congruence rule to a term *)
fun congc prover ctxt maxt cong t = let val rthm = Thm.incr_indexes (maxt + 1) cong; val rlhs = fst (Thm.dest_equals (Drule.strip_imp_concl (Thm.cprop_of rthm))); val insts = Thm.match (rlhs, t) (* Thm.match can raise Pattern.MATCH;
is handled when congc is called *) val thm' =
Thm.instantiate insts (Thm.rename_boundvars (Thm.term_of rlhs) (Thm.term_of t) rthm); val _ = cond_tracing ctxt (fn () => print_thm0 ctxt "Applying congruence rule:" thm'); fun err (msg, thm) = (cond_tracing ctxt (fn () => print_thm0 ctxt msg thm); NONE); in
(case prover thm' of
NONE => err ("Congruence proof failed. Could not prove", thm')
| SOME thm2 =>
(case check_conv ctxt true (Drule.beta_eta_conversion t) thm2 of
NONE => err ("Congruence proof failed. Should not have proved", thm2)
| SOME thm2' => if op aconv (apply2 Thm.term_of (Thm.dest_equals (Thm.cprop_of thm2'))) then NONE else SOME thm2')) end;
val vA = (("A", 0), propT); val vB = (("B", 0), propT); val vC = (("C", 0), propT);
fun transitive1 NONE NONE = NONE
| transitive1 (SOME thm1) NONE = SOME thm1
| transitive1 NONE (SOME thm2) = SOME thm2
| transitive1 (SOME thm1) (SOME thm2) = SOME (Thm.transitive thm1 thm2);
fun transitive2 thm = transitive1 (SOME thm); fun transitive3 thm = transitive1 thm o SOME;
fun bottomc ((simprem, useprem, mutsimp), prover, maxidx) = let fun botc skel ctxt t = if is_Var skel then NONE else
(case subc skel ctxt t of
some as SOME thm1 =>
(case rewritec (prover, maxidx) ctxt (Thm.rhs_of thm1) of
SOME (thm2, skel2) =>
transitive2 (Thm.transitive thm1 thm2)
(botc skel2 ctxt (Thm.rhs_of thm2))
| NONE => some)
| NONE =>
(case rewritec (prover, maxidx) ctxt t of
SOME (thm2, skel2) => transitive2 thm2
(botc skel2 ctxt (Thm.rhs_of thm2))
| NONE => NONE))
and try_botc ctxt t =
(case botc skel0 ctxt t of
SOME trec1 => trec1
| NONE => Thm.reflexive t)
and subc skel ctxt t0 = letval Simpset (_, {congs, ...}) = simpset_of ctxt in
(case Thm.term_of t0 of
Abs (a, _, _) => letval ((v, t'), ctxt') = Variable.dest_abs_cterm t0 ctxt in
(case botc (skel_body skel) ctxt' t'of
SOME thm => SOME (Thm.abstract_rule a v thm)
| NONE => NONE) end
| t $ _ =>
(case t of Const ("Pure.imp", _) $ _ => impc t0 ctxt
| Abs _ => letval thm = Thm.beta_conversion false t0 in
(case subc skel0 ctxt (Thm.rhs_of thm) of
NONE => SOME thm
| SOME thm' => SOME (Thm.transitive thm thm')) end
| _ => let fun appc () = letval (ct, cu) = Thm.dest_comb t0 in
(case botc (skel_fun skel) ctxt ct of
SOME thm1 =>
(case botc (skel_arg skel) ctxt cu of
SOME thm2 => SOME (Thm.combination thm1 thm2)
| NONE => SOME (Thm.combination thm1 (Thm.reflexive cu)))
| NONE =>
(case botc (skel_arg skel) ctxt cu of
SOME thm1 => SOME (Thm.combination (Thm.reflexive ct) thm1)
| NONE => NONE)) end;
val (h, ts) = strip_comb t;
(*Prefer congprocs over plain cong rules. In congprocs prefer most specific rules. Ifthereisamatchingcongproc,thenlookintotheresult: 1.plainequality:considernormalisationcomplete(justaswithaplaincongruencerule),
2. conditional rule: treat like congruence rules like SOME cong case below.*)
fun app_cong () =
(case app_congprocs ctxt t0 of
SOME (thm, _) => SOME thm
| NONE => Option.mapPartial (Congtab.lookup (fst congs)) (cong_name h)); in
(case app_cong () of
NONE => appc ()
| SOME cong => (*post processing: some partial applications h t1 ... tj, j <= length ts,
may be a redex. Example: map (\<lambda>x. x) = (\<lambda>xs. xs) wrt map_cong*)
(let val thm = congc (prover ctxt) ctxt maxidx cong t0; val t = the_default t0 (Option.map Thm.rhs_of thm); val (cl, cr) = Thm.dest_comb t handle CTERM _ => Thm.dest_comb t0; (*e.g. congproc has
normalized such that head is removed from t*) val dVar = Var (("", 0), dummyT); val skel = list_comb (h, replicate (length ts) dVar); in
(case botc skel ctxt cl of
NONE => thm
| SOME thm' => transitive3 thm (Thm.combination thm' (Thm.reflexive cr))) endhandle Pattern.MATCH => appc ())) end)
| _ => NONE) end and impc ct ctxt = if mutsimp then mut_impc0 [] ct [] [] ctxt else nonmut_impc ct ctxt
and rules_of_prem prem ctxt = if maxidx_of_term (Thm.term_of prem) <> ~1 then
(cond_tracing ctxt (fn () =>
print_term ctxt "Cannot add premise as rewrite rule because it contains (type) unknowns:"
(Thm.term_of prem));
(([], NONE), ctxt)) else let val (asm, ctxt') = Thm.assume_hyps prem ctxt; val (rews, ctxt'') = extract_safe_rrules asm ctxt'; in ((rews, SOME asm), ctxt'') end
and add_rrules (rrss, asms) ctxt =
(fold o fold) insert_rrule rrss ctxt |> add_prems (map_filter I asms)
and disch r prem eq = let val (lhs, rhs) = Thm.dest_equals (Thm.cprop_of eq); val eq' =
Thm.implies_elim
(Thm.instantiate (TVars.empty, Vars.make3 (vA, prem) (vB, lhs) (vC, rhs))
Drule.imp_cong)
(Thm.implies_intr prem eq); in ifnot r then eq' else let val (prem', concl) = Thm.dest_implies lhs; val (prem'', _) = Thm.dest_implies rhs; in
Thm.transitive
(Thm.transitive
(Thm.instantiate (TVars.empty, Vars.make3 (vA, prem') (vB, prem) (vC, concl))
Drule.swap_prems_eq)
eq')
(Thm.instantiate (TVars.empty, Vars.make3 (vA, prem) (vB, prem'') (vC, concl))
Drule.swap_prems_eq) end end
(*Rewrite the subgoals of a proof state (represented by a theorem)*) fun rewrite_goals_rule ctxt thms th =
Conv.fconv_rule (Conv.prems_conv ~1 (rewrite_cterm (true, true, true) simple_prover
(init_simpset thms ctxt))) th;
(** meta-rewriting tactics **)
(*Rewrite all subgoals*) fun rewrite_goals_tac ctxt defs = PRIMITIVE (rewrite_goals_rule ctxt defs);
(*Rewrite one subgoal*) fun generic_rewrite_goal_tac mode prover_tac ctxt i thm = if0 < i andalso i <= Thm.nprems_of thm then
Seq.single (Conv.gconv_rule (rewrite_cterm mode (SINGLE o prover_tac) ctxt) i thm) else Seq.empty;
(*Prunes all redundant parameters from the proof state by rewriting.*) fun prune_params_tac ctxt = rewrite_goals_tac ctxt [Drule.triv_forall_equality];
(* for folding definitions, handling critical pairs *)
(*The depth of nesting in a term*) fun term_depth (Abs (_, _, t)) = 1 + term_depth t
| term_depth (f $ t) = 1 + Int.max (term_depth f, term_depth t)
| term_depth _ = 0;
val lhs_of_thm = #1 o Logic.dest_equals o Thm.prop_of;
(*folding should handle critical pairs! E.g. K \<equiv> Inl 0, S \<equiv> Inr (Inl 0)
Returns longest lhs first to avoid folding its subexpressions.*) fun sort_lhs_depths defs = letval keylist = AList.make (term_depth o lhs_of_thm) defs val keys = sort_distinct (rev_order o int_ord) (map #2 keylist) inmap (AList.find (op =) keylist) keys end;
val rev_defs = sort_lhs_depths o map Thm.symmetric;
fun fold_rule ctxt defs = fold (rewrite_rule ctxt) (rev_defs defs); fun fold_goals_tac ctxt defs = EVERY (map (rewrite_goals_tac ctxt) (rev_defs defs));
(* HHF normal form: \<And> before \<Longrightarrow>, outermost \<And> generalized *)
local
fun gen_norm_hhf protect ss ctxt0 th0 = let val (ctxt, th) = Thm.join_transfer_context (ctxt0, th0); val th' = if Drule.is_norm_hhf protect (Thm.prop_of th) then th else
Conv.fconv_rule (rewrite_cterm (true, false, false) (K (K NONE)) (put_simpset ss ctxt)) th; in th' |> Thm.adjust_maxidx_thm ~1 |> Variable.gen_all ctxt end;
val hhf_ss =
Context.the_local_context ()
|> init_simpset Drule.norm_hhf_eqs
|> simpset_of;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.