src/Pure/simplifier.ML
author wenzelm
Wed Dec 12 23:36:07 2012 +0100 (2012-12-12 ago)
changeset 50499 f496b2b7bafb
parent 50107 289181e3e524
child 51580 64ef8260dc60
permissions -rw-r--r--
rendering of selected dialog_result as active_result_color, depending on dynamic command status in output panel, but not static popups etc.;
     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) = Pretty.big_list (name ^ ":") (map pretty_cterm lhss);
   125     fun pretty_cong (name, thm) =
   126       Pretty.block [Pretty.str (name ^ ":"), Pretty.brk 1, pretty_thm thm];
   127 
   128     val {simps, procs, congs, loopers, unsafe_solvers, safe_solvers, ...} = dest_ss ss;
   129   in
   130     [Pretty.big_list "simplification rules:" (map (pretty_thm o #2) simps),
   131       Pretty.big_list "simplification procedures:" (map pretty_proc (sort_wrt #1 procs)),
   132       Pretty.big_list "congruences:" (map pretty_cong congs),
   133       Pretty.strs ("loopers:" :: map quote loopers),
   134       Pretty.strs ("unsafe solvers:" :: map quote unsafe_solvers),
   135       Pretty.strs ("safe solvers:" :: map quote safe_solvers)]
   136     |> Pretty.chunks
   137   end;
   138 
   139 
   140 
   141 (** simpset data **)
   142 
   143 (* attributes *)
   144 
   145 fun attrib f = Thm.declaration_attribute (map_ss o f);
   146 
   147 val simp_add = attrib add_simp;
   148 val simp_del = attrib del_simp;
   149 val cong_add = attrib add_cong;
   150 val cong_del = attrib del_cong;
   151 
   152 
   153 (* local simpset *)
   154 
   155 fun map_simpset f = Context.proof_map (map_ss f);
   156 fun simpset_of ctxt = Raw_Simplifier.context ctxt (get_ss (Context.Proof ctxt));
   157 
   158 val _ = Context.>> (Context.map_theory
   159   (ML_Antiquote.value (Binding.name "simpset")
   160     (Scan.succeed "Simplifier.simpset_of ML_context")));
   161 
   162 
   163 (* global simpset *)
   164 
   165 fun map_simpset_global f = Context.theory_map (map_ss f);
   166 fun global_simpset_of thy =
   167   Raw_Simplifier.context (Proof_Context.init_global thy) (get_ss (Context.Theory thy));
   168 
   169 fun Addsimprocs args = Context.>> (map_ss (fn ss => ss addsimprocs args));
   170 fun Delsimprocs args = Context.>> (map_ss (fn ss => ss delsimprocs args));
   171 
   172 
   173 
   174 (** named simprocs **)
   175 
   176 (* get simprocs *)
   177 
   178 fun check_simproc ctxt = Name_Space.check (Context.Proof ctxt) (get_simprocs ctxt) #> #1;
   179 val the_simproc = Name_Space.get o get_simprocs;
   180 
   181 val _ =
   182   Context.>> (Context.map_theory
   183    (ML_Antiquote.value (Binding.name "simproc")
   184       (Args.context -- Scan.lift (Parse.position Args.name)
   185         >> (fn (ctxt, name) =>
   186           "Simplifier.the_simproc ML_context " ^
   187             ML_Syntax.print_string (check_simproc ctxt name)))));
   188 
   189 
   190 (* define simprocs *)
   191 
   192 local
   193 
   194 fun gen_simproc prep {name = b, lhss, proc, identifier} lthy =
   195   let
   196     val simproc = make_simproc
   197       {name = Local_Theory.full_name lthy b,
   198        lhss =
   199         let
   200           val lhss' = prep lthy lhss;
   201           val ctxt' = fold Variable.auto_fixes lhss' lthy;
   202         in Variable.export_terms ctxt' lthy lhss' end
   203         |> map (Thm.cterm_of (Proof_Context.theory_of lthy)),
   204        proc = proc,
   205        identifier = identifier};
   206   in
   207     lthy |> Local_Theory.declaration {syntax = false, pervasive = true} (fn phi => fn context =>
   208       let
   209         val b' = Morphism.binding phi b;
   210         val simproc' = transform_simproc phi simproc;
   211       in
   212         context
   213         |> Data.map (fn (ss, tab) =>
   214           (ss addsimprocs [simproc'], #2 (Name_Space.define context true (b', simproc') tab)))
   215       end)
   216   end;
   217 
   218 in
   219 
   220 val def_simproc = gen_simproc Syntax.check_terms;
   221 val def_simproc_cmd = gen_simproc Syntax.read_terms;
   222 
   223 end;
   224 
   225 
   226 
   227 (** simplification tactics and rules **)
   228 
   229 fun solve_all_tac solvers ss =
   230   let
   231     val (_, {subgoal_tac, ...}) = Raw_Simplifier.internal_ss ss;
   232     val solve_tac = subgoal_tac (Raw_Simplifier.set_solvers solvers ss) THEN_ALL_NEW (K no_tac);
   233   in DEPTH_SOLVE (solve_tac 1) end;
   234 
   235 (*NOTE: may instantiate unknowns that appear also in other subgoals*)
   236 fun generic_simp_tac safe mode ss =
   237   let
   238     val (_, {loop_tacs, solvers = (unsafe_solvers, solvers), ...}) = Raw_Simplifier.internal_ss ss;
   239     val loop_tac = FIRST' (map (fn (_, tac) => tac ss) (rev loop_tacs));
   240     val solve_tac = FIRST' (map (Raw_Simplifier.solver ss)
   241       (rev (if safe then solvers else unsafe_solvers)));
   242 
   243     fun simp_loop_tac i =
   244       Raw_Simplifier.generic_rewrite_goal_tac mode (solve_all_tac unsafe_solvers) ss i THEN
   245       (solve_tac i ORELSE TRY ((loop_tac THEN_ALL_NEW simp_loop_tac) i));
   246   in SELECT_GOAL (simp_loop_tac 1) end;
   247 
   248 local
   249 
   250 fun simp rew mode ss thm =
   251   let
   252     val (_, {solvers = (unsafe_solvers, _), ...}) = Raw_Simplifier.internal_ss ss;
   253     val tacf = solve_all_tac (rev unsafe_solvers);
   254     fun prover s th = Option.map #1 (Seq.pull (tacf s th));
   255   in rew mode prover ss thm end;
   256 
   257 in
   258 
   259 val simp_thm = simp Raw_Simplifier.rewrite_thm;
   260 val simp_cterm = simp Raw_Simplifier.rewrite_cterm;
   261 
   262 end;
   263 
   264 
   265 (* tactics *)
   266 
   267 val simp_tac = generic_simp_tac false (false, false, false);
   268 val asm_simp_tac = generic_simp_tac false (false, true, false);
   269 val full_simp_tac = generic_simp_tac false (true, false, false);
   270 val asm_lr_simp_tac = generic_simp_tac false (true, true, false);
   271 val asm_full_simp_tac = generic_simp_tac false (true, true, true);
   272 
   273 (*not totally safe: may instantiate unknowns that appear also in other subgoals*)
   274 val safe_simp_tac = generic_simp_tac true (false, false, false);
   275 val safe_asm_simp_tac = generic_simp_tac true (false, true, false);
   276 val safe_full_simp_tac = generic_simp_tac true (true, false, false);
   277 val safe_asm_lr_simp_tac = generic_simp_tac true (true, true, false);
   278 val safe_asm_full_simp_tac = generic_simp_tac true (true, true, true);
   279 
   280 
   281 (* conversions *)
   282 
   283 val          simplify = simp_thm (false, false, false);
   284 val      asm_simplify = simp_thm (false, true, false);
   285 val     full_simplify = simp_thm (true, false, false);
   286 val   asm_lr_simplify = simp_thm (true, true, false);
   287 val asm_full_simplify = simp_thm (true, true, true);
   288 
   289 val          rewrite = simp_cterm (false, false, false);
   290 val      asm_rewrite = simp_cterm (false, true, false);
   291 val     full_rewrite = simp_cterm (true, false, false);
   292 val   asm_lr_rewrite = simp_cterm (true, true, false);
   293 val asm_full_rewrite = simp_cterm (true, true, true);
   294 
   295 
   296 
   297 (** concrete syntax of attributes **)
   298 
   299 (* add / del *)
   300 
   301 val simpN = "simp";
   302 val congN = "cong";
   303 val onlyN = "only";
   304 val no_asmN = "no_asm";
   305 val no_asm_useN = "no_asm_use";
   306 val no_asm_simpN = "no_asm_simp";
   307 val asm_lrN = "asm_lr";
   308 
   309 
   310 (* simprocs *)
   311 
   312 local
   313 
   314 val add_del =
   315   (Args.del -- Args.colon >> K (op delsimprocs) ||
   316     Scan.option (Args.add -- Args.colon) >> K (op addsimprocs))
   317   >> (fn f => fn simproc => fn phi => Thm.declaration_attribute
   318       (K (map_ss (fn ss => f (ss, [transform_simproc phi simproc])))));
   319 
   320 in
   321 
   322 val simproc_att =
   323   (Args.context -- Scan.lift add_del) :|-- (fn (ctxt, decl) =>
   324     Scan.repeat1 (Scan.lift (Args.named_attribute (decl o the_simproc ctxt o check_simproc ctxt))))
   325   >> (fn atts => Thm.declaration_attribute (fn th =>
   326         fold (fn att => Thm.attribute_declaration (Morphism.form att) th) atts));
   327 
   328 end;
   329 
   330 
   331 (* conversions *)
   332 
   333 local
   334 
   335 fun conv_mode x =
   336   ((Args.parens (Args.$$$ no_asmN) >> K simplify ||
   337     Args.parens (Args.$$$ no_asm_simpN) >> K asm_simplify ||
   338     Args.parens (Args.$$$ no_asm_useN) >> K full_simplify ||
   339     Scan.succeed asm_full_simplify) |> Scan.lift) x;
   340 
   341 in
   342 
   343 val simplified = conv_mode -- Attrib.thms >>
   344   (fn (f, ths) => Thm.rule_attribute (fn context =>
   345     f ((if null ths then I else Raw_Simplifier.clear_ss)
   346         (simpset_of (Context.proof_of context)) addsimps ths)));
   347 
   348 end;
   349 
   350 
   351 (* setup attributes *)
   352 
   353 val _ = Context.>> (Context.map_theory
   354  (Attrib.setup (Binding.name simpN) (Attrib.add_del simp_add simp_del)
   355     "declaration of Simplifier rewrite rule" #>
   356   Attrib.setup (Binding.name congN) (Attrib.add_del cong_add cong_del)
   357     "declaration of Simplifier congruence rule" #>
   358   Attrib.setup (Binding.name "simproc") simproc_att
   359     "declaration of simplification procedures" #>
   360   Attrib.setup (Binding.name "simplified") simplified "simplified rule"));
   361 
   362 
   363 
   364 (** method syntax **)
   365 
   366 val cong_modifiers =
   367  [Args.$$$ congN -- Args.colon >> K ((I, cong_add): Method.modifier),
   368   Args.$$$ congN -- Args.add -- Args.colon >> K (I, cong_add),
   369   Args.$$$ congN -- Args.del -- Args.colon >> K (I, cong_del)];
   370 
   371 val simp_modifiers =
   372  [Args.$$$ simpN -- Args.colon >> K (I, simp_add),
   373   Args.$$$ simpN -- Args.add -- Args.colon >> K (I, simp_add),
   374   Args.$$$ simpN -- Args.del -- Args.colon >> K (I, simp_del),
   375   Args.$$$ simpN -- Args.$$$ onlyN -- Args.colon
   376     >> K (Context.proof_map (map_ss Raw_Simplifier.clear_ss), simp_add)]
   377    @ cong_modifiers;
   378 
   379 val simp_modifiers' =
   380  [Args.add -- Args.colon >> K (I, simp_add),
   381   Args.del -- Args.colon >> K (I, simp_del),
   382   Args.$$$ onlyN -- Args.colon
   383     >> K (Context.proof_map (map_ss Raw_Simplifier.clear_ss), simp_add)]
   384    @ cong_modifiers;
   385 
   386 val simp_options =
   387  (Args.parens (Args.$$$ no_asmN) >> K simp_tac ||
   388   Args.parens (Args.$$$ no_asm_simpN) >> K asm_simp_tac ||
   389   Args.parens (Args.$$$ no_asm_useN) >> K full_simp_tac ||
   390   Args.parens (Args.$$$ asm_lrN) >> K asm_lr_simp_tac ||
   391   Scan.succeed asm_full_simp_tac);
   392 
   393 fun simp_method more_mods meth =
   394   Scan.lift simp_options --|
   395     Method.sections (more_mods @ simp_modifiers') >>
   396     (fn tac => fn ctxt => METHOD (fn facts => meth ctxt tac facts));
   397 
   398 
   399 
   400 (** setup **)
   401 
   402 fun method_setup more_mods =
   403   Method.setup (Binding.name simpN)
   404     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   405       HEADGOAL (Method.insert_tac facts THEN'
   406         (CHANGED_PROP oo tac) (simpset_of ctxt))))
   407     "simplification" #>
   408   Method.setup (Binding.name "simp_all")
   409     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   410       ALLGOALS (Method.insert_tac facts) THEN
   411         (CHANGED_PROP o PARALLEL_GOALS o ALLGOALS o tac) (simpset_of ctxt)))
   412     "simplification (all goals)";
   413 
   414 fun easy_setup reflect trivs = method_setup [] #> Context.theory_map (map_ss (fn _ =>
   415   let
   416     val trivialities = Drule.reflexive_thm :: trivs;
   417 
   418     fun unsafe_solver_tac ss =
   419       FIRST' [resolve_tac (trivialities @ Raw_Simplifier.prems_of ss), assume_tac];
   420     val unsafe_solver = mk_solver "easy unsafe" unsafe_solver_tac;
   421 
   422     (*no premature instantiation of variables during simplification*)
   423     fun safe_solver_tac ss =
   424       FIRST' [match_tac (trivialities @ Raw_Simplifier.prems_of ss), eq_assume_tac];
   425     val safe_solver = mk_solver "easy safe" safe_solver_tac;
   426 
   427     fun mk_eq thm =
   428       if can Logic.dest_equals (Thm.concl_of thm) then [thm]
   429       else [thm RS reflect] handle THM _ => [];
   430 
   431     fun mksimps thm = mk_eq (Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm);
   432   in
   433     empty_ss
   434     setSSolver safe_solver
   435     setSolver unsafe_solver
   436     |> set_subgoaler asm_simp_tac
   437     |> set_mksimps (K mksimps)
   438   end));
   439 
   440 end;
   441 
   442 structure Basic_Simplifier: BASIC_SIMPLIFIER = Simplifier;
   443 open Basic_Simplifier;