12

Back when reflection was still incipient, on the days of Scala 2.10.0 milestones, I asked a question about how could I use it to see the trees of code snippets from REPL. The excellent answer went further than I asked, and showed how they can be used to parse and evaluate trees as well, so I went ahead and tried to use that on a little project I had going on today.

Unfortunately, code parsed and evaluated that way doesn't seem to see any REPL definition:

scala> val x = 1
x: Int = 1

scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox

scala> val tb = scala.reflect.runtime.universe.runtimeMirror(
  getClass.getClassLoader).mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = ...

scala> tb.eval(tb.parse("x"))
scala.tools.reflect.ToolBoxError: reflective compilation has failed:

not found: value x

Is there a way to get it to recognize definitions made on REPL?

Community
  • 1
  • 1
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • As opposed to not in the REPL? I wrote the exact same code (https://gist.github.com/jedesah/5812481) in an sbt project and I get the same behaviour as in the REPL. If this is how ToolBox works in some other context, I'd be very curious to know. – jedesah Jun 19 '13 at 08:13
  • @UndercoverAgent Code in the toolbox has access to anything you can reach from "root" -- otherwise it would be quite useless. In the case you showed, that variable was not available at the "root". – Daniel C. Sobral Jun 19 '13 at 14:44
  • Useless is a bit of a strong word, it could be used to evaluate self contained trees. In any case, this little project you are/were working on, is it open source? I would love to see an example of accessing external (from the tree itself) definitions, I'm not sure exactly what you mean by reach them from the "root". – jedesah Jun 20 '13 at 04:33
  • Okay, never mind, I get it! :-) – jedesah Jun 21 '13 at 02:38
  • It's not really a project. I tried to write a two-liner unit test suite for use with REPL, which would have worked except for this little detail here. – Daniel C. Sobral Jun 24 '13 at 15:36

1 Answers1

6

Recently I dug into repl, when trying to make it support type macros, so I'm well equipped to explain why it doesn't work. Getting it to work would be the next step :)

I know that you know that every snippet entered into repl gets wrapped into some boilerplate before being compiled. Therefore that x ends up being a field in a nested-nested-nested object in a package with a weird name.

Apparently, repl keeps track of all defined symbols and then injects the necessary imports along with the boilerplate it generates. Therefore subsequent lines can see that x unqualified. To the contrast, toolboxes simply reuse repl's classloader, but don't do anything about the imports, hence the failure.

A workaround would be to somehow get to an object representing a repl, ask it about defined symbols and then generate corresponding imports into the code that you feed to a toolbox. If you file a ticket, I'll try to code up a workaround after the 2.10.1 code freeze madness ends (supposedly, end of this week).

Eugene Burmako
  • 13,028
  • 1
  • 46
  • 59