Parse a String to Expr

Is there any way to parse a String (maybe loaded from a file) to scala.quoted.Expr[T] to benefit from Scala 3 macros?

I have several usecases for such functionality. One of them could be as follows. Suppose we’ve got a text file with several scala style interpolations within it:

This textfile is created on ${java.time.LocalDateTime.now()} by ${user.name}

If I load this file in a string, I will not be able to create an interpolated string from the text file. But if I could make an Expr from the file contents, lots of valuable options will open.

Think of a plain text wiki system for example, where each article resides in a plain text file. But portions of that articles will be automatically calculated by the parser. For example a live backlinks section can be added to the final html representation. Or a table of contents can be automatically generated. This generation will use simple scala function calls within curely brackets, as it is a usual interpolated text.

1 Like

What’s your use case? Remember that Expr is mainly a compile-time concept, and parsing is typically run-time. So depending on what you’re trying to accomplish, this may or may not make sense.

I did not understand the question or the counter-question.

If you have a String, it knows how to make an Expr[String].

There is an example and the reference.

For me, “What’s your use case?” is like the famous scene in Monty Python, “What’s your favorite colour [sic]?”

Or like when the shopkeeper says what are you looking for? and I say, what have you got.

Maybe there is a compendium of Scala 3 macro examples.

I want to load a scala source file (loading source file contents gives you a string value) and create an AST from that source code, then use some AST transformations by Scala macros before executing it. Also, I edited the original question and included a clear usecase.

The intended string comes from a text file which contains Scala source code, so that snippet if executed may not necessarily create a value of type String hence it’s not going to be Expr[String] if parsed, but a general AST. Also, I edited the original question and included a clear usecase.

@shvahabi
In principle this should be doable in Scala 3 like it’s doable with c.parse in Scala 2 macros.
Just there’s no convenient API.

It’s not clear whether you’d like to parse or compile a String (depending on which compilation stage you stop, the latter can lead to something starting from a typed AST and ending at emitting bytecode). There are different times:

  1. compile time of a macro
  2. compile time of main code i.e. runtime of the macro i.e. the time of macro expansion
  3. runtime of main code.

If you parse/typecheck/compile a String at time 2 you can’t have T in Expr[T] at time 1.

Please see my answer in https://stackoverflow.com/questions/70945320/how-to-compile-and-execute-scala-code-at-run-time-in-scala3 (It’s possible that Mark’s answer there can be adopted too but I didn’t try.) See the part after “You can implement Eval in Scala 3 yourself using actual compiler…”. There are the lines commented out:

  // val unit = run.units.head
  // println("untyped tree=" + unit.untpdTree)
  // println("typed tree=" + unit.tpdTree)

You can have an untyped tree and typed tree here.
scala.quoted.Expr can be downcasted to a wrapper over typed tree.
While writing the answer, I was using 3.1.3.
How scala.quoted types (Symbols, Trees etc.) can be downcasted to implementation types you can see in https://stackoverflow.com/questions/74549477/scala3-crafting-types-through-metaprogramming/ (I downcasted Symbols but not Trees here).

1 Like

Thanks Dmytro, for your detailed explanation; and if you look at your answer on stack overflow, you’ll find the same question from me asked two years ago below it within the comments. But now that you mentioned the commented portion of your code, and the 3 stopping stages that makes my question in some cases irrelevant, it means I need to reread everything again. Actually, I very well remember that I successfully used your code from stack overflow, the part which instructs about using Scala 3 Repl interpreter, but I had problems understanding other parts.

Anyway, since maybe the problem is with me and my understanding of meta-programming, can you please introduce me some book or course online for programming with macros in Scala or any other language that gives me a sound foundation for understanding meta-programming in general. I guess I lack a lot of basic concepts and effective knowledge. Meta programming is not easy to experiment with, and I read the Scala guide on meta-programming several times without understanding any deeper. Thanks in advance.

RockTheJVM’s course on metaprogramming is what you need. You are right there are almost zero resources on Scala metaprogramming (I really wonder how people who know it learned it? Dark magic of some sort?)

3 Likes