wenzelm@16014: (* Title: Pure/simplifier.ML wenzelm@16014: ID: $Id$ wenzelm@16014: Author: Tobias Nipkow and Markus Wenzel, TU Muenchen wenzelm@16014: wenzelm@16014: Generic simplifier, suitable for most logics (see also wenzelm@16014: meta_simplifier.ML for the actual meta-level rewriting engine). wenzelm@16014: *) wenzelm@16014: wenzelm@16014: signature BASIC_SIMPLIFIER = wenzelm@16014: sig wenzelm@16014: include BASIC_META_SIMPLIFIER wenzelm@17883: val change_simpset: (simpset -> simpset) -> unit wenzelm@16014: val simpset_of: theory -> simpset wenzelm@17883: val simpset: unit -> simpset wenzelm@16014: val SIMPSET: (simpset -> tactic) -> tactic wenzelm@16014: val SIMPSET': (simpset -> 'a -> tactic) -> 'a -> tactic wenzelm@16014: val Addsimps: thm list -> unit wenzelm@16014: val Delsimps: thm list -> unit wenzelm@16014: val Addsimprocs: simproc list -> unit wenzelm@16014: val Delsimprocs: simproc list -> unit wenzelm@16014: val Addcongs: thm list -> unit wenzelm@16014: val Delcongs: thm list -> unit wenzelm@16014: val local_simpset_of: Proof.context -> simpset wenzelm@17967: val generic_simp_tac: bool -> bool * bool * bool -> simpset -> int -> tactic wenzelm@16014: val safe_asm_full_simp_tac: simpset -> int -> tactic wenzelm@16014: val simp_tac: simpset -> int -> tactic wenzelm@16014: val asm_simp_tac: simpset -> int -> tactic wenzelm@16014: val full_simp_tac: simpset -> int -> tactic wenzelm@16014: val asm_lr_simp_tac: simpset -> int -> tactic wenzelm@16014: val asm_full_simp_tac: simpset -> int -> tactic wenzelm@16014: val Simp_tac: int -> tactic wenzelm@16014: val Asm_simp_tac: int -> tactic wenzelm@16014: val Full_simp_tac: int -> tactic wenzelm@16014: val Asm_lr_simp_tac: int -> tactic wenzelm@16014: val Asm_full_simp_tac: int -> tactic wenzelm@16014: val simplify: simpset -> thm -> thm wenzelm@16014: val asm_simplify: simpset -> thm -> thm wenzelm@16014: val full_simplify: simpset -> thm -> thm wenzelm@16014: val asm_lr_simplify: simpset -> thm -> thm wenzelm@16014: val asm_full_simplify: simpset -> thm -> thm wenzelm@16014: end; wenzelm@16014: wenzelm@16014: signature SIMPLIFIER = wenzelm@16014: sig wenzelm@16014: include BASIC_SIMPLIFIER wenzelm@17004: val clear_ss: simpset -> simpset wenzelm@17723: val debug_bounds: bool ref wenzelm@17883: val inherit_context: simpset -> simpset -> simpset wenzelm@17898: val the_context: simpset -> Proof.context wenzelm@17898: val context: Proof.context -> simpset -> simpset wenzelm@17898: val theory_context: theory -> simpset -> simpset wenzelm@16458: val simproc_i: theory -> string -> term list wenzelm@16458: -> (theory -> simpset -> term -> thm option) -> simproc wenzelm@16458: val simproc: theory -> string -> string list wenzelm@16458: -> (theory -> simpset -> term -> thm option) -> simproc wenzelm@23598: val rewrite: simpset -> conv wenzelm@23598: val asm_rewrite: simpset -> conv wenzelm@23598: val full_rewrite: simpset -> conv wenzelm@23598: val asm_lr_rewrite: simpset -> conv wenzelm@23598: val asm_full_rewrite: simpset -> conv wenzelm@22379: val get_ss: Context.generic -> simpset wenzelm@22379: val map_ss: (simpset -> simpset) -> Context.generic -> Context.generic wenzelm@18728: val attrib: (simpset * thm list -> simpset) -> attribute wenzelm@18728: val simp_add: attribute wenzelm@18728: val simp_del: attribute wenzelm@18728: val cong_add: attribute wenzelm@18728: val cong_del: attribute wenzelm@26497: val map_simpset: (simpset -> simpset) -> theory -> theory wenzelm@24024: val get_simproc: Context.generic -> xstring -> simproc wenzelm@22236: val def_simproc: {name: string, lhss: string list, wenzelm@22236: proc: morphism -> simpset -> cterm -> thm option, identifier: thm list} -> wenzelm@22201: local_theory -> local_theory wenzelm@22236: val def_simproc_i: {name: string, lhss: term list, wenzelm@22236: proc: morphism -> simpset -> cterm -> thm option, identifier: thm list} -> wenzelm@22201: local_theory -> local_theory wenzelm@18033: val cong_modifiers: (Args.T list -> (Method.modifier * Args.T list)) list wenzelm@18033: val simp_modifiers': (Args.T list -> (Method.modifier * Args.T list)) list wenzelm@16014: val simp_modifiers: (Args.T list -> (Method.modifier * Args.T list)) list wenzelm@16014: val method_setup: (Args.T list -> (Method.modifier * Args.T list)) list wenzelm@18708: -> theory -> theory wenzelm@18708: val easy_setup: thm -> thm list -> theory -> theory wenzelm@16014: end; wenzelm@16014: wenzelm@16014: structure Simplifier: SIMPLIFIER = wenzelm@16014: struct wenzelm@16014: wenzelm@21708: open MetaSimplifier; wenzelm@21708: wenzelm@21708: wenzelm@17883: (** simpset data **) wenzelm@16014: wenzelm@26497: structure SimpsetData = GenericDataFun wenzelm@22846: ( wenzelm@26497: type T = simpset; wenzelm@26497: val empty = empty_ss; wenzelm@26497: fun extend ss = MetaSimplifier.inherit_context empty_ss ss; wenzelm@26497: fun merge _ = merge_ss; wenzelm@22846: ); wenzelm@16014: wenzelm@26497: val get_ss = SimpsetData.get; wenzelm@26497: val map_ss = SimpsetData.map; wenzelm@26497: wenzelm@26497: wenzelm@26497: (* attributes *) wenzelm@26497: wenzelm@26497: fun attrib f = Thm.declaration_attribute (fn th => map_ss (fn ss => f (ss, [th]))); wenzelm@16014: wenzelm@26497: val simp_add = attrib (op addsimps); wenzelm@26497: val simp_del = attrib (op delsimps); wenzelm@26497: val cong_add = attrib (op addcongs); wenzelm@26497: val cong_del = attrib (op delcongs); wenzelm@26497: wenzelm@16014: wenzelm@26497: (* global simpset *) wenzelm@26497: wenzelm@26497: fun map_simpset f = Context.theory_map (map_ss f); wenzelm@26497: fun change_simpset f = Context.>> (Context.map_theory (map_simpset f)); wenzelm@26497: fun simpset_of thy = MetaSimplifier.context (ProofContext.init thy) (get_ss (Context.Theory thy)); wenzelm@26425: val simpset = simpset_of o ML_Context.the_global_context; wenzelm@16014: wenzelm@17883: fun SIMPSET tacf st = tacf (simpset_of (Thm.theory_of_thm st)) st; wenzelm@17883: fun SIMPSET' tacf i st = tacf (simpset_of (Thm.theory_of_thm st)) i st; wenzelm@16014: wenzelm@17883: fun Addsimps args = change_simpset (fn ss => ss addsimps args); wenzelm@17883: fun Delsimps args = change_simpset (fn ss => ss delsimps args); wenzelm@17883: fun Addsimprocs args = change_simpset (fn ss => ss addsimprocs args); wenzelm@17883: fun Delsimprocs args = change_simpset (fn ss => ss delsimprocs args); wenzelm@17883: fun Addcongs args = change_simpset (fn ss => ss addcongs args); wenzelm@17883: fun Delcongs args = change_simpset (fn ss => ss delcongs args); wenzelm@16014: wenzelm@16014: wenzelm@26497: (* local simpset *) wenzelm@16014: wenzelm@26497: fun local_simpset_of ctxt = MetaSimplifier.context ctxt (get_ss (Context.Proof ctxt)); wenzelm@16014: wenzelm@27338: val _ = ML_Antiquote.value "simpset" wenzelm@27338: (Scan.succeed "Simplifier.local_simpset_of (ML_Context.the_local_context ())"); wenzelm@22132: wenzelm@16014: wenzelm@17967: wenzelm@22201: (** named simprocs **) wenzelm@22201: wenzelm@23655: fun err_dup_simproc name = error ("Duplicate simproc: " ^ quote name); wenzelm@22201: wenzelm@22236: wenzelm@22204: (* data *) wenzelm@22204: wenzelm@22201: structure Simprocs = GenericDataFun wenzelm@22201: ( wenzelm@22236: type T = simproc NameSpace.table; wenzelm@22201: val empty = NameSpace.empty_table; wenzelm@22201: val extend = I; wenzelm@22236: fun merge _ simprocs = NameSpace.merge_tables eq_simproc simprocs wenzelm@23655: handle Symtab.DUP dup => err_dup_simproc dup; wenzelm@22201: ); wenzelm@22201: wenzelm@22204: wenzelm@22204: (* get simprocs *) wenzelm@22204: wenzelm@24024: fun get_simproc context xname = wenzelm@22204: let wenzelm@24024: val (space, tab) = Simprocs.get context; wenzelm@22204: val name = NameSpace.intern space xname; wenzelm@22204: in wenzelm@22204: (case Symtab.lookup tab name of wenzelm@22236: SOME proc => proc wenzelm@22204: | NONE => error ("Undefined simplification procedure: " ^ quote name)) wenzelm@22204: end; wenzelm@22204: wenzelm@27338: val _ = ML_Antiquote.value "simproc" (Scan.lift Args.name >> (fn name => wenzelm@27338: "Simplifier.get_simproc (ML_Context.the_generic_context ()) " ^ ML_Syntax.print_string name)); wenzelm@22204: wenzelm@22204: wenzelm@22204: (* define simprocs *) wenzelm@22201: wenzelm@22201: local wenzelm@22201: wenzelm@22236: fun gen_simproc prep {name, lhss, proc, identifier} lthy = wenzelm@22201: let haftmann@28991: val b = Binding.name name; wenzelm@22236: val naming = LocalTheory.full_naming lthy; wenzelm@22236: val simproc = make_simproc haftmann@28991: {name = LocalTheory.full_name lthy b, wenzelm@22236: lhss = wenzelm@22236: let wenzelm@22236: val lhss' = prep lthy lhss; wenzelm@22236: val ctxt' = lthy wenzelm@22236: |> fold Variable.declare_term lhss' wenzelm@22236: |> fold Variable.auto_fixes lhss'; wenzelm@22236: in Variable.export_terms ctxt' lthy lhss' end wenzelm@22236: |> map (Thm.cterm_of (ProofContext.theory_of lthy)), wenzelm@22236: proc = proc, wenzelm@22236: identifier = identifier} wenzelm@22236: |> morph_simproc (LocalTheory.target_morphism lthy); wenzelm@22201: in wenzelm@24024: lthy |> LocalTheory.declaration (fn phi => wenzelm@22201: let haftmann@28991: val b' = Morphism.binding phi b; wenzelm@22236: val simproc' = morph_simproc phi simproc; wenzelm@22201: in wenzelm@24024: Simprocs.map (fn simprocs => haftmann@28965: NameSpace.bind naming (b', simproc') simprocs |> snd haftmann@28863: handle Symtab.DUP dup => err_dup_simproc dup) wenzelm@24024: #> map_ss (fn ss => ss addsimprocs [simproc']) wenzelm@22201: end) wenzelm@22201: end; wenzelm@22201: wenzelm@22201: in wenzelm@22201: wenzelm@24509: val def_simproc = gen_simproc Syntax.read_terms; wenzelm@24509: val def_simproc_i = gen_simproc Syntax.check_terms; wenzelm@22201: wenzelm@22201: end; wenzelm@22201: wenzelm@22201: wenzelm@22201: wenzelm@17967: (** simplification tactics and rules **) wenzelm@17967: wenzelm@17967: fun solve_all_tac solvers ss = wenzelm@17967: let wenzelm@17967: val (_, {subgoal_tac, ...}) = MetaSimplifier.rep_ss ss; wenzelm@17967: val solve_tac = subgoal_tac (MetaSimplifier.set_solvers solvers ss) THEN_ALL_NEW (K no_tac); wenzelm@17967: in DEPTH_SOLVE (solve_tac 1) end; wenzelm@17967: wenzelm@17967: (*NOTE: may instantiate unknowns that appear also in other subgoals*) wenzelm@17967: fun generic_simp_tac safe mode ss = wenzelm@17967: let wenzelm@17967: val (_, {loop_tacs, solvers = (unsafe_solvers, solvers), ...}) = MetaSimplifier.rep_ss ss; haftmann@21286: val loop_tac = FIRST' (map (fn (_, tac) => tac ss) (rev loop_tacs)); wenzelm@17967: val solve_tac = FIRST' (map (MetaSimplifier.solver ss) haftmann@22717: (rev (if safe then solvers else unsafe_solvers))); wenzelm@17967: wenzelm@17967: fun simp_loop_tac i = wenzelm@23536: asm_rewrite_goal_tac mode (solve_all_tac unsafe_solvers) ss i THEN wenzelm@17967: (solve_tac i ORELSE TRY ((loop_tac THEN_ALL_NEW simp_loop_tac) i)); wenzelm@17967: in simp_loop_tac end; wenzelm@17967: wenzelm@17967: local wenzelm@17967: wenzelm@17967: fun simp rew mode ss thm = wenzelm@17967: let wenzelm@17967: val (_, {solvers = (unsafe_solvers, _), ...}) = MetaSimplifier.rep_ss ss; haftmann@22717: val tacf = solve_all_tac (rev unsafe_solvers); wenzelm@17967: fun prover s th = Option.map #1 (Seq.pull (tacf s th)); wenzelm@17967: in rew mode prover ss thm end; wenzelm@17967: wenzelm@17967: in wenzelm@17967: wenzelm@17967: val simp_thm = simp MetaSimplifier.rewrite_thm; wenzelm@17967: val simp_cterm = simp MetaSimplifier.rewrite_cterm; wenzelm@17967: wenzelm@17967: end; wenzelm@17967: wenzelm@17967: wenzelm@16806: (* tactics *) wenzelm@16806: wenzelm@16014: val simp_tac = generic_simp_tac false (false, false, false); wenzelm@16014: val asm_simp_tac = generic_simp_tac false (false, true, false); wenzelm@16014: val full_simp_tac = generic_simp_tac false (true, false, false); wenzelm@16014: val asm_lr_simp_tac = generic_simp_tac false (true, true, false); wenzelm@16014: val asm_full_simp_tac = generic_simp_tac false (true, true, true); wenzelm@16014: val safe_asm_full_simp_tac = generic_simp_tac true (true, true, true); wenzelm@16014: wenzelm@16014: (*the abstraction over the proof state delays the dereferencing*) wenzelm@16014: fun Simp_tac i st = simp_tac (simpset ()) i st; wenzelm@16014: fun Asm_simp_tac i st = asm_simp_tac (simpset ()) i st; wenzelm@16014: fun Full_simp_tac i st = full_simp_tac (simpset ()) i st; wenzelm@16014: fun Asm_lr_simp_tac i st = asm_lr_simp_tac (simpset ()) i st; wenzelm@16014: fun Asm_full_simp_tac i st = asm_full_simp_tac (simpset ()) i st; wenzelm@16014: wenzelm@16806: wenzelm@16806: (* conversions *) wenzelm@16806: wenzelm@17967: val simplify = simp_thm (false, false, false); wenzelm@17967: val asm_simplify = simp_thm (false, true, false); wenzelm@17967: val full_simplify = simp_thm (true, false, false); wenzelm@17967: val asm_lr_simplify = simp_thm (true, true, false); wenzelm@17967: val asm_full_simplify = simp_thm (true, true, true); wenzelm@16014: wenzelm@17967: val rewrite = simp_cterm (false, false, false); wenzelm@17967: val asm_rewrite = simp_cterm (false, true, false); wenzelm@17967: val full_rewrite = simp_cterm (true, false, false); wenzelm@17967: val asm_lr_rewrite = simp_cterm (true, true, false); wenzelm@17967: val asm_full_rewrite = simp_cterm (true, true, true); wenzelm@16014: wenzelm@16014: wenzelm@16014: wenzelm@16014: (** concrete syntax of attributes **) wenzelm@16014: wenzelm@16014: (* add / del *) wenzelm@16014: wenzelm@16014: val simpN = "simp"; wenzelm@16014: val congN = "cong"; wenzelm@16014: val addN = "add"; wenzelm@16014: val delN = "del"; wenzelm@16014: val onlyN = "only"; wenzelm@16014: val no_asmN = "no_asm"; wenzelm@16014: val no_asm_useN = "no_asm_use"; wenzelm@16014: val no_asm_simpN = "no_asm_simp"; wenzelm@16014: val asm_lrN = "asm_lr"; wenzelm@16014: wenzelm@16014: wenzelm@24024: (* simprocs *) wenzelm@24024: wenzelm@24024: local wenzelm@24024: wenzelm@24024: val add_del = wenzelm@24024: (Args.del -- Args.colon >> K (op delsimprocs) || wenzelm@24024: Scan.option (Args.add -- Args.colon) >> K (op addsimprocs)) wenzelm@24024: >> (fn f => fn simproc => fn phi => Thm.declaration_attribute wenzelm@24024: (K (map_ss (fn ss => f (ss, [morph_simproc phi simproc]))))); wenzelm@24024: wenzelm@24024: in wenzelm@24024: wenzelm@24024: val simproc_att = Attrib.syntax wenzelm@24024: (Scan.peek (fn context => wenzelm@24024: add_del :|-- (fn decl => wenzelm@24024: Scan.repeat1 (Args.named_attribute (decl o get_simproc context)) wenzelm@24024: >> (Library.apply o map Morphism.form)))); wenzelm@24024: wenzelm@24024: end; wenzelm@24124: wenzelm@24024: wenzelm@16014: (* conversions *) wenzelm@16014: wenzelm@16014: local wenzelm@16014: wenzelm@16014: fun conv_mode x = wenzelm@16014: ((Args.parens (Args.$$$ no_asmN) >> K simplify || wenzelm@16014: Args.parens (Args.$$$ no_asm_simpN) >> K asm_simplify || wenzelm@16014: Args.parens (Args.$$$ no_asm_useN) >> K full_simplify || wenzelm@16014: Scan.succeed asm_full_simplify) |> Scan.lift) x; wenzelm@16014: wenzelm@16014: in wenzelm@16014: wenzelm@18688: val simplified = wenzelm@27021: Attrib.syntax (conv_mode -- Attrib.thms >> (fn (f, ths) => Thm.rule_attribute (fn context => wenzelm@27021: f ((if null ths then I else MetaSimplifier.clear_ss) wenzelm@27021: (local_simpset_of (Context.proof_of context)) addsimps ths)))); wenzelm@16014: wenzelm@16014: end; wenzelm@16014: wenzelm@16014: wenzelm@16014: (* setup attributes *) wenzelm@16014: wenzelm@26463: val _ = Context.>> (Context.map_theory wenzelm@18708: (Attrib.add_attributes wenzelm@24024: [(simpN, Attrib.add_del_args simp_add simp_del, "declaration of Simplifier rewrite rule"), wenzelm@18728: (congN, Attrib.add_del_args cong_add cong_del, "declaration of Simplifier congruence rule"), wenzelm@24024: ("simproc", simproc_att, "declaration of simplification procedures"), wenzelm@26463: ("simplified", simplified, "simplified rule")])); wenzelm@16014: wenzelm@16014: wenzelm@16014: wenzelm@16014: (** proof methods **) wenzelm@16014: wenzelm@16014: (* simplification *) wenzelm@16014: wenzelm@16014: val simp_options = wenzelm@16014: (Args.parens (Args.$$$ no_asmN) >> K simp_tac || wenzelm@16014: Args.parens (Args.$$$ no_asm_simpN) >> K asm_simp_tac || wenzelm@16014: Args.parens (Args.$$$ no_asm_useN) >> K full_simp_tac || wenzelm@16014: Args.parens (Args.$$$ asm_lrN) >> K asm_lr_simp_tac || wenzelm@16014: Scan.succeed asm_full_simp_tac); wenzelm@16014: wenzelm@16014: val cong_modifiers = wenzelm@18728: [Args.$$$ congN -- Args.colon >> K ((I, cong_add): Method.modifier), wenzelm@18728: Args.$$$ congN -- Args.add -- Args.colon >> K (I, cong_add), wenzelm@18728: Args.$$$ congN -- Args.del -- Args.colon >> K (I, cong_del)]; wenzelm@16014: wenzelm@16014: val simp_modifiers = wenzelm@18728: [Args.$$$ simpN -- Args.colon >> K (I, simp_add), wenzelm@18728: Args.$$$ simpN -- Args.add -- Args.colon >> K (I, simp_add), wenzelm@18728: Args.$$$ simpN -- Args.del -- Args.colon >> K (I, simp_del), wenzelm@17883: Args.$$$ simpN -- Args.$$$ onlyN -- Args.colon wenzelm@26497: >> K (Context.proof_map (map_ss MetaSimplifier.clear_ss), simp_add)] wenzelm@16014: @ cong_modifiers; wenzelm@16014: wenzelm@16014: val simp_modifiers' = wenzelm@18728: [Args.add -- Args.colon >> K (I, simp_add), wenzelm@18728: Args.del -- Args.colon >> K (I, simp_del), wenzelm@18688: Args.$$$ onlyN -- Args.colon wenzelm@26497: >> K (Context.proof_map (map_ss MetaSimplifier.clear_ss), simp_add)] wenzelm@16014: @ cong_modifiers; wenzelm@16014: wenzelm@16014: fun simp_args more_mods = wenzelm@24124: Method.sectioned_args (Args.bang_facts -- Scan.lift simp_options) wenzelm@16684: (more_mods @ simp_modifiers'); wenzelm@16014: wenzelm@24124: fun simp_method (prems, tac) ctxt = Method.METHOD (fn facts => wenzelm@16014: ALLGOALS (Method.insert_tac (prems @ facts)) THEN wenzelm@24124: (CHANGED_PROP o ALLGOALS o tac) (local_simpset_of ctxt)); wenzelm@16014: wenzelm@24124: fun simp_method' (prems, tac) ctxt = Method.METHOD (fn facts => wenzelm@16014: HEADGOAL (Method.insert_tac (prems @ facts) THEN' wenzelm@24124: ((CHANGED_PROP) oo tac) (local_simpset_of ctxt))); wenzelm@16014: wenzelm@16014: wenzelm@16014: wenzelm@18708: (** setup **) wenzelm@18708: wenzelm@18708: fun method_setup more_mods = Method.add_methods wenzelm@16014: [(simpN, simp_args more_mods simp_method', "simplification"), wenzelm@16014: ("simp_all", simp_args more_mods simp_method, "simplification (all goals)")]; wenzelm@16014: wenzelm@26497: fun easy_setup reflect trivs = method_setup [] #> Context.theory_map (map_ss (fn _ => wenzelm@16014: let wenzelm@16014: val trivialities = Drule.reflexive_thm :: trivs; wenzelm@16014: wenzelm@16014: fun unsafe_solver_tac prems = FIRST' [resolve_tac (trivialities @ prems), assume_tac]; wenzelm@16014: val unsafe_solver = mk_solver "easy unsafe" unsafe_solver_tac; wenzelm@16014: wenzelm@16014: (*no premature instantiation of variables during simplification*) wenzelm@16014: fun safe_solver_tac prems = FIRST' [match_tac (trivialities @ prems), eq_assume_tac]; wenzelm@16014: val safe_solver = mk_solver "easy safe" safe_solver_tac; wenzelm@16014: wenzelm@16014: fun mk_eq thm = wenzelm@20872: if can Logic.dest_equals (Thm.concl_of thm) then [thm] wenzelm@16014: else [thm RS reflect] handle THM _ => []; wenzelm@16014: wenzelm@26653: fun mksimps thm = mk_eq (Thm.forall_elim_vars (#maxidx (Thm.rep_thm thm) + 1) thm); wenzelm@26497: in wenzelm@26497: empty_ss setsubgoaler asm_simp_tac wenzelm@26497: setSSolver safe_solver wenzelm@26497: setSolver unsafe_solver wenzelm@26497: setmksimps mksimps wenzelm@26497: end)); wenzelm@16014: wenzelm@16014: end; wenzelm@16014: wenzelm@16014: structure BasicSimplifier: BASIC_SIMPLIFIER = Simplifier; wenzelm@16014: open BasicSimplifier;