| author | hoelzl | 
| Tue, 10 Mar 2015 11:56:32 +0100 | |
| changeset 59665 | 37adca7fd48f | 
| parent 59138 | 853a8cb902aa | 
| child 59697 | 43e14b0e2ef8 | 
| permissions | -rw-r--r-- | 
| 34136 | 1  | 
/* Title: Pure/General/exn.scala  | 
| 
45673
 
cd41e3903fbf
separate compilation of PIDE vs. Pure sources, which enables independent Scala library;
 
wenzelm 
parents: 
45667 
diff
changeset
 | 
2  | 
Module: PIDE  | 
| 34136 | 3  | 
Author: Makarius  | 
4  | 
||
| 
43761
 
e72ba84ae58f
tuned signature -- corresponding to Scala version;
 
wenzelm 
parents: 
34313 
diff
changeset
 | 
5  | 
Support for exceptions (arbitrary throwables).  | 
| 34136 | 6  | 
*/  | 
7  | 
||
8  | 
package isabelle  | 
|
9  | 
||
10  | 
||
11  | 
object Exn  | 
|
12  | 
{
 | 
|
| 44158 | 13  | 
/* exceptions as values */  | 
| 34136 | 14  | 
|
15  | 
sealed abstract class Result[A]  | 
|
| 43762 | 16  | 
case class Res[A](res: A) extends Result[A]  | 
17  | 
case class Exn[A](exn: Throwable) extends Result[A]  | 
|
| 34136 | 18  | 
|
19  | 
def capture[A](e: => A): Result[A] =  | 
|
20  | 
    try { Res(e) }
 | 
|
| 
34313
 
2f890016afab
treat *all* JVM throwables as "exceptions", cf. ML version;
 
wenzelm 
parents: 
34300 
diff
changeset
 | 
21  | 
    catch { case exn: Throwable => Exn[A](exn) }
 | 
| 34136 | 22  | 
|
23  | 
def release[A](result: Result[A]): A =  | 
|
24  | 
    result match {
 | 
|
25  | 
case Res(x) => x  | 
|
26  | 
case Exn(exn) => throw exn  | 
|
27  | 
}  | 
|
| 44158 | 28  | 
|
| 
59136
 
c2b23cb8a677
added Par_List in Scala, in accordance to ML version;
 
wenzelm 
parents: 
57831 
diff
changeset
 | 
29  | 
def release_first[A](results: List[Result[A]]): List[A] =  | 
| 59138 | 30  | 
    results.find({ case Exn(exn) => !is_interrupt(exn) case _ => false }) match {
 | 
31  | 
case Some(Exn(exn)) => throw exn  | 
|
32  | 
case _ => results.map(release(_))  | 
|
33  | 
}  | 
|
| 
59136
 
c2b23cb8a677
added Par_List in Scala, in accordance to ML version;
 
wenzelm 
parents: 
57831 
diff
changeset
 | 
34  | 
|
| 44158 | 35  | 
|
| 
56667
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
36  | 
/* interrupts */  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
37  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
38  | 
def is_interrupt(exn: Throwable): Boolean =  | 
| 56670 | 39  | 
  {
 | 
40  | 
var found_interrupt = false  | 
|
41  | 
var e = exn  | 
|
42  | 
    while (!found_interrupt && e != null) {
 | 
|
43  | 
found_interrupt |= e.isInstanceOf[InterruptedException]  | 
|
44  | 
e = e.getCause  | 
|
45  | 
}  | 
|
46  | 
found_interrupt  | 
|
47  | 
}  | 
|
| 
56667
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
48  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
49  | 
object Interrupt  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
50  | 
  {
 | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
51  | 
def apply(): Throwable = new InterruptedException  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
52  | 
def unapply(exn: Throwable): Boolean = is_interrupt(exn)  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
53  | 
|
| 56861 | 54  | 
    def expose() { if (Thread.interrupted()) throw apply() }
 | 
55  | 
    def impose() { Thread.currentThread.interrupt }
 | 
|
| 56860 | 56  | 
|
| 
56862
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
57  | 
def postpone[A](body: => A): Option[A] =  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
58  | 
    {
 | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
59  | 
val interrupted = Thread.interrupted  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
60  | 
      val result = capture { body }
 | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
61  | 
if (interrupted) impose()  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
62  | 
      result match {
 | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
63  | 
case Res(x) => Some(x)  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
64  | 
case Exn(e) =>  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
65  | 
          if (is_interrupt(e)) { impose(); None }
 | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
66  | 
else throw e  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
67  | 
}  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
68  | 
}  | 
| 
 
e6f7ed54d64e
more robust process kill -- postpone interrupts on current thread;
 
wenzelm 
parents: 
56861 
diff
changeset
 | 
69  | 
|
| 
56667
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
70  | 
val return_code = 130  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
71  | 
}  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
72  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
73  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
74  | 
/* POSIX return code */  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
75  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
76  | 
def return_code(exn: Throwable, rc: Int): Int =  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
77  | 
if (is_interrupt(exn)) Interrupt.return_code else rc  | 
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
78  | 
|
| 
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
79  | 
|
| 44158 | 80  | 
/* message */  | 
81  | 
||
82  | 
  private val runtime_exception = Class.forName("java.lang.RuntimeException")
 | 
|
83  | 
||
| 
48479
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
84  | 
def user_message(exn: Throwable): Option[String] =  | 
| 48476 | 85  | 
    if (exn.isInstanceOf[java.io.IOException]) {
 | 
86  | 
val msg = exn.getMessage  | 
|
| 
48479
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
87  | 
Some(if (msg == null) "I/O error" else "I/O error: " + msg)  | 
| 48476 | 88  | 
}  | 
89  | 
    else if (exn.getClass == runtime_exception) {
 | 
|
| 44158 | 90  | 
val msg = exn.getMessage  | 
| 
57831
 
885888a880fb
more general notion of "user error" including empty message -- NB: Output.error_message needs non-empty string to emit anything;
 
wenzelm 
parents: 
56862 
diff
changeset
 | 
91  | 
Some(if (msg == null || msg == "") "Error" else msg)  | 
| 44158 | 92  | 
}  | 
| 
48479
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
93  | 
else if (exn.isInstanceOf[RuntimeException]) Some(exn.toString)  | 
| 
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
94  | 
else None  | 
| 
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
95  | 
|
| 
 
819f7a5f3e7f
more general notion of user ERROR (cf. 44f56fe01528);
 
wenzelm 
parents: 
48476 
diff
changeset
 | 
96  | 
def message(exn: Throwable): String =  | 
| 
56667
 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 
wenzelm 
parents: 
52066 
diff
changeset
 | 
97  | 
user_message(exn) getOrElse (if (is_interrupt(exn)) "Interrupt" else exn.toString)  | 
| 34136 | 98  | 
}  | 
99  |