| author | blanchet | 
| Tue, 19 Apr 2011 14:52:22 +0200 | |
| changeset 42419 | 9c81298fa4e1 | 
| parent 42223 | 098c86e53153 | 
| child 43537 | 80803078552e | 
| permissions | -rw-r--r-- | 
| 34136 | 1  | 
(* Title: Pure/General/exn.ML  | 
| 23962 | 2  | 
Author: Makarius  | 
3  | 
||
| 28444 | 4  | 
Extra support for exceptions.  | 
| 23962 | 5  | 
*)  | 
6  | 
||
| 28444 | 7  | 
signature EXN =  | 
8  | 
sig  | 
|
| 34136 | 9  | 
datatype 'a result = Result of 'a | Exn of exn  | 
| 28444 | 10  | 
val get_result: 'a result -> 'a option  | 
11  | 
val get_exn: 'a result -> exn option  | 
|
12  | 
  val capture: ('a -> 'b) -> 'a -> 'b result
 | 
|
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 | 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 | 26  | 
val release_all: 'a result list -> 'a list  | 
27  | 
val release_first: 'a result list -> 'a list  | 
|
28  | 
end;  | 
|
29  | 
||
30  | 
structure Exn: EXN =  | 
|
| 23962 | 31  | 
struct  | 
32  | 
||
| 28444 | 33  | 
(* runtime exceptions as values *)  | 
34  | 
||
| 23962 | 35  | 
datatype 'a result =  | 
36  | 
Result of 'a |  | 
|
37  | 
Exn of exn;  | 
|
38  | 
||
39  | 
fun get_result (Result x) = SOME x  | 
|
40  | 
| get_result _ = NONE;  | 
|
41  | 
||
42  | 
fun get_exn (Exn exn) = SOME exn  | 
|
43  | 
| get_exn _ = NONE;  | 
|
44  | 
||
45  | 
fun capture f x = Result (f x) handle e => Exn e;  | 
|
46  | 
||
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 | 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 | 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 | 57  | 
|
| 28444 | 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 | 60  | 
|
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 | 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 | 85  | 
|
| 28444 | 86  | 
fun release_all results =  | 
87  | 
if List.all (fn Result _ => true | _ => false) results  | 
|
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 | 90  | 
|
91  | 
fun release_first results = release_all results  | 
|
| 
31427
 
5a07cc86675d
reraise exceptions to preserve original position (ML system specific);
 
wenzelm 
parents: 
29564 
diff
changeset
 | 
92  | 
handle EXCEPTIONS (exn :: _) => reraise exn;  | 
| 28444 | 93  | 
|
| 23962 | 94  | 
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
 | 
95  | 
|
| 
 
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  | 
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
 | 
97  |