summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-05-29 22:58:03 +0000
committerPaul Phillips <paulp@improving.org>2009-05-29 22:58:03 +0000
commit661f1ba10e5062fd987c4cafe43ad1f0dc3f5491 (patch)
tree072736f2f6ee0aaadec200b3775f02378d8d433b /src
parentc36e3cc0a6599092f752ec7304d164cc06b9739c (diff)
downloadscala-661f1ba10e5062fd987c4cafe43ad1f0dc3f5491.tar.gz
scala-661f1ba10e5062fd987c4cafe43ad1f0dc3f5491.tar.bz2
scala-661f1ba10e5062fd987c4cafe43ad1f0dc3f5491.zip
Endless exploration of exception handling synta...
Endless exploration of exception handling syntax continues.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala20
-rw-r--r--src/library/scala/util/control/Exception.scala73
3 files changed, 58 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 4869ff04f1..6173753c6d 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -16,7 +16,7 @@ import scala.collection.immutable.ListSet
import scala.collection.mutable
import scala.collection.mutable.{ ListBuffer, HashSet, ArrayBuffer }
import scala.util.{ ScalaClassLoader, URLClassLoader }
-import scala.util.control.Exception.{ Catcher, catching, unwrapping }
+import scala.util.control.Exception.{ Catcher, catching, ultimately, unwrapping }
import io.{ PlainFile, VirtualDirectory }
import reporters.{ ConsoleReporter, Reporter }
@@ -94,11 +94,9 @@ class Interpreter(val settings: Settings, out: PrintWriter)
/** Temporarily be quiet */
def beQuietDuring[T](operation: => T): T = {
val wasPrinting = printResults
- try {
+ ultimately(printResults = wasPrinting) {
printResults = false
operation
- } finally {
- printResults = wasPrinting
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index 392685c4c0..3d1bfd547a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -5,6 +5,7 @@
// $Id$
package scala.tools.nsc.interpreter
+import scala.util.control.Exception._
/** Reads lines from an input stream */
trait InteractiveReader {
@@ -14,14 +15,12 @@ trait InteractiveReader {
protected def readOneLine(prompt: String): String
val interactive: Boolean
- def readLine(prompt: String): String =
- try {
- readOneLine(prompt)
- }
- catch {
+ def readLine(prompt: String): String = {
+ def handler: Catcher[String] = {
case e: IOException if restartSystemCall(e) => readLine(prompt)
- case e => throw e
}
+ catching(handler) { readOneLine(prompt) }
+ }
// hack necessary for OSX jvm suspension because read calls are not restarted after SIGTSTP
private def restartSystemCall(e: Exception): Boolean =
@@ -31,6 +30,7 @@ trait InteractiveReader {
object InteractiveReader {
val msgEINTR = "Interrupted system call"
+ private val exes = List(classOf[Exception], classOf[NoClassDefFoundError])
def createDefault(): InteractiveReader = createDefault(null)
@@ -38,10 +38,8 @@ object InteractiveReader {
* library is available, but otherwise uses a <code>SimpleReader</code>.
*/
def createDefault(interpreter: Interpreter): InteractiveReader =
- try {
- new JLineReader(interpreter)
- } catch {
- case _: Exception | _: NoClassDefFoundError => new SimpleReader
- }
+ catching(exes: _*)
+ . opt (new JLineReader(interpreter))
+ . getOrElse (new SimpleReader)
}
diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala
index 491d11219c..49dad8cf9f 100644
--- a/src/library/scala/util/control/Exception.scala
+++ b/src/library/scala/util/control/Exception.scala
@@ -7,6 +7,7 @@ package scala.util.control
* <b>import</b> scala.util.control.Exception._
* <b>import</b> java.net._
*
+ * <b>val</b> s = "http://www.scala-lang.org/"
* <b>val</b> x1 = catching(classOf[MalformedURLException]) opt new URL(s)
* <b>val</b> x2 = catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)
* </pre>
@@ -17,6 +18,9 @@ import java.lang.reflect.InvocationTargetException
object Exception
{
+ // We get lots of crashes using this, so for now we just use Class[_]
+ // type ExClass = Class[_ <: Throwable]
+
type Catcher[+T] = PartialFunction[Throwable, T]
type ExceptionCatcher[+T] = PartialFunction[Exception, T]
@@ -51,17 +55,17 @@ object Exception
class Finally private[Exception](body: => Unit) extends Described {
protected val name = "Finally"
- def and(other: => Unit) = new Finally({ body ; other })
- def invoke() { body }
+ def and(other: => Unit): Finally = new Finally({ body ; other })
+ def invoke(): Unit = { body }
}
/** A container class for catch/finally logic. */
class Catch[+T] private[Exception](
private[Exception] val pf: Catcher[T],
- private[Exception] val fin: Finally)
+ private[Exception] val fin: Option[Finally])
extends Described
{
- def this(pf: Catcher[T]) = this(pf, noFinally)
+ def this(pf: Catcher[T]) = this(pf, None)
protected val name = "Catch"
/** Create a new Catch with additional exception handling logic. */
@@ -69,14 +73,17 @@ object Exception
def or[U >: T](other: Catch[U]): Catch[U] = or(other.pf)
/** Apply this catch logic to the supplied body. */
- def apply[U >: T](body: => U): U =
+ def apply[U >: T](body: => U): U = {
try { body }
catch { case e if pf.isDefinedAt(e) => pf(e) }
- finally { fin.invoke() }
+ finally { fin.map(_.invoke()) }
+ }
/* Create an empty Try container with this Catch and the supplied Finally */
- def andFinally(fin2: Finally): Catch[T] = new Catch(pf, fin and fin2)
- def andFinally(fin: => Unit): Catch[T] = andFinally(new Finally(fin))
+ def andFinally(body: => Unit): Catch[T] = fin match {
+ case None => new Catch(pf, Some(new Finally(body)))
+ case Some(f) => new Catch(pf, Some(f and body))
+ }
/** Apply this catch logic to the supplied body, mapping the result
* into Option[T] - None if any exception was caught, Some(T) otherwise.
@@ -108,63 +115,77 @@ object Exception
class Try[+T] private[Exception](body: => T, val catcher: Catch[T]) {
/** Execute "body" using catch/finally logic "catcher" */
def apply(): T = catcher(body)
- def apply[U >: T](body2: => U): U = catcher(body2)
+ def apply[U >: T](other: => U): U = catcher(other)
/** As apply, but map caught exceptions to None and success to Some(T) */
def opt(): Option[T] = catcher opt body
- def opt[U >: T](body2: => U): Option[U] = catcher opt body2
+ def opt[U >: T](other: => U): Option[U] = catcher opt other
/** As apply, but map caught exceptions to Left(ex) and success to Right(x) */
def either(): Either[Throwable, T] = catcher either body
- def either[U >: T](body2: => U): Either[Throwable, U] = catcher either body2
+ def either[U >: T](other: => U): Either[Throwable, U] = catcher either other
/** Create a new Try with the supplied body replacing the current body */
- def tryInstead[U >: T](body2: => U) = new Try(body2, catcher)
+ def tryInstead[U >: T](other: => U) = new Try(other, catcher)
/** Create a new Try with the supplied logic appended to the existing Catch logic. */
- def or[U >: T](pf2: Catcher[U]) = new Try(body, catcher or pf2)
+ def or[U >: T](pf: Catcher[U]) = new Try(body, catcher or pf)
/** Create a new Try with the supplied code appended to the existing Finally. */
- def andFinally(fin2: => Unit) = new Try(body, catcher andFinally fin2)
+ def andFinally(fin: => Unit) = new Try(body, catcher andFinally fin)
override def toString() = List("Try(<body>)", catcher.toString) mkString " "
}
- /** The empty Finally object. */
- final val noFinally = new Finally(()) withDesc "()"
-
- /** The empty Catch object. */
- final val noCatch: Catch[Nothing] = new Catch(
+ final val nothingCatcher: PartialFunction[Throwable, Nothing] =
new PartialFunction[Throwable, Nothing] {
def isDefinedAt(x: Throwable) = false
def apply(x: Throwable) = throw x
}
- ) withDesc "<nothing>"
+ /** The empty Catch object. */
+ final val noCatch: Catch[Nothing] = new Catch(nothingCatcher) withDesc "<nothing>"
/** Creates a Catch object which will catch any of the supplied exceptions.
* Since the returned Catch object has no specific logic defined and will simply
* rethrow the exceptions it catches, you will typically want to call "opt" or
* "either" on the return value, or assign custom logic by calling "withApply".
*/
- def catching[T](exceptions: Class[_ <: Throwable]*): Catch[T] =
+ def catching[T](exceptions: Class[_]*): Catch[T] =
new Catch(pfFromExceptions(exceptions : _*)) withDesc exceptions.map(_.getName).mkString(", ")
def catching[T](c: Catcher[T]): Catch[T] = new Catch(c)
/** Creates a Catch object which catches and ignores any of the supplied exceptions. */
- def ignoring(exceptions: Class[_ <: Throwable]*): Catch[Unit] =
+ def ignoring(exceptions: Class[_]*): Catch[Unit] =
catching(exceptions: _*) withApply (_ => ())
/** Creates a Catch object which maps all the supplied exceptions to 'None'. */
- def failing[T](exceptions: Class[_ <: Throwable]*): Catch[Option[T]] =
+ def failing[T](exceptions: Class[_]*): Catch[Option[T]] =
catching(exceptions: _*) withApply (_ => None)
- def handling[T](exceptions: Class[_ <: Throwable]*) = new {
+ /** Returns a partially constructed Catch object, which you must give
+ * an exception handler function as an argument to "by". Example:
+ * handling(ex1, ex2) by (_.printStackTrace)
+ */
+ def handling[T](exceptions: Class[_]*) = new {
def by(f: (Throwable) => T): Catch[T] = catching(exceptions: _*) withApply f
}
+ /** Returns a Catch object with no catch logic and the argument as Finally. */
+ def ultimately[T](body: => Unit): Catch[T] = noCatch andFinally body
+
+ /** Experimental */
+ def saving[A](oldVal: A, newVal: A, setter: (A) => Unit): Catch[Nothing] = {
+ new Catch(nothingCatcher, Some(new Finally(setter(oldVal)))) {
+ override def apply[U](body: => U): U = {
+ setter(newVal)
+ super.apply(body)
+ }
+ }
+ }
+
/** Creates a Catch object which unwraps any of the supplied exceptions. */
- def unwrapping[T](exceptions: Class[_ <: Throwable]*): Catch[T] = {
+ def unwrapping[T](exceptions: Class[_]*): Catch[T] = {
def unwrap(x: Throwable): Throwable =
if (wouldMatch(x, exceptions) && x.getCause != null) unwrap(x.getCause)
else x
@@ -176,7 +197,7 @@ object Exception
private def wouldMatch(x: AnyRef, classes: collection.Sequence[Class[_]]): Boolean =
classes exists (_ isAssignableFrom x.getClass)
- private def pfFromExceptions(exceptions: Class[_ <: Throwable]*) =
+ private def pfFromExceptions(exceptions: Class[_]*) =
new PartialFunction[Throwable, Nothing] {
def apply(x: Throwable) = throw x
def isDefinedAt(x: Throwable) = wouldMatch(x, exceptions)