From 69feaa89167ebeb708535dd4abf3a79a410130f0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 7 Jan 2017 14:47:18 +0700 Subject: Change scheme to use Selectable Use base types instead of implicits. This is more robust in the presence of type abstraction. --- library/src/scala/Projector.scala | 10 ---- library/src/scala/Selectable.scala | 8 ++++ library/src/scala/reflect/Projector.scala | 71 ----------------------------- library/src/scala/reflect/Selectable.scala | 73 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 81 deletions(-) delete mode 100644 library/src/scala/Projector.scala create mode 100644 library/src/scala/Selectable.scala delete mode 100644 library/src/scala/reflect/Projector.scala create mode 100644 library/src/scala/reflect/Selectable.scala (limited to 'library') diff --git a/library/src/scala/Projector.scala b/library/src/scala/Projector.scala deleted file mode 100644 index cff73f84d..000000000 --- a/library/src/scala/Projector.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scala -import scala.reflect.ClassTag -import scala.annotation.implicitNotFound - -@implicitNotFound("no projector instance found to implement reflective access to structural type ${T}") -trait Projector[-T] extends Any { - def get(receiver: T, name: String): Any - def getMethod(receiver: T, name: String, paramClasses: ClassTag[_]*): Any = - new UnsupportedOperationException("getMethod") -} diff --git a/library/src/scala/Selectable.scala b/library/src/scala/Selectable.scala new file mode 100644 index 000000000..c5c714ca9 --- /dev/null +++ b/library/src/scala/Selectable.scala @@ -0,0 +1,8 @@ +package scala +import scala.reflect.ClassTag + +trait Selectable extends Any { + def selectDynamic(name: String): Any + def selectDynamicMethod(name: String, paramClasses: ClassTag[_]*): Any = + new UnsupportedOperationException("selectDynamicMethod") +} diff --git a/library/src/scala/reflect/Projector.scala b/library/src/scala/reflect/Projector.scala deleted file mode 100644 index b5732ee17..000000000 --- a/library/src/scala/reflect/Projector.scala +++ /dev/null @@ -1,71 +0,0 @@ -package scala.reflect - -class Projector extends scala.Projector[Any] { - import Projector._ - def get(receiver: Any, name: String): Any = { - val rcls = receiver.getClass - try { - val fld = rcls.getField(name) - fld.get(receiver) - } - catch { - case ex: NoSuchFieldError => - getMethod(receiver, name).asInstanceOf[() => Any]() - } - } - - override def getMethod(receiver: Any, name: String, paramTypes: ClassTag[_]*): Any = { - val rcls = receiver.getClass - val paramClasses = paramTypes.map(_.runtimeClass) - val mth = rcls.getMethod(name, paramClasses: _*) - paramTypes.length match { - case 0 => () => - mth.invoke(receiver) - case 1 => (x0: Any) => - mth.invoke(receiver, x0.asInstanceOf[Object]) - case 2 => (x0: Any, x1: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object]) - case 3 => (x0: Any, x1: Any, x2: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object], - x2.asInstanceOf[Object]) - case 4 => (x0: Any, x1: Any, x2: Any, x3: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object], - x2.asInstanceOf[Object], - x3.asInstanceOf[Object]) - case 5 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object], - x2.asInstanceOf[Object], - x3.asInstanceOf[Object], - x4.asInstanceOf[Object]) - case 6 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object], - x2.asInstanceOf[Object], - x3.asInstanceOf[Object], - x4.asInstanceOf[Object], - x5.asInstanceOf[Object]) - case 7 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any, x6: Any) => - mth.invoke(receiver, - x0.asInstanceOf[Object], - x1.asInstanceOf[Object], - x2.asInstanceOf[Object], - x3.asInstanceOf[Object], - x4.asInstanceOf[Object], - x5.asInstanceOf[Object], - x6.asInstanceOf[Object]) - } - } -} - -object Projector { - implicit val reflectiveProjector: scala.Projector[Any] = new Projector -} \ No newline at end of file diff --git a/library/src/scala/reflect/Selectable.scala b/library/src/scala/reflect/Selectable.scala new file mode 100644 index 000000000..0dbdbc293 --- /dev/null +++ b/library/src/scala/reflect/Selectable.scala @@ -0,0 +1,73 @@ +package scala.reflect + +class Selectable(val receiver: Any) extends AnyVal with scala.Selectable { + def selectDynamic(name: String): Any = { + val rcls = receiver.getClass + try { + val fld = rcls.getField(name) + fld.get(receiver) + } + catch { + case ex: NoSuchFieldError => + selectDynamicMethod(name).asInstanceOf[() => Any]() + } + } + + override def selectDynamicMethod(name: String, paramTypes: ClassTag[_]*): Any = { + val rcls = receiver.getClass + val paramClasses = paramTypes.map(_.runtimeClass) + val mth = rcls.getMethod(name, paramClasses: _*) + paramTypes.length match { + case 0 => () => + mth.invoke(receiver) + case 1 => (x0: Any) => + mth.invoke(receiver, x0.asInstanceOf[Object]) + case 2 => (x0: Any, x1: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object]) + case 3 => (x0: Any, x1: Any, x2: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object], + x2.asInstanceOf[Object]) + case 4 => (x0: Any, x1: Any, x2: Any, x3: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object], + x2.asInstanceOf[Object], + x3.asInstanceOf[Object]) + case 5 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object], + x2.asInstanceOf[Object], + x3.asInstanceOf[Object], + x4.asInstanceOf[Object]) + case 6 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object], + x2.asInstanceOf[Object], + x3.asInstanceOf[Object], + x4.asInstanceOf[Object], + x5.asInstanceOf[Object]) + case 7 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any, x6: Any) => + mth.invoke(receiver, + x0.asInstanceOf[Object], + x1.asInstanceOf[Object], + x2.asInstanceOf[Object], + x3.asInstanceOf[Object], + x4.asInstanceOf[Object], + x5.asInstanceOf[Object], + x6.asInstanceOf[Object]) + } + } +} + +object Selectable { + implicit def reflectiveSelectable(receiver: Any): scala.Selectable = receiver match { + case receiver: scala.Selectable => receiver + case _ => new Selectable(receiver) + } +} -- cgit v1.2.3