summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristopher Vogt <github.com.nsp@cvogt.org>2012-04-14 00:57:09 +0200
committerChristopher Vogt <github.com.nsp@cvogt.org>2012-04-14 01:29:08 +0200
commit53a0e803f03fe715c214c01c03f82baa19d7f2c2 (patch)
treecdb45306f7641606bc35633893283aa0390c8b60 /src
parent020043c3a6e19718175cbbfe76cedab8db7e0498 (diff)
downloadscala-53a0e803f03fe715c214c01c03f82baa19d7f2c2.tar.gz
scala-53a0e803f03fe715c214c01c03f82baa19d7f2c2.tar.bz2
scala-53a0e803f03fe715c214c01c03f82baa19d7f2c2.zip
implemented DynamicProxy as portrayed by the Scala reflection team
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/reflect/DynamicProxy.scala67
-rwxr-xr-xsrc/library/scala/reflect/api/Names.scala4
2 files changed, 69 insertions, 2 deletions
diff --git a/src/library/scala/reflect/DynamicProxy.scala b/src/library/scala/reflect/DynamicProxy.scala
new file mode 100644
index 0000000000..8449cb4063
--- /dev/null
+++ b/src/library/scala/reflect/DynamicProxy.scala
@@ -0,0 +1,67 @@
+package scala.reflect
+/**
+ * A dynamic proxy which redirect method calls and attribute access to a given
+ * target object at runtime using reflection.
+ * A usage example can be found in test/files/run/dynamic-reflect.scala
+ * Not supported (yet):
+ * - implicit conversions and parameters
+ * - multiple arguments lists
+ * - explicit type arguments
+ */
+trait DynamicProxy extends Dynamic{
+ val dynamicProxyTarget : AnyRef
+
+ import scala.reflect.mirror._
+ /**
+ * boxing to preserve information on primitive types for overloading resolution
+ */
+ case class DynamicReflectBoxed( class_ : Class[_], value: Any )
+ object DynamicReflectBoxed{
+ implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v )
+ }
+
+ def selectDynamic( method:String ) = {
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
+ invoke( dynamicProxyTarget, symbol )()
+ }
+
+ def updateDynamic( method:String )( value : Any ) = {
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method+"_=").encodedName )
+ invoke( dynamicProxyTarget, symbol )( value )
+ }
+
+ def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any
+ = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* )
+
+ def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = {
+ val class_ = dynamicProxyTarget.getClass
+ var i = 0
+ val toolbox = mkToolBox(mkConsoleReporter(),"")
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
+ if(args.size == 0){
+ invoke( dynamicProxyTarget, symbol )()
+ } else {
+ val call =
+ Apply(
+ Select(
+ TypeApply(
+ Select(
+ Select(
+ Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this, null))
+ , newTermName("dynamicProxyTarget")
+ ),
+ newTermName("asInstanceOf") )
+ , List(TypeTree().setType(classToType(class_)))
+ )
+ ,newTermName(method).encodedName
+ )
+ ,args.map{ case(name,box) =>
+ val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value, null))
+ if( name == "" ) value
+ else AssignOrNamedArg( Ident(name), value )
+ }.toList
+ )
+ toolbox.runExpr( call )
+ }
+ }
+}
diff --git a/src/library/scala/reflect/api/Names.scala b/src/library/scala/reflect/api/Names.scala
index c72774dfc7..d92d056751 100755
--- a/src/library/scala/reflect/api/Names.scala
+++ b/src/library/scala/reflect/api/Names.scala
@@ -34,12 +34,12 @@ trait Names {
def toTypeName: TypeName
/** Replaces all occurrences of $op_names in this name by corresponding operator symbols.
- * Example: `foo_+=` becomes `foo_$plus$eq`.
+ * Example: `foo_$plus$eq` becomes `foo_+=`
*/
def decoded: String
/** Replaces all occurrences of operator symbols in this name by corresponding $op_names.
- * Example: `foo_$plus$eq` becomes `foo_+=`
+ * Example: `foo_+=` becomes `foo_$plus$eq`.
*/
def encoded: String