From 5fb26c6a889cf1609823338df8783bf880769b3f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 24 Nov 2011 09:25:00 +0000 Subject: [PATCH] Fast PartialFunction # orElse. --- src/actors/scala/actors/Actor.scala | 2 +- src/actors/scala/actors/Future.scala | 2 +- src/actors/scala/actors/Reactor.scala | 2 +- .../scala/reflect/internal/Flags.scala | 1 + src/compiler/scala/tools/cmd/FromString.scala | 10 ++++---- .../AbstractOrMissingHandler.scala | 2 +- .../tools/nsc/matching/ParallelMatching.scala | 2 +- src/library/scala/Function.scala | 2 +- src/library/scala/PartialFunction.scala | 7 +++--- .../runtime/AbstractPartialFunction.scala | 24 ++++++++++++------- .../scala/util/control/Exception.scala | 2 +- 11 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala index b2cd69e9145c..b746f6826826 100644 --- a/src/actors/scala/actors/Actor.scala +++ b/src/actors/scala/actors/Actor.scala @@ -247,7 +247,7 @@ object Actor extends Combinators { private class RecursiveProxyHandler(a: ReplyReactor, f: PartialFunction[Any, Unit]) extends scala.runtime.AbstractPartialFunction[Any, Unit] { - def isDefinedAt(m: Any): Boolean = + def _isDefinedAt(m: Any): Boolean = true // events are immediately removed from the mailbox def apply(m: Any) { if (f.isDefinedAt(m)) f(m) diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala index 4de73507fb6c..eec43013d355 100644 --- a/src/actors/scala/actors/Future.scala +++ b/src/actors/scala/actors/Future.scala @@ -201,7 +201,7 @@ object Futures { def awaitWith(partFuns: Seq[PartialFunction[Any, Pair[Int, Any]]]) { val reaction: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] { - def isDefinedAt(msg: Any) = msg match { + def _isDefinedAt(msg: Any) = msg match { case TIMEOUT => true case _ => partFuns exists (_ isDefinedAt msg) } diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala index 8f0492f14963..7d21e9f91ea2 100644 --- a/src/actors/scala/actors/Reactor.scala +++ b/src/actors/scala/actors/Reactor.scala @@ -39,7 +39,7 @@ private[actors] object Reactor { } val waitingForNone: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] { - def isDefinedAt(x: Any) = false + def _isDefinedAt(x: Any) = false def apply(x: Any) {} } } diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala index 209ca94e506a..50d5b5cb827d 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/compiler/scala/reflect/internal/Flags.scala @@ -96,6 +96,7 @@ class ModifierFlags { final val INTERFACE = 0x00000080 // symbol is an interface (i.e. a trait which defines only abstract methods) final val MUTABLE = 0x00001000 // symbol is a mutable variable. final val PARAM = 0x00002000 // symbol is a (value or type) parameter to a method + final val MACRO = 0x00008000 // symbol is a macro definition final val COVARIANT = 0x00010000 // symbol is a covariant type variable final val BYNAMEPARAM = 0x00010000 // parameter is by name diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index 992530c76707..e4504702d468 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -16,7 +16,7 @@ import scala.reflect.OptManifest */ abstract class FromString[+T](implicit m: OptManifest[T]) extends scala.runtime.AbstractPartialFunction[String, T] { def apply(s: String): T - def isDefinedAt(s: String): Boolean = true + def _isDefinedAt(s: String): Boolean = true def zero: T = apply("") def targetString: String = m.toString @@ -30,20 +30,20 @@ object FromString { /** Path related stringifiers. */ val ExistingFile: FromString[File] = new FromString[File] { - override def isDefinedAt(s: String) = toFile(s).isFile + override def _isDefinedAt(s: String) = toFile(s).isFile def apply(s: String): File = if (isDefinedAt(s)) toFile(s) else cmd.runAndExit(println("'%s' is not an existing file." format s)) } val ExistingDir: FromString[Directory] = new FromString[Directory] { - override def isDefinedAt(s: String) = toDir(s).isDirectory + override def _isDefinedAt(s: String) = toDir(s).isDirectory def apply(s: String): Directory = if (isDefinedAt(s)) toDir(s) else cmd.runAndExit(println("'%s' is not an existing directory." format s)) } def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] { private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory - override def isDefinedAt(s: String) = resolve(s).isDirectory + override def _isDefinedAt(s: String) = resolve(s).isDirectory def apply(s: String): Directory = if (isDefinedAt(s)) resolve(s) else cmd.runAndExit(println("'%s' is not an existing directory." format resolve(s))) @@ -65,7 +65,7 @@ object FromString { /** Implicit as the most likely to be useful as-is. */ implicit val IntFromString: FromString[Int] = new FromString[Int] { - override def isDefinedAt(s: String) = safeToInt(s).isDefined + override def _isDefinedAt(s: String) = safeToInt(s).isDefined def apply(s: String) = safeToInt(s).get def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None } } diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala index d21d67db6ef3..33ef4a432d6a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package interpreter class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends scala.runtime.AbstractPartialFunction[Throwable, T] { - def isDefinedAt(t: Throwable) = t match { + def _isDefinedAt(t: Throwable) = t match { case _: AbstractMethodError => true case _: NoSuchMethodError => true case _: MissingRequirementError => true diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 481a997c0001..c97d65c6bc7c 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -433,7 +433,7 @@ trait ParallelMatching extends ast.TreeDSL case (false, false) => pivotLen == x.nonStarLength } - def isDefinedAt(pat: Pattern) = pat match { + def _isDefinedAt(pat: Pattern) = pat match { case x: SequenceLikePattern => seqIsDefinedAt(x) case WildcardPattern() => true case _ => false diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala index f1e93d6c7602..4a10b657355d 100644 --- a/src/library/scala/Function.scala +++ b/src/library/scala/Function.scala @@ -41,7 +41,7 @@ object Function { */ def unlift[T, R](f: T => Option[R]): PartialFunction[T, R] = new runtime.AbstractPartialFunction[T, R] { def apply(x: T): R = f(x).get - def isDefinedAt(x: T): Boolean = f(x).isDefined + def _isDefinedAt(x: T): Boolean = f(x).isDefined override def lift: T => Option[R] = f } diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala index 254a610648a8..b2910c2278b3 100644 --- a/src/library/scala/PartialFunction.scala +++ b/src/library/scala/PartialFunction.scala @@ -41,7 +41,7 @@ trait PartialFunction[-A, +B] extends (A => B) { */ def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = new runtime.AbstractPartialFunction[A1, B1] { - def isDefinedAt(x: A1): Boolean = + def _isDefinedAt(x: A1): Boolean = PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x) def apply(x: A1): B1 = if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x) @@ -59,7 +59,7 @@ trait PartialFunction[-A, +B] extends (A => B) { * arguments `x` to `k(this(x))`. */ override def andThen[C](k: B => C) : PartialFunction[A, C] = new runtime.AbstractPartialFunction[A, C] { - def isDefinedAt(x: A): Boolean = PartialFunction.this.isDefinedAt(x) + def _isDefinedAt(x: A): Boolean = PartialFunction.this.isDefinedAt(x) def apply(x: A): C = k(PartialFunction.this.apply(x)) } @@ -90,7 +90,8 @@ trait PartialFunction[-A, +B] extends (A => B) { */ object PartialFunction { private[this] final val empty_pf: PartialFunction[Any, Nothing] = new runtime.AbstractPartialFunction[Any, Nothing] { - def isDefinedAt(x: Any) = false + def _isDefinedAt(x: Any) = false + override def isDefinedAt(x: Any) = false def apply(x: Any): Nothing = throw new MatchError(x) override def orElse[A1, B1](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = that override def orElseFast[A1, B1](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = that diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala index b188cbb37d73..f48d99f5af50 100644 --- a/src/library/scala/runtime/AbstractPartialFunction.scala +++ b/src/library/scala/runtime/AbstractPartialFunction.scala @@ -23,24 +23,30 @@ abstract class AbstractPartialFunction[-T1, +R] with PartialFunction[T1, R] with Cloneable { - private var fallBack: PartialFunction[T1 @uncheckedVariance, R @uncheckedVariance] = PartialFunction.empty + private var fallBackField: PartialFunction[T1 @uncheckedVariance, R @uncheckedVariance] = _ - override protected def missingCase(x: T1): R = synchronized { - fallBack(x) + def fallBack: PartialFunction[T1, R] = synchronized { + if (fallBackField == null) fallBackField = PartialFunction.empty + fallBackField } + override protected def missingCase(x: T1): R = fallBack(x) + // Question: Need to ensure that fallBack is overwritten before any access // Is the `synchronized` here the right thing to achieve this? // Is there a cheaper way? - override def orElseFast[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = { + override def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = { val result = this.clone.asInstanceOf[AbstractPartialFunction[A1, B1]] result.synchronized { - result.fallBack = this.fallBack orElseFast that + result.fallBackField = this.fallBackField orElse that result } } -/* - def isDefinedAt(x: T1): scala.Boolean = isDefinedAtCurrent(x) || fallBack.isDefinedAt(x) - def isDefinedAtCurrent(x: T1): scala.Boolean = false -*/ + + def isDefinedAt(x: T1): scala.Boolean = _isDefinedAt(x) || fallBack.isDefinedAt(x) + def _isDefinedAt(x: T1): scala.Boolean + } + + + diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index 5fc938d18c2f..5e3f8b6451f7 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -232,6 +232,6 @@ object Exception { private def pfFromExceptions(exceptions: Class[_]*): PartialFunction[Throwable, Nothing] = new scala.runtime.AbstractPartialFunction[Throwable, Nothing] { def apply(x: Throwable) = throw x - def isDefinedAt(x: Throwable) = wouldMatch(x, exceptions) + def _isDefinedAt(x: Throwable) = wouldMatch(x, exceptions) } }