Skip to content

Add Tree.of and Term.of to transform Expr into Tree #10332

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
merged 1 commit into from
Nov 16, 2020
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
28 changes: 15 additions & 13 deletions compiler/src/scala/quoted/internal/impl/QuoteContextImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,20 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl

extension [T](self: scala.quoted.Expr[T]):
def show: String =
reflect.TreeMethodsImpl.show(self.asReflectTree)
reflect.TreeMethodsImpl.show(reflect.Term.of(self))

def showAnsiColored: String =
reflect.TreeMethodsImpl.showAnsiColored(self.asReflectTree)
reflect.TreeMethodsImpl.showAnsiColored(reflect.Term.of(self))

def matches(that: scala.quoted.Expr[Any]): Boolean =
treeMatch(self.asReflectTree, that.asReflectTree).nonEmpty

def asReflectTree: reflect.Term =
val expr = self.asInstanceOf[ExprImpl]
expr.checkScopeId(QuoteContextImpl.this.hashCode)
expr.tree
treeMatch(reflect.Term.of(self), reflect.Term.of(that)).nonEmpty

end extension

extension [X](self: scala.quoted.Expr[Any]):
/** Checks is the `quoted.Expr[?]` is valid expression of type `X` */
def isExprOf(using scala.quoted.Type[X]): Boolean =
reflect.TypeReprMethodsImpl.<:<(self.asReflectTree.tpe)(reflect.TypeRepr.of[X])
reflect.TypeReprMethodsImpl.<:<(reflect.Term.of(self).tpe)(reflect.TypeRepr.of[X])

/** Convert this to an `quoted.Expr[X]` if this expression is a valid expression of type `X` or throws */
def asExprOf(using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
Expand All @@ -74,7 +69,7 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
else
throw Exception(
s"""Expr cast exception: ${self.show}
|of type: ${reflect.TypeReprMethodsImpl.show(self.asReflectTree.tpe)}
|of type: ${reflect.TypeReprMethodsImpl.show(reflect.Term.of(self).tpe)}
|did not conform to type: ${reflect.TypeReprMethodsImpl.show(reflect.TypeRepr.of[X])}
|""".stripMargin
)
Expand All @@ -89,7 +84,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl

type Tree = tpd.Tree

object Tree extends TreeModule
object Tree extends TreeModule:
def of(expr: Expr[Any]): Tree = Term.of(expr)
end Tree

object TreeMethodsImpl extends TreeMethods:
extension (self: Tree):
Expand Down Expand Up @@ -328,6 +325,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
end TermTypeTest

object Term extends TermModule:
def of(expr: Expr[Any]): Term =
val exprImpl = expr.asInstanceOf[ExprImpl]
exprImpl.checkScopeId(QuoteContextImpl.this.hashCode)
exprImpl.tree

def betaReduce(tree: Term): Option[Term] =
tree match
case app @ tpd.Apply(tpd.Select(fn, nme.apply), args) if dotc.core.Symbols.defn.isFunctionType(fn.tpe) =>
Expand Down Expand Up @@ -2551,8 +2553,8 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl

object ExprMatch extends ExprMatchModule:
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] =
val scrutineeTree = QuoteContextImpl.this.asReflectTree(scrutinee)
val patternTree = QuoteContextImpl.this.asReflectTree(pattern)
val scrutineeTree = reflect.Term.of(scrutinee)
val patternTree = reflect.Term.of(pattern)
treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
end ExprMatch

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/reference/metaprogramming/tasty-reflect.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ trees. For example the `Literal(_)` extractor used below.
```scala
def natConstImpl(x: Expr[Int])(using qctx: QuoteContext): Expr[Int] = {
import qctx.reflect._
val xTree: Term = x.unseal
val xTree: Term = Term.of(x)
xTree match {
case Inlined(_, _, Literal(Constant(n: Int))) =>
if (n <= 0) {
Expand Down
5 changes: 3 additions & 2 deletions library/src-bootstrapped/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ object Expr {
* Some bindings may be elided as an early optimization.
*/
def betaReduce[T](expr: Expr[T])(using qctx: QuoteContext): Expr[T] =
qctx.reflect.Term.betaReduce(expr.unseal) match
import qctx.reflect._
Term.betaReduce(Term.of(expr)) match
case Some(expr1) => expr1.asExpr.asInstanceOf[Expr[T]]
case _ => expr

Expand All @@ -24,7 +25,7 @@ object Expr {
*/
def block[T](statements: List[Expr[Any]], expr: Expr[T])(using qctx: QuoteContext): Expr[T] = {
import qctx.reflect._
Block(statements.map(_.unseal), expr.unseal).asExpr.asInstanceOf[Expr[T]]
Block(statements.map(Term.of), Term.of(expr)).asExpr.asInstanceOf[Expr[T]]
}

/** Lift a value into an expression containing the construction of that value */
Expand Down
5 changes: 3 additions & 2 deletions library/src-bootstrapped/scala/quoted/ExprMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ trait ExprMap:
type X
val expr = tree.asExpr.asInstanceOf[Expr[X]]
val t = tpe.asType.asInstanceOf[Type[X]]
transform(expr)(using qctx, t).unseal
val transformedExpr = transform(expr)(using qctx, t)
Term.of(transformedExpr)
case _ =>
transformTermChildren(tree, tpe)

Expand Down Expand Up @@ -144,7 +145,7 @@ trait ExprMap:
trees mapConserve (transformTypeCaseDef(_))

}
new MapChildren().transformTermChildren(e.unseal, TypeRepr.of[T]).asExprOf[T]
new MapChildren().transformTermChildren(Term.of(e), TypeRepr.of[T]).asExprOf[T]
}

end ExprMap
2 changes: 1 addition & 1 deletion library/src/scala/quoted/Const.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object Const {
case Inlined(_, Nil, e) => rec(e)
case _ => None
}
rec(expr.unseal)
rec(Term.of(expr))
}

}
5 changes: 4 additions & 1 deletion library/src/scala/quoted/QuoteContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ trait QuoteContext { self: internal.QuoteUnpickler & internal.QuoteMatching =>
unlift.fromExpr(self)(using QuoteContext.this).getOrElse(reportError)

/** View this expression `quoted.Expr[T]` as a `Term` */
@deprecated("Use reflect.Term.of", "")
def unseal: reflect.Term = self.asReflectTree // TODO remove

/** View this expression `quoted.Expr[T]` as a `Term` */
def asReflectTree: reflect.Term
@deprecated("Use reflect.Term.of", "")
def asReflectTree: reflect.Term = // TODO remove
reflect.Term.of(self)
end extension

// Extension methods for `Expr[Any]` that take another explicit type parameter
Expand Down
8 changes: 7 additions & 1 deletion library/src/scala/quoted/Reflection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ trait Reflection { reflection =>

val Tree: TreeModule

trait TreeModule { this: Tree.type => }
trait TreeModule { this: Tree.type =>
/** Returns the Term representation this expression */
def of(expr: Expr[Any]): Tree
}

given TreeMethods as TreeMethods = TreeMethodsImpl
protected val TreeMethodsImpl: TreeMethods
Expand Down Expand Up @@ -372,6 +375,9 @@ trait Reflection { reflection =>

trait TermModule { this: Term.type =>

/** Returns the Term representation this expression */
def of(expr: Expr[Any]): Term

/** Returns a term that is functionally equivalent to `t`,
* however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)`
* then it optimizes this the top most call by returning the `Some`
Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/quoted/Varargs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Varargs {
*/
def apply[T](xs: Seq[Expr[T]])(using tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
import qctx.reflect._
Repeated(xs.map[Term](_.unseal).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
Repeated(xs.map(Term.of).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
}

/** Matches a literal sequence of expressions and return a sequence of expressions.
Expand All @@ -40,7 +40,7 @@ object Varargs {
case Inlined(_, Nil, e) => rec(e)
case _ => None
}
rec(expr.unseal)
rec(Term.of(expr))
}

}
14 changes: 9 additions & 5 deletions library/src/scala/quoted/report.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ object report:

/** Report an error at the position of the macro expansion */
def error(msg: => String)(using qctx: QuoteContext): Unit =
qctx.reflect.Reporting.error(msg, qctx.reflect.Position.ofMacroExpansion)
import qctx.reflect._
Reporting.error(msg, Position.ofMacroExpansion)

/** Report an error at the on the position of `expr` */
def error(msg: => String, expr: Expr[Any])(using qctx: QuoteContext): Unit =
qctx.reflect.Reporting.error(msg, expr.unseal.pos)
import qctx.reflect._
Reporting.error(msg, Term.of(expr).pos)

/** Report an error at the position of the macro expansion and throws a StopQuotedContext */
def throwError(msg: => String)(using qctx: QuoteContext): Nothing = {
Expand All @@ -23,11 +25,13 @@ object report:

/** Report a warning */
def warning(msg: => String)(using qctx: QuoteContext): Unit =
qctx.reflect.Reporting.warning(msg, qctx.reflect.Position.ofMacroExpansion)
import qctx.reflect._
Reporting.warning(msg, Position.ofMacroExpansion)

/** Report a warning at the on the position of `expr` */
def warning(msg: => String, expr: Expr[_])(using qctx: QuoteContext): Unit =
qctx.reflect.Reporting.warning(msg, expr.unseal.pos)
def warning(msg: => String, expr: Expr[Any])(using qctx: QuoteContext): Unit =
import qctx.reflect._
Reporting.warning(msg, Term.of(expr).pos)

/** Throwable used to stop the expansion of a macro after an error was reported */
class StopQuotedContext extends Throwable
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/i6432/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Macro {
sc match {
case '{ StringContext(${Varargs(parts)}: _*) } =>
for (part @ Const(s) <- parts)
Reporting.error(s, part.unseal.pos)
Reporting.error(s, Term.of(part).pos)
}
'{}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/i6432b/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Macro {
sc match {
case '{ StringContext(${Varargs(parts)}: _*) } =>
for (part @ Const(s) <- parts)
Reporting.error(s, part.unseal.pos)
Reporting.error(s, Term.of(part).pos)
}
'{}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/i6976/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ object macros {

def mcrImpl(body: Expr[Any])(using ctx: QuoteContext) : Expr[Any] = {
import ctx.reflect._
body.unseal match { case Block(_, _) => '{2} }
Term.of(body) match { case Block(_, _) => '{2} }
}
}
3 changes: 2 additions & 1 deletion tests/neg-macros/i7698.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ trait Show[T] {
}

def showInterpolatorImpl(sc: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using qctx: QuoteContext): Expr[String] =
argsExpr.unseal match
import qctx.reflect._
Term.of(argsExpr) match
case '{ $arg: $t } => // error
case '[ Int ] => // error
???
Expand Down
3 changes: 2 additions & 1 deletion tests/neg-macros/i9801/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ def triggerStackOverflow(n: Int): Expr[Double] = {
inline def loop(inline prog: Double): Double = ${impl('prog)}

def impl(prog: Expr[Double])(using QuoteContext) : Expr[Double] =
import qctx.reflect._
try {
triggerStackOverflow(0)
} catch {
case e =>
qctx.reflect.Reporting.error(e.getMessage, prog.unseal.pos)
qctx.reflect.Reporting.error(e.getMessage, Term.of(prog).pos)
'{ 42.0 }
}
2 changes: 1 addition & 1 deletion tests/neg-macros/tasty-macro-assert-1/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object Asserts {
def impl(cond: Expr[Boolean])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._

val tree = cond.unseal
val tree = Term.of(cond)

def isOps(tpe: TypeRepr): Boolean = tpe match {
case tpe: TermRef => tpe.termSymbol.isDefDef && tpe.name == "Ops"// TODO check that the parent is Asserts
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/tasty-macro-assert-2/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object Asserts {
def impl(cond: Expr[Boolean])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._

val tree = cond.unseal
val tree = Term.of(cond)

def isOps(tpe: TypeRepr): Boolean = tpe match {
case tpe: TermRef => tpe.termSymbol.isDefDef && tpe.name == "Ops"// TODO check that the parent is Asserts
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/tasty-macro-error/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ object Macros {

def impl(x: Expr[Any])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._
Reporting.error("here is the the argument is " + x.unseal.underlyingArgument.show, x.unseal.underlyingArgument.pos)
Reporting.error("here is the the argument is " + Term.of(x).underlyingArgument.show, Term.of(x).underlyingArgument.pos)
'{}
}

Expand Down
6 changes: 3 additions & 3 deletions tests/neg-macros/tasty-macro-positions/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ object Macros {

def impl(x: Expr[Any])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._
val pos = x.unseal.underlyingArgument.pos
Reporting.error("here is the the argument is " + x.unseal.underlyingArgument.show, pos)
Reporting.error("here (+5) is the the argument is " + x.unseal.underlyingArgument.show, pos.sourceFile, pos.start + 5, pos.end + 5)
val pos = Term.of(x).underlyingArgument.pos
Reporting.error("here is the the argument is " + Term.of(x).underlyingArgument.show, pos)
Reporting.error("here (+5) is the the argument is " + Term.of(x).underlyingArgument.show, pos.sourceFile, pos.start + 5, pos.end + 5)
'{}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object FIntepolator {

def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using qctx: QuoteContext) : Expr[String] = {
import qctx.reflect._
Reporting.error("there are no parts", strCtxExpr.unseal.underlyingArgument.pos)
Reporting.error("there are no parts", Term.of(strCtxExpr).underlyingArgument.pos)
'{ ($strCtxExpr).s($argsExpr: _*) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Macro {
object FIntepolator {
def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using qctx: QuoteContext) : Expr[String] = {
import qctx.reflect._
Reporting.error("there are no args", argsExpr.unseal.underlyingArgument.pos)
Reporting.error("there are no args", Term.of(argsExpr).underlyingArgument.pos)
'{ ($strCtxExpr).s($argsExpr: _*) }
}

Expand Down
6 changes: 3 additions & 3 deletions tests/neg-staging/i5941/macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ object Lens {
import util._
// obj.copy(field = value)
def setterBody(obj: Expr[S], value: Expr[T], field: String): Expr[S] =
Select.overloaded(obj.unseal, "copy", Nil, NamedArg(field, value.unseal) :: Nil, TypeBounds.empty).asExprOf[S]
Select.overloaded(Term.of(obj), "copy", Nil, NamedArg(field, Term.of(value)) :: Nil, TypeBounds.empty).asExprOf[S]

// exception: getter.unseal.underlyingArgument
getter.unseal match {
// exception: Term.of(getter).underlyingArgument
Term.of(getter) match {
case Inlined(
None, Nil,
Block(
Expand Down
2 changes: 1 addition & 1 deletion tests/pending/run/tasty-comments/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ object Macros {
def impl[T](x: Expr[T])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._

val tree = x.unseal
val tree = Term.of(x)
tree.symbol.comment.map(_.raw) match {
case Some(str) => '{ println(${str}) }
case None => '{ println() }
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-macros/i6171/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ object scalatest {

def assertImpl(x: Expr[Any])(using qctx: QuoteContext) : Expr[Unit] = {
import qctx.reflect._
x.unseal.underlyingArgument
Term.of(x).underlyingArgument
'{ () }
}
}
4 changes: 2 additions & 2 deletions tests/pos-macros/i6535/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ object scalatest {
import util._
import ValDef.let

cond.unseal.underlyingArgument match {
Term.of(cond).underlyingArgument match {
case t @ Apply(Select(lhs, op), rhs :: Nil) =>
let(lhs) { left =>
let(rhs) { right =>
Expand All @@ -19,7 +19,7 @@ object scalatest {
val r = right.asExpr
val b = result.asExprOf[Boolean]
val code = '{ scala.Predef.assert($b) }
code.unseal
Term.of(code)
}
}
}.asExprOf[Unit]
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-macros/i7011/Macros_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ inline def mcr(body: => Any): Unit = ${mcrImpl('body)}
def mcrImpl[T](body: Expr[Any])(using QuoteContext) : Expr[Any] = {
import qctx.reflect._

val bTree = body.unseal
val bTree = Term.of(body)
val under = bTree.underlyingArgument

val res = '{Box(${under.asInstanceOf[Term].asExpr})}
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-macros/i7030/Macros_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ def innerImpl(exprs: Expr[Any])(using QuoteContext): Expr[Any] =
inline def outer(expr: => Any): Any = ${outerImpl('expr)}
def outerImpl(body: Expr[Any])(using QuoteContext): Expr[Any] = {
import qctx.reflect._
body.unseal.underlyingArgument.asExpr
Term.of(body).underlyingArgument.asExpr
}
2 changes: 1 addition & 1 deletion tests/pos-macros/i8325/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object A:

def transformImplExpr[A:Type](using qctx: QuoteContext)(expr: Expr[A]): Expr[A] = {
import qctx.reflect._
expr.unseal match {
Term.of(expr) match {
case Inlined(x,y,z) => transformImplExpr(z.asExpr.asInstanceOf[Expr[A]])
case Apply(fun,args) => '{ A.pure(${Apply(fun,args).asExpr.asInstanceOf[Expr[A]]}) }
case other => expr
Expand Down
Loading