1

「アイテム」の特性と、それらのアイテムの「コンテナ」の別の特性があるとします。

sealed trait Item
case class Marble() extends Item
case class Book() extends Item

sealed trait Container[Item]
case object Pouch extends Container[Marble]
case object Shelf extends Container[Book]

上記の型情報を使用して、マクロとランタイム リフレクションを介してマップを作成したいと思います。

// Map(classOf[Marble] -> Pouch, classOf[Book] -> Shelf)
val itemToContainer = typeParamMap[Container[_], Item](Pouch, Shelf)

これは私の試みで、うまくコンパイルされ、TypeTags のリストを返すだけの中間形式で動作します:

object Macros {
  def getTag[T](implicit ttag: ru.TypeTag[T]) = ttag

  def getBaseParam(child: ru.Type, base: ru.Symbol, paramBase: ru.Symbol) =
    child.baseType(base)
      .find(_.baseClasses.contains(paramBase))
      .get
      .typeSymbol
      .asClass // TODO how to get java.lang.Class from here?

  def typeParamMapImpl[B, P](c: Context)(children: c.Expr[B]*)(baseTag: c.Expr[ru.WeakTypeTag[B]], paramTag: c.Expr[ru.WeakTypeTag[P]]) = {
    import c.universe._

    val getTagTree = Select(Ident(newTermName("Macros")), "getTag")
    val typeTags = c.Expr[List[ru.TypeTag[_]]](Apply(reify(List).tree, children.map( t =>
      c.Expr(TypeApply(getTagTree, List(t.tree))).tree
    ).toList))

    reify {
      typeTags.splice.map { child =>
        getBaseParam(child.tpe, baseTag.splice.tpe.typeSymbol, paramTag.splice.tpe.typeSymbol) -> child.tpe
      }.toMap
    }
  }

  def typeParamMap[B, P](children: B*)(implicit baseTag: ru.WeakTypeTag[B], paramTag: ru.WeakTypeTag[P]) = macro Macros.typeParamMapImpl[B, P]
}

ただし、これを呼び出してコンパイルしようとすると、大きなコンパイラ エラーが発生します: https://gist.github.com/4647812

誰でも問題を見つけることができますか、またはこれについてのより良い方法を提案できますか?

ありがとう!

4

0 に答える 0