[英]Writing a pattern matching macro
I need some help writing a macro that produces a pattern match. 我需要一些帮助来编写一个产生模式匹配的宏。
This is as far as I got: 这是我得到的:
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 =>
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]
}
Here is an example: 这是一个例子:
sealed trait Foo
case class Bar() extends Foo
case class Baz() extends Foo
object FooFmt extends SealedTraitFormat[Foo] {
val test = writes(Bar())
}
The current error is: 目前的错误是:
[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] ^
(note that play.api.libs.json
is my package, so that's correct). (注意
play.api.libs.json
是我的包,所以这是正确的)。 I'm not sure what to make of this error... 我不知道该怎么做这个错误......
The expanded macro should look like this 扩展的宏应该如下所示
def writes(value: Foo): JsValue = value match {
case x: Bar => ???
case x: Baz => ???
}
It appears to me, that it probably looks like case x: Class[Bar] => ???
在我看来,它可能看起来像
case x: Class[Bar] => ???
now. 现在。 So my guess is I need to use
reifyType
instead of reifyRuntimeClass
. 所以我的猜测是我需要使用
reifyType
而不是reifyRuntimeClass
。 Basically, how do I get the tree from a Type
? 基本上,我如何从
Type
获取树?
The following seems to work, or at least compile: 以下似乎工作,或至少编译:
val cases = subs.toList.map { sub =>
val pat = Bind(newTermName("x"), Typed(Ident("_"), Ident(sub.asClass)))
val body = reify(???).tree // TODO
CaseDef(pat, body)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.