src/Pure/Isar/runtime.ML
author wenzelm
Fri, 19 Aug 2011 12:51:14 +0200
changeset 45170 e43f0ea90c9a
parent 45154 89f40a5939b2
child 46074 b6c527c64789
permissions -rw-r--r--
more focused use of Multithreading.interrupted: retain interrupts within task group boundary, without loss of information;
wenzelm@31476
     1
(*  Title:      Pure/Isar/runtime.ML
wenzelm@31476
     2
    Author:     Makarius
wenzelm@31476
     3
wenzelm@31476
     4
Isar toplevel runtime support.
wenzelm@31476
     5
*)
wenzelm@31476
     6
wenzelm@31476
     7
signature RUNTIME =
wenzelm@31476
     8
sig
wenzelm@31476
     9
  exception UNDEF
wenzelm@31476
    10
  exception TERMINATE
wenzelm@31476
    11
  exception EXCURSION_FAIL of exn * string
wenzelm@31476
    12
  exception TOPLEVEL_ERROR
wenzelm@39782
    13
  val debug: bool Unsynchronized.ref
wenzelm@31476
    14
  val exn_context: Proof.context option -> exn -> exn
wenzelm@45153
    15
  val exn_messages: (exn -> Position.T) -> exn -> (serial * string) list
wenzelm@31476
    16
  val exn_message: (exn -> Position.T) -> exn -> string
wenzelm@31476
    17
  val debugging: ('a -> 'b) -> 'a -> 'b
wenzelm@31476
    18
  val controlled_execution: ('a -> 'b) -> 'a -> 'b
wenzelm@33603
    19
  val toplevel_error: (exn -> unit) -> ('a -> 'b) -> 'a -> 'b
wenzelm@31476
    20
end;
wenzelm@31476
    21
wenzelm@31476
    22
structure Runtime: RUNTIME =
wenzelm@31476
    23
struct
wenzelm@31476
    24
wenzelm@31476
    25
(** exceptions **)
wenzelm@31476
    26
wenzelm@31476
    27
exception UNDEF;
wenzelm@31476
    28
exception TERMINATE;
wenzelm@31476
    29
exception EXCURSION_FAIL of exn * string;
wenzelm@31476
    30
exception TOPLEVEL_ERROR;
wenzelm@31476
    31
wenzelm@39782
    32
val debug = Unsynchronized.ref false;
wenzelm@39782
    33
wenzelm@31476
    34
wenzelm@31476
    35
(* exn_context *)
wenzelm@31476
    36
wenzelm@31476
    37
exception CONTEXT of Proof.context * exn;
wenzelm@31476
    38
wenzelm@31476
    39
fun exn_context NONE exn = exn
wenzelm@39538
    40
  | exn_context (SOME ctxt) exn = if Exn.is_interrupt exn then exn else CONTEXT (ctxt, exn);
wenzelm@31476
    41
wenzelm@31476
    42
wenzelm@31476
    43
(* exn_message *)
wenzelm@31476
    44
wenzelm@31476
    45
fun if_context NONE _ _ = []
wenzelm@31476
    46
  | if_context (SOME ctxt) f xs = map (f ctxt) xs;
wenzelm@31476
    47
wenzelm@39200
    48
fun exn_messages exn_position e =
wenzelm@31476
    49
  let
wenzelm@31476
    50
    fun raised exn name msgs =
wenzelm@31476
    51
      let val pos = Position.str_of (exn_position exn) in
wenzelm@31476
    52
        (case msgs of
wenzelm@31476
    53
          [] => "exception " ^ name ^ " raised" ^ pos
wenzelm@31476
    54
        | [msg] => "exception " ^ name ^ " raised" ^ pos ^ ": " ^ msg
wenzelm@31476
    55
        | _ => cat_lines (("exception " ^ name ^ " raised" ^ pos ^ ":") :: msgs))
wenzelm@31476
    56
      end;
wenzelm@31476
    57
wenzelm@39782
    58
    val detailed = ! debug;
wenzelm@31476
    59
wenzelm@45153
    60
    fun flatten _ (CONTEXT (ctxt, exn)) = flatten (SOME ctxt) exn
wenzelm@45153
    61
      | flatten context (Exn.EXCEPTIONS exns) = maps (flatten context) exns
wenzelm@45153
    62
      | flatten context exn =
wenzelm@45153
    63
          (case Par_Exn.dest exn of
wenzelm@45154
    64
            SOME exns => maps (flatten context) exns
wenzelm@45153
    65
          | NONE => [(context, Par_Exn.serial exn)]);
wenzelm@45153
    66
wenzelm@45153
    67
    fun exn_msgs (context, (i, exn)) =
wenzelm@45153
    68
      (case exn of
wenzelm@45153
    69
        EXCURSION_FAIL (exn, loc) =>
wenzelm@45153
    70
          map (apsnd (fn msg => msg ^ Markup.markup Markup.no_report ("\n" ^ loc)))
wenzelm@45153
    71
            (sorted_msgs context exn)
wenzelm@45153
    72
      | _ =>
wenzelm@45153
    73
        let
wenzelm@45153
    74
          val msg =
wenzelm@45125
    75
            (case exn of
wenzelm@45153
    76
              TERMINATE => "Exit"
wenzelm@45153
    77
            | TimeLimit.TimeOut => "Timeout"
wenzelm@45153
    78
            | TOPLEVEL_ERROR => "Error"
wenzelm@45153
    79
            | ERROR msg => msg
wenzelm@45153
    80
            | Fail msg => raised exn "Fail" [msg]
wenzelm@45125
    81
            | THEORY (msg, thys) =>
wenzelm@45153
    82
                raised exn "THEORY" (msg :: (if detailed then map Context.str_of_thy thys else []))
wenzelm@45125
    83
            | Ast.AST (msg, asts) =>
wenzelm@45153
    84
                raised exn "AST" (msg ::
wenzelm@45153
    85
                  (if detailed then map (Pretty.string_of o Ast.pretty_ast) asts else []))
wenzelm@45125
    86
            | TYPE (msg, Ts, ts) =>
wenzelm@45153
    87
                raised exn "TYPE" (msg ::
wenzelm@45125
    88
                  (if detailed then
wenzelm@45125
    89
                    if_context context Syntax.string_of_typ Ts @
wenzelm@45125
    90
                    if_context context Syntax.string_of_term ts
wenzelm@45153
    91
                   else []))
wenzelm@45125
    92
            | TERM (msg, ts) =>
wenzelm@45153
    93
                raised exn "TERM" (msg ::
wenzelm@45153
    94
                  (if detailed then if_context context Syntax.string_of_term ts else []))
wenzelm@45125
    95
            | THM (msg, i, thms) =>
wenzelm@45153
    96
                raised exn ("THM " ^ string_of_int i) (msg ::
wenzelm@45153
    97
                  (if detailed then if_context context Display.string_of_thm thms else []))
wenzelm@45153
    98
            | _ => raised exn (General.exnMessage exn) []);
wenzelm@45153
    99
        in [(i, msg)] end)
wenzelm@45153
   100
      and sorted_msgs context exn =
wenzelm@45154
   101
        sort_distinct (int_ord o pairself fst) (maps exn_msgs (flatten context exn));
wenzelm@45153
   102
wenzelm@45153
   103
  in sorted_msgs NONE e end;
wenzelm@39200
   104
wenzelm@39200
   105
fun exn_message exn_position exn =
wenzelm@39200
   106
  (case exn_messages exn_position exn of
wenzelm@39201
   107
    [] => "Interrupt"
wenzelm@45153
   108
  | msgs => cat_lines (map snd msgs));
wenzelm@31476
   109
wenzelm@31476
   110
wenzelm@31476
   111
(** controlled execution **)
wenzelm@31476
   112
wenzelm@31476
   113
fun debugging f x =
wenzelm@39782
   114
  if ! debug then
wenzelm@31476
   115
    Exn.release (exception_trace (fn () =>
wenzelm@44633
   116
      Exn.Res (f x) handle
wenzelm@31476
   117
        exn as UNDEF => Exn.Exn exn
wenzelm@31476
   118
      | exn as EXCURSION_FAIL _ => Exn.Exn exn))
wenzelm@31476
   119
  else f x;
wenzelm@31476
   120
wenzelm@42595
   121
fun controlled_execution f x =
wenzelm@45170
   122
  (f |> debugging |> Future.interruptible_task) x;
wenzelm@31476
   123
wenzelm@39515
   124
fun toplevel_error output_exn f x = f x
wenzelm@39515
   125
  handle exn =>
wenzelm@39515
   126
    if Exn.is_interrupt exn then reraise exn
wenzelm@39515
   127
    else
wenzelm@39515
   128
      let
wenzelm@39515
   129
        val ctxt = Option.map Context.proof_of (Context.thread_data ());
wenzelm@39515
   130
        val _ = output_exn (exn_context ctxt exn);
wenzelm@39515
   131
      in raise TOPLEVEL_ERROR end;
wenzelm@31476
   132
wenzelm@31476
   133
end;
wenzelm@31476
   134