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