Skip to content

Use current compiler context to show Expr in macros #6258

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions library/src-bootstrapped/scala/quoted/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import scala.runtime.quoted.Unpickler.Pickled

sealed abstract class Type[T <: AnyKind] {
type `$splice` = T

/** Show a source code like representation of this type */
final def show(implicit toolbox: Toolbox): String = toolbox.show(this.asInstanceOf[Type[Any]])
}

/** Some basic type tags, currently incomplete */
object Type {

implicit class TypeOps[T](tpe: Type[T]) {
/** Show a source code like representation of this type */
def show(implicit toolbox: Toolbox): String = toolbox.show(tpe.asInstanceOf[Type[Any]])
}

implicit def UnitTag: Type[Unit] = new TaggedType[Unit]
implicit def BooleanTag: Type[Boolean] = new TaggedType[Boolean]
implicit def ByteTag: Type[Byte] = new TaggedType[Byte]
Expand Down
10 changes: 9 additions & 1 deletion library/src-bootstrapped/scala/tasty/reflect/QuotedOps.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package scala.tasty.reflect

/** Extension methods on scala.quoted.{Expr|Type} to convert to scala.tasty.Tasty objects */
trait QuotedOps extends Core {
trait QuotedOps extends Core { self: Printers =>

implicit class QuotedExprAPI[T](expr: scala.quoted.Expr[T]) {
/** View this expression `quoted.Expr[T]` as a `Term` */
Expand All @@ -11,12 +11,20 @@ trait QuotedOps extends Core {
/** Checked cast to a `quoted.Expr[U]` */
def cast[U: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[U] =
kernel.QuotedExpr_cast[U](expr)

/** Show a source code like representation of this expression */
def show(implicit ctx: Context): String =
unseal.showCode
}

implicit class QuotedTypeAPI[T <: AnyKind](tpe: scala.quoted.Type[T]) {
/** View this expression `quoted.Type[T]` as a `TypeTree` */
def unseal(implicit ctx: Context): TypeTree =
kernel.QuotedType_unseal(tpe)

/** Show a source code like representation of this type */
def show(implicit ctx: Context): String =
unseal.showCode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolasstucki We need to allow one option color: Boolean = false here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be inheriting the one from the compiler. Is that the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to create a new setting with the setting enabled or disabled

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In macro usage, usually, there will never be a need for colors -- because the text will be used for values. Inheriting from the compiler is not the correct behavior.

The Toobox settings does not work as expected. I currently use the following walkaround:

def (str: String) clean: String = str.replaceAll("\u001B\\[[;\\d]*m", "")

}

implicit class TermToQuotedAPI(term: Term) {
Expand Down
9 changes: 6 additions & 3 deletions library/src-non-bootstrapped/scala/quoted/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import scala.runtime.quoted.Unpickler.Pickled

sealed abstract class Type[T] {
type `$splice` = T

/** Show a source code like representation of this type */
final def show(implicit toolbox: Toolbox): String = toolbox.show(this)
}

/** Some basic type tags, currently incomplete */
object Type {

implicit class TypeOps[T](tpe: Type[T]) {
/** Show a source code like representation of this type */
def show(implicit toolbox: Toolbox): String = toolbox.show(tpe.asInstanceOf[Type[Any]])
}

implicit def UnitTag: Type[Unit] = new TaggedType[Unit]
implicit def BooleanTag: Type[Boolean] = new TaggedType[Boolean]
implicit def ByteTag: Type[Byte] = new TaggedType[Byte]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package scala.tasty.reflect

/** Extension methods on scala.quoted.{Expr|Type} to convert to scala.tasty.Tasty objects */
trait QuotedOps extends Core {
trait QuotedOps extends Core { self: Printers =>

implicit class QuotedExprAPI[T](expr: scala.quoted.Expr[T]) {
/** View this expression `quoted.Expr[T]` as a `Term` */
Expand All @@ -11,12 +11,20 @@ trait QuotedOps extends Core {
/** Checked cast to a `quoted.Expr[U]` */
def cast[U: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[U] =
kernel.QuotedExpr_cast[U](expr)

/** Show a source code like representation of this expression */
def show(implicit ctx: Context): String =
unseal.showCode
}

implicit class QuotedTypeAPI[T](tpe: scala.quoted.Type[T]) {
/** View this expression `quoted.Type[T]` as a `TypeTree` */
def unseal(implicit ctx: Context): TypeTree =
kernel.QuotedType_unseal(tpe)

/** Show a source code like representation of this type */
def show(implicit ctx: Context): String =
unseal.showCode
}

implicit class TermToQuotedAPI(term: Term) {
Expand Down
8 changes: 5 additions & 3 deletions library/src/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ sealed abstract class Expr[+T] {
*/
final def run(implicit toolbox: Toolbox): T = toolbox.run(this)

/** Show a source code like representation of this expression */
final def show(implicit toolbox: Toolbox): String = toolbox.show(this)

}

object Expr {

// TODO simplify using new extension methods

implicit class ExprOps[T](expr: Expr[T]) {
/** Show a source code like representation of this expression */
def show(implicit toolbox: Toolbox): String = toolbox.show(expr)
}

implicit class AsFunction0[R](private val f: Expr[() => R]) extends AnyVal {
def apply(): Expr[R] = new Exprs.FunctionAppliedTo[R](f, Array.empty)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ object Macro {
}

object FIntepolator {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): Expr[String] = {
import reflect._
error("there are no args", argsExpr.unseal.underlyingArgument.pos)
Expand Down
8 changes: 5 additions & 3 deletions tests/run-with-compiler/quote-impure-by-name/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import scala.quoted._
import scala.quoted.autolift._

import scala.tasty.Reflection

class Index[K, Keys](val index: String) extends AnyVal {
override def toString: String = index
}
object Index {

implicit def zero[K, T]: Index[K, (K, T)] = new Index("0")

implicit inline def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ${ succImpl('prev)('[K], '[H], '[T]) }
implicit inline def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ${ succImpl[K, H, T]('prev) }

def succImpl[K, H, T](prev: Expr[Index[K, T]])(implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def succImpl[K, H, T](prev: Expr[Index[K, T]])(implicit k: Type[K], h: Type[H], t: Type[T], relection: Reflection): Expr[Index[K, (H, T)]] = {
import relection._
val value = s"1 + {${prev.show}}"
'{new Index(${value})}
}
Expand Down
18 changes: 8 additions & 10 deletions tests/run-with-compiler/quote-inline-function.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,25 @@ Normal function
f.apply(x$1)
i = i.+(1)
}
while ({
do {
val x$2: scala.Int = i
f.apply(x$2)
i = i.+(1)
i.<(j)
}) ()
} while (i.<(j))
}

By name function
{
var i: scala.Int = 0
val j: scala.Int = 5
while (i.<(j)) {
val x$1: scala.Int = i
scala.Predef.println(x$1)
val x$3: scala.Int = i
scala.Predef.println(x$3)
i = i.+(1)
}
while ({
val x$2: scala.Int = i
scala.Predef.println(x$2)
do {
val x$4: scala.Int = i
scala.Predef.println(x$4)
i = i.+(1)
i.<(j)
}) ()
} while (i.<(j))
}
5 changes: 3 additions & 2 deletions tests/run-with-compiler/quote-inline-function/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import scala.quoted._
import scala.quoted.autolift._
import scala.tasty.Reflection

object Macros {

inline def foreach1(start: Int, end: Int, f: Int => Unit): String = ${impl('start, 'end, 'f)}
inline def foreach2(start: Int, end: Int, f: => Int => Unit): String = ${impl('start, 'end, 'f)}

def impl(start: Expr[Int], end: Expr[Int], f: Expr[Int => Unit]): Expr[String] = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def impl(start: Expr[Int], end: Expr[Int], f: Expr[Int => Unit])(implicit reflect: Reflection): Expr[String] = {
import reflect._
val res = '{
var i = $start
val j = $end
Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/quote-unrolled-foreach.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object Test {
println(code4.show)
println()

val liftedArray = Array(1, 2, 3, 4)
val liftedArray: Expr[Array[Int]] = Array(1, 2, 3, 4)
println(liftedArray.show)
println()

Expand Down
2 changes: 1 addition & 1 deletion tests/run/type-show/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import scala.tasty._
object TypeToolbox {
inline def show[A]: String = ${ showImpl('[A]) }
private def showImpl[A, B](a: Type[A])(implicit refl: Reflection): Expr[String] = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(this.getClass.getClassLoader)
import refl._
a.show.toExpr
}
}