src/Provers/classical.ML
changeset 60945 88aaecbaf61e
parent 60944 bb75b61dba5d
child 60946 46ec72073dc1
equal deleted inserted replaced
60944:bb75b61dba5d 60945:88aaecbaf61e
    95 
    95 
    96 signature CLASSICAL =
    96 signature CLASSICAL =
    97 sig
    97 sig
    98   include BASIC_CLASSICAL
    98   include BASIC_CLASSICAL
    99   val classical_rule: Proof.context -> thm -> thm
    99   val classical_rule: Proof.context -> thm -> thm
       
   100   type rule = thm * thm * thm
   100   type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net
   101   type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net
   101   val rep_cs: claset ->
   102   val rep_cs: claset ->
   102    {safeIs: thm Item_Net.T,
   103    {safeIs: rule Item_Net.T,
   103     safeEs: thm Item_Net.T,
   104     safeEs: rule Item_Net.T,
   104     unsafeIs: thm Item_Net.T,
   105     unsafeIs: rule Item_Net.T,
   105     unsafeEs: thm Item_Net.T,
   106     unsafeEs: rule Item_Net.T,
   106     swrappers: (string * (Proof.context -> wrapper)) list,
   107     swrappers: (string * (Proof.context -> wrapper)) list,
   107     uwrappers: (string * (Proof.context -> wrapper)) list,
   108     uwrappers: (string * (Proof.context -> wrapper)) list,
   108     safe0_netpair: netpair,
   109     safe0_netpair: netpair,
   109     safep_netpair: netpair,
   110     safep_netpair: netpair,
   110     unsafe_netpair: netpair,
   111     unsafe_netpair: netpair,
   207   in rule_by_tactic ctxt (TRYALL (eresolve_tac ctxt [revcut_rl])) rl end;
   208   in rule_by_tactic ctxt (TRYALL (eresolve_tac ctxt [revcut_rl])) rl end;
   208 
   209 
   209 
   210 
   210 (**** Classical rule sets ****)
   211 (**** Classical rule sets ****)
   211 
   212 
       
   213 type rule = thm * thm * thm;  (*external form vs. internal forms*)
   212 type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net;
   214 type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net;
   213 type wrapper = (int -> tactic) -> int -> tactic;
   215 type wrapper = (int -> tactic) -> int -> tactic;
   214 
   216 
   215 datatype claset =
   217 datatype claset =
   216   CS of
   218   CS of
   217    {safeIs         : thm Item_Net.T,          (*safe introduction rules*)
   219    {safeIs: rule Item_Net.T,  (*safe introduction rules*)
   218     safeEs         : thm Item_Net.T,          (*safe elimination rules*)
   220     safeEs: rule Item_Net.T,  (*safe elimination rules*)
   219     unsafeIs       : thm Item_Net.T,          (*unsafe introduction rules*)
   221     unsafeIs: rule Item_Net.T,  (*unsafe introduction rules*)
   220     unsafeEs       : thm Item_Net.T,          (*unsafe elimination rules*)
   222     unsafeEs: rule Item_Net.T,  (*unsafe elimination rules*)
   221     swrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming safe_step_tac*)
   223     swrappers: (string * (Proof.context -> wrapper)) list,  (*for transforming safe_step_tac*)
   222     uwrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming step_tac*)
   224     uwrappers: (string * (Proof.context -> wrapper)) list,  (*for transforming step_tac*)
   223     safe0_netpair  : netpair,                 (*nets for trivial cases*)
   225     safe0_netpair: netpair,  (*nets for trivial cases*)
   224     safep_netpair  : netpair,                 (*nets for >0 subgoals*)
   226     safep_netpair: netpair,  (*nets for >0 subgoals*)
   225     unsafe_netpair : netpair,                 (*nets for unsafe rules*)
   227     unsafe_netpair: netpair,  (*nets for unsafe rules*)
   226     dup_netpair    : netpair,                 (*nets for duplication*)
   228     dup_netpair: netpair,  (*nets for duplication*)
   227     extra_netpair  : Context_Rules.netpair};  (*nets for extra rules*)
   229     extra_netpair: Context_Rules.netpair};  (*nets for extra rules*)
       
   230 
       
   231 val empty_rules: rule Item_Net.T =
       
   232   Item_Net.init (Thm.eq_thm_prop o apply2 #1) (single o Thm.full_prop_of o #1);
   228 
   233 
   229 val empty_netpair = (Net.empty, Net.empty);
   234 val empty_netpair = (Net.empty, Net.empty);
   230 
   235 
   231 val empty_cs =
   236 val empty_cs =
   232   CS
   237   CS
   233    {safeIs = Thm.full_rules,
   238    {safeIs = empty_rules,
   234     safeEs = Thm.full_rules,
   239     safeEs = empty_rules,
   235     unsafeIs = Thm.full_rules,
   240     unsafeIs = empty_rules,
   236     unsafeEs = Thm.full_rules,
   241     unsafeEs = empty_rules,
   237     swrappers = [],
   242     swrappers = [],
   238     uwrappers = [],
   243     uwrappers = [],
   239     safe0_netpair = empty_netpair,
   244     safe0_netpair = empty_netpair,
   240     safep_netpair = empty_netpair,
   245     safep_netpair = empty_netpair,
   241     unsafe_netpair = empty_netpair,
   246     unsafe_netpair = empty_netpair,
   248 (*** Adding (un)safe introduction or elimination rules.
   253 (*** Adding (un)safe introduction or elimination rules.
   249 
   254 
   250     In case of overlap, new rules are tried BEFORE old ones!!
   255     In case of overlap, new rules are tried BEFORE old ones!!
   251 ***)
   256 ***)
   252 
   257 
   253 fun default_context (SOME context) _ = Context.proof_of context
       
   254   | default_context NONE th = Proof_Context.init_global (Thm.theory_of_thm th);
       
   255 
       
   256 (*For use with biresolve_tac.  Combines intro rules with swap to handle negated
   258 (*For use with biresolve_tac.  Combines intro rules with swap to handle negated
   257   assumptions.  Pairs elim rules with true. *)
   259   assumptions.  Pairs elim rules with true. *)
   258 fun joinrules (intrs, elims) =
   260 fun joinrules (intrs, elims) =
   259   (map (pair true) (elims @ swapify intrs)) @ map (pair false) intrs;
   261   (map (pair true) (elims @ swapify intrs)) @ map (pair false) intrs;
   260 
   262 
   281 
   283 
   282 fun delete_tagged_list rls = fold_rev Tactic.delete_tagged_brl rls;
   284 fun delete_tagged_list rls = fold_rev Tactic.delete_tagged_brl rls;
   283 fun delete x = delete_tagged_list (joinrules x);
   285 fun delete x = delete_tagged_list (joinrules x);
   284 fun delete' x = delete_tagged_list (joinrules' x);
   286 fun delete' x = delete_tagged_list (joinrules' x);
   285 
   287 
   286 fun bad_thm (SOME context) msg th =
   288 fun bad_thm ctxt msg th = error (msg ^ "\n" ^ Display.string_of_thm ctxt th);
   287       error (msg ^ "\n" ^ Display.string_of_thm (Context.proof_of context) th)
   289 
   288   | bad_thm NONE msg th = raise THM (msg, 0, [th]);
   290 fun make_elim ctxt th =
   289 
   291   if has_fewer_prems 1 th then bad_thm ctxt "Ill-formed destruction rule" th
   290 fun make_elim opt_context th =
       
   291   if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed destruction rule" th
       
   292   else Tactic.make_elim th;
   292   else Tactic.make_elim th;
   293 
   293 
   294 fun warn_thm (SOME (Context.Proof ctxt)) msg th =
   294 fun warn_thm ctxt msg th =
   295       if Context_Position.is_really_visible ctxt
   295   if Context_Position.is_really_visible ctxt
   296       then warning (msg ^ Display.string_of_thm ctxt th) else ()
   296   then warning (msg ^ Display.string_of_thm ctxt th) else ();
   297   | warn_thm _ _ _ = ();
   297 
   298 
   298 fun warn_rules ctxt msg rules (r: rule) =
   299 fun warn_rules opt_context msg rules th =
   299   Item_Net.member rules r andalso (warn_thm ctxt msg (#1 r); true);
   300   Item_Net.member rules th andalso (warn_thm opt_context msg th; true);
   300 
   301 
   301 fun warn_claset ctxt r (CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   302 fun warn_claset opt_context th (CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   302   warn_rules ctxt "Rule already declared as safe introduction (intro!)\n" safeIs r orelse
   303   warn_rules opt_context "Rule already declared as safe introduction (intro!)\n" safeIs th orelse
   303   warn_rules ctxt "Rule already declared as safe elimination (elim!)\n" safeEs r orelse
   304   warn_rules opt_context "Rule already declared as safe elimination (elim!)\n" safeEs th orelse
   304   warn_rules ctxt "Rule already declared as introduction (intro)\n" unsafeIs r orelse
   305   warn_rules opt_context "Rule already declared as introduction (intro)\n" unsafeIs th orelse
   305   warn_rules ctxt "Rule already declared as elimination (elim)\n" unsafeEs r;
   306   warn_rules opt_context "Rule already declared as elimination (elim)\n" unsafeEs th;
       
   307 
   306 
   308 
   307 
   309 (*** Safe rules ***)
   308 (*** Safe rules ***)
   310 
   309 
   311 fun addSI w opt_context th
   310 fun add_safe_intro w r
   312     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   311     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   313       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   312       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   314   if warn_rules opt_context "Ignoring duplicate safe introduction (intro!)\n" safeIs th then cs
   313   if Item_Net.member safeIs r then cs
   315   else
   314   else
   316     let
   315     let
   317       val ctxt = default_context opt_context th;
   316       val (th, th', _) = r;
   318       val th' = flat_rule ctxt th;
       
   319       val (safe0_rls, safep_rls) = (*0 subgoals vs 1 or more*)
   317       val (safe0_rls, safep_rls) = (*0 subgoals vs 1 or more*)
   320         List.partition Thm.no_prems [th'];
   318         List.partition Thm.no_prems [th'];
   321       val nI = Item_Net.length safeIs + 1;
   319       val nI = Item_Net.length safeIs + 1;
   322       val nE = Item_Net.length safeEs;
   320       val nE = Item_Net.length safeEs;
   323       val _ = warn_claset opt_context th cs;
       
   324     in
   321     in
   325       CS
   322       CS
   326        {safeIs = Item_Net.update th safeIs,
   323        {safeIs = Item_Net.update r safeIs,
   327         safe0_netpair = insert (nI, nE) (safe0_rls, []) safe0_netpair,
   324         safe0_netpair = insert (nI, nE) (safe0_rls, []) safe0_netpair,
   328         safep_netpair = insert (nI, nE) (safep_rls, []) safep_netpair,
   325         safep_netpair = insert (nI, nE) (safep_rls, []) safep_netpair,
   329         safeEs = safeEs,
   326         safeEs = safeEs,
   330         unsafeIs = unsafeIs,
   327         unsafeIs = unsafeIs,
   331         unsafeEs = unsafeEs,
   328         unsafeEs = unsafeEs,
   334         unsafe_netpair = unsafe_netpair,
   331         unsafe_netpair = unsafe_netpair,
   335         dup_netpair = dup_netpair,
   332         dup_netpair = dup_netpair,
   336         extra_netpair = insert' (the_default 0 w) (nI, nE) ([th], []) extra_netpair}
   333         extra_netpair = insert' (the_default 0 w) (nI, nE) ([th], []) extra_netpair}
   337     end;
   334     end;
   338 
   335 
   339 fun addSE w opt_context th
   336 fun add_safe_elim w r
   340     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   337     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   341       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   338       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   342   if warn_rules opt_context "Ignoring duplicate safe elimination (elim!)\n" safeEs th then cs
   339   if Item_Net.member safeEs r then cs
   343   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
       
   344   else
   340   else
   345     let
   341     let
   346       val ctxt = default_context opt_context th;
   342       val (th, th', _) = r;
   347       val th' = classical_rule ctxt (flat_rule ctxt th);
       
   348       val (safe0_rls, safep_rls) = (*0 subgoals vs 1 or more*)
   343       val (safe0_rls, safep_rls) = (*0 subgoals vs 1 or more*)
   349         List.partition (fn rl => Thm.nprems_of rl=1) [th'];
   344         List.partition (fn rl => Thm.nprems_of rl = 1) [th'];
   350       val nI = Item_Net.length safeIs;
   345       val nI = Item_Net.length safeIs;
   351       val nE = Item_Net.length safeEs + 1;
   346       val nE = Item_Net.length safeEs + 1;
   352       val _ = warn_claset opt_context th cs;
       
   353     in
   347     in
   354       CS
   348       CS
   355        {safeEs = Item_Net.update th safeEs,
   349        {safeEs = Item_Net.update r safeEs,
   356         safe0_netpair = insert (nI, nE) ([], safe0_rls) safe0_netpair,
   350         safe0_netpair = insert (nI, nE) ([], safe0_rls) safe0_netpair,
   357         safep_netpair = insert (nI, nE) ([], safep_rls) safep_netpair,
   351         safep_netpair = insert (nI, nE) ([], safep_rls) safep_netpair,
   358         safeIs = safeIs,
   352         safeIs = safeIs,
   359         unsafeIs = unsafeIs,
   353         unsafeIs = unsafeIs,
   360         unsafeEs = unsafeEs,
   354         unsafeEs = unsafeEs,
   363         unsafe_netpair = unsafe_netpair,
   357         unsafe_netpair = unsafe_netpair,
   364         dup_netpair = dup_netpair,
   358         dup_netpair = dup_netpair,
   365         extra_netpair = insert' (the_default 0 w) (nI, nE) ([], [th]) extra_netpair}
   359         extra_netpair = insert' (the_default 0 w) (nI, nE) ([], [th]) extra_netpair}
   366     end;
   360     end;
   367 
   361 
   368 fun addSD w opt_context th = addSE w opt_context (make_elim opt_context th);
   362 fun addSI w ctxt th (cs as CS {safeIs, ...}) =
   369 
   363   let
   370 
   364     val th' = flat_rule ctxt th;
   371 (*** Hazardous (unsafe) rules ***)
   365     val r = (th, th', th');
   372 
   366     val _ =
   373 fun addI w opt_context th
   367       warn_rules ctxt "Ignoring duplicate safe introduction (intro!)\n" safeIs r orelse
       
   368       warn_claset ctxt r cs;
       
   369   in add_safe_intro w r cs end;
       
   370 
       
   371 fun addSE w ctxt th (cs as CS {safeEs, ...}) =
       
   372   let
       
   373     val _ = has_fewer_prems 1 th andalso bad_thm ctxt "Ill-formed elimination rule" th;
       
   374     val th' = classical_rule ctxt (flat_rule ctxt th);
       
   375     val r = (th, th', th');
       
   376     val _ =
       
   377       warn_rules ctxt "Ignoring duplicate safe elimination (elim!)\n" safeEs r orelse
       
   378       warn_claset ctxt r cs;
       
   379   in add_safe_elim w r cs end;
       
   380 
       
   381 fun addSD w ctxt th = addSE w ctxt (make_elim ctxt th);
       
   382 
       
   383 
       
   384 (*** Unsafe rules ***)
       
   385 
       
   386 fun add_unsafe_intro w r
   374     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   387     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   375       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   388       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   376   if warn_rules opt_context "Ignoring duplicate introduction (intro)\n" unsafeIs th then cs
   389   if Item_Net.member unsafeIs r then cs
   377   else
   390   else
   378     let
   391     let
   379       val ctxt = default_context opt_context th;
   392       val (th, th', th'') = r;
   380       val th' = flat_rule ctxt th;
       
   381       val nI = Item_Net.length unsafeIs + 1;
   393       val nI = Item_Net.length unsafeIs + 1;
   382       val nE = Item_Net.length unsafeEs;
   394       val nE = Item_Net.length unsafeEs;
   383       val _ = warn_claset opt_context th cs;
       
   384     in
   395     in
   385       CS
   396       CS
   386        {unsafeIs = Item_Net.update th unsafeIs,
   397        {unsafeIs = Item_Net.update r unsafeIs,
   387         unsafe_netpair = insert (nI, nE) ([th'], []) unsafe_netpair,
   398         unsafe_netpair = insert (nI, nE) ([th'], []) unsafe_netpair,
   388         dup_netpair = insert (nI, nE) ([dup_intr th'], []) dup_netpair,
   399         dup_netpair = insert (nI, nE) ([th''], []) dup_netpair,
   389         safeIs = safeIs,
   400         safeIs = safeIs,
   390         safeEs = safeEs,
   401         safeEs = safeEs,
   391         unsafeEs = unsafeEs,
   402         unsafeEs = unsafeEs,
   392         swrappers = swrappers,
   403         swrappers = swrappers,
   393         uwrappers = uwrappers,
   404         uwrappers = uwrappers,
   394         safe0_netpair = safe0_netpair,
   405         safe0_netpair = safe0_netpair,
   395         safep_netpair = safep_netpair,
   406         safep_netpair = safep_netpair,
   396         extra_netpair = insert' (the_default 1 w) (nI, nE) ([th], []) extra_netpair}
   407         extra_netpair = insert' (the_default 1 w) (nI, nE) ([th], []) extra_netpair}
   397     end
   408     end;
   398     handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   409 
   399       bad_thm opt_context "Ill-formed introduction rule" th;
   410 fun add_unsafe_elim w r
   400 
       
   401 fun addE w opt_context th
       
   402     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   411     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   403       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   412       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   404   if warn_rules opt_context "Ignoring duplicate elimination (elim)\n" unsafeEs th then cs
   413   if Item_Net.member unsafeEs r then cs
   405   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
       
   406   else
   414   else
   407     let
   415     let
   408       val ctxt = default_context opt_context th;
   416       val (th, th', th'') = r;
   409       val th' = classical_rule ctxt (flat_rule ctxt th);
       
   410       val nI = Item_Net.length unsafeIs;
   417       val nI = Item_Net.length unsafeIs;
   411       val nE = Item_Net.length unsafeEs + 1;
   418       val nE = Item_Net.length unsafeEs + 1;
   412       val _ = warn_claset opt_context th cs;
       
   413     in
   419     in
   414       CS
   420       CS
   415        {unsafeEs = Item_Net.update th unsafeEs,
   421        {unsafeEs = Item_Net.update r unsafeEs,
   416         unsafe_netpair = insert (nI, nE) ([], [th']) unsafe_netpair,
   422         unsafe_netpair = insert (nI, nE) ([], [th']) unsafe_netpair,
   417         dup_netpair = insert (nI, nE) ([], [dup_elim ctxt th']) dup_netpair,
   423         dup_netpair = insert (nI, nE) ([], [th'']) dup_netpair,
   418         safeIs = safeIs,
   424         safeIs = safeIs,
   419         safeEs = safeEs,
   425         safeEs = safeEs,
   420         unsafeIs = unsafeIs,
   426         unsafeIs = unsafeIs,
   421         swrappers = swrappers,
   427         swrappers = swrappers,
   422         uwrappers = uwrappers,
   428         uwrappers = uwrappers,
   423         safe0_netpair = safe0_netpair,
   429         safe0_netpair = safe0_netpair,
   424         safep_netpair = safep_netpair,
   430         safep_netpair = safep_netpair,
   425         extra_netpair = insert' (the_default 1 w) (nI, nE) ([], [th]) extra_netpair}
   431         extra_netpair = insert' (the_default 1 w) (nI, nE) ([], [th]) extra_netpair}
   426     end;
   432     end;
   427 
   433 
   428 fun addD w opt_context th = addE w opt_context (make_elim opt_context th);
   434 fun addI w ctxt th (cs as CS {unsafeIs, ...}) =
   429 
   435   let
       
   436     val th' = flat_rule ctxt th;
       
   437     val th'' = dup_intr th' handle THM _ => bad_thm ctxt "Ill-formed introduction rule" th;
       
   438     val r = (th, th', th'');
       
   439     val _ =
       
   440       warn_rules ctxt "Ignoring duplicate introduction (intro)\n" unsafeIs r orelse
       
   441       warn_claset ctxt r cs;
       
   442   in add_unsafe_intro w r cs end;
       
   443 
       
   444 fun addE w ctxt th (cs as CS {unsafeEs, ...}) =
       
   445   let
       
   446     val _ = has_fewer_prems 1 th andalso bad_thm ctxt "Ill-formed elimination rule" th;
       
   447     val th' = classical_rule ctxt (flat_rule ctxt th);
       
   448     val th'' = dup_elim ctxt th' handle THM _ => bad_thm ctxt "Ill-formed elimination rule" th;
       
   449     val r = (th, th', th'');
       
   450     val _ =
       
   451       warn_rules ctxt "Ignoring duplicate elimination (elim)\n" unsafeEs r orelse
       
   452       warn_claset ctxt r cs;
       
   453   in add_unsafe_elim w r cs end;
       
   454 
       
   455 fun addD w ctxt th = addE w ctxt (make_elim ctxt th);
   430 
   456 
   431 
   457 
   432 (*** Deletion of rules
   458 (*** Deletion of rules
   433      Working out what to delete, requires repeating much of the code used
   459      Working out what to delete, requires repeating much of the code used
   434         to insert.
   460         to insert.
   435 ***)
   461 ***)
   436 
   462 
   437 fun delSI opt_context th
   463 fun delSI ctxt th
   438     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   464     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   439       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   465       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   440   if Item_Net.member safeIs th then
   466   if Item_Net.member safeIs (th, th, th) then
   441     let
   467     let
   442       val ctxt = default_context opt_context th;
       
   443       val th' = flat_rule ctxt th;
   468       val th' = flat_rule ctxt th;
       
   469       val r = (th, th', th');
   444       val (safe0_rls, safep_rls) = List.partition Thm.no_prems [th'];
   470       val (safe0_rls, safep_rls) = List.partition Thm.no_prems [th'];
   445     in
   471     in
   446       CS
   472       CS
   447        {safe0_netpair = delete (safe0_rls, []) safe0_netpair,
   473        {safe0_netpair = delete (safe0_rls, []) safe0_netpair,
   448         safep_netpair = delete (safep_rls, []) safep_netpair,
   474         safep_netpair = delete (safep_rls, []) safep_netpair,
   449         safeIs = Item_Net.remove th safeIs,
   475         safeIs = Item_Net.remove r safeIs,
   450         safeEs = safeEs,
   476         safeEs = safeEs,
   451         unsafeIs = unsafeIs,
   477         unsafeIs = unsafeIs,
   452         unsafeEs = unsafeEs,
   478         unsafeEs = unsafeEs,
   453         swrappers = swrappers,
   479         swrappers = swrappers,
   454         uwrappers = uwrappers,
   480         uwrappers = uwrappers,
   456         dup_netpair = dup_netpair,
   482         dup_netpair = dup_netpair,
   457         extra_netpair = delete' ([th], []) extra_netpair}
   483         extra_netpair = delete' ([th], []) extra_netpair}
   458     end
   484     end
   459   else cs;
   485   else cs;
   460 
   486 
   461 fun delSE opt_context th
   487 fun delSE ctxt th
   462     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   488     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   463       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   489       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   464   if Item_Net.member safeEs th then
   490   if Item_Net.member safeEs (th, th, th) then
   465     let
   491     let
   466       val ctxt = default_context opt_context th;
       
   467       val th' = classical_rule ctxt (flat_rule ctxt th);
   492       val th' = classical_rule ctxt (flat_rule ctxt th);
       
   493       val r = (th, th', th');
   468       val (safe0_rls, safep_rls) = List.partition (fn rl => Thm.nprems_of rl = 1) [th'];
   494       val (safe0_rls, safep_rls) = List.partition (fn rl => Thm.nprems_of rl = 1) [th'];
   469     in
   495     in
   470       CS
   496       CS
   471        {safe0_netpair = delete ([], safe0_rls) safe0_netpair,
   497        {safe0_netpair = delete ([], safe0_rls) safe0_netpair,
   472         safep_netpair = delete ([], safep_rls) safep_netpair,
   498         safep_netpair = delete ([], safep_rls) safep_netpair,
   473         safeIs = safeIs,
   499         safeIs = safeIs,
   474         safeEs = Item_Net.remove th safeEs,
   500         safeEs = Item_Net.remove r safeEs,
   475         unsafeIs = unsafeIs,
   501         unsafeIs = unsafeIs,
   476         unsafeEs = unsafeEs,
   502         unsafeEs = unsafeEs,
   477         swrappers = swrappers,
   503         swrappers = swrappers,
   478         uwrappers = uwrappers,
   504         uwrappers = uwrappers,
   479         unsafe_netpair = unsafe_netpair,
   505         unsafe_netpair = unsafe_netpair,
   480         dup_netpair = dup_netpair,
   506         dup_netpair = dup_netpair,
   481         extra_netpair = delete' ([], [th]) extra_netpair}
   507         extra_netpair = delete' ([], [th]) extra_netpair}
   482     end
   508     end
   483   else cs;
   509   else cs;
   484 
   510 
   485 fun delI opt_context th
   511 fun delI ctxt th
   486     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   512     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   487       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   513       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   488   if Item_Net.member unsafeIs th then
   514   if Item_Net.member unsafeIs (th, th, th) then
   489     let
   515     let
   490       val ctxt = default_context opt_context th;
       
   491       val th' = flat_rule ctxt th;
   516       val th' = flat_rule ctxt th;
       
   517       val th'' = dup_intr th';
       
   518       val r = (th, th', th'');
   492     in
   519     in
   493       CS
   520       CS
   494        {unsafe_netpair = delete ([th'], []) unsafe_netpair,
   521        {unsafe_netpair = delete ([th'], []) unsafe_netpair,
   495         dup_netpair = delete ([dup_intr th'], []) dup_netpair,
   522         dup_netpair = delete ([th''], []) dup_netpair,
   496         safeIs = safeIs,
   523         safeIs = safeIs,
   497         safeEs = safeEs,
   524         safeEs = safeEs,
   498         unsafeIs = Item_Net.remove th unsafeIs,
   525         unsafeIs = Item_Net.remove r unsafeIs,
   499         unsafeEs = unsafeEs,
   526         unsafeEs = unsafeEs,
   500         swrappers = swrappers,
   527         swrappers = swrappers,
   501         uwrappers = uwrappers,
   528         uwrappers = uwrappers,
   502         safe0_netpair = safe0_netpair,
   529         safe0_netpair = safe0_netpair,
   503         safep_netpair = safep_netpair,
   530         safep_netpair = safep_netpair,
   504         extra_netpair = delete' ([th], []) extra_netpair}
   531         extra_netpair = delete' ([th], []) extra_netpair}
   505     end
   532     end
   506   else cs
   533   else cs;
   507   handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   534 
   508     bad_thm opt_context "Ill-formed introduction rule" th;
   535 fun delE ctxt th
   509 
       
   510 fun delE opt_context th
       
   511     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   536     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   512       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   537       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   513   if Item_Net.member unsafeEs th then
   538   if Item_Net.member unsafeEs (th, th, th) then
   514     let
   539     let
   515       val ctxt = default_context opt_context th;
       
   516       val th' = classical_rule ctxt (flat_rule ctxt th);
   540       val th' = classical_rule ctxt (flat_rule ctxt th);
       
   541       val th'' = dup_elim ctxt th';
       
   542       val r = (th, th', th'');
   517     in
   543     in
   518       CS
   544       CS
   519        {unsafe_netpair = delete ([], [th']) unsafe_netpair,
   545        {unsafe_netpair = delete ([], [th']) unsafe_netpair,
   520         dup_netpair = delete ([], [dup_elim ctxt th']) dup_netpair,
   546         dup_netpair = delete ([], [th'']) dup_netpair,
   521         safeIs = safeIs,
   547         safeIs = safeIs,
   522         safeEs = safeEs,
   548         safeEs = safeEs,
   523         unsafeIs = unsafeIs,
   549         unsafeIs = unsafeIs,
   524         unsafeEs = Item_Net.remove th unsafeEs,
   550         unsafeEs = Item_Net.remove r unsafeEs,
   525         swrappers = swrappers,
   551         swrappers = swrappers,
   526         uwrappers = uwrappers,
   552         uwrappers = uwrappers,
   527         safe0_netpair = safe0_netpair,
   553         safe0_netpair = safe0_netpair,
   528         safep_netpair = safep_netpair,
   554         safep_netpair = safep_netpair,
   529         extra_netpair = delete' ([], [th]) extra_netpair}
   555         extra_netpair = delete' ([], [th]) extra_netpair}
   530     end
   556     end
   531   else cs;
   557   else cs;
   532 
   558 
   533 (*Delete ALL occurrences of "th" in the claset (perhaps from several lists)*)
   559 (*Delete ALL occurrences of "th" in the claset (perhaps from several lists)*)
   534 fun delrule opt_context th (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   560 fun delrule ctxt th (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   535   let val th' = Tactic.make_elim th in
   561   let
   536     if Item_Net.member safeIs th orelse Item_Net.member safeEs th orelse
   562     val th' = Tactic.make_elim th;
   537       Item_Net.member unsafeIs th orelse Item_Net.member unsafeEs th orelse
   563     val r = (th, th, th);
   538       Item_Net.member safeEs th' orelse Item_Net.member unsafeEs th'
   564     val r' = (th', th', th');
       
   565   in
       
   566     if Item_Net.member safeIs r orelse Item_Net.member safeEs r orelse
       
   567       Item_Net.member unsafeIs r orelse Item_Net.member unsafeEs r orelse
       
   568       Item_Net.member safeEs r' orelse Item_Net.member unsafeEs r'
   539     then
   569     then
   540       cs
   570       cs
   541       |> delE opt_context th'
   571       |> delE ctxt th'
   542       |> delSE opt_context th'
   572       |> delSE ctxt th'
   543       |> delE opt_context th
   573       |> delE ctxt th
   544       |> delI opt_context th
   574       |> delI ctxt th
   545       |> delSE opt_context th
   575       |> delSE ctxt th
   546       |> delSI opt_context th
   576       |> delSI ctxt th
   547     else (warn_thm opt_context "Undeclared classical rule\n" th; cs)
   577     else (warn_thm ctxt "Undeclared classical rule\n" th; cs)
   548   end;
   578   end;
   549 
   579 
   550 
   580 
   551 
   581 
   552 (** claset data **)
   582 (** claset data **)
   582     cs' as CS {safeIs = safeIs2, safeEs = safeEs2, unsafeIs = unsafeIs2, unsafeEs = unsafeEs2,
   612     cs' as CS {safeIs = safeIs2, safeEs = safeEs2, unsafeIs = unsafeIs2, unsafeEs = unsafeEs2,
   583       swrappers, uwrappers, ...}) =
   613       swrappers, uwrappers, ...}) =
   584   if pointer_eq (cs, cs') then cs
   614   if pointer_eq (cs, cs') then cs
   585   else
   615   else
   586     cs
   616     cs
   587     |> merge_thms (addSI NONE NONE) safeIs safeIs2
   617     |> merge_thms (add_safe_intro NONE) safeIs safeIs2
   588     |> merge_thms (addSE NONE NONE) safeEs safeEs2
   618     |> merge_thms (add_safe_elim NONE) safeEs safeEs2
   589     |> merge_thms (addI NONE NONE) unsafeIs unsafeIs2
   619     |> merge_thms (add_unsafe_intro NONE) unsafeIs unsafeIs2
   590     |> merge_thms (addE NONE NONE) unsafeEs unsafeEs2
   620     |> merge_thms (add_unsafe_elim NONE) unsafeEs unsafeEs2
   591     |> map_swrappers (fn ws => AList.merge (op =) (K true) (ws, swrappers))
   621     |> map_swrappers (fn ws => AList.merge (op =) (K true) (ws, swrappers))
   592     |> map_uwrappers (fn ws => AList.merge (op =) (K true) (ws, uwrappers));
   622     |> map_uwrappers (fn ws => AList.merge (op =) (K true) (ws, uwrappers));
   593 
   623 
   594 
   624 
   595 (* data *)
   625 (* data *)
   618 fun put_claset cs = map_claset (K cs);
   648 fun put_claset cs = map_claset (K cs);
   619 
   649 
   620 fun print_claset ctxt =
   650 fun print_claset ctxt =
   621   let
   651   let
   622     val {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers, ...} = rep_claset_of ctxt;
   652     val {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers, ...} = rep_claset_of ctxt;
   623     val pretty_thms = map (Display.pretty_thm_item ctxt) o Item_Net.content;
   653     val pretty_thms = map (Display.pretty_thm_item ctxt o #1) o Item_Net.content;
   624   in
   654   in
   625     [Pretty.big_list "safe introduction rules (intro!):" (pretty_thms safeIs),
   655     [Pretty.big_list "safe introduction rules (intro!):" (pretty_thms safeIs),
   626       Pretty.big_list "introduction rules (intro):" (pretty_thms unsafeIs),
   656       Pretty.big_list "introduction rules (intro):" (pretty_thms unsafeIs),
   627       Pretty.big_list "safe elimination rules (elim!):" (pretty_thms safeEs),
   657       Pretty.big_list "safe elimination rules (elim!):" (pretty_thms safeEs),
   628       Pretty.big_list "elimination rules (elim):" (pretty_thms unsafeEs),
   658       Pretty.big_list "elimination rules (elim):" (pretty_thms unsafeEs),
   632   end;
   662   end;
   633 
   663 
   634 
   664 
   635 (* old-style declarations *)
   665 (* old-style declarations *)
   636 
   666 
   637 fun decl f (ctxt, ths) = map_claset (fold_rev (f (SOME (Context.Proof ctxt))) ths) ctxt;
   667 fun decl f (ctxt, ths) = map_claset (fold_rev (f ctxt) ths) ctxt;
   638 
   668 
   639 val op addSIs = decl (addSI NONE);
   669 val op addSIs = decl (addSI NONE);
   640 val op addSEs = decl (addSE NONE);
   670 val op addSEs = decl (addSE NONE);
   641 val op addSDs = decl (addSD NONE);
   671 val op addSDs = decl (addSD NONE);
   642 val op addIs = decl (addI NONE);
   672 val op addIs = decl (addI NONE);
   858 
   888 
   859 
   889 
   860 (* attributes *)
   890 (* attributes *)
   861 
   891 
   862 fun attrib f =
   892 fun attrib f =
   863   Thm.declaration_attribute (fn th => fn opt_context =>
   893   Thm.declaration_attribute (fn th => fn context =>
   864     map_cs (f (SOME opt_context) th) opt_context);
   894     map_cs (f (Context.proof_of context) th) context);
   865 
   895 
   866 val safe_elim = attrib o addSE;
   896 val safe_elim = attrib o addSE;
   867 val safe_intro = attrib o addSI;
   897 val safe_intro = attrib o addSI;
   868 val safe_dest = attrib o addSD;
   898 val safe_dest = attrib o addSD;
   869 val unsafe_elim = attrib o addE;
   899 val unsafe_elim = attrib o addE;
   870 val unsafe_intro = attrib o addI;
   900 val unsafe_intro = attrib o addI;
   871 val unsafe_dest = attrib o addD;
   901 val unsafe_dest = attrib o addD;
   872 
   902 
   873 val rule_del =
   903 val rule_del =
   874   Thm.declaration_attribute (fn th => fn opt_context =>
   904   Thm.declaration_attribute (fn th => fn context =>
   875     opt_context |> map_cs (delrule (SOME opt_context) th) |>
   905     context
   876     Thm.attribute_declaration Context_Rules.rule_del th);
   906     |> map_cs (delrule (Context.proof_of context) th)
       
   907     |> Thm.attribute_declaration Context_Rules.rule_del th);
   877 
   908 
   878 
   909 
   879 
   910 
   880 (** concrete syntax of attributes **)
   911 (** concrete syntax of attributes **)
   881 
   912