title: Writing a pattern matching macro
body: <p>I need some help writing a macro that produces a pattern match.</p>
  
  <p>This is as far as I got:</p>
  
  <pre><code>import scala.reflect.macros.Context
  import language.experimental.macros
  
  trait JsValue
  
  object SealedTraitFormat {
    def writesImpl[A: c.WeakTypeTag](c: Context)(value: c.Expr[A]): c.Expr[JsValue] = {
      val aTpeW   = c.weakTypeOf[A]
      val aClazz  = aTpeW.typeSymbol.asClass
      require(aClazz.isSealed, s"Type $aTpeW is not sealed")
      val subs    = aClazz.knownDirectSubclasses
      require(subs.nonEmpty  , s"Type $aTpeW does not have known direct subclasses")
      import c.universe._
  
      val cases = subs.toList.map { sub =&gt;
        val pat   = Bind(newTermName("x"), Typed(Ident("_"),
          c.reifyRuntimeClass(sub.asClass.toType)))
        val body  = Ident("???") // TODO
        CaseDef(pat, body)
      }
      val m = Match(value.tree, cases)
      c.Expr[JsValue](m)
    }
  }
  trait SealedTraitFormat[A] {
    def writes(value: A): JsValue = macro SealedTraitFormat.writesImpl[A]
  }
  </code></pre>
  
  <p>Here is an example:</p>
  
  <pre><code>sealed trait Foo
  case class Bar() extends Foo
  case class Baz() extends Foo
  
  object FooFmt extends SealedTraitFormat[Foo] {
    val test = writes(Bar())
  }
  </code></pre>
  
  <p>The current error is:</p>
  
  <pre><code>[warn] .../FooTest.scala:8: fruitless type test: a value of type play.api.libs.json.Bar cannot also be a Class[play.api.libs.json.Bar]
  [warn]   val test = writes(Bar())
  [warn]                    ^
  [error] .../FooTest.scala:8: pattern type is incompatible with expected type;
  [error]  found   : Class[play.api.libs.json.Bar](classOf[play.api.libs.json.Bar])
  [error]  required: play.api.libs.json.Bar
  [error]   val test = writes(Bar())
  [error]                    ^
  </code></pre>
  
  <p>(note that <code>play.api.libs.json</code> is my package, so that's correct). I'm not sure what to make of this error...</p>
  
  <hr>
  
  <p>The expanded macro should look like this</p>
  
  <pre><code>def writes(value: Foo): JsValue = value match {
    case x: Bar =&gt; ???
    case x: Baz =&gt; ???
  }
  </code></pre>
  
  <p>It appears to me, that it probably looks like <code>case x: Class[Bar] =&gt; ???</code> now. So my guess is I need to use <code>reifyType</code> instead of <code>reifyRuntimeClass</code>. Basically, how do I get the tree from a <code>Type</code>?</p>