more focused use of Multithreading.interrupted: retain interrupts within task group boundary, without loss of information;
1 (* Title: Pure/Isar/runtime.ML
4 Isar toplevel runtime support.
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
22 structure Runtime: RUNTIME =
29 exception EXCURSION_FAIL of exn * string;
30 exception TOPLEVEL_ERROR;
32 val debug = Unsynchronized.ref false;
37 exception CONTEXT of Proof.context * exn;
39 fun exn_context NONE exn = exn
40 | exn_context (SOME ctxt) exn = if Exn.is_interrupt exn then exn else CONTEXT (ctxt, exn);
45 fun if_context NONE _ _ = []
46 | if_context (SOME ctxt) f xs = map (f ctxt) xs;
48 fun exn_messages exn_position e =
50 fun raised exn name msgs =
51 let val pos = Position.str_of (exn_position exn) in
53 [] => "exception " ^ name ^ " raised" ^ pos
54 | [msg] => "exception " ^ name ^ " raised" ^ pos ^ ": " ^ msg
55 | _ => cat_lines (("exception " ^ name ^ " raised" ^ pos ^ ":") :: msgs))
58 val detailed = ! debug;
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)]);
67 fun exn_msgs (context, (i, exn)) =
69 EXCURSION_FAIL (exn, loc) =>
70 map (apsnd (fn msg => msg ^ Markup.markup Markup.no_report ("\n" ^ loc)))
71 (sorted_msgs context exn)
77 | TimeLimit.TimeOut => "Timeout"
78 | TOPLEVEL_ERROR => "Error"
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 ::
89 if_context context Syntax.string_of_typ Ts @
90 if_context context Syntax.string_of_term 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) []);
100 and sorted_msgs context exn =
101 sort_distinct (int_ord o pairself fst) (maps exn_msgs (flatten context exn));
103 in sorted_msgs NONE e end;
105 fun exn_message exn_position exn =
106 (case exn_messages exn_position exn of
108 | msgs => cat_lines (map snd msgs));
111 (** controlled execution **)
115 Exn.release (exception_trace (fn () =>
117 exn as UNDEF => Exn.Exn exn
118 | exn as EXCURSION_FAIL _ => Exn.Exn exn))
121 fun controlled_execution f x =
122 (f |> debugging |> Future.interruptible_task) x;
124 fun toplevel_error output_exn f x = f x
126 if Exn.is_interrupt exn then reraise exn
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;