src/Pure/simplifier.ML
author wenzelm
Fri Mar 29 22:14:27 2013 +0100 (2013-03-29)
changeset 51580 64ef8260dc60
parent 50107 289181e3e524
child 51584 98029ceda8ce
permissions -rw-r--r--
Pretty.item markup for improved readability of lists of items;
     1 (*  Title:      Pure/simplifier.ML
     2     Author:     Tobias Nipkow and Markus Wenzel, TU Muenchen
     3 
     4 Generic simplifier, suitable for most logics (see also
     5 raw_simplifier.ML for the actual meta-level rewriting engine).
     6 *)
     7 
     8 signature BASIC_SIMPLIFIER =
     9 sig
    10   include BASIC_RAW_SIMPLIFIER
    11   val map_simpset: (simpset -> simpset) -> Proof.context -> Proof.context
    12   val simpset_of: Proof.context -> simpset
    13   val global_simpset_of: theory -> simpset
    14   val Addsimprocs: simproc list -> unit
    15   val Delsimprocs: simproc list -> unit
    16   val simp_tac: simpset -> int -> tactic
    17   val asm_simp_tac: simpset -> int -> tactic
    18   val full_simp_tac: simpset -> int -> tactic
    19   val asm_lr_simp_tac: simpset -> int -> tactic
    20   val asm_full_simp_tac: simpset -> int -> tactic
    21   val safe_simp_tac: simpset -> int -> tactic
    22   val safe_asm_simp_tac: simpset -> int -> tactic
    23   val safe_full_simp_tac: simpset -> int -> tactic
    24   val safe_asm_lr_simp_tac: simpset -> int -> tactic
    25   val safe_asm_full_simp_tac: simpset -> int -> tactic
    26   val simplify: simpset -> thm -> thm
    27   val asm_simplify: simpset -> thm -> thm
    28   val full_simplify: simpset -> thm -> thm
    29   val asm_lr_simplify: simpset -> thm -> thm
    30   val asm_full_simplify: simpset -> thm -> thm
    31 end;
    32 
    33 signature SIMPLIFIER =
    34 sig
    35   include BASIC_SIMPLIFIER
    36   val map_simpset_global: (simpset -> simpset) -> theory -> theory
    37   val pretty_ss: Proof.context -> simpset -> Pretty.T
    38   val clear_ss: simpset -> simpset
    39   val default_mk_sym: simpset -> thm -> thm option
    40   val debug_bounds: bool Unsynchronized.ref
    41   val prems_of: simpset -> thm list
    42   val add_simp: thm -> simpset -> simpset
    43   val del_simp: thm -> simpset -> simpset
    44   val add_eqcong: thm -> simpset -> simpset
    45   val del_eqcong: thm -> simpset -> simpset
    46   val add_cong: thm -> simpset -> simpset
    47   val del_cong: thm -> simpset -> simpset
    48   val add_prems: thm list -> simpset -> simpset
    49   val mksimps: simpset -> thm -> thm list
    50   val set_mksimps: (simpset -> thm -> thm list) -> simpset -> simpset
    51   val set_mkcong: (simpset -> thm -> thm) -> simpset -> simpset
    52   val set_mksym: (simpset -> thm -> thm option) -> simpset -> simpset
    53   val set_mkeqTrue: (simpset -> thm -> thm option) -> simpset -> simpset
    54   val set_termless: (term * term -> bool) -> simpset -> simpset
    55   val set_subgoaler: (simpset -> int -> tactic) -> simpset -> simpset
    56   val inherit_context: simpset -> simpset -> simpset
    57   val the_context: simpset -> Proof.context
    58   val context: Proof.context -> simpset -> simpset
    59   val global_context: theory -> simpset -> simpset
    60   val with_context: Proof.context -> (simpset -> simpset) -> simpset -> simpset
    61   val simproc_global_i: theory -> string -> term list ->
    62     (theory -> simpset -> term -> thm option) -> simproc
    63   val simproc_global: theory -> string -> string list ->
    64     (theory -> simpset -> term -> thm option) -> simproc
    65   val rewrite: simpset -> conv
    66   val asm_rewrite: simpset -> conv
    67   val full_rewrite: simpset -> conv
    68   val asm_lr_rewrite: simpset -> conv
    69   val asm_full_rewrite: simpset -> conv
    70   val get_ss: Context.generic -> simpset
    71   val map_ss: (simpset -> simpset) -> Context.generic -> Context.generic
    72   val attrib: (thm -> simpset -> simpset) -> attribute
    73   val simp_add: attribute
    74   val simp_del: attribute
    75   val cong_add: attribute
    76   val cong_del: attribute
    77   val check_simproc: Proof.context -> xstring * Position.T -> string
    78   val the_simproc: Proof.context -> string -> simproc
    79   val def_simproc: {name: binding, lhss: term list,
    80     proc: morphism -> simpset -> cterm -> thm option, identifier: thm list} ->
    81     local_theory -> local_theory
    82   val def_simproc_cmd: {name: binding, lhss: string list,
    83     proc: morphism -> simpset -> cterm -> thm option, identifier: thm list} ->
    84     local_theory -> local_theory
    85   val cong_modifiers: Method.modifier parser list
    86   val simp_modifiers': Method.modifier parser list
    87   val simp_modifiers: Method.modifier parser list
    88   val method_setup: Method.modifier parser list -> theory -> theory
    89   val easy_setup: thm -> thm list -> theory -> theory
    90 end;
    91 
    92 structure Simplifier: SIMPLIFIER =
    93 struct
    94 
    95 open Raw_Simplifier;
    96 
    97 
    98 (** data **)
    99 
   100 structure Data = Generic_Data
   101 (
   102   type T = simpset * simproc Name_Space.table;
   103   val empty : T = (empty_ss, Name_Space.empty_table "simproc");
   104   fun extend (ss, tab) = (Raw_Simplifier.inherit_context empty_ss ss, tab);
   105   fun merge ((ss1, tab1), (ss2, tab2)) =
   106     (merge_ss (ss1, ss2), Name_Space.merge_tables (tab1, tab2));
   107 );
   108 
   109 val get_ss = fst o Data.get;
   110 
   111 fun map_ss f context =
   112   Data.map (apfst ((Raw_Simplifier.with_context (Context.proof_of context) f))) context;
   113 
   114 val get_simprocs = snd o Data.get o Context.Proof;
   115 
   116 
   117 
   118 (** pretty printing **)
   119 
   120 fun pretty_ss ctxt ss =
   121   let
   122     val pretty_cterm = Syntax.pretty_term ctxt o Thm.term_of;
   123     val pretty_thm = Display.pretty_thm ctxt;
   124     fun pretty_proc (name, lhss) =
   125       Pretty.big_list (name ^ ":") (map (Pretty.item o single o pretty_cterm) lhss);
   126     fun pretty_cong (name, thm) =
   127       Pretty.block [Pretty.str (name ^ ":"), Pretty.brk 1, pretty_thm thm];
   128 
   129     val {simps, procs, congs, loopers, unsafe_solvers, safe_solvers, ...} = dest_ss ss;
   130   in
   131     [Pretty.big_list "simplification rules:" (map (Pretty.item o single o pretty_thm o #2) simps),
   132       Pretty.big_list "simplification procedures:" (map pretty_proc (sort_wrt #1 procs)),
   133       Pretty.big_list "congruences:" (map pretty_cong congs),
   134       Pretty.strs ("loopers:" :: map quote loopers),
   135       Pretty.strs ("unsafe solvers:" :: map quote unsafe_solvers),
   136       Pretty.strs ("safe solvers:" :: map quote safe_solvers)]
   137     |> Pretty.chunks
   138   end;
   139 
   140 
   141 
   142 (** simpset data **)
   143 
   144 (* attributes *)
   145 
   146 fun attrib f = Thm.declaration_attribute (map_ss o f);
   147 
   148 val simp_add = attrib add_simp;
   149 val simp_del = attrib del_simp;
   150 val cong_add = attrib add_cong;
   151 val cong_del = attrib del_cong;
   152 
   153 
   154 (* local simpset *)
   155 
   156 fun map_simpset f = Context.proof_map (map_ss f);
   157 fun simpset_of ctxt = Raw_Simplifier.context ctxt (get_ss (Context.Proof ctxt));
   158 
   159 val _ = Context.>> (Context.map_theory
   160   (ML_Antiquote.value (Binding.name "simpset")
   161     (Scan.succeed "Simplifier.simpset_of ML_context")));
   162 
   163 
   164 (* global simpset *)
   165 
   166 fun map_simpset_global f = Context.theory_map (map_ss f);
   167 fun global_simpset_of thy =
   168   Raw_Simplifier.context (Proof_Context.init_global thy) (get_ss (Context.Theory thy));
   169 
   170 fun Addsimprocs args = Context.>> (map_ss (fn ss => ss addsimprocs args));
   171 fun Delsimprocs args = Context.>> (map_ss (fn ss => ss delsimprocs args));
   172 
   173 
   174 
   175 (** named simprocs **)
   176 
   177 (* get simprocs *)
   178 
   179 fun check_simproc ctxt = Name_Space.check (Context.Proof ctxt) (get_simprocs ctxt) #> #1;
   180 val the_simproc = Name_Space.get o get_simprocs;
   181 
   182 val _ =
   183   Context.>> (Context.map_theory
   184    (ML_Antiquote.value (Binding.name "simproc")
   185       (Args.context -- Scan.lift (Parse.position Args.name)
   186         >> (fn (ctxt, name) =>
   187           "Simplifier.the_simproc ML_context " ^
   188             ML_Syntax.print_string (check_simproc ctxt name)))));
   189 
   190 
   191 (* define simprocs *)
   192 
   193 local
   194 
   195 fun gen_simproc prep {name = b, lhss, proc, identifier} lthy =
   196   let
   197     val simproc = make_simproc
   198       {name = Local_Theory.full_name lthy b,
   199        lhss =
   200         let
   201           val lhss' = prep lthy lhss;
   202           val ctxt' = fold Variable.auto_fixes lhss' lthy;
   203         in Variable.export_terms ctxt' lthy lhss' end
   204         |> map (Thm.cterm_of (Proof_Context.theory_of lthy)),
   205        proc = proc,
   206        identifier = identifier};
   207   in
   208     lthy |> Local_Theory.declaration {syntax = false, pervasive = true} (fn phi => fn context =>
   209       let
   210         val b' = Morphism.binding phi b;
   211         val simproc' = transform_simproc phi simproc;
   212       in
   213         context
   214         |> Data.map (fn (ss, tab) =>
   215           (ss addsimprocs [simproc'], #2 (Name_Space.define context true (b', simproc') tab)))
   216       end)
   217   end;
   218 
   219 in
   220 
   221 val def_simproc = gen_simproc Syntax.check_terms;
   222 val def_simproc_cmd = gen_simproc Syntax.read_terms;
   223 
   224 end;
   225 
   226 
   227 
   228 (** simplification tactics and rules **)
   229 
   230 fun solve_all_tac solvers ss =
   231   let
   232     val (_, {subgoal_tac, ...}) = Raw_Simplifier.internal_ss ss;
   233     val solve_tac = subgoal_tac (Raw_Simplifier.set_solvers solvers ss) THEN_ALL_NEW (K no_tac);
   234   in DEPTH_SOLVE (solve_tac 1) end;
   235 
   236 (*NOTE: may instantiate unknowns that appear also in other subgoals*)
   237 fun generic_simp_tac safe mode ss =
   238   let
   239     val (_, {loop_tacs, solvers = (unsafe_solvers, solvers), ...}) = Raw_Simplifier.internal_ss ss;
   240     val loop_tac = FIRST' (map (fn (_, tac) => tac ss) (rev loop_tacs));
   241     val solve_tac = FIRST' (map (Raw_Simplifier.solver ss)
   242       (rev (if safe then solvers else unsafe_solvers)));
   243 
   244     fun simp_loop_tac i =
   245       Raw_Simplifier.generic_rewrite_goal_tac mode (solve_all_tac unsafe_solvers) ss i THEN
   246       (solve_tac i ORELSE TRY ((loop_tac THEN_ALL_NEW simp_loop_tac) i));
   247   in SELECT_GOAL (simp_loop_tac 1) end;
   248 
   249 local
   250 
   251 fun simp rew mode ss thm =
   252   let
   253     val (_, {solvers = (unsafe_solvers, _), ...}) = Raw_Simplifier.internal_ss ss;
   254     val tacf = solve_all_tac (rev unsafe_solvers);
   255     fun prover s th = Option.map #1 (Seq.pull (tacf s th));
   256   in rew mode prover ss thm end;
   257 
   258 in
   259 
   260 val simp_thm = simp Raw_Simplifier.rewrite_thm;
   261 val simp_cterm = simp Raw_Simplifier.rewrite_cterm;
   262 
   263 end;
   264 
   265 
   266 (* tactics *)
   267 
   268 val simp_tac = generic_simp_tac false (false, false, false);
   269 val asm_simp_tac = generic_simp_tac false (false, true, false);
   270 val full_simp_tac = generic_simp_tac false (true, false, false);
   271 val asm_lr_simp_tac = generic_simp_tac false (true, true, false);
   272 val asm_full_simp_tac = generic_simp_tac false (true, true, true);
   273 
   274 (*not totally safe: may instantiate unknowns that appear also in other subgoals*)
   275 val safe_simp_tac = generic_simp_tac true (false, false, false);
   276 val safe_asm_simp_tac = generic_simp_tac true (false, true, false);
   277 val safe_full_simp_tac = generic_simp_tac true (true, false, false);
   278 val safe_asm_lr_simp_tac = generic_simp_tac true (true, true, false);
   279 val safe_asm_full_simp_tac = generic_simp_tac true (true, true, true);
   280 
   281 
   282 (* conversions *)
   283 
   284 val          simplify = simp_thm (false, false, false);
   285 val      asm_simplify = simp_thm (false, true, false);
   286 val     full_simplify = simp_thm (true, false, false);
   287 val   asm_lr_simplify = simp_thm (true, true, false);
   288 val asm_full_simplify = simp_thm (true, true, true);
   289 
   290 val          rewrite = simp_cterm (false, false, false);
   291 val      asm_rewrite = simp_cterm (false, true, false);
   292 val     full_rewrite = simp_cterm (true, false, false);
   293 val   asm_lr_rewrite = simp_cterm (true, true, false);
   294 val asm_full_rewrite = simp_cterm (true, true, true);
   295 
   296 
   297 
   298 (** concrete syntax of attributes **)
   299 
   300 (* add / del *)
   301 
   302 val simpN = "simp";
   303 val congN = "cong";
   304 val onlyN = "only";
   305 val no_asmN = "no_asm";
   306 val no_asm_useN = "no_asm_use";
   307 val no_asm_simpN = "no_asm_simp";
   308 val asm_lrN = "asm_lr";
   309 
   310 
   311 (* simprocs *)
   312 
   313 local
   314 
   315 val add_del =
   316   (Args.del -- Args.colon >> K (op delsimprocs) ||
   317     Scan.option (Args.add -- Args.colon) >> K (op addsimprocs))
   318   >> (fn f => fn simproc => fn phi => Thm.declaration_attribute
   319       (K (map_ss (fn ss => f (ss, [transform_simproc phi simproc])))));
   320 
   321 in
   322 
   323 val simproc_att =
   324   (Args.context -- Scan.lift add_del) :|-- (fn (ctxt, decl) =>
   325     Scan.repeat1 (Scan.lift (Args.named_attribute (decl o the_simproc ctxt o check_simproc ctxt))))
   326   >> (fn atts => Thm.declaration_attribute (fn th =>
   327         fold (fn att => Thm.attribute_declaration (Morphism.form att) th) atts));
   328 
   329 end;
   330 
   331 
   332 (* conversions *)
   333 
   334 local
   335 
   336 fun conv_mode x =
   337   ((Args.parens (Args.$$$ no_asmN) >> K simplify ||
   338     Args.parens (Args.$$$ no_asm_simpN) >> K asm_simplify ||
   339     Args.parens (Args.$$$ no_asm_useN) >> K full_simplify ||
   340     Scan.succeed asm_full_simplify) |> Scan.lift) x;
   341 
   342 in
   343 
   344 val simplified = conv_mode -- Attrib.thms >>
   345   (fn (f, ths) => Thm.rule_attribute (fn context =>
   346     f ((if null ths then I else Raw_Simplifier.clear_ss)
   347         (simpset_of (Context.proof_of context)) addsimps ths)));
   348 
   349 end;
   350 
   351 
   352 (* setup attributes *)
   353 
   354 val _ = Context.>> (Context.map_theory
   355  (Attrib.setup (Binding.name simpN) (Attrib.add_del simp_add simp_del)
   356     "declaration of Simplifier rewrite rule" #>
   357   Attrib.setup (Binding.name congN) (Attrib.add_del cong_add cong_del)
   358     "declaration of Simplifier congruence rule" #>
   359   Attrib.setup (Binding.name "simproc") simproc_att
   360     "declaration of simplification procedures" #>
   361   Attrib.setup (Binding.name "simplified") simplified "simplified rule"));
   362 
   363 
   364 
   365 (** method syntax **)
   366 
   367 val cong_modifiers =
   368  [Args.$$$ congN -- Args.colon >> K ((I, cong_add): Method.modifier),
   369   Args.$$$ congN -- Args.add -- Args.colon >> K (I, cong_add),
   370   Args.$$$ congN -- Args.del -- Args.colon >> K (I, cong_del)];
   371 
   372 val simp_modifiers =
   373  [Args.$$$ simpN -- Args.colon >> K (I, simp_add),
   374   Args.$$$ simpN -- Args.add -- Args.colon >> K (I, simp_add),
   375   Args.$$$ simpN -- Args.del -- Args.colon >> K (I, simp_del),
   376   Args.$$$ simpN -- Args.$$$ onlyN -- Args.colon
   377     >> K (Context.proof_map (map_ss Raw_Simplifier.clear_ss), simp_add)]
   378    @ cong_modifiers;
   379 
   380 val simp_modifiers' =
   381  [Args.add -- Args.colon >> K (I, simp_add),
   382   Args.del -- Args.colon >> K (I, simp_del),
   383   Args.$$$ onlyN -- Args.colon
   384     >> K (Context.proof_map (map_ss Raw_Simplifier.clear_ss), simp_add)]
   385    @ cong_modifiers;
   386 
   387 val simp_options =
   388  (Args.parens (Args.$$$ no_asmN) >> K simp_tac ||
   389   Args.parens (Args.$$$ no_asm_simpN) >> K asm_simp_tac ||
   390   Args.parens (Args.$$$ no_asm_useN) >> K full_simp_tac ||
   391   Args.parens (Args.$$$ asm_lrN) >> K asm_lr_simp_tac ||
   392   Scan.succeed asm_full_simp_tac);
   393 
   394 fun simp_method more_mods meth =
   395   Scan.lift simp_options --|
   396     Method.sections (more_mods @ simp_modifiers') >>
   397     (fn tac => fn ctxt => METHOD (fn facts => meth ctxt tac facts));
   398 
   399 
   400 
   401 (** setup **)
   402 
   403 fun method_setup more_mods =
   404   Method.setup (Binding.name simpN)
   405     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   406       HEADGOAL (Method.insert_tac facts THEN'
   407         (CHANGED_PROP oo tac) (simpset_of ctxt))))
   408     "simplification" #>
   409   Method.setup (Binding.name "simp_all")
   410     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   411       ALLGOALS (Method.insert_tac facts) THEN
   412         (CHANGED_PROP o PARALLEL_GOALS o ALLGOALS o tac) (simpset_of ctxt)))
   413     "simplification (all goals)";
   414 
   415 fun easy_setup reflect trivs = method_setup [] #> Context.theory_map (map_ss (fn _ =>
   416   let
   417     val trivialities = Drule.reflexive_thm :: trivs;
   418 
   419     fun unsafe_solver_tac ss =
   420       FIRST' [resolve_tac (trivialities @ Raw_Simplifier.prems_of ss), assume_tac];
   421     val unsafe_solver = mk_solver "easy unsafe" unsafe_solver_tac;
   422 
   423     (*no premature instantiation of variables during simplification*)
   424     fun safe_solver_tac ss =
   425       FIRST' [match_tac (trivialities @ Raw_Simplifier.prems_of ss), eq_assume_tac];
   426     val safe_solver = mk_solver "easy safe" safe_solver_tac;
   427 
   428     fun mk_eq thm =
   429       if can Logic.dest_equals (Thm.concl_of thm) then [thm]
   430       else [thm RS reflect] handle THM _ => [];
   431 
   432     fun mksimps thm = mk_eq (Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm);
   433   in
   434     empty_ss
   435     setSSolver safe_solver
   436     setSolver unsafe_solver
   437     |> set_subgoaler asm_simp_tac
   438     |> set_mksimps (K mksimps)
   439   end));
   440 
   441 end;
   442 
   443 structure Basic_Simplifier: BASIC_SIMPLIFIER = Simplifier;
   444 open Basic_Simplifier;