| author | wenzelm | 
| Wed, 08 Apr 2020 14:25:28 +0200 | |
| changeset 71736 | a2afc7ed2c68 | 
| parent 63925 | 500646ef617a | 
| child 73275 | f0db1e4c89bc | 
| permissions | -rw-r--r-- | 
| 62508 
d0b68218ea55
discontinued RAW session: bootstrap directly from isabelle_process RAW_ML_SYSTEM;
 wenzelm parents: 
62505diff
changeset | 1 | (* Title: Pure/General/exn.ML | 
| 23962 | 2 | Author: Makarius | 
| 3 | ||
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 4 | Support for exceptions. | 
| 23962 | 5 | *) | 
| 6 | ||
| 62491 | 7 | signature BASIC_EXN = | 
| 8 | sig | |
| 9 | exception ERROR of string | |
| 10 | val error: string -> 'a | |
| 11 | val cat_error: string -> string -> 'a | |
| 12 | end; | |
| 13 | ||
| 28444 | 14 | signature EXN = | 
| 15 | sig | |
| 62491 | 16 | include BASIC_EXN | 
| 62821 | 17 | val polyml_location: exn -> PolyML.location option | 
| 62505 | 18 | val reraise: exn -> 'a | 
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 19 | datatype 'a result = Res of 'a | Exn of exn | 
| 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 20 | val get_res: 'a result -> 'a option | 
| 28444 | 21 | val get_exn: 'a result -> exn option | 
| 22 |   val capture: ('a -> 'b) -> 'a -> 'b result
 | |
| 23 | val release: 'a result -> 'a | |
| 61077 
06cca32aa519
thread context for exceptions from forks, e.g. relevant when printing errors;
 wenzelm parents: 
56667diff
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: 
56667diff
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: 
56667diff
changeset | 26 | val map_exn: (exn -> exn) -> 'a result -> 'a result | 
| 28444 | 27 | exception Interrupt | 
| 39232 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 28 | val interrupt: unit -> 'a | 
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
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: 
34136diff
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: 
34136diff
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: 
39472diff
changeset | 32 |   val interruptible_capture: ('a -> 'b) -> 'a -> 'b result
 | 
| 56667 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 33 | val return_code: exn -> int -> int | 
| 56628 | 34 |   val capture_exit: int -> ('a -> 'b) -> 'a -> 'b
 | 
| 28459 
f6a4d913cfb1
simplified Exn.EXCEPTIONS, flatten nested occurrences;
 wenzelm parents: 
28444diff
changeset | 35 | exception EXCEPTIONS of exn list | 
| 62505 | 36 | val trace: (exn -> string) -> (string -> unit) -> (unit -> 'a) -> 'a | 
| 28444 | 37 | end; | 
| 38 | ||
| 39 | structure Exn: EXN = | |
| 23962 | 40 | struct | 
| 41 | ||
| 62821 | 42 | (* location *) | 
| 62505 | 43 | |
| 62821 | 44 | val polyml_location = PolyML.Exception.exceptionLocation; | 
| 45 | ||
| 46 | val reraise = PolyML.Exception.reraise; | |
| 62505 | 47 | |
| 48 | ||
| 62492 | 49 | (* user errors *) | 
| 50 | ||
| 51 | exception ERROR of string; | |
| 52 | ||
| 53 | fun error msg = raise ERROR msg; | |
| 54 | ||
| 55 | fun cat_error "" msg = error msg | |
| 56 | | cat_error msg "" = error msg | |
| 57 | | cat_error msg1 msg2 = error (msg1 ^ "\n" ^ msg2); | |
| 58 | ||
| 59 | ||
| 44158 | 60 | (* exceptions as values *) | 
| 28444 | 61 | |
| 23962 | 62 | datatype 'a result = | 
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 63 | Res of 'a | | 
| 23962 | 64 | Exn of exn; | 
| 65 | ||
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 66 | fun get_res (Res x) = SOME x | 
| 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 67 | | get_res _ = NONE; | 
| 23962 | 68 | |
| 69 | fun get_exn (Exn exn) = SOME exn | |
| 70 | | get_exn _ = NONE; | |
| 71 | ||
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 72 | fun capture f x = Res (f x) handle e => Exn e; | 
| 23962 | 73 | |
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
changeset | 74 | fun release (Res y) = y | 
| 31427 
5a07cc86675d
reraise exceptions to preserve original position (ML system specific);
 wenzelm parents: 
29564diff
changeset | 75 | | release (Exn e) = reraise e; | 
| 23962 | 76 | |
| 61077 
06cca32aa519
thread context for exceptions from forks, e.g. relevant when printing errors;
 wenzelm parents: 
56667diff
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: 
56667diff
changeset | 78 | | map_res f (Exn e) = Exn e; | 
| 42223 
098c86e53153
more precise propagation of reports/results through some inner syntax layers;
 wenzelm parents: 
40483diff
changeset | 79 | |
| 61077 
06cca32aa519
thread context for exceptions from forks, e.g. relevant when printing errors;
 wenzelm parents: 
56667diff
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: 
56667diff
changeset | 81 | |
| 
06cca32aa519
thread context for exceptions from forks, e.g. relevant when printing errors;
 wenzelm parents: 
56667diff
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: 
56667diff
changeset | 83 | | map_exn f (Exn e) = Exn (f e); | 
| 39472 | 84 | |
| 28444 | 85 | |
| 39232 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 86 | (* interrupts *) | 
| 28444 | 87 | |
| 63925 | 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: 
34136diff
changeset | 89 | |
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 90 | fun interrupt () = raise Interrupt; | 
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 91 | |
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
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: 
39472diff
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: 
34136diff
changeset | 94 | | is_interrupt _ = false; | 
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 95 | |
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
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: 
34136diff
changeset | 97 | |
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
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: 
34136diff
changeset | 99 | | is_interrupt_exn _ = false; | 
| 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
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: 
39472diff
changeset | 101 | fun interruptible_capture f x = | 
| 43761 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 wenzelm parents: 
43537diff
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: 
39472diff
changeset | 103 | |
| 39232 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 104 | |
| 56667 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 105 | (* POSIX return code *) | 
| 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 106 | |
| 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 107 | fun return_code exn rc = | 
| 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 108 | if is_interrupt exn then (130: int) else rc; | 
| 56628 | 109 | |
| 110 | fun capture_exit rc f x = | |
| 56667 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56628diff
changeset | 111 | f x handle exn => exit (return_code exn rc); | 
| 56628 | 112 | |
| 113 | ||
| 44247 | 114 | (* concatenated exceptions *) | 
| 39232 
69c6d3e87660
more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
 wenzelm parents: 
34136diff
changeset | 115 | |
| 28459 
f6a4d913cfb1
simplified Exn.EXCEPTIONS, flatten nested occurrences;
 wenzelm parents: 
28444diff
changeset | 116 | exception EXCEPTIONS of exn list; | 
| 28444 | 117 | |
| 62505 | 118 | |
| 119 | (* low-level trace *) | |
| 120 | ||
| 121 | fun trace exn_message output e = | |
| 122 | PolyML.Exception.traceException | |
| 123 | (e, fn (trace, exn) => | |
| 124 | let | |
| 125 | val title = "Exception trace - " ^ exn_message exn; | |
| 126 | val () = output (String.concatWith "\n" (title :: trace)); | |
| 127 | in reraise exn end); | |
| 128 | ||
| 23962 | 129 | end; |