src/Pure/General/exn.ML
author wenzelm
Thu, 21 Sep 2023 23:45:03 +0200
changeset 78681 38fe769658be
parent 78674 88f47c70187a
child 78683 cde40295ffd6
permissions -rw-r--r--
clarified modules; clarified signature;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
62508
d0b68218ea55 discontinued RAW session: bootstrap directly from isabelle_process RAW_ML_SYSTEM;
wenzelm
parents: 62505
diff changeset
     1
(*  Title:      Pure/General/exn.ML
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
     3
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
     4
Support for exceptions.
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
     5
*)
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
     6
62491
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
     7
signature BASIC_EXN =
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
     8
sig
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
     9
  exception ERROR of string
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
    10
  val error: string -> 'a
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
    11
  val cat_error: string -> string -> 'a
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
    12
end;
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
    13
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    14
signature EXN =
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    15
sig
62491
7187cb7a77c5 clarified modules;
wenzelm
parents: 62198
diff changeset
    16
  include BASIC_EXN
62821
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    17
  val polyml_location: exn -> PolyML.location option
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    18
  val reraise: exn -> 'a
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    19
  datatype 'a result = Res of 'a | Exn of exn
78674
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    20
  val is_res: 'a result -> bool
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    21
  val is_exn: 'a result -> bool
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    22
  val get_res: 'a result -> 'a option
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    23
  val get_exn: 'a result -> exn option
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    24
  val capture: ('a -> 'b) -> 'a -> 'b result
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    25
  val release: 'a result -> 'a
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    26
  val map_res: ('a -> 'b) -> 'a result -> 'b result
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    27
  val maps_res: ('a -> 'b result) -> 'a result -> 'b result
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    28
  val map_exn: (exn -> exn) -> 'a result -> 'a result
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    29
  val is_interrupt: exn -> bool
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    30
  val is_interrupt_exn: 'a result -> bool
40234
39af96cc57cb added Exn.interruptible_capture, which reraises interrupts as required by user-code (when Exn.capture is not immediately followed by Exn.release);
wenzelm
parents: 39472
diff changeset
    31
  val interruptible_capture: ('a -> 'b) -> 'a -> 'b result
78673
90b12b919b5f clarified signature (again): follow Isabelle/Java/Scala;
wenzelm
parents: 78671
diff changeset
    32
  val failure_rc: exn -> int
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
    33
  exception EXCEPTIONS of exn list
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    34
  val trace: (exn -> string) -> (string -> unit) -> (unit -> 'a) -> 'a
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    35
end;
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    36
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    37
structure Exn: EXN =
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    38
struct
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    39
62821
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    40
(* location *)
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    41
62821
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    42
val polyml_location = PolyML.Exception.exceptionLocation;
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    43
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    44
val reraise = PolyML.Exception.reraise;
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    45
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    46
62492
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    47
(* user errors *)
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    48
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    49
exception ERROR of string;
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    50
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    51
fun error msg = raise ERROR msg;
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    52
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    53
fun cat_error "" msg = error msg
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    54
  | cat_error msg "" = error msg
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    55
  | cat_error msg1 msg2 = error (msg1 ^ "\n" ^ msg2);
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    56
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    57
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43761
diff changeset
    58
(* exceptions as values *)
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    59
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    60
datatype 'a result =
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    61
  Res of 'a |
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    62
  Exn of exn;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    63
78674
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    64
fun is_res (Res _) = true
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    65
  | is_res _ = false;
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    66
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    67
fun is_exn (Exn _) = true
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    68
  | is_exn _ = false;
88f47c70187a clarified signature;
wenzelm
parents: 78673
diff changeset
    69
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    70
fun get_res (Res x) = SOME x
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    71
  | get_res _ = NONE;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    72
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    73
fun get_exn (Exn exn) = SOME exn
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    74
  | get_exn _ = NONE;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    75
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    76
fun capture f x = Res (f x) handle e => Exn e;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    77
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    78
fun release (Res y) = y
31427
5a07cc86675d reraise exceptions to preserve original position (ML system specific);
wenzelm
parents: 29564
diff changeset
    79
  | release (Exn e) = reraise e;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    80
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    81
fun map_res f (Res x) = Res (f x)
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    82
  | map_res f (Exn e) = Exn e;
42223
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    83
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    84
fun maps_res f = (fn Res x => x | Exn e => Exn e) o map_res f;
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    85
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    86
fun map_exn f (Res x) = Res x
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    87
  | map_exn f (Exn e) = Exn (f e);
39472
1cf49add5b40 Exn.map_result
haftmann
parents: 39233
diff changeset
    88
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    89
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    90
(* interrupts *)
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    91
78681
38fe769658be clarified modules;
wenzelm
parents: 78674
diff changeset
    92
fun is_interrupt Thread.Thread.Interrupt = true
40234
39af96cc57cb added Exn.interruptible_capture, which reraises interrupts as required by user-code (when Exn.capture is not immediately followed by Exn.release);
wenzelm
parents: 39472
diff changeset
    93
  | is_interrupt (IO.Io {cause, ...}) = is_interrupt cause
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    94
  | is_interrupt _ = false;
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    95
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    96
fun is_interrupt_exn (Exn exn) = is_interrupt exn
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    97
  | is_interrupt_exn _ = false;
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    98
40234
39af96cc57cb added Exn.interruptible_capture, which reraises interrupts as required by user-code (when Exn.capture is not immediately followed by Exn.release);
wenzelm
parents: 39472
diff changeset
    99
fun interruptible_capture f x =
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
   100
  Res (f x) handle e => if is_interrupt e then reraise e else Exn e;
40234
39af96cc57cb added Exn.interruptible_capture, which reraises interrupts as required by user-code (when Exn.capture is not immediately followed by Exn.release);
wenzelm
parents: 39472
diff changeset
   101
78673
90b12b919b5f clarified signature (again): follow Isabelle/Java/Scala;
wenzelm
parents: 78671
diff changeset
   102
fun failure_rc exn = if is_interrupt exn then 130 else 2;
90b12b919b5f clarified signature (again): follow Isabelle/Java/Scala;
wenzelm
parents: 78671
diff changeset
   103
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
   104
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents: 44246
diff changeset
   105
(* concatenated exceptions *)
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
   106
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
   107
exception EXCEPTIONS of exn list;
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
   108
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   109
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   110
(* low-level trace *)
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   111
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   112
fun trace exn_message output e =
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   113
  PolyML.Exception.traceException
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   114
    (e, fn (trace, exn) =>
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   115
      let
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   116
        val title = "Exception trace - " ^ exn_message exn;
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   117
        val () = output (String.concatWith "\n" (title :: trace));
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   118
      in reraise exn end);
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   119
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
   120
end;