Skip to content

Commit a9ea7c8

Browse files
committed
Add Expr.asTree and Expr.asTerm
* Add `Expr.asTree` and `Expr.asTerm` under `reflect` * Deprecate `Tree.of` and `Term.of` for simpler migration from M2 to M3 This change make the intent of the operation clearer. We call `asTerm` to see the expression as a `Term` just like we call `asExpr` make the `Term` and `Expr[Any]`. It will simplify code that needs to acceess the trees. As these are extension methods, they can also be accessed explicilty using `reflect.asTerm(expr)` or `reflect.asTree(expr)` which can be useful in some situations.
1 parent c042be9 commit a9ea7c8

File tree

94 files changed

+204
-190
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+204
-190
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,20 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
4848

4949
extension [T](self: scala.quoted.Expr[T]):
5050
def show: String =
51-
reflect.TreeMethods.show(reflect.Term.of(self))
51+
reflect.TreeMethods.show(reflect.asTerm(self))
5252

5353
def showAnsiColored: String =
54-
reflect.TreeMethods.showAnsiColored(reflect.Term.of(self))
54+
reflect.TreeMethods.showAnsiColored(reflect.asTerm(self))
5555

5656
def matches(that: scala.quoted.Expr[Any]): Boolean =
57-
treeMatch(reflect.Term.of(self), reflect.Term.of(that)).nonEmpty
57+
treeMatch(reflect.asTerm(self), reflect.asTerm(that)).nonEmpty
5858

5959
end extension
6060

6161
extension [X](self: scala.quoted.Expr[Any]):
6262
/** Checks is the `quoted.Expr[?]` is valid expression of type `X` */
6363
def isExprOf(using scala.quoted.Type[X]): Boolean =
64-
reflect.TypeReprMethods.<:<(reflect.Term.of(self).tpe)(reflect.TypeRepr.of[X])
64+
reflect.TypeReprMethods.<:<(reflect.asTerm(self).tpe)(reflect.TypeRepr.of[X])
6565

6666
/** Convert this to an `quoted.Expr[X]` if this expression is a valid expression of type `X` or throws */
6767
def asExprOf(using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
@@ -70,7 +70,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
7070
else
7171
throw Exception(
7272
s"""Expr cast exception: ${self.show}
73-
|of type: ${reflect.TypeReprMethods.show(reflect.Term.of(self).tpe)}
73+
|of type: ${reflect.TypeReprMethods.show(reflect.asTerm(self).tpe)}
7474
|did not conform to type: ${reflect.TypeReprMethods.show(reflect.TypeRepr.of[X])}
7575
|""".stripMargin
7676
)
@@ -79,11 +79,17 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
7979

8080
object reflect extends reflectModule:
8181

82+
extension (expr: Expr[Any]):
83+
def asTree: Tree = expr.asTerm
84+
def asTerm: Term =
85+
val exprImpl = expr.asInstanceOf[ExprImpl]
86+
exprImpl.checkScopeId(QuotesImpl.this.hashCode)
87+
exprImpl.tree
88+
end extension
89+
8290
type Tree = tpd.Tree
8391

84-
object Tree extends TreeModule:
85-
def of(expr: Expr[Any]): Tree = Term.of(expr)
86-
end Tree
92+
object Tree extends TreeModule
8793

8894
given TreeMethods: TreeMethods with
8995
extension (self: Tree):
@@ -350,11 +356,6 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
350356
end TermTypeTest
351357

352358
object Term extends TermModule:
353-
def of(expr: Expr[Any]): Term =
354-
val exprImpl = expr.asInstanceOf[ExprImpl]
355-
exprImpl.checkScopeId(QuotesImpl.this.hashCode)
356-
exprImpl.tree
357-
358359
def betaReduce(tree: Term): Option[Term] =
359360
tree match
360361
case app @ tpd.Apply(tpd.Select(fn, nme.apply), args) if dotc.core.Symbols.defn.isFunctionType(fn.tpe) =>
@@ -2624,7 +2625,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
26242625
dotc.report.error(msg, Position.ofMacroExpansion)
26252626

26262627
def error(msg: String, expr: Expr[Any]): Unit =
2627-
dotc.report.error(msg, Term.of(expr).pos)
2628+
dotc.report.error(msg, asTerm(expr).pos)
26282629

26292630
def error(msg: String, pos: Position): Unit =
26302631
dotc.report.error(msg, pos)
@@ -2645,7 +2646,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
26452646
dotc.report.warning(msg, Position.ofMacroExpansion)
26462647

26472648
def warning(msg: String, expr: Expr[Any]): Unit =
2648-
dotc.report.warning(msg, Term.of(expr).pos)
2649+
dotc.report.warning(msg, asTerm(expr).pos)
26492650

26502651
def warning(msg: String, pos: Position): Unit =
26512652
dotc.report.warning(msg, pos)
@@ -2717,8 +2718,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
27172718

27182719
object ExprMatch extends ExprMatchModule:
27192720
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] =
2720-
val scrutineeTree = reflect.Term.of(scrutinee)
2721-
val patternTree = reflect.Term.of(pattern)
2721+
val scrutineeTree = reflect.asTerm(scrutinee)
2722+
val patternTree = reflect.asTerm(pattern)
27222723
treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
27232724
end ExprMatch
27242725

docs/docs/reference/metaprogramming/tasty-reflect.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ trees. For example the `Literal(_)` extractor used below.
4242
```scala
4343
def natConstImpl(x: Expr[Int])(using Quotes): Expr[Int] = {
4444
import quotes.reflect._
45-
val xTree: Term = Term.of(x)
45+
val xTree: Term = x.asTerm
4646
xTree match {
4747
case Inlined(_, _, Literal(Constant(n: Int))) =>
4848
if (n <= 0) {

library/src-bootstrapped/scala/quoted/Expr.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ object Expr {
1919
*/
2020
def betaReduce[T](expr: Expr[T])(using Quotes): Expr[T] =
2121
import quotes.reflect._
22-
Term.betaReduce(Term.of(expr)) match
22+
Term.betaReduce(expr.asTerm) match
2323
case Some(expr1) => expr1.asExpr.asInstanceOf[Expr[T]]
2424
case _ => expr
2525

@@ -29,7 +29,7 @@ object Expr {
2929
*/
3030
def block[T](statements: List[Expr[Any]], expr: Expr[T])(using Quotes): Expr[T] = {
3131
import quotes.reflect._
32-
Block(statements.map(Term.of), Term.of(expr)).asExpr.asInstanceOf[Expr[T]]
32+
Block(statements.map(asTerm), expr.asTerm).asExpr.asInstanceOf[Expr[T]]
3333
}
3434

3535
/** Creates an expression that will construct the value `x` */

library/src-bootstrapped/scala/quoted/FromExpr.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ object FromExpr {
9090
case Inlined(_, Nil, e) => rec(e)
9191
case _ => None
9292
}
93-
rec(Term.of(expr))
93+
rec(expr.asTerm)
9494
}
9595

9696
/** Default implementation of `FromExpr[Option]`

library/src/scala/quoted/Const.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ object Const {
3232
case Inlined(_, Nil, e) => rec(e)
3333
case _ => None
3434
}
35-
rec(Term.of(expr))
35+
rec(expr.asTerm)
3636
}
3737

3838
}

library/src/scala/quoted/ExprMap.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ trait ExprMap:
100100
transformTermChildren(tree, tpe)(owner)
101101
case _ if tree.isExpr =>
102102
// WARNING: Never do a cast like this in user code (accepable within the stdlib).
103-
// In theory we should use `tree.asExpr match { case '{ $expr: t } => Term.of(transform(expr)) }`
103+
// In theory we should use `tree.asExpr match { case '{ $expr: t } => transform(expr).asTerm }`
104104
// This is to avoid conflicts when re-boostrapping the library.
105105
type X
106106
val expr = tree.asExpr.asInstanceOf[Expr[X]]
107107
val t = tpe.asType.asInstanceOf[Type[X]]
108108
val transformedExpr = transform(expr)(using t)
109-
Term.of(transformedExpr)
109+
transformedExpr.asTerm
110110
case _ =>
111111
transformTermChildren(tree, tpe)(owner)
112112

@@ -145,7 +145,7 @@ trait ExprMap:
145145
trees.mapConserve(x => transformTypeCaseDef(x)(owner))
146146

147147
}
148-
new MapChildren().transformTermChildren(Term.of(e), TypeRepr.of[T])(Symbol.spliceOwner).asExprOf[T]
148+
new MapChildren().transformTermChildren(e.asTerm, TypeRepr.of[T])(Symbol.spliceOwner).asExprOf[T]
149149
}
150150

151151
end ExprMap

library/src/scala/quoted/Quotes.scala

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
7979
* import scala.quoted._
8080
* def f(expr: Expr[Int])(using Quotes) =
8181
* import quotes.reflect._
82-
* val tree: Tree = Term.of(expr)
82+
* val ast: Term = expr.asTerm // or `expr.asTree`
8383
* ...
8484
* ```
8585
*
@@ -204,11 +204,22 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
204204
*/
205205
trait reflectModule { self: reflect.type =>
206206

207+
extension (expr: Expr[Any]):
208+
209+
/** Returns the `Tree` representation this expression.
210+
* Same as `asTerm` but typed as a `Tree`.
211+
*/
212+
def asTree: Tree
213+
214+
/** Returns the `Term` representation this expression */
215+
def asTerm: Term
216+
217+
end extension
218+
207219
///////////////
208220
// TREES //
209221
///////////////
210222

211-
212223
/** Tree representing code written in the source */
213224
type Tree <: AnyRef
214225

@@ -218,7 +229,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
218229
/** Methods of the module object `val Tree` */
219230
trait TreeModule { this: Tree.type =>
220231
/** Returns the Term representation this expression */
221-
def of(expr: Expr[Any]): Tree
232+
@deprecated("Use `expr.asTree` instead (must `import quotes.reflect._`). This will be removed in 3.0.0-RC1", "3.0.0-M3")
233+
def of(expr: Expr[Any]): Tree = expr.asTree
222234
}
223235

224236
/** Makes extension methods on `Tree` available without any imports */
@@ -521,7 +533,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
521533
trait TermModule { this: Term.type =>
522534

523535
/** Returns the Term representation this expression */
524-
def of(expr: Expr[Any]): Term
536+
@deprecated("Use `expr.asTerm` instead (must `import quotes.reflect._`). This will be removed in 3.0.0-RC1", "3.0.0-M3")
537+
def of(expr: Expr[Any]): Term = expr.asTerm
525538

526539
/** Returns a term that is functionally equivalent to `t`,
527540
* however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)`

library/src/scala/quoted/Varargs.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ object Varargs {
2121
*/
2222
def apply[T](xs: Seq[Expr[T]])(using Type[T])(using Quotes): Expr[Seq[T]] = {
2323
import quotes.reflect._
24-
Repeated(xs.map(Term.of).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
24+
Repeated(xs.map(_.asTerm).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
2525
}
2626

2727
/** Matches a literal sequence of expressions and return a sequence of expressions.
@@ -44,7 +44,7 @@ object Varargs {
4444
case Inlined(_, Nil, e) => rec(e)
4545
case _ => None
4646
}
47-
rec(Term.of(expr))
47+
rec(expr.asTerm)
4848
}
4949

5050
}

tests/neg-macros/i6432/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object Macro {
1010
sc match {
1111
case '{ StringContext(${Varargs(parts)}: _*) } =>
1212
for (part @ Const(s) <- parts)
13-
report.error(s, Term.of(part).pos)
13+
report.error(s, part.asTree.pos)
1414
}
1515
'{}
1616
}

tests/neg-macros/i6432b/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object Macro {
1010
sc match {
1111
case '{ StringContext(${Varargs(parts)}: _*) } =>
1212
for (part @ Const(s) <- parts)
13-
report.error(s, Term.of(part).pos)
13+
report.error(s, part.asTree.pos)
1414
}
1515
'{}
1616
}

0 commit comments

Comments
 (0)