1 (* Title: HOL/Tools/Sledgehammer/sledgehammer_util.ML
2 Author: Jasmin Blanchette, TU Muenchen
4 General-purpose functions used by the Sledgehammer modules.
7 signature SLEDGEHAMMER_UTIL =
9 val plural_s : int -> string
10 val serial_commas : string -> string list -> string list
11 val simplify_spaces : string -> string
12 val parse_bool_option : bool -> string -> string -> bool option
13 val parse_time_option : string -> string -> Time.time option
14 val subgoal_count : Proof.state -> int
15 val reserved_isar_keyword_table : unit -> unit Symtab.table
16 val thms_in_proof : string list option -> thm -> string list
19 structure Sledgehammer_Util : SLEDGEHAMMER_UTIL =
24 fun plural_s n = if n = 1 then "" else "s"
26 val serial_commas = Try.serial_commas
27 val simplify_spaces = strip_spaces false (K true)
29 fun parse_bool_option option name s =
31 "smart" => if option then NONE else raise Option
32 | "false" => SOME false
36 handle Option.Option =>
37 let val ss = map quote ((option ? cons "smart") ["true", "false"]) in
38 error ("Parameter " ^ quote name ^ " must be assigned " ^
39 space_implode " " (serial_commas "or" ss) ^ ".")
43 exists (fn s => not (Symbol.is_digit s) andalso s <> ".") o raw_explode (* FIXME Symbol.explode (?) *)
45 fun parse_time_option _ "none" = NONE
46 | parse_time_option name s =
47 let val secs = if has_junk s then NONE else Real.fromString s in
48 if is_none secs orelse Real.< (the secs, 0.0) then
49 error ("Parameter " ^ quote name ^ " must be assigned a nonnegative \
50 \number of seconds (e.g., \"60\", \"0.5\") or \"none\".")
52 SOME (seconds (the secs))
55 val subgoal_count = Try.subgoal_count
57 fun reserved_isar_keyword_table () =
58 Keyword.dest () |-> union (op =) |> map (rpair ()) |> Symtab.make
60 (* FIXME: Similar yet different code in "mirabelle.ML". The code here has a few
61 fixes that seem to be missing over there; or maybe the two code portions are
62 not doing the same? *)
63 fun fold_body_thms thm_name f =
65 fun app n (PBody {thms, ...}) =
66 thms |> fold (fn (_, (name, prop, body)) => fn x =>
68 val body' = Future.join body
70 n + (if name = "" orelse
71 (* uncommon case where the proved theorem occurs twice
72 (e.g., "Transitive_Closure.trancl_into_trancl") *)
73 (n = 1 andalso name = thm_name) then
77 val x' = x |> n' <= 1 ? app n' body'
78 in (x' |> n = 1 ? f (name, prop, body')) end)
81 fun thms_in_proof all_names th =
85 SOME names => member (op =) names
86 | NONE => (fn s => s <> "" andalso not (String.isPrefix "Pure." s))
87 fun collect (s, _, _) = is_name_ok s ? insert (op =) s
89 [] |> fold_body_thms (Thm.get_name_hint th) collect [Thm.proof_body_of th]