src/Pure/General/exn.ML
author wenzelm
Thu, 23 Jun 2011 23:05:38 +0200
changeset 43537 80803078552e
parent 42223 098c86e53153
child 43761 e72ba84ae58f
permissions -rw-r--r--
clarified EXCEPTIONS [] (cf. Exn.is_interrupt and Runtime.exn_message);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents: 32100
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
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
     4
Extra 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
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
     7
signature EXN =
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
     8
sig
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents: 32100
diff changeset
     9
  datatype 'a result = Result of 'a | Exn of exn
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    10
  val get_result: 'a result -> 'a option
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    11
  val get_exn: 'a result -> exn option
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    12
  val capture: ('a -> 'b) -> 'a -> 'b result
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    13
  val release: 'a result -> 'a
42223
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    14
  val flat_result: 'a result result -> 'a result
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
    15
  val map_result: ('a -> 'b) -> 'a result -> 'b result
42223
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    16
  val maps_result: ('a -> 'b result) -> 'a result -> 'b result
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    17
  exception Interrupt
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    18
  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
    19
  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
    20
  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
    21
  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
    22
  val interruptible_capture: ('a -> 'b) -> 'a -> 'b result
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
    23
  exception EXCEPTIONS of exn list
32100
8ac6b1102f16 added flatten/flatten_list -- supercedes internal plain_exns;
wenzelm
parents: 31427
diff changeset
    24
  val flatten: exn -> exn list
8ac6b1102f16 added flatten/flatten_list -- supercedes internal plain_exns;
wenzelm
parents: 31427
diff changeset
    25
  val flatten_list: exn list -> exn list
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    26
  val release_all: 'a result list -> 'a list
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    27
  val release_first: 'a result list -> 'a list
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    28
end;
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    29
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    30
structure Exn: EXN =
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    31
struct
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    32
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    33
(* runtime exceptions as values *)
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    34
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    35
datatype 'a result =
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    36
  Result of 'a |
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    37
  Exn of exn;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    38
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    39
fun get_result (Result x) = SOME x
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    40
  | get_result _ = NONE;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    41
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    42
fun get_exn (Exn exn) = SOME exn
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    43
  | get_exn _ = NONE;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    44
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    45
fun capture f x = Result (f x) handle e => Exn e;
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    46
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    47
fun release (Result y) = y
31427
5a07cc86675d reraise exceptions to preserve original position (ML system specific);
wenzelm
parents: 29564
diff changeset
    48
  | release (Exn e) = reraise e;
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    49
42223
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    50
fun flat_result (Result x) = x
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    51
  | flat_result (Exn e) = Exn e;
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    52
39472
1cf49add5b40 Exn.map_result
haftmann
parents: 39233
diff changeset
    53
fun map_result f (Result x) = Result (f x)
42223
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    54
  | map_result f (Exn e) = Exn e;
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    55
098c86e53153 more precise propagation of reports/results through some inner syntax layers;
wenzelm
parents: 40483
diff changeset
    56
fun maps_result f = flat_result o map_result f;
39472
1cf49add5b40 Exn.map_result
haftmann
parents: 39233
diff changeset
    57
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    58
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    59
(* interrupts *)
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    60
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    61
exception Interrupt = Interrupt;
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    62
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    63
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
    64
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    65
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
    66
  | 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
    67
  | is_interrupt _ = false;
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    68
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    69
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
    70
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    71
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
    72
  | 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
    73
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
    74
fun interruptible_capture f x =
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
    75
  Result (f x) handle e => if is_interrupt e then reraise e else Exn e;
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
    76
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    77
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    78
(* nested exceptions *)
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    79
28459
f6a4d913cfb1 simplified Exn.EXCEPTIONS, flatten nested occurrences;
wenzelm
parents: 28444
diff changeset
    80
exception EXCEPTIONS of exn list;
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    81
39232
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    82
fun flatten (EXCEPTIONS exns) = flatten_list exns
69c6d3e87660 more abstract treatment of interrupts in structure Exn -- hardly ever need to mention Interrupt literally;
wenzelm
parents: 34136
diff changeset
    83
  | flatten exn = if is_interrupt exn then [] else [exn]
32100
8ac6b1102f16 added flatten/flatten_list -- supercedes internal plain_exns;
wenzelm
parents: 31427
diff changeset
    84
and flatten_list exns = List.concat (map flatten exns);
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    85
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    86
fun release_all results =
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    87
  if List.all (fn Result _ => true | _ => false) results
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    88
  then map (fn Result x => x) results
32100
8ac6b1102f16 added flatten/flatten_list -- supercedes internal plain_exns;
wenzelm
parents: 31427
diff changeset
    89
  else raise EXCEPTIONS (flatten_list (List.mapPartial get_exn results));
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    90
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    91
fun release_first results = release_all results
43537
80803078552e clarified EXCEPTIONS [] (cf. Exn.is_interrupt and Runtime.exn_message);
wenzelm
parents: 42223
diff changeset
    92
  handle EXCEPTIONS [] => interrupt ()
80803078552e clarified EXCEPTIONS [] (cf. Exn.is_interrupt and Runtime.exn_message);
wenzelm
parents: 42223
diff changeset
    93
    | EXCEPTIONS (exn :: _) => reraise exn;
28444
283d5e41953d more robust treatment of Interrupt;
wenzelm
parents: 23962
diff changeset
    94
23962
e0358fac0541 Runtime exceptions as values (from library.ML);
wenzelm
parents:
diff changeset
    95
end;
40483
3848283c14bb treat pervasive "Interrupt" constructor as illegal -- superseded by Exn.Interrupt for internal use and Exn.is_interrupt/Exn.interrupt in user-space;
wenzelm
parents: 40234
diff changeset
    96
3848283c14bb treat pervasive "Interrupt" constructor as illegal -- superseded by Exn.Interrupt for internal use and Exn.is_interrupt/Exn.interrupt in user-space;
wenzelm
parents: 40234
diff changeset
    97
datatype illegal = Interrupt;
3848283c14bb treat pervasive "Interrupt" constructor as illegal -- superseded by Exn.Interrupt for internal use and Exn.is_interrupt/Exn.interrupt in user-space;
wenzelm
parents: 40234
diff changeset
    98