From aa6ebe938639f07dd6f5612e645f1449f37a86eb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 5 Jan 2017 16:02:09 +0700 Subject: Implement structural type member access New scheme for implementing structural type member access. --- library/src/scala/Projector.scala | 10 +++++ library/src/scala/reflect/Projector.scala | 71 +++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 library/src/scala/Projector.scala create mode 100644 library/src/scala/reflect/Projector.scala (limited to 'library') diff --git a/library/src/scala/Projector.scala b/library/src/scala/Projector.scala new file mode 100644 index 000000000..cff73f84d --- /dev/null +++ b/library/src/scala/Projector.scala @@ -0,0 +1,10 @@ +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/reflect/Projector.scala b/library/src/scala/reflect/Projector.scala new file mode 100644 index 000000000..68240da76 --- /dev/null +++ b/library/src/scala/reflect/Projector.scala @@ -0,0 +1,71 @@ +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 def reflectiveProjector: scala.Projector[Any] = new Projector +} \ No newline at end of file -- cgit v1.2.3