Skip to content

Macro based string interpolation #5095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
allanrenucci opened this issue Sep 12, 2018 · 2 comments
Closed

Macro based string interpolation #5095

allanrenucci opened this issue Sep 12, 2018 · 2 comments

Comments

@allanrenucci
Copy link
Contributor

The goal of this issue is to discuss how one could implement a macro based string interpolator similar to densh/joyquote:

Let's consider an hypothetical xml interpolator.

In Scala 2, one can write:

implicit class XmlQuote(val sc: StringContext) {
  def xml(args: Any*): Xml = macro QuoteImpl.apply
}

class QuoteImpl(val c: blackbox.Context) {
  import c.universe._
  def apply(args: Tree*): Tree = ???
}

Let's see how this could translate to Dotty macros. A naive translation would be:

import scala.quoted._
import scala.tasty.Tasty

implicit class XmlQuote(val sc: StringContext) {
  rewrite def xml(args: Any*): Xml = ~QuoteImpl.apply('(ctx), '(args))
}

object QuoteImpl {
  def apply(ctx: Expr[StringContext], args: Expr[Seq[Any]])(implicit tasty: Tasty): Expr[Xml] = ???
}

The issue with this approach is that the apply macro doesn't see the tree for ctx and args as they are lifted out by the compiler and we only see references to the lifted values. To prevent parameters from being lifted out, one needs to make them by name:

import scala.quoted._
import scala.tasty.Tasty

implicit rewrite def XmlQuote(ctx: => StringContext): XmlQuote = new XmlQuote(ctx)

class XmlQuote(val sc: StringContext) {
  rewrite def xml(args: => Any*): Xml = ~QuoteImpl.apply('(ctx), '(args))
}

object QuoteImpl {
  def apply(ctx: Expr[StringContext], args: Expr[Seq[Any]])(implicit tasty: Tasty): Expr[Xml] = ???
}
@odersky
Copy link
Contributor

odersky commented Sep 12, 2018

That looks like a good solution to me!

@allanrenucci
Copy link
Contributor Author

#5096 implements the proposed solution. However, one should not need to make arguments by name to be able inspect the argument trees. So the proper solution should be:

import scala.quoted._
import scala.tasty.Tasty

implicit class XmlQuote(val sc: StringContext) {
  rewrite def xml(args: Any*): Xml = ~QuoteImpl.apply('(ctx), '(args))
}

object QuoteImpl {
  def apply(ctx: Expr[StringContext], args: Expr[Seq[Any]])(implicit tasty: Tasty): Expr[Xml] = ???
}

Closing in favor of #5132

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants