如何获得AST表示的值的类型?

时间:2019-04-22 22:09:34

标签: scala scala-macros scala-quasiquotes scala-meta

我正在尝试编写以下内容:

https://{your-tenant-name}.b2clogin.com/tfp/{your-tenant-name}.onmicrosoft.com/{your-policy-name}/v2.0/.well-known/openid-configuration

我需要捕获import scala.reflect.runtime.universe._ val value: Tree = /* some AST */ val tpe = typeOf(value) // This should be the result type of the AST. // This is pseudocode. What should // actually go on this line? q""" type U = $tpe val v: U = $value """ 中AST value表示的值的类型,并将其分配给tpe。如何做到这一点?

编辑:这里不能为U提供类型注释并通过准引用对其进行匹配。用例是无形的extensible record,它具有诸如value之类的复杂类型,例如String with labelled.KeyTag[1, String] :: Long with labelled.KeyTag[three, Long] :: HNil。另外,val ls = (1 ->> "two") :: ("three" ->> 4L) :: HNil AST是通过编程生成的,而不是文字。

2 个答案:

答案 0 :(得分:2)

获取一个ToolBox,使用它对value进行类型检查,并询问带注释的树的类型。

import scala.runtime.reflect.currentMirror
val toolbox = currentMirror.mkToolBox()
val tpe = TypeTree(toolbox.typecheck(value).tpe)

您编写的代码表明您正在运行时执行此操作。您在注释中陈述的用例使您看起来好像在编译时宏中。在这种情况下,请在typecheck中使用类似的Context方法。否则将不会进行类型检查; value可能是错误的Tree的{​​{1}},表示由Universe创建的新编译器实例在当前程序的上下文中运行的事实(是一个编译器),而ToolBox所代表的反射是关于包含编译器操纵的代码的未来上下文的。

答案 1 :(得分:0)

尝试在$tpt中使用q"$mods val $tname: $tpt = $expr"

val t: Tree = reify {
  val value: Int = 3
}.tree

val tpe = t match {
  case q"{$mods val $tname: $tpt = $expr; $_}" => tpt
} // Int

https://docs.scala-lang.org/overviews/quasiquotes/syntax-summary.html#definitions

相关问题:How does one use quasiquotes to obtain the type of a value?