From 5fb68614da51c601e354d13ae123820b355594d0 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 19 Oct 2011 21:31:55 +0000 Subject: AbstractPartialFunction. Contributed by Todd Vierling with minor mods by extempore. This is an obvious extension of AbstractFunctionN which I had some issue making work at the time. Sounds kind of pitiful given that the compiler patch is about two lines, but let's all agree to believe it was a different world then. This example program is impacted as follows: class A { def f: PartialFunction[Any, Int] = { case x: String => 1 } def g: PartialFunction[Any, Int] = f orElse { case x: List[_] => 2 } def h: PartialFunction[Any, Int] = g orElse { case x: Set[_] => 3 } } Before: 34943 bytes of bytecode After: 4217 bytes of bytecode A mere 88% reduction in size. "'Tis but a trifle!" Closes SI-5096, SI-5097. --- src/actors/scala/actors/Actor.scala | 2 +- src/actors/scala/actors/Future.scala | 2 +- src/actors/scala/actors/Reactor.scala | 3 +-- src/compiler/scala/reflect/internal/Definitions.scala | 1 + src/compiler/scala/tools/cmd/FromString.scala | 2 +- .../tools/nsc/interpreter/AbstractOrMissingHandler.scala | 2 +- src/compiler/scala/tools/nsc/matching/ParallelMatching.scala | 2 +- src/compiler/scala/tools/nsc/transform/UnCurry.scala | 1 + src/library/scala/Function.scala | 2 +- src/library/scala/PartialFunction.scala | 6 +++--- src/library/scala/runtime/AbstractPartialFunction.scala | 11 +++++++++++ src/library/scala/util/control/Exception.scala | 4 ++-- 12 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 src/library/scala/runtime/AbstractPartialFunction.scala (limited to 'src') diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala index ba4d90f0b3..b2cd69e914 100644 --- a/src/actors/scala/actors/Actor.scala +++ b/src/actors/scala/actors/Actor.scala @@ -246,7 +246,7 @@ object Actor extends Combinators { rawSelf.react(new RecursiveProxyHandler(rawSelf, f)) private class RecursiveProxyHandler(a: ReplyReactor, f: PartialFunction[Any, Unit]) - extends PartialFunction[Any, Unit] { + extends scala.runtime.AbstractPartialFunction[Any, Unit] { def isDefinedAt(m: Any): Boolean = true // events are immediately removed from the mailbox def apply(m: Any) { diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala index 735c13190b..4de73507fb 100644 --- a/src/actors/scala/actors/Future.scala +++ b/src/actors/scala/actors/Future.scala @@ -200,7 +200,7 @@ object Futures { Actor.timer.schedule(timerTask, timeout) def awaitWith(partFuns: Seq[PartialFunction[Any, Pair[Int, Any]]]) { - val reaction: PartialFunction[Any, Unit] = new PartialFunction[Any, Unit] { + val reaction: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] { 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 507c18d04e..8f0492f149 100644 --- a/src/actors/scala/actors/Reactor.scala +++ b/src/actors/scala/actors/Reactor.scala @@ -38,11 +38,10 @@ private[actors] object Reactor { } } - val waitingForNone = new PartialFunction[Any, Unit] { + val waitingForNone: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] { def isDefinedAt(x: Any) = false def apply(x: Any) {} } - } /** diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 2e64b0eb6d..c0b894dc01 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -186,6 +186,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // fundamental reference classes lazy val ScalaObjectClass = getMember(ScalaPackageClass, tpnme.ScalaObject) lazy val PartialFunctionClass = getClass("scala.PartialFunction") + lazy val AbstractPartialFunctionClass = getClass("scala.runtime.AbstractPartialFunction") lazy val SymbolClass = getClass("scala.Symbol") lazy val StringClass = getClass(sn.String) lazy val StringModule = StringClass.linkedClassOfClass diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index 3792c26c34..992530c767 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -14,7 +14,7 @@ import scala.reflect.OptManifest * example instances are in the companion object, but in general * either IntFromString will suffice or you'll want custom transformers. */ -abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] { +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 zero: T = apply("") diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala index 2f47685757..d21d67db6e 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interpreter -class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends PartialFunction[Throwable, T] { +class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends scala.runtime.AbstractPartialFunction[Throwable, T] { def isDefinedAt(t: Throwable) = t match { case _: AbstractMethodError => true case _: NoSuchMethodError => true diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 197839c7e0..b073bb3c96 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -422,7 +422,7 @@ trait ParallelMatching extends ast.TreeDSL // Should the given pattern join the expanded pivot in the success matrix? If so, // this partial function will be defined for the pattern, and the result of the apply // is the expanded sequence of new patterns. - lazy val successMatrixFn = new PartialFunction[Pattern, List[Pattern]] { + lazy val successMatrixFn = new scala.runtime.AbstractPartialFunction[Pattern, List[Pattern]] { private def seqIsDefinedAt(x: SequenceLikePattern) = (hasStar, x.hasStar) match { case (true, true) => true case (true, false) => pivotLen <= x.nonStarLength diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 864939ebfd..b15f73887a 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -247,6 +247,7 @@ abstract class UnCurry extends InfoTransform val anonClass = owner newAnonymousFunctionClass fun.pos setFlag (FINAL | SYNTHETIC | inConstructorFlag) def parents = if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe) + else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe) else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe) anonClass setInfo ClassInfoType(parents, new Scope, anonClass) diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala index 23224b27e8..f1e93d6c76 100644 --- a/src/library/scala/Function.scala +++ b/src/library/scala/Function.scala @@ -39,7 +39,7 @@ object Function { * f returns `Some(_)` and undefined where `f` returns `None`. * @see [[scala.PartialFunction#lift]] */ - def unlift[T, R](f: T => Option[R]): PartialFunction[T, R] = new PartialFunction[T, R] { + 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 override def lift: T => Option[R] = f diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala index 51bb3dc93e..69e4dab675 100644 --- a/src/library/scala/PartialFunction.scala +++ b/src/library/scala/PartialFunction.scala @@ -36,7 +36,7 @@ trait PartialFunction[-A, +B] extends (A => B) { * takes `x` to `this(x)` where `this` is defined, and to `that(x)` where it is not. */ def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = - new PartialFunction[A1, B1] { + new runtime.AbstractPartialFunction[A1, B1] { def isDefinedAt(x: A1): Boolean = PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x) def apply(x: A1): B1 = @@ -51,7 +51,7 @@ trait PartialFunction[-A, +B] extends (A => B) { * @return a partial function with the same domain as this partial function, which maps * arguments `x` to `k(this(x))`. */ - override def andThen[C](k: B => C) : PartialFunction[A, C] = new PartialFunction[A, C] { + 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 apply(x: A): C = k(PartialFunction.this.apply(x)) } @@ -82,7 +82,7 @@ trait PartialFunction[-A, +B] extends (A => B) { * @since 2.8 */ object PartialFunction { - private[this] final val empty_pf = new PartialFunction[Any, Nothing] { + private[this] final val empty_pf: PartialFunction[Any, Nothing] = new runtime.AbstractPartialFunction[Any, Nothing] { def isDefinedAt(x: Any) = false def apply(x: Any): Nothing = sys.error("undefined") override def orElse[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 new file mode 100644 index 0000000000..2f8b54356f --- /dev/null +++ b/src/library/scala/runtime/AbstractPartialFunction.scala @@ -0,0 +1,11 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.runtime + +abstract class AbstractPartialFunction[-T1, +R] extends AbstractFunction1[T1, R] with PartialFunction[T1, R] diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index c8470d2504..5fc938d18c 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -229,8 +229,8 @@ object Exception { private def wouldMatch(x: Throwable, classes: collection.Seq[Class[_]]): Boolean = classes exists (_ isAssignableFrom x.getClass) - private def pfFromExceptions(exceptions: Class[_]*) = - new PartialFunction[Throwable, Nothing] { + 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) } -- cgit v1.2.3