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