the great beautification

- reify() all trees, no bricolage
- use rediscovered c.TypeTag factory to splice in calculated types
- give meaningful names to type parameters and humunguosly explode val
  names
This commit is contained in:
Roland 2013-01-25 22:00:11 +01:00
parent e55e57060b
commit f5934b9cca
7 changed files with 99 additions and 120 deletions

View file

@ -87,17 +87,20 @@ 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))
}
}
/*
* HORRIBLE HACK AHEAD
@ -105,7 +108,7 @@ trait Channels[P <: ChannelList, C <: ChannelList] extends Actor {
* Id 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

View file

@ -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]]

View file

@ -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))))))
}
}

View file

@ -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 ", "}")
}
}

View file

@ -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)

View file

@ -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]])
}
}

View file

@ -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 _