src/HOL/Tools/Sledgehammer/sledgehammer_util.ML
author blanchet
Mon, 23 Jul 2012 15:32:30 +0200
changeset 49449 aaaec69db3db
parent 49407 ca998fa08cd9
child 49671 5caa414ce9a2
permissions -rw-r--r--
ensure all calls to "mash" program are synchronous
blanchet@36062
     1
(*  Title:      HOL/Tools/Sledgehammer/sledgehammer_util.ML
blanchet@35961
     2
    Author:     Jasmin Blanchette, TU Muenchen
blanchet@35961
     3
blanchet@35961
     4
General-purpose functions used by the Sledgehammer modules.
blanchet@35961
     5
*)
blanchet@35961
     6
blanchet@35961
     7
signature SLEDGEHAMMER_UTIL =
blanchet@35961
     8
sig
blanchet@49407
     9
  val sledgehammerN : string
blanchet@36140
    10
  val plural_s : int -> string
blanchet@35961
    11
  val serial_commas : string -> string list -> string list
blanchet@38977
    12
  val simplify_spaces : string -> string
blanchet@49398
    13
  val infinite_timeout : Time.time
blanchet@49333
    14
  val time_mult : real -> Time.time -> Time.time
blanchet@35961
    15
  val parse_bool_option : bool -> string -> string -> bool option
blanchet@35961
    16
  val parse_time_option : string -> string -> Time.time option
blanchet@38290
    17
  val subgoal_count : Proof.state -> int
blanchet@38935
    18
  val reserved_isar_keyword_table : unit -> unit Symtab.table
blanchet@49331
    19
  val thms_in_proof : unit Symtab.table option -> thm -> string list
blanchet@35961
    20
end;
blanchet@39564
    21
blanchet@35961
    22
structure Sledgehammer_Util : SLEDGEHAMMER_UTIL =
blanchet@35961
    23
struct
blanchet@35961
    24
blanchet@43926
    25
open ATP_Util
blanchet@43926
    26
blanchet@49407
    27
val sledgehammerN = "sledgehammer"
blanchet@49407
    28
blanchet@36140
    29
fun plural_s n = if n = 1 then "" else "s"
blanchet@36062
    30
blanchet@43870
    31
val serial_commas = Try.serial_commas
blanchet@43926
    32
val simplify_spaces = strip_spaces false (K true)
blanchet@38199
    33
blanchet@49398
    34
val infinite_timeout = seconds 31536000.0 (* one year *)
blanchet@49398
    35
blanchet@49333
    36
fun time_mult k t =
blanchet@49333
    37
  Time.fromMilliseconds (Real.ceil (k * Real.fromInt (Time.toMilliseconds t)))
blanchet@49333
    38
blanchet@35961
    39
fun parse_bool_option option name s =
blanchet@35961
    40
  (case s of
blanchet@35961
    41
     "smart" => if option then NONE else raise Option
blanchet@35961
    42
   | "false" => SOME false
blanchet@35961
    43
   | "true" => SOME true
blanchet@35961
    44
   | "" => SOME true
blanchet@35961
    45
   | _ => raise Option)
blanchet@35961
    46
  handle Option.Option =>
blanchet@35961
    47
         let val ss = map quote ((option ? cons "smart") ["true", "false"]) in
blanchet@35961
    48
           error ("Parameter " ^ quote name ^ " must be assigned " ^
blanchet@35961
    49
                  space_implode " " (serial_commas "or" ss) ^ ".")
blanchet@35961
    50
         end
blanchet@35961
    51
blanchet@40582
    52
val has_junk =
wenzelm@40875
    53
  exists (fn s => not (Symbol.is_digit s) andalso s <> ".") o raw_explode (* FIXME Symbol.explode (?) *)
blanchet@40582
    54
blanchet@35961
    55
fun parse_time_option _ "none" = NONE
blanchet@35961
    56
  | parse_time_option name s =
blanchet@40582
    57
    let val secs = if has_junk s then NONE else Real.fromString s in
blanchet@43875
    58
      if is_none secs orelse Real.< (the secs, 0.0) then
blanchet@43875
    59
        error ("Parameter " ^ quote name ^ " must be assigned a nonnegative \
blanchet@40582
    60
               \number of seconds (e.g., \"60\", \"0.5\") or \"none\".")
blanchet@35961
    61
      else
blanchet@40582
    62
        SOME (seconds (the secs))
blanchet@35961
    63
    end
blanchet@35961
    64
blanchet@43870
    65
val subgoal_count = Try.subgoal_count
blanchet@38290
    66
blanchet@38935
    67
fun reserved_isar_keyword_table () =
blanchet@49307
    68
  Keyword.dest () |-> union (op =) |> map (rpair ()) |> Symtab.make
blanchet@38935
    69
blanchet@49266
    70
(* FIXME: Similar yet different code in "mirabelle.ML". The code here has a few
blanchet@49266
    71
   fixes that seem to be missing over there; or maybe the two code portions are
blanchet@49266
    72
   not doing the same? *)
blanchet@49266
    73
fun fold_body_thms thm_name f =
blanchet@49266
    74
  let
blanchet@49266
    75
    fun app n (PBody {thms, ...}) =
blanchet@49331
    76
      thms |> fold (fn (_, (name, _, body)) => fn accum =>
blanchet@49331
    77
          let
blanchet@49331
    78
            (* The second disjunct caters for the uncommon case where the proved
blanchet@49331
    79
               theorem occurs in its own proof (e.g.,
blanchet@49331
    80
               "Transitive_Closure.trancl_into_trancl"). *)
blanchet@49331
    81
            val no_name = (name = "" orelse (n = 1 andalso name = thm_name))
blanchet@49331
    82
            val accum =
blanchet@49331
    83
              accum |> (if n = 1 andalso not no_name then f name else I)
blanchet@49331
    84
            val n = n + (if no_name then 0 else 1)
blanchet@49331
    85
          in accum |> (if n <= 1 then app n (Future.join body) else I) end)
blanchet@49266
    86
  in fold (app 0) end
blanchet@49266
    87
blanchet@49266
    88
fun thms_in_proof all_names th =
blanchet@49266
    89
  let
blanchet@49331
    90
    val collect =
blanchet@49266
    91
      case all_names of
blanchet@49331
    92
        SOME names => (fn s => Symtab.defined names s ? insert (op =) s)
blanchet@49331
    93
      | NONE => insert (op =)
blanchet@49266
    94
    val names =
blanchet@49266
    95
      [] |> fold_body_thms (Thm.get_name_hint th) collect [Thm.proof_body_of th]
blanchet@49266
    96
  in names end
blanchet@49266
    97
blanchet@35961
    98
end;