src/Pure/simplifier.ML
author wenzelm
Tue Sep 26 20:54:40 2017 +0200 (21 months ago)
changeset 66695 91500c024c7f
parent 64556 851ae0e7b09c
child 67146 909dcdec2122
permissions -rw-r--r--
tuned;
     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 simp_tac: Proof.context -> int -> tactic
    12   val asm_simp_tac: Proof.context -> int -> tactic
    13   val full_simp_tac: Proof.context -> int -> tactic
    14   val asm_lr_simp_tac: Proof.context -> int -> tactic
    15   val asm_full_simp_tac: Proof.context -> int -> tactic
    16   val safe_simp_tac: Proof.context -> int -> tactic
    17   val safe_asm_simp_tac: Proof.context -> int -> tactic
    18   val safe_full_simp_tac: Proof.context -> int -> tactic
    19   val safe_asm_lr_simp_tac: Proof.context -> int -> tactic
    20   val safe_asm_full_simp_tac: Proof.context -> int -> tactic
    21   val simplify: Proof.context -> thm -> thm
    22   val asm_simplify: Proof.context -> thm -> thm
    23   val full_simplify: Proof.context -> thm -> thm
    24   val asm_lr_simplify: Proof.context -> thm -> thm
    25   val asm_full_simplify: Proof.context -> thm -> thm
    26 end;
    27 
    28 signature SIMPLIFIER =
    29 sig
    30   include BASIC_SIMPLIFIER
    31   val map_ss: (Proof.context -> Proof.context) -> Context.generic -> Context.generic
    32   val attrib: (thm -> Proof.context -> Proof.context) -> attribute
    33   val simp_add: attribute
    34   val simp_del: attribute
    35   val cong_add: attribute
    36   val cong_del: attribute
    37   val check_simproc: Proof.context -> xstring * Position.T -> string
    38   val the_simproc: Proof.context -> string -> simproc
    39   type 'a simproc_spec = {lhss: 'a list, proc: morphism -> Proof.context -> cterm -> thm option}
    40   val make_simproc: Proof.context -> string -> term simproc_spec -> simproc
    41   val define_simproc: binding -> term simproc_spec -> local_theory -> local_theory
    42   val define_simproc_cmd: binding -> string simproc_spec -> local_theory -> local_theory
    43   val pretty_simpset: bool -> Proof.context -> Pretty.T
    44   val default_mk_sym: Proof.context -> thm -> thm option
    45   val prems_of: Proof.context -> thm list
    46   val add_simp: thm -> Proof.context -> Proof.context
    47   val del_simp: thm -> Proof.context -> Proof.context
    48   val init_simpset: thm list -> Proof.context -> Proof.context
    49   val add_eqcong: thm -> Proof.context -> Proof.context
    50   val del_eqcong: thm -> Proof.context -> Proof.context
    51   val add_cong: thm -> Proof.context -> Proof.context
    52   val del_cong: thm -> Proof.context -> Proof.context
    53   val add_prems: thm list -> Proof.context -> Proof.context
    54   val mksimps: Proof.context -> thm -> thm list
    55   val set_mksimps: (Proof.context -> thm -> thm list) -> Proof.context -> Proof.context
    56   val set_mkcong: (Proof.context -> thm -> thm) -> Proof.context -> Proof.context
    57   val set_mksym: (Proof.context -> thm -> thm option) -> Proof.context -> Proof.context
    58   val set_mkeqTrue: (Proof.context -> thm -> thm option) -> Proof.context -> Proof.context
    59   val set_termless: (term * term -> bool) -> Proof.context -> Proof.context
    60   val set_subgoaler: (Proof.context -> int -> tactic) -> Proof.context -> Proof.context
    61   type trace_ops
    62   val set_trace_ops: trace_ops -> theory -> theory
    63   val rewrite: Proof.context -> conv
    64   val asm_rewrite: Proof.context -> conv
    65   val full_rewrite: Proof.context -> conv
    66   val asm_lr_rewrite: Proof.context -> conv
    67   val asm_full_rewrite: Proof.context -> conv
    68   val cong_modifiers: Method.modifier parser list
    69   val simp_modifiers': Method.modifier parser list
    70   val simp_modifiers: Method.modifier parser list
    71   val method_setup: Method.modifier parser list -> theory -> theory
    72   val unsafe_solver_tac: Proof.context -> int -> tactic
    73   val unsafe_solver: solver
    74   val safe_solver_tac: Proof.context -> int -> tactic
    75   val safe_solver: solver
    76 end;
    77 
    78 structure Simplifier: SIMPLIFIER =
    79 struct
    80 
    81 open Raw_Simplifier;
    82 
    83 
    84 (** declarations **)
    85 
    86 (* attributes *)
    87 
    88 fun attrib f = Thm.declaration_attribute (map_ss o f);
    89 
    90 val simp_add = attrib add_simp;
    91 val simp_del = attrib del_simp;
    92 val cong_add = attrib add_cong;
    93 val cong_del = attrib del_cong;
    94 
    95 
    96 (** named simprocs **)
    97 
    98 structure Simprocs = Generic_Data
    99 (
   100   type T = simproc Name_Space.table;
   101   val empty : T = Name_Space.empty_table "simproc";
   102   val extend = I;
   103   fun merge data : T = Name_Space.merge_tables data;
   104 );
   105 
   106 
   107 (* get simprocs *)
   108 
   109 val get_simprocs = Simprocs.get o Context.Proof;
   110 
   111 fun check_simproc ctxt = Name_Space.check (Context.Proof ctxt) (get_simprocs ctxt) #> #1;
   112 val the_simproc = Name_Space.get o get_simprocs;
   113 
   114 val _ = Theory.setup
   115   (ML_Antiquotation.value @{binding simproc}
   116     (Args.context -- Scan.lift (Parse.position Args.name)
   117       >> (fn (ctxt, name) =>
   118         "Simplifier.the_simproc ML_context " ^ ML_Syntax.print_string (check_simproc ctxt name))));
   119 
   120 
   121 (* define simprocs *)
   122 
   123 type 'a simproc_spec = {lhss: 'a list, proc: morphism -> Proof.context -> cterm -> thm option};
   124 
   125 fun make_simproc ctxt name {lhss, proc} =
   126   let
   127     val ctxt' = fold Variable.auto_fixes lhss ctxt;
   128     val lhss' = Variable.export_terms ctxt' ctxt lhss;
   129   in
   130     cert_simproc (Proof_Context.theory_of ctxt) name {lhss = lhss', proc = proc}
   131   end;
   132 
   133 local
   134 
   135 fun def_simproc prep b {lhss, proc} lthy =
   136   let
   137     val simproc =
   138       make_simproc lthy (Local_Theory.full_name lthy b) {lhss = prep lthy lhss, proc = proc};
   139   in
   140     lthy |> Local_Theory.declaration {syntax = false, pervasive = false} (fn phi => fn context =>
   141       let
   142         val b' = Morphism.binding phi b;
   143         val simproc' = transform_simproc phi simproc;
   144       in
   145         context
   146         |> Simprocs.map (#2 o Name_Space.define context true (b', simproc'))
   147         |> map_ss (fn ctxt => ctxt addsimprocs [simproc'])
   148       end)
   149   end;
   150 
   151 in
   152 
   153 val define_simproc = def_simproc Syntax.check_terms;
   154 val define_simproc_cmd = def_simproc Syntax.read_terms;
   155 
   156 end;
   157 
   158 
   159 
   160 (** pretty_simpset **)
   161 
   162 fun pretty_simpset verbose ctxt =
   163   let
   164     val pretty_term = Syntax.pretty_term ctxt;
   165     val pretty_thm = Thm.pretty_thm ctxt;
   166     val pretty_thm_item = Thm.pretty_thm_item ctxt;
   167 
   168     fun pretty_simproc (name, lhss) =
   169       Pretty.block
   170         (Pretty.mark_str name :: Pretty.str ":" :: Pretty.fbrk ::
   171           Pretty.fbreaks (map (Pretty.item o single o pretty_term) lhss));
   172 
   173     fun pretty_cong_name (const, name) =
   174       pretty_term ((if const then Const else Free) (name, dummyT));
   175     fun pretty_cong (name, thm) =
   176       Pretty.block [pretty_cong_name name, Pretty.str ":", Pretty.brk 1, pretty_thm thm];
   177 
   178     val {simps, procs, congs, loopers, unsafe_solvers, safe_solvers, ...} =
   179       dest_ss (simpset_of ctxt);
   180     val simprocs =
   181       Name_Space.markup_entries verbose ctxt (Name_Space.space_of_table (get_simprocs ctxt)) procs;
   182   in
   183     [Pretty.big_list "simplification rules:" (map (pretty_thm_item o #2) simps),
   184       Pretty.big_list "simplification procedures:" (map pretty_simproc simprocs),
   185       Pretty.big_list "congruences:" (map pretty_cong congs),
   186       Pretty.strs ("loopers:" :: map quote loopers),
   187       Pretty.strs ("unsafe solvers:" :: map quote unsafe_solvers),
   188       Pretty.strs ("safe solvers:" :: map quote safe_solvers)]
   189     |> Pretty.chunks
   190   end;
   191 
   192 
   193 
   194 (** simplification tactics and rules **)
   195 
   196 fun solve_all_tac solvers ctxt =
   197   let
   198     val {subgoal_tac, ...} = Raw_Simplifier.internal_ss (simpset_of ctxt);
   199     val solve_tac = subgoal_tac (Raw_Simplifier.set_solvers solvers ctxt) THEN_ALL_NEW (K no_tac);
   200   in DEPTH_SOLVE (solve_tac 1) end;
   201 
   202 (*NOTE: may instantiate unknowns that appear also in other subgoals*)
   203 fun generic_simp_tac safe mode ctxt =
   204   let
   205     val {loop_tacs, solvers = (unsafe_solvers, solvers), ...} =
   206       Raw_Simplifier.internal_ss (simpset_of ctxt);
   207     val loop_tac = FIRST' (map (fn (_, tac) => tac ctxt) (rev loop_tacs));
   208     val solve_tac = FIRST' (map (Raw_Simplifier.solver ctxt)
   209       (rev (if safe then solvers else unsafe_solvers)));
   210 
   211     fun simp_loop_tac i =
   212       Raw_Simplifier.generic_rewrite_goal_tac mode (solve_all_tac unsafe_solvers) ctxt i THEN
   213       (solve_tac i ORELSE TRY ((loop_tac THEN_ALL_NEW simp_loop_tac) i));
   214   in PREFER_GOAL (simp_loop_tac 1) end;
   215 
   216 local
   217 
   218 fun simp rew mode ctxt thm =
   219   let
   220     val {solvers = (unsafe_solvers, _), ...} = Raw_Simplifier.internal_ss (simpset_of ctxt);
   221     val tacf = solve_all_tac (rev unsafe_solvers);
   222     fun prover s th = Option.map #1 (Seq.pull (tacf s th));
   223   in rew mode prover ctxt thm end;
   224 
   225 in
   226 
   227 val simp_thm = simp Raw_Simplifier.rewrite_thm;
   228 val simp_cterm = simp Raw_Simplifier.rewrite_cterm;
   229 
   230 end;
   231 
   232 
   233 (* tactics *)
   234 
   235 val simp_tac = generic_simp_tac false (false, false, false);
   236 val asm_simp_tac = generic_simp_tac false (false, true, false);
   237 val full_simp_tac = generic_simp_tac false (true, false, false);
   238 val asm_lr_simp_tac = generic_simp_tac false (true, true, false);
   239 val asm_full_simp_tac = generic_simp_tac false (true, true, true);
   240 
   241 (*not totally safe: may instantiate unknowns that appear also in other subgoals*)
   242 val safe_simp_tac = generic_simp_tac true (false, false, false);
   243 val safe_asm_simp_tac = generic_simp_tac true (false, true, false);
   244 val safe_full_simp_tac = generic_simp_tac true (true, false, false);
   245 val safe_asm_lr_simp_tac = generic_simp_tac true (true, true, false);
   246 val safe_asm_full_simp_tac = generic_simp_tac true (true, true, true);
   247 
   248 
   249 (* conversions *)
   250 
   251 val          simplify = simp_thm (false, false, false);
   252 val      asm_simplify = simp_thm (false, true, false);
   253 val     full_simplify = simp_thm (true, false, false);
   254 val   asm_lr_simplify = simp_thm (true, true, false);
   255 val asm_full_simplify = simp_thm (true, true, true);
   256 
   257 val          rewrite = simp_cterm (false, false, false);
   258 val      asm_rewrite = simp_cterm (false, true, false);
   259 val     full_rewrite = simp_cterm (true, false, false);
   260 val   asm_lr_rewrite = simp_cterm (true, true, false);
   261 val asm_full_rewrite = simp_cterm (true, true, true);
   262 
   263 
   264 
   265 (** concrete syntax of attributes **)
   266 
   267 (* add / del *)
   268 
   269 val simpN = "simp";
   270 val congN = "cong";
   271 val onlyN = "only";
   272 val no_asmN = "no_asm";
   273 val no_asm_useN = "no_asm_use";
   274 val no_asm_simpN = "no_asm_simp";
   275 val asm_lrN = "asm_lr";
   276 
   277 
   278 (* simprocs *)
   279 
   280 local
   281 
   282 val add_del =
   283   (Args.del -- Args.colon >> K (op delsimprocs) ||
   284     Scan.option (Args.add -- Args.colon) >> K (op addsimprocs))
   285   >> (fn f => fn simproc => fn phi => Thm.declaration_attribute
   286       (K (Raw_Simplifier.map_ss (fn ctxt => f (ctxt, [transform_simproc phi simproc])))));
   287 
   288 in
   289 
   290 val simproc_att =
   291   (Args.context -- Scan.lift add_del) :|-- (fn (ctxt, decl) =>
   292     Scan.repeat1 (Scan.lift (Args.named_attribute (decl o the_simproc ctxt o check_simproc ctxt))))
   293   >> (fn atts => Thm.declaration_attribute (fn th =>
   294         fold (fn att => Thm.attribute_declaration (Morphism.form att) th) atts));
   295 
   296 end;
   297 
   298 
   299 (* conversions *)
   300 
   301 local
   302 
   303 fun conv_mode x =
   304   ((Args.parens (Args.$$$ no_asmN) >> K simplify ||
   305     Args.parens (Args.$$$ no_asm_simpN) >> K asm_simplify ||
   306     Args.parens (Args.$$$ no_asm_useN) >> K full_simplify ||
   307     Scan.succeed asm_full_simplify) |> Scan.lift) x;
   308 
   309 in
   310 
   311 val simplified = conv_mode -- Attrib.thms >>
   312   (fn (f, ths) => Thm.rule_attribute ths (fn context =>
   313     f ((if null ths then I else Raw_Simplifier.clear_simpset)
   314         (Context.proof_of context) addsimps ths)));
   315 
   316 end;
   317 
   318 
   319 (* setup attributes *)
   320 
   321 val _ = Theory.setup
   322  (Attrib.setup @{binding simp} (Attrib.add_del simp_add simp_del)
   323     "declaration of Simplifier rewrite rule" #>
   324   Attrib.setup @{binding cong} (Attrib.add_del cong_add cong_del)
   325     "declaration of Simplifier congruence rule" #>
   326   Attrib.setup @{binding simproc} simproc_att
   327     "declaration of simplification procedures" #>
   328   Attrib.setup @{binding simplified} simplified "simplified rule");
   329 
   330 
   331 
   332 (** method syntax **)
   333 
   334 val cong_modifiers =
   335  [Args.$$$ congN -- Args.colon >> K (Method.modifier cong_add \<^here>),
   336   Args.$$$ congN -- Args.add -- Args.colon >> K (Method.modifier cong_add \<^here>),
   337   Args.$$$ congN -- Args.del -- Args.colon >> K (Method.modifier cong_del \<^here>)];
   338 
   339 val simp_modifiers =
   340  [Args.$$$ simpN -- Args.colon >> K (Method.modifier simp_add \<^here>),
   341   Args.$$$ simpN -- Args.add -- Args.colon >> K (Method.modifier simp_add \<^here>),
   342   Args.$$$ simpN -- Args.del -- Args.colon >> K (Method.modifier simp_del \<^here>),
   343   Args.$$$ simpN -- Args.$$$ onlyN -- Args.colon >>
   344     K {init = Raw_Simplifier.clear_simpset, attribute = simp_add, pos = \<^here>}]
   345    @ cong_modifiers;
   346 
   347 val simp_modifiers' =
   348  [Args.add -- Args.colon >> K (Method.modifier simp_add \<^here>),
   349   Args.del -- Args.colon >> K (Method.modifier simp_del \<^here>),
   350   Args.$$$ onlyN -- Args.colon >>
   351     K {init = Raw_Simplifier.clear_simpset, attribute = simp_add, pos = \<^here>}]
   352    @ cong_modifiers;
   353 
   354 val simp_options =
   355  (Args.parens (Args.$$$ no_asmN) >> K simp_tac ||
   356   Args.parens (Args.$$$ no_asm_simpN) >> K asm_simp_tac ||
   357   Args.parens (Args.$$$ no_asm_useN) >> K full_simp_tac ||
   358   Args.parens (Args.$$$ asm_lrN) >> K asm_lr_simp_tac ||
   359   Scan.succeed asm_full_simp_tac);
   360 
   361 fun simp_method more_mods meth =
   362   Scan.lift simp_options --|
   363     Method.sections (more_mods @ simp_modifiers') >>
   364     (fn tac => fn ctxt => METHOD (fn facts => meth ctxt tac facts));
   365 
   366 
   367 
   368 (** setup **)
   369 
   370 fun method_setup more_mods =
   371   Method.setup @{binding simp}
   372     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   373       HEADGOAL (Method.insert_tac ctxt facts THEN'
   374         (CHANGED_PROP oo tac) ctxt)))
   375     "simplification" #>
   376   Method.setup @{binding simp_all}
   377     (simp_method more_mods (fn ctxt => fn tac => fn facts =>
   378       ALLGOALS (Method.insert_tac ctxt facts) THEN
   379         (CHANGED_PROP o PARALLEL_ALLGOALS o tac) ctxt))
   380     "simplification (all goals)";
   381 
   382 fun unsafe_solver_tac ctxt =
   383   FIRST' [resolve_tac ctxt (Drule.reflexive_thm :: Raw_Simplifier.prems_of ctxt), assume_tac ctxt];
   384 val unsafe_solver = mk_solver "Pure unsafe" unsafe_solver_tac;
   385 
   386 (*no premature instantiation of variables during simplification*)
   387 fun safe_solver_tac ctxt =
   388   FIRST' [match_tac ctxt (Drule.reflexive_thm :: Raw_Simplifier.prems_of ctxt), eq_assume_tac];
   389 val safe_solver = mk_solver "Pure safe" safe_solver_tac;
   390 
   391 val _ =
   392   Theory.setup
   393     (method_setup [] #> Context.theory_map (map_ss (fn ctxt =>
   394       empty_simpset ctxt
   395       setSSolver safe_solver
   396       setSolver unsafe_solver
   397       |> set_subgoaler asm_simp_tac)));
   398 
   399 end;
   400 
   401 structure Basic_Simplifier: BASIC_SIMPLIFIER = Simplifier;
   402 open Basic_Simplifier;