diff --git a/akka-channels/src/main/scala/akka/channels/Channels.scala b/akka-channels/src/main/scala/akka/channels/Channels.scala index 65c9c9040c..cc1ea5115c 100644 --- a/akka-channels/src/main/scala/akka/channels/Channels.scala +++ b/akka-channels/src/main/scala/akka/channels/Channels.scala @@ -87,16 +87,19 @@ trait Channels[P <: ChannelList, C <: ChannelList] extends Actor { * } * }}} */ - def channel[T]: Channels[P, C]#Behaviorist[Nothing, T] = macro macros.Channel.impl[T, C, P] + def channel[T]: (Nothing ⇒ Unit) = macro macros.Channel.impl[ChannelList, ChannelList, T, C, P] - class Behaviorist[-R, Ch](tt: ru.TypeTag[Ch], wrapped: Boolean) { + def behaviorist[R, Ch: ru.TypeTag](wrapped: Boolean): (R ⇒ Unit) = new Behaviorist[R, Ch](wrapped) + private class Behaviorist[-R, Ch: ru.TypeTag](wrapped: Boolean) extends (R ⇒ Unit) { private def ff(recv: R): FF = if (wrapped) F1(recv.asInstanceOf[(WrappedMessage[ChannelList], ChannelRef[ChannelList]) ⇒ Unit]) else F2(recv.asInstanceOf[(Any, ChannelRef[ChannelList]) ⇒ Unit]) - def apply(recv: R): Unit = + def apply(recv: R): Unit = { + val tt = implicitly[ru.TypeTag[Ch]] behavior ++= (for (t ← inputChannels(ru)(tt.tpe)) yield tt.mirror.runtimeClass(t.widen) -> ff(recv)) + } } /* @@ -105,7 +108,7 @@ trait Channels[P <: ChannelList, C <: ChannelList] extends Actor { * I’d like to keep this a trait, but traits cannot have constructor * arguments, not even TypeTags. */ - protected var channelListTypeTag: TypeTag[C] = _ + var channelListTypeTag: TypeTag[C] = _ /** * Sort so that subtypes always precede their supertypes, but without diff --git a/akka-channels/src/main/scala/akka/channels/macros/Ask.scala b/akka-channels/src/main/scala/akka/channels/macros/Ask.scala index 2b0b30b040..a6129ffd77 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/Ask.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/Ask.scala @@ -14,51 +14,51 @@ import scala.reflect.api.{ TypeCreator } object Ask { import Helpers._ - def impl[A, T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = ChannelRef[T] - })(msg: c.Expr[M]): c.Expr[Future[A]] = { + def impl[ReturnT, Channel <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = ChannelRef[Channel] + })(msg: c.Expr[Msg]): c.Expr[Future[ReturnT]] = { import c.universe._ - val chT = weakTypeOf[T] - val msgT = weakTypeOf[M] - val out = replyChannels(c.universe)(chT, msgT) + val tpeChannel = weakTypeOf[Channel] + val tpeMsg = weakTypeOf[Msg] + val out = replyChannels(c.universe)(tpeChannel, tpeMsg) if (out.isEmpty) - abort(c, s"This ChannelRef does not support messages of type $msgT") + abort(c, s"This ChannelRef does not support messages of type $tpeMsg") - implicit val tA = weakTT[A](c)(c.universe.lub(out)) - reify(askOps[A](c.prefix.splice.actorRef, msg.splice)(imp[Timeout](c).splice)) + implicit val ttReturn = c.TypeTag[ReturnT](c.universe.lub(out)) + reify(askOps[ReturnT](c.prefix.splice.actorRef, msg.splice)(imp[Timeout](c).splice)) } - def opsImpl[A, T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = AnyOps[M] - })(channel: c.Expr[ChannelRef[T]]): c.Expr[Future[A]] = { + def opsImpl[ReturnT, Channel <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = AnyOps[Msg] + })(channel: c.Expr[ChannelRef[Channel]]): c.Expr[Future[ReturnT]] = { import c.universe._ - val chT = weakTypeOf[T] - val msgT = weakTypeOf[M] - val out = replyChannels(c.universe)(chT, msgT) + val tpeChannel = weakTypeOf[Channel] + val tpeMsg = weakTypeOf[Msg] + val out = replyChannels(c.universe)(tpeChannel, tpeMsg) if (out.isEmpty) - abort(c, s"This ChannelRef does not support messages of type $msgT") + abort(c, s"This ChannelRef does not support messages of type $tpeMsg") - implicit val tA = weakTT[A](c)(c.universe.lub(out)) - reify(askOps[A](channel.splice.actorRef, c.prefix.splice.value)(imp[Timeout](c).splice)) + implicit val ttReturn = c.TypeTag[ReturnT](c.universe.lub(out)) + reify(askOps[ReturnT](channel.splice.actorRef, c.prefix.splice.value)(imp[Timeout](c).splice)) } - def futureImpl[A, T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = FutureOps[M] - })(channel: c.Expr[ChannelRef[T]]): c.Expr[Future[A]] = { + def futureImpl[ReturnT, Channel <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = FutureOps[Msg] + })(channel: c.Expr[ChannelRef[Channel]]): c.Expr[Future[ReturnT]] = { import c.universe._ - val chT = weakTypeOf[T] - val msgT = weakTypeOf[M] - val reply = replyChannels(c.universe)(chT, msgT) match { - case Nil ⇒ abort(c, s"This ChannelRef does not support messages of type $msgT") + val tpeChannel = weakTypeOf[Channel] + val tpeMsg = weakTypeOf[Msg] + val reply = replyChannels(c.universe)(tpeChannel, tpeMsg) match { + case Nil ⇒ abort(c, s"This ChannelRef does not support messages of type $tpeMsg") case x :: Nil ⇒ x case xs ⇒ toChannels(c.universe)(xs) } - implicit val tA = weakTT[A](c)(reply) - reify(askFuture[M, A](channel.splice.actorRef, c.prefix.splice.future)(imp[Timeout](c).splice)) + implicit val ttReturn = c.TypeTag[ReturnT](reply) + reify(askFuture[Msg, ReturnT](channel.splice.actorRef, c.prefix.splice.future)(imp[Timeout](c).splice)) } @inline def askOps[T](target: ActorRef, msg: Any)(implicit t: Timeout): Future[T] = akka.pattern.ask(target, msg).asInstanceOf[Future[T]] diff --git a/akka-channels/src/main/scala/akka/channels/macros/Channel.scala b/akka-channels/src/main/scala/akka/channels/macros/Channel.scala index f5234778de..68ccec4dfb 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/Channel.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/Channel.scala @@ -1,8 +1,7 @@ package akka.channels.macros import akka.channels._ -import scala.reflect.runtime.{ universe ⇒ ru } -import ru.TypeTag +import scala.reflect.runtime.universe import scala.reflect.macros.Context import scala.reflect.api.Universe @@ -18,59 +17,41 @@ object Channel { * C is the channel list of the enclosing Channels * P is the parent channel list */ - def impl[T: c.WeakTypeTag, C <: ChannelList: c.WeakTypeTag, P <: ChannelList: c.WeakTypeTag]( + def impl[ReplyChannels <: ChannelList, MsgTChan <: ChannelList, MsgT: c.WeakTypeTag, MyChannels <: ChannelList: c.WeakTypeTag, ParentChannels <: ChannelList: c.WeakTypeTag]( c: Context { - type PrefixType = Channels[P, C] - }): c.Expr[Channels[P, C]#Behaviorist[Nothing, T]] = { + type PrefixType = Channels[ParentChannels, MyChannels] + }): c.Expr[(Nothing ⇒ Unit)] = { - val tT = c.weakTypeOf[T] - val tC = c.weakTypeOf[C] + val tpeMsgT = c.weakTypeOf[MsgT] + val tpeMyChannels = c.weakTypeOf[MyChannels] import c.universe._ - val undefined = missingChannels(c.universe)(tC, inputChannels(c.universe)(tT)) + val undefined = missingChannels(c.universe)(tpeMyChannels, inputChannels(c.universe)(tpeMsgT)) if (undefined.nonEmpty) { - c.error(c.enclosingPosition, s"no channel defined for types ${undefined mkString ", "}") - reify(null) + c.abort(c.enclosingPosition, s"no channel defined for types ${undefined mkString ", "}") } else { - checkUnique(c.universe)(tT, tC) foreach (c.error(c.enclosingPosition, _)) - val channels = toChannels(c.universe)(replyChannels(c.universe)(tC, tT)) - val (receive, wrapped) = - if (tT <:< typeOf[ChannelList]) { - appliedType(typeOf[Function2[_, _, _]].typeConstructor, List( - appliedType(typeOf[WrappedMessage[_]].typeConstructor, List(tT)), - appliedType(typeOf[ChannelRef[_]].typeConstructor, List(channels)), - typeOf[Unit])) -> true - } else { - appliedType(typeOf[Function2[_, _, _]].typeConstructor, List( - tT, - appliedType(typeOf[ChannelRef[_]].typeConstructor, List(channels)), - typeOf[Unit])) -> false + checkUnique(c.universe)(tpeMsgT, tpeMyChannels) foreach (c.error(c.enclosingPosition, _)) + val channels = toChannels(c.universe)(replyChannels(c.universe)(tpeMyChannels, tpeMsgT)) + val wrapped = tpeMsgT <:< typeOf[ChannelList] + implicit val ttMyChannels = c.TypeTag[MyChannels](tpeMyChannels) + implicit val ttReplyChannels = c.TypeTag[ReplyChannels](channels) + implicit val ttMsgT = c.TypeTag[MsgT](tpeMsgT) + implicit val ttMsgTChan = c.TypeTag[MsgTChan](tpeMsgT) // this is MsgT reinterpreted as <: ChannelList + val prepTree = reify(if (c.prefix.splice.channelListTypeTag == null) + c.prefix.splice.channelListTypeTag = universe.typeTag[MyChannels]) + if (wrapped) + reify { + prepTree.splice + c.prefix.splice.behaviorist[(WrappedMessage[MsgTChan], ChannelRef[ReplyChannels]) ⇒ Unit, MsgT]( + bool(c, wrapped).splice)(universe.typeTag[MsgT]) + } + else + reify { + prepTree.splice + c.prefix.splice.behaviorist[(MsgT, ChannelRef[ReplyChannels]) ⇒ Unit, MsgT]( + bool(c, wrapped).splice)(universe.typeTag[MsgT]) } - c.Expr( - Block(List( - If( - { - val cltt = c.Expr(Select(c.prefix.tree, "channelListTypeTag")) - reify(cltt.splice == null).tree - }, - Apply( - Select(c.prefix.tree, "channelListTypeTag_$eq"), - List(TypeApply( - Select(Select(Select(Select(Select(Ident("scala"), "reflect"), "runtime"), nme.PACKAGE), "universe"), "typeTag"), - List(TypeTree().setType(c.weakTypeOf[C]))))), - c.literalUnit.tree)), - Apply( - Select( - New(AppliedTypeTree(Select(c.prefix.tree, newTypeName("Behaviorist")), List( - TypeTree().setType(receive), - TypeTree().setType(tT)))), - nme.CONSTRUCTOR), - List( - TypeApply( - Select(Select(Select(Select(Select(Ident("scala"), "reflect"), "runtime"), nme.PACKAGE), "universe"), "typeTag"), - List(TypeTree().setType(tT))), - Literal(Constant(wrapped)))))) } } diff --git a/akka-channels/src/main/scala/akka/channels/macros/CreateChild.scala b/akka-channels/src/main/scala/akka/channels/macros/CreateChild.scala index 94b3ba8abc..1d38f4c52c 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/CreateChild.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/CreateChild.scala @@ -10,25 +10,26 @@ import akka.actor.Props object CreateChild { import Helpers._ - def impl[C <: ChannelList: c.WeakTypeTag, Pa <: ChannelList: c.WeakTypeTag, Ch <: ChannelList: c.WeakTypeTag]( + def impl[MyChannels <: ChannelList: c.WeakTypeTag, ParentChannels <: ChannelList: c.WeakTypeTag, ChildChannels <: ChannelList: c.WeakTypeTag]( c: Context { - type PrefixType = Channels[_, C] - })(factory: c.Expr[Channels[Pa, Ch]]): c.Expr[ChannelRef[Ch]] = { + type PrefixType = Channels[_, MyChannels] + })(factory: c.Expr[Channels[ParentChannels, ChildChannels]]): c.Expr[ChannelRef[ChildChannels]] = { import c.universe._ - if (weakTypeOf[Pa] =:= weakTypeOf[Nothing]) { + + if (weakTypeOf[ParentChannels] =:= weakTypeOf[Nothing]) { c.abort(c.enclosingPosition, "Parent argument must not be Nothing") } - if (weakTypeOf[Ch] =:= weakTypeOf[Nothing]) { + if (weakTypeOf[ChildChannels] =:= weakTypeOf[Nothing]) { c.abort(c.enclosingPosition, "channel list must not be Nothing") } - val missing = missingChannels(c.universe)(weakTypeOf[C], inputChannels(c.universe)(weakTypeOf[Pa])) + + val missing = missingChannels(c.universe)(weakTypeOf[MyChannels], inputChannels(c.universe)(weakTypeOf[ParentChannels])) if (missing.isEmpty) { - implicit val t = c.TypeTag[Ch](c.weakTypeOf[Ch]) - reify(new ChannelRef[Ch](c.prefix.splice.context.actorOf(Props(factory.splice)))) + implicit val t = c.TypeTag[ChildChannels](c.weakTypeOf[ChildChannels]) + reify(new ChannelRef[ChildChannels](c.prefix.splice.context.actorOf(Props(factory.splice)))) } else { - c.error(c.enclosingPosition, s"This actor cannot support a child requiring channels ${missing mkString ", "}") - reify(???) + c.abort(c.enclosingPosition, s"This actor cannot support a child requiring channels ${missing mkString ", "}") } } diff --git a/akka-channels/src/main/scala/akka/channels/macros/Helpers.scala b/akka-channels/src/main/scala/akka/channels/macros/Helpers.scala index 549640ce32..94b92040e6 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/Helpers.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/Helpers.scala @@ -25,13 +25,7 @@ object Helpers { c.Expr[T](TypeApply(Ident("implicitly"), List(TypeTree().setType(weakTypeOf[T])))) } - def weakTT[T](c: Context)(tpe: c.universe.Type): c.WeakTypeTag[T] = - c.universe.WeakTypeTag[T](c.mirror, new TypeCreator { - def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]) = { - val imp = m.universe.mkImporter(c.universe) - imp.importType(tpe) - } - }) + def bool(c: Context, b: Boolean): c.Expr[Boolean] = c.Expr[Boolean](c.universe.Literal(c.universe.Constant(b))) def checkUnique(u: Universe)(channel: u.Type, list: u.Type): Option[String] = { val channels = inputChannels(u)(list) groupBy (_.erasure) diff --git a/akka-channels/src/main/scala/akka/channels/macros/Narrow.scala b/akka-channels/src/main/scala/akka/channels/macros/Narrow.scala index 2f9f6d3db5..f4b74b49ad 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/Narrow.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/Narrow.scala @@ -9,16 +9,16 @@ import scala.reflect.api.Universe object Narrow { import Helpers._ - def impl[C <: ChannelList: c.WeakTypeTag, T <: ChannelList: c.WeakTypeTag]( + def impl[Desired <: ChannelList: c.WeakTypeTag, MyChannels <: ChannelList: c.WeakTypeTag]( c: Context { - type PrefixType = ChannelRef[T] - }): c.Expr[ChannelRef[C]] = { + type PrefixType = ChannelRef[MyChannels] + }): c.Expr[ChannelRef[Desired]] = { import c.{ universe ⇒ u } - narrowCheck(u)(u.weakTypeOf[T], u.weakTypeOf[C]) match { + narrowCheck(u)(u.weakTypeOf[MyChannels], u.weakTypeOf[Desired]) match { case Nil ⇒ // okay case err :: Nil ⇒ c.error(c.enclosingPosition, err) case list ⇒ c.error(c.enclosingPosition, list mkString ("multiple errors:\n - ", "\n - ", "")) } - u.reify(c.prefix.splice.asInstanceOf[ChannelRef[C]]) + u.reify(c.prefix.splice.asInstanceOf[ChannelRef[Desired]]) } } \ No newline at end of file diff --git a/akka-channels/src/main/scala/akka/channels/macros/Tell.scala b/akka-channels/src/main/scala/akka/channels/macros/Tell.scala index e01fd80266..4395cb77ef 100644 --- a/akka-channels/src/main/scala/akka/channels/macros/Tell.scala +++ b/akka-channels/src/main/scala/akka/channels/macros/Tell.scala @@ -14,40 +14,40 @@ import akka.dispatch.ExecutionContexts object Tell { import Helpers._ - def impl[T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = ChannelRef[T] - })(msg: c.Expr[M]): c.Expr[Unit] = { - val tT = c.universe.weakTypeOf[T] - val (tS, senderTree, sender) = getSenderChannel(c) + def impl[MyChannels <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = ChannelRef[MyChannels] + })(msg: c.Expr[Msg]): c.Expr[Unit] = { + val tpeMyChannels = c.universe.weakTypeOf[MyChannels] + val (tpeSender, senderTree, sender) = getSenderChannel(c) - verify(c)(senderTree, c.universe.weakTypeOf[M], tS, tT) + verify(c)(senderTree, c.universe.weakTypeOf[Msg], tpeSender, tpeMyChannels) c.universe.reify(c.prefix.splice.actorRef.tell(msg.splice, sender.splice)) } - def opsImpl[T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = AnyOps[M] - })(channel: c.Expr[ChannelRef[T]]): c.Expr[Unit] = { - val tT = c.universe.weakTypeOf[T] - val (tS, senderTree, sender) = getSenderChannel(c) + def opsImpl[MyChannels <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = AnyOps[Msg] + })(channel: c.Expr[ChannelRef[MyChannels]]): c.Expr[Unit] = { + val tpeMyChannels = c.universe.weakTypeOf[MyChannels] + val (tpeSender, senderTree, sender) = getSenderChannel(c) - verify(c)(senderTree, c.universe.weakTypeOf[M], tS, tT) + verify(c)(senderTree, c.universe.weakTypeOf[Msg], tpeSender, tpeMyChannels) c.universe.reify(channel.splice.actorRef.tell(c.prefix.splice.value, sender.splice)) } - def futureImpl[T <: ChannelList: c.WeakTypeTag, M: c.WeakTypeTag](c: Context { - type PrefixType = FutureOps[M] - })(channel: c.Expr[ChannelRef[T]]): c.Expr[Future[M]] = { - val tT = c.universe.weakTypeOf[T] - val (tS, senderTree, sender) = getSenderChannel(c) + def futureImpl[MyChannels <: ChannelList: c.WeakTypeTag, Msg: c.WeakTypeTag](c: Context { + type PrefixType = FutureOps[Msg] + })(channel: c.Expr[ChannelRef[MyChannels]]): c.Expr[Future[Msg]] = { + val tpeMyChannels = c.universe.weakTypeOf[MyChannels] + val (tpeSender, senderTree, sender) = getSenderChannel(c) - verify(c)(senderTree, c.universe.weakTypeOf[M], tS, tT) + verify(c)(senderTree, c.universe.weakTypeOf[Msg], tpeSender, tpeMyChannels) - c.universe.reify(pipeTo[M](c.prefix.splice, channel.splice, sender.splice)) + c.universe.reify(pipeTo[Msg](c.prefix.splice, channel.splice, sender.splice)) } - @inline def pipeTo[M](f: FutureOps[M], c: ChannelRef[_], snd: ActorRef): Future[M] = + @inline def pipeTo[Msg](f: FutureOps[Msg], c: ChannelRef[_], snd: ActorRef): Future[Msg] = f.future.andThen { case Success(s) ⇒ c.actorRef.tell(s, snd) case _ ⇒