在 REPL 中将代码扩展为 Raw AST Scala 3
Expand Code to Raw AST Scala 3 in the REPL
我目前正在进行大量的编译器研究。这不仅需要编写编译器插件,还需要修改 dotty 编译器,从解析器到类型器。因此,我需要不断查看原始 AST 以勾勒出必要的转换。
在 Scala 2 中,反射库提供了以下功能:
val expression = ....
val tree = reify{expression}.tree
showRaw(tree)
现在据我了解from the docs,最后一步已被Printer.TreeStructure.show(tree)
取代
但是,我在元编程文档中找不到任何替代 reify
的内容。现在我显然可以在 Scala 程序中使用各种元编程技术并将树打印到 stdout
,但与在 REPL 中扩展以进行快速手动验证相比,这是一个非常耗时的过程。
有没有办法在 Scala 3 REPL 中做到这一点?
您可以在项目中定义自己的reify
import scala.quoted.*
object App {
inline def reify(inline a: Any) = ${reifyImpl('a)}
def reifyImpl(a: Expr[Any])(using Quotes): Expr[String] = {
import quotes.reflect.*
Literal(StringConstant(Printer.TreeStructure.show(a.asTerm))).asExprOf[String]
}
}
并在 REPL 中使用它
sbt console
scala> import App.reify
scala> reify{ class A }
val res0: String = Inlined(None, Nil, Block(List(ClassDef("A", DefDef("<init>", List(TermParamClause(Nil)), Inferred(), None), List(Apply(Select(New(Inferred()), "<init>"), Nil)), None, Nil)), Literal(UnitConstant())))
不幸的是,直接在 REPL 中定义 reify
似乎不起作用
scala> import scala.quoted.*; inline def reify(inline a: Any) = ${reifyImpl('a)}; def reifyImpl(a: Expr[Any])(using Quotes): Expr[String] = {import quotes.reflect.*; Literal(StringConstant(Printer.TreeStructure.show(a.asTerm))).asExprOf[String]}
def reify(a: Any): String
def reifyImpl
(a: quoted.Expr[Any])(using x: quoted.Quotes): quoted.Expr[String]
scala> reify{class A}
-- Error:
1 |reify{class A}
|^^^^^^^^^^^^^^
|Failed to evaluate macro.
| Caused by class java.lang.ClassNotFoundException: rs$line
| java.lang.ClassLoader.loadClass(ClassLoader.java:418)
| java.lang.ClassLoader.loadClass(ClassLoader.java:351)
| dotty.tools.repl.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:55)
| dotty.tools.dotc.transform.Splicer$Interpreter.loadReplLineClass(Splicer.scala:402)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretedStaticMethodCall(Splicer.scala:354)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree(Splicer.scala:260)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree$$anonfun(Splicer.scala:281)
|
| This location contains code that was inlined from rs$line:1
我目前正在进行大量的编译器研究。这不仅需要编写编译器插件,还需要修改 dotty 编译器,从解析器到类型器。因此,我需要不断查看原始 AST 以勾勒出必要的转换。
在 Scala 2 中,反射库提供了以下功能:
val expression = ....
val tree = reify{expression}.tree
showRaw(tree)
现在据我了解from the docs,最后一步已被Printer.TreeStructure.show(tree)
但是,我在元编程文档中找不到任何替代 reify
的内容。现在我显然可以在 Scala 程序中使用各种元编程技术并将树打印到 stdout
,但与在 REPL 中扩展以进行快速手动验证相比,这是一个非常耗时的过程。
有没有办法在 Scala 3 REPL 中做到这一点?
您可以在项目中定义自己的reify
import scala.quoted.*
object App {
inline def reify(inline a: Any) = ${reifyImpl('a)}
def reifyImpl(a: Expr[Any])(using Quotes): Expr[String] = {
import quotes.reflect.*
Literal(StringConstant(Printer.TreeStructure.show(a.asTerm))).asExprOf[String]
}
}
并在 REPL 中使用它
sbt console
scala> import App.reify
scala> reify{ class A }
val res0: String = Inlined(None, Nil, Block(List(ClassDef("A", DefDef("<init>", List(TermParamClause(Nil)), Inferred(), None), List(Apply(Select(New(Inferred()), "<init>"), Nil)), None, Nil)), Literal(UnitConstant())))
不幸的是,直接在 REPL 中定义 reify
似乎不起作用
scala> import scala.quoted.*; inline def reify(inline a: Any) = ${reifyImpl('a)}; def reifyImpl(a: Expr[Any])(using Quotes): Expr[String] = {import quotes.reflect.*; Literal(StringConstant(Printer.TreeStructure.show(a.asTerm))).asExprOf[String]}
def reify(a: Any): String
def reifyImpl
(a: quoted.Expr[Any])(using x: quoted.Quotes): quoted.Expr[String]
scala> reify{class A}
-- Error:
1 |reify{class A}
|^^^^^^^^^^^^^^
|Failed to evaluate macro.
| Caused by class java.lang.ClassNotFoundException: rs$line
| java.lang.ClassLoader.loadClass(ClassLoader.java:418)
| java.lang.ClassLoader.loadClass(ClassLoader.java:351)
| dotty.tools.repl.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:55)
| dotty.tools.dotc.transform.Splicer$Interpreter.loadReplLineClass(Splicer.scala:402)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretedStaticMethodCall(Splicer.scala:354)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree(Splicer.scala:260)
| dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree$$anonfun(Splicer.scala:281)
|
| This location contains code that was inlined from rs$line:1