src/HOL/Tools/Sledgehammer/sledgehammer_util.ML
changeset 57306 ff10067b2248
parent 57108 dc0b4f50e288
child 57727 02a53c1bbb6c
child 57838 c21f2c52f54b
--- a/src/HOL/Tools/Sledgehammer/sledgehammer_util.ML	Tue Jun 24 14:56:08 2014 +0200
+++ b/src/HOL/Tools/Sledgehammer/sledgehammer_util.ML	Tue Jun 24 15:08:19 2014 +0200
@@ -19,7 +19,8 @@
   val parse_time : string -> string -> Time.time
   val subgoal_count : Proof.state -> int
   val reserved_isar_keyword_table : unit -> unit Symtab.table
-  val thms_in_proof : (string Symtab.table * string Symtab.table) option -> thm -> string list
+  val thms_in_proof : int -> (string Symtab.table * string Symtab.table) option -> thm ->
+    string list option
   val thms_of_name : Proof.context -> string -> thm list
   val one_day : Time.time
   val one_year : Time.time
@@ -84,11 +85,13 @@
 fun reserved_isar_keyword_table () =
   Keyword.dest () |-> union (op =) |> map (rpair ()) |> Symtab.make
 
+exception TOO_MANY of unit
+
 (* FIXME: Similar yet different code in "mirabelle.ML". The code here has a few fixes that seem to
    be missing over there; or maybe the two code portions are not doing the same? *)
-fun fold_body_thm outer_name (map_plain_name, map_inclass_name) =
+fun fold_body_thm max_thms outer_name (map_plain_name, map_inclass_name) body =
   let
-    fun app_thm map_name (_, (name, _, body)) accum =
+    fun app_thm map_name (_, (name, _, body)) (accum as (num_thms, names)) =
       let
         val (anonymous, enter_class) =
           (* The "name = outer_name" case caters for the uncommon case where the proved theorem
@@ -98,18 +101,25 @@
           else (false, false)
       in
         if anonymous then
-          accum |> app_body (if enter_class then map_inclass_name else map_name) (Future.join body)
+          app_body (if enter_class then map_inclass_name else map_name) (Future.join body) accum
         else
-          accum |> union (op =) (the_list (map_name name))
+          (case map_name name of
+            SOME name' =>
+            if member (op =) names name' then accum
+            else if num_thms = max_thms then raise TOO_MANY ()
+            else (num_thms + 1, name' :: names)
+          | NONE => accum)
       end
     and app_body map_name (PBody {thms, ...}) = fold (app_thm map_name) thms
   in
-    app_body map_plain_name
+    snd (app_body map_plain_name body (0, []))
   end
 
-fun thms_in_proof name_tabs th =
+fun thms_in_proof max_thms name_tabs th =
   let val map_names = (case name_tabs of SOME p => pairself Symtab.lookup p | NONE => `I SOME) in
-    fold_body_thm (Thm.get_name_hint th) map_names (Proofterm.strip_thm (Thm.proof_body_of th)) []
+    SOME (fold_body_thm max_thms (Thm.get_name_hint th) map_names
+      (Proofterm.strip_thm (Thm.proof_body_of th)))
+    handle TOO_MANY () => NONE
   end
 
 fun thms_of_name ctxt name =