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