I am having trouble constructing correct Scala (2.13.3) syntax trees at runtime. Suppose we define the following class.
class Foo(x: Int)
I would like to construct the syntax tree for the following line of code.
new Foo(1)
For reference, we can generate the correct syntax tree using ru.reify
. We can also type check this tree to confirm it is valid.
val expectedTree = ru.reify {
new Foo(1)
}
println(ru.showRaw(expectedTree))
// Apply(
// Select(
// New(Ident(my.package.Foo)), <-- What does Ident hold here?
// termNames.CONSTRUCTOR
// ),
// List(
// Literal(Constant(1))
// )
// )
val toolbox = mirror.mkToolBox()
toolbox.typecheck(expectedTree).tpe
// my.package.Foo
However, if I cannot figure out how to properly code the same syntax tree from scratch. Below is my initial attempt. I also tried the same thing with TermName
instead of TypeName
and see the same result.
import ru._
val actualTree = Apply(
Select(
New(Ident(TypeName("my.package.Foo"))),
termNames.CONSTRUCTOR
),
List(
Literal(Constant(1))
)
)
println(ru.showRaw(actualTree))
// Apply(
// Select(
// New(Ident(TypeName("my.package.Foo"))), <-- Ident holds a TypeName
// termNames.CONSTRUCTOR
// ),
// List(
// Literal(Constant(1))
// )
// )
val toolbox = mirror.mkToolBox()
toolbox.typecheck(actualTree).tpe
// ToolBoxError: reflective typecheck has failed: not found: type my.package.Foo
The actualTree
is obviously not valid because it doesn't type check. If we inspect the printed output, we can see that the Ident
appears to be different between the expectedTree
and the actualTree
.
From the API, it seems like Ident
must hold a Name
object, but I cannot figure out which kind of name is required here. Furthermore, the printed output of the expectedTree
doesn't indicate that the Ident
is holding a Name
at all. Is this some other kind of Ident
? What would the proper code be to manually construct the AST of new Foo(1)
?
Aucun commentaire:
Enregistrer un commentaire