src/Pure/General/exn.scala
author wenzelm
Tue, 29 Apr 2014 13:32:13 +0200
changeset 56782 433cf57550fa
parent 56671 06853449cf0a
child 56860 dc71c3d0e909
permissions -rw-r--r--
more systematic Isabelle output, like in classic Isabelle/ML (without markup);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     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
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     3
    Author:     Makarius
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     4
43761
e72ba84ae58f tuned signature -- corresponding to Scala version;
wenzelm
parents: 34313
diff changeset
     5
Support for exceptions (arbitrary throwables).
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     6
*/
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     7
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     8
package isabelle
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
     9
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    10
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    11
object Exn
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    12
{
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    13
  /* exceptions as values */
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    14
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    15
  sealed abstract class Result[A]
43762
wenzelm
parents: 43761
diff changeset
    16
  case class Res[A](res: A) extends Result[A]
wenzelm
parents: 43761
diff changeset
    17
  case class Exn[A](exn: Throwable) extends Result[A]
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    18
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    19
  def capture[A](e: => A): Result[A] =
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    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
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    22
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    23
  def release[A](result: Result[A]): A =
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    24
    result match {
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    25
      case Res(x) => x
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    26
      case Exn(exn) => throw exn
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    27
    }
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    28
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    29
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    30
  /* interrupts */
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    31
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    32
  def is_interrupt(exn: Throwable): Boolean =
56670
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    33
  {
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    34
    var found_interrupt = false
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    35
    var e = exn
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    36
    while (!found_interrupt && e != null) {
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    37
      found_interrupt |= e.isInstanceOf[InterruptedException]
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    38
      e = e.getCause
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    39
    }
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    40
    found_interrupt
3f23441453d0 detect nested interrupts;
wenzelm
parents: 56667
diff changeset
    41
  }
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    42
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    43
  object Interrupt
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    44
  {
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    45
    def apply(): Throwable = new InterruptedException
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    46
    def unapply(exn: Throwable): Boolean = is_interrupt(exn)
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    47
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    48
    val return_code = 130
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    49
  }
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
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    52
  /* POSIX return code */
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    53
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    54
  def return_code(exn: Throwable, rc: Int): Int =
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    55
    if (is_interrupt(exn)) Interrupt.return_code else rc
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    56
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    57
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    58
  /* message */
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    59
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    60
  private val runtime_exception = Class.forName("java.lang.RuntimeException")
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    61
48479
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    62
  def user_message(exn: Throwable): Option[String] =
48476
44f56fe01528 human-readable I/O error;
wenzelm
parents: 45673
diff changeset
    63
    if (exn.isInstanceOf[java.io.IOException]) {
44f56fe01528 human-readable I/O error;
wenzelm
parents: 45673
diff changeset
    64
      val msg = exn.getMessage
48479
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    65
      Some(if (msg == null) "I/O error" else "I/O error: " + msg)
48476
44f56fe01528 human-readable I/O error;
wenzelm
parents: 45673
diff changeset
    66
    }
44f56fe01528 human-readable I/O error;
wenzelm
parents: 45673
diff changeset
    67
    else if (exn.getClass == runtime_exception) {
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    68
      val msg = exn.getMessage
48479
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    69
      Some(if (msg == null) "Error" else msg)
44158
fe6d1ae7a065 clarified Exn.message;
wenzelm
parents: 43762
diff changeset
    70
    }
48479
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    71
    else if (exn.isInstanceOf[RuntimeException]) Some(exn.toString)
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    72
    else None
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    73
819f7a5f3e7f more general notion of user ERROR (cf. 44f56fe01528);
wenzelm
parents: 48476
diff changeset
    74
  def message(exn: Throwable): String =
56667
65e84b0ef974 more abstract Exn.Interrupt and POSIX return code;
wenzelm
parents: 52066
diff changeset
    75
    user_message(exn) getOrElse (if (is_interrupt(exn)) "Interrupt" else exn.toString)
34136
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    76
}
3dcb46ae6185 added basic library -- Scala version;
wenzelm
parents:
diff changeset
    77