src/Pure/General/exn.ML
author wenzelm
Fri, 17 Mar 2017 20:33:27 +0100
changeset 65292 e3bd1e7ddd23
parent 63925 500646ef617a
child 73275 f0db1e4c89bc
permissions -rw-r--r--
more robust JDBC initialization, e.g. required for Isabelle/jEdit startup;
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
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    20
  val get_res: 'a result -> 'a option
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    21
  val get_exn: 'a result -> exn option
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    22
  val capture: ('a -> 'b) -> 'a -> 'b result
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    23
  val release: 'a result -> 'a
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    24
  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
    25
  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
    26
  val map_exn: (exn -> exn) -> 'a result -> 'a result
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    27
  exception Interrupt
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    28
  val interrupt: unit -> 'a
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 interrupt_exn: 'a result
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    31
  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
    32
  val interruptible_capture: ('a -> 'b) -> 'a -> 'b result
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
    33
  val return_code: exn -> int -> int
56628
a2df9de46060 tuned -- avoid warning about catch-all handler;
wenzelm
parents: 44247
diff changeset
    34
  val capture_exit: int -> ('a -> 'b) -> 'a -> 'b
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
    35
  exception EXCEPTIONS of exn list
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    36
  val trace: (exn -> string) -> (string -> unit) -> (unit -> 'a) -> 'a
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    37
end;
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    38
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    39
structure Exn: EXN =
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    40
struct
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    41
62821
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    42
(* location *)
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    43
62821
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    44
val polyml_location = PolyML.Exception.exceptionLocation;
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    45
48c24d0b6d85 tuned signature;
wenzelm
parents: 62508
diff changeset
    46
val reraise = PolyML.Exception.reraise;
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    47
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
    48
62492
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    49
(* user errors *)
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    50
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    51
exception ERROR of string;
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    52
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    53
fun error msg = raise ERROR msg;
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    54
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    55
fun cat_error "" msg = error msg
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    56
  | cat_error msg "" = error msg
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    57
  | cat_error msg1 msg2 = error (msg1 ^ "\n" ^ msg2);
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    58
0e53fade87fe clarified modules;
wenzelm
parents: 62491
diff changeset
    59
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43761
diff changeset
    60
(* exceptions as values *)
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    61
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    62
datatype 'a result =
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    63
  Res of 'a |
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    64
  Exn of exn;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    65
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    66
fun get_res (Res x) = SOME x
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    67
  | get_res _ = NONE;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    68
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    69
fun get_exn (Exn exn) = SOME exn
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    70
  | get_exn _ = NONE;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    71
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    72
fun capture f x = Res (f x) handle e => Exn e;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    73
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
    74
fun release (Res y) = y
31427
5a07cc86675d reraise exceptions to preserve original position (ML system specific);
wenzelm
parents: 29564
diff changeset
    75
  | release (Exn e) = reraise e;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    76
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    77
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
    78
  | 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
    79
61077
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    80
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
    81
06cca32aa519 thread context for exceptions from forks, e.g. relevant when printing errors;
wenzelm
parents: 56667
diff changeset
    82
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
    83
  | map_exn f (Exn e) = Exn (f e);
39472
1cf49add5b40 Exn.map_result
haftmann
parents: 39233
diff changeset
    84
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    85
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    86
(* interrupts *)
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    87
63925
500646ef617a avoid old SML90;
wenzelm
parents: 62923
diff changeset
    88
exception Interrupt = Thread.Thread.Interrupt;
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    89
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    90
fun interrupt () = raise Interrupt;
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    91
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    92
fun is_interrupt 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
val interrupt_exn = Exn Interrupt;
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    97
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    98
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
    99
  | 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
   100
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
fun interruptible_capture f x =
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 43537
diff changeset
   102
  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
   103
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
   104
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
   105
(* POSIX return code *)
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
   106
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
   107
fun return_code exn rc =
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
   108
  if is_interrupt exn then (130: int) else rc;
56628
a2df9de46060 tuned -- avoid warning about catch-all handler;
wenzelm
parents: 44247
diff changeset
   109
a2df9de46060 tuned -- avoid warning about catch-all handler;
wenzelm
parents: 44247
diff changeset
   110
fun capture_exit rc f x =
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 56628
diff changeset
   111
  f x handle exn => exit (return_code exn rc);
56628
a2df9de46060 tuned -- avoid warning about catch-all handler;
wenzelm
parents: 44247
diff changeset
   112
a2df9de46060 tuned -- avoid warning about catch-all handler;
wenzelm
parents: 44247
diff changeset
   113
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents: 44246
diff changeset
   114
(* concatenated exceptions *)
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
   115
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
   116
exception EXCEPTIONS of exn list;
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
   117
62505
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   118
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   119
(* low-level trace *)
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   120
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   121
fun trace exn_message output e =
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   122
  PolyML.Exception.traceException
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   123
    (e, fn (trace, exn) =>
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   124
      let
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   125
        val title = "Exception trace - " ^ exn_message exn;
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   126
        val () = output (String.concatWith "\n" (title :: trace));
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   127
      in reraise exn end);
9e2a65912111 clarified modules;
wenzelm
parents: 62492
diff changeset
   128
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
   129
end;