Skip to content

Commit 761405d

Browse files
committed
Join literal sequence Expr logic into Exprs
Currently we have `Expr.ofSeq` and `ExprSeq.unapply` to handle such cases. Instead we provide a single `Exprs` that contains an `apply` and `unapply`. Furthermore having both `Expr.ofSeq` and `Expr.ofList` has lead to confusions on which one to use for varargs. This will help guide users to the correct logic to use for varargs.
1 parent 44f6bd3 commit 761405d

File tree

19 files changed

+48
-39
lines changed

19 files changed

+48
-39
lines changed

docs/docs/reference/metaprogramming/macros.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ It is possible to deconstruct or extract values out of `Expr` using pattern matc
618618

619619
* `scala.quoted.Const`: matches an expression of a literal value and returns the value.
620620
* `scala.quoted.Value`: matches an expression of a value and returns the value.
621-
* `scala.quoted.ExprSeq`: matches an explicit sequence of expresions and returns them. These sequences are useful to get individual `Expr[T]` out of a varargs expression of type `Expr[Seq[T]]`.
621+
* `scala.quoted.Exprs`: matches an explicit sequence of expresions and returns them. These sequences are useful to get individual `Expr[T]` out of a varargs expression of type `Expr[Seq[T]]`.
622622
* `scala.quoted.ConstSeq`: matches an explicit sequence of literal values and returns them.
623623
* `scala.quoted.ValueSeq`: matches an explicit sequence of values and returns them.
624624

@@ -628,7 +628,7 @@ inline def sum(inline args: Int*): Int = ${ sumExpr('args) }
628628
private def sumExpr(argsExpr: Expr[Seq[Int]])(using QuoteContext): Expr[Int] = argsExpr match {
629629
case ConstSeq(args) => // args is of type Seq[Int]
630630
Expr(args.sum) // precompute result of sum
631-
case ExprSeq(argExprs) => // argExprs is of type Seq[Expr[Int]]
631+
case Exprs(argExprs) => // argExprs is of type Seq[Expr[Int]]
632632
val staticSum: Int = argExprs.map {
633633
case Const(arg) => arg
634634
case _ => 0
@@ -664,12 +664,12 @@ private def optimizeExpr(body: Expr[Int])(using QuoteContext): Expr[Int] = body
664664
// Match a call to sum with an argument $n of type Int. n will be the Expr[Int] representing the argument.
665665
case '{ sum($n) } => n
666666
// Match a call to sum and extracts all its args in an `Expr[Seq[Int]]`
667-
case '{ sum(${ExprSeq(args)}: _*) } => sumExpr(args)
667+
case '{ sum(${Exprs(args)}: _*) } => sumExpr(args)
668668
case body => body
669669
}
670670
private def sumExpr(args1: Seq[Expr[Int]])(using QuoteContext): Expr[Int] = {
671671
def flatSumArgs(arg: Expr[Int]): Seq[Expr[Int]] = arg match {
672-
case '{ sum(${ExprSeq(subArgs)}: _*) } => subArgs.flatMap(flatSumArgs)
672+
case '{ sum(${Exprs(subArgs)}: _*) } => subArgs.flatMap(flatSumArgs)
673673
case arg => Seq(arg)
674674
}
675675
val args2 = args1.flatMap(flatSumArgs)
@@ -707,7 +707,7 @@ inline def (sc: StringContext).showMe(inline args: Any*): String = ${ showMeExpr
707707

708708
private def showMeExpr(sc: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using qctx: QuoteContext): Expr[String] = {
709709
argsExpr match {
710-
case ExprSeq(argExprs) =>
710+
case Exprs(argExprs) =>
711711
val argShowedExprs = argExprs.map {
712712
case '{ $arg: $tp } =>
713713
val showTp = '[Show[$tp]]

library/src-bootstrapped/dotty/internal/StringContextMacro.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ object StringContextMacro {
6464
def notStatic =
6565
qctx.throwError("Expected statically known String Context", strCtxExpr)
6666
def splitParts(seq: Expr[Seq[String]]) = (seq, seq) match {
67-
case (ExprSeq(p1), ConstSeq(p2)) => (p1.toList, p2.toList)
67+
case (Exprs(p1), ConstSeq(p2)) => (p1.toList, p2.toList)
6868
case (_, _) => notStatic
6969
}
7070
val (partsExpr, parts) = strCtxExpr match {
@@ -74,7 +74,7 @@ object StringContextMacro {
7474
}
7575

7676
val args = argsExpr match {
77-
case ExprSeq(args) => args
77+
case Exprs(args) => args
7878
case _ => qctx.throwError("Expected statically known argument list", argsExpr)
7979
}
8080

library/src/scala/quoted/ConstSeq.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ object ConstSeq {
1616
* ```
1717
*/
1818
def unapply[T](expr: Expr[Seq[T]])(using qctx: QuoteContext): Option[Seq[T]] = expr match {
19-
case ExprSeq(elems) =>
19+
case Exprs(elems) =>
2020
elems.foldRight(Option(List.empty[T])) { (elem, acc) =>
2121
(elem, acc) match {
2222
case (Const(value), Some(lst)) => Some(value :: lst)

library/src/scala/quoted/Expr.scala

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,9 @@ object Expr {
108108
* `Seq(e1, e2, ...)` where `ei: Expr[T]`
109109
* to an expression equivalent to
110110
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
111-
*
112-
* Usage:
113-
* ```scala
114-
* '{ List(${Expr.ofSeq(List(1, 2, 3))}: _*) } // equvalent to '{ List(1, 2, 3) }
115111
* ```
116112
*/
117-
def ofSeq[T](xs: Seq[Expr[T]])(using tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
118-
import qctx.tasty.{_, given _}
119-
Repeated(xs.map[Term](_.unseal).toList, tp.unseal).seal.asInstanceOf[Expr[Seq[T]]]
120-
}
121-
113+
def ofSeq[T](xs: Seq[Expr[T]])(using tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = Exprs(xs)
122114

123115
/** Lifts this list of expressions into an expression of a list
124116
*
@@ -128,7 +120,7 @@ object Expr {
128120
* `'{ List($e1, $e2, ...) }` typed as an `Expr[List[T]]`
129121
*/
130122
def ofList[T](xs: Seq[Expr[T]])(using Type[T], QuoteContext): Expr[List[T]] =
131-
if (xs.isEmpty) '{ Nil } else '{ List(${ofSeq(xs)}: _*) }
123+
if (xs.isEmpty) '{ Nil } else '{ List(${Exprs(xs)}: _*) }
132124

133125
/** Lifts this sequence of expressions into an expression of a tuple
134126
*
@@ -186,7 +178,7 @@ object Expr {
186178
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }, '{ $x8: $t8 }, '{ $x9: $t9 }, '{ $x10: $t10 }, '{ $x11: $t11 }, '{ $x12: $t12 }, '{ $x13: $t13 }, '{ $x14: $t14 }, '{ $x15: $t15 }, '{ $x16: $t16 }, '{ $x17: $t17 }, '{ $x18: $t18 }, '{ $x19: $t19 }, '{ $x20: $t20 }, '{ $x21: $t21 }, '{ $x22: $t22 }) =>
187179
'{ Tuple22($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22) }
188180
case _ =>
189-
'{ Tuple.fromIArray(IArray(${ofSeq(seq)}: _*)) }
181+
'{ Tuple.fromIArray(IArray(${Exprs(seq)}: _*)) }
190182
}
191183
}
192184

library/src/scala/quoted/ExprSeq.scala renamed to library/src/scala/quoted/Exprs.scala

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
package scala.quoted
22

33
/** Literal sequence of expressions */
4-
object ExprSeq {
4+
object Exprs {
5+
6+
/** Lifts this sequence of expressions into an expression of a sequence
7+
*
8+
* Transforms a sequence of expression
9+
* `Seq(e1, e2, ...)` where `ei: Expr[T]`
10+
* to an expression equivalent to
11+
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
12+
*
13+
* Usage:
14+
* ```scala
15+
* '{ List(${Exprs(List(1, 2, 3))}: _*) } // equvalent to '{ List(1, 2, 3) }
16+
* ```
17+
*/
18+
def apply[T](xs: Seq[Expr[T]])(using tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
19+
import qctx.tasty.{_, given _}
20+
Repeated(xs.map[Term](_.unseal).toList, tp.unseal).seal.asInstanceOf[Expr[Seq[T]]]
21+
}
522

623
/** Matches a literal sequence of expressions and return a sequence of expressions.
724
*
825
* Usage:
926
* ```scala
1027
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
1128
* def sumExpr(argsExpr: Expr[Seq[Int]])(using QuoteContext): Expr[Int] = argsExpr match
12-
* case ExprSeq(argExprs) =>
29+
* case Exprs(argExprs) =>
1330
* // argExprs: Seq[Expr[Int]]
1431
* ...
1532
* }

library/src/scala/quoted/ValueSeq.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ object ValueSeq {
1616
* ```
1717
*/
1818
def unapply[T](expr: Expr[Seq[T]])(using valueOf: ValueOfExpr[T], qctx: QuoteContext): Option[Seq[T]] = expr match {
19-
case ExprSeq(elems) =>
19+
case Exprs(elems) =>
2020
elems.foldRight(Option(List.empty[T])) { (elem, acc) =>
2121
(elem, acc) match {
2222
case (Value(value), Some(lst)) => Some(value :: lst)

library/src/scala/quoted/matching/package.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ package object matching {
2020
@deprecated("use scala.quoted.ConstSeq instead", "0.23.0")
2121
val ConstSeq: quoted.ConstSeq.type = quoted.ConstSeq
2222

23-
@deprecated("use scala.quoted.ExprSeq instead", "0.23.0")
24-
val ExprSeq: quoted.ExprSeq.type = quoted.ExprSeq
23+
@deprecated("use scala.quoted.Exprs instead", "0.23.0")
24+
val ExprSeq: quoted.Exprs.type = quoted.Exprs
2525

2626
@deprecated("use scala.quoted.Lambda instead", "0.23.0")
2727
val Lambda: quoted.Lambda.type = quoted.Lambda

tests/neg-macros/i6432/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object Macro {
99
def impl(sc: Expr[StringContext])(using qctx: QuoteContext) : Expr[Unit] = {
1010
import qctx.tasty._
1111
sc match {
12-
case '{ StringContext(${ExprSeq(parts)}: _*) } =>
12+
case '{ StringContext(${Exprs(parts)}: _*) } =>
1313
for (part @ Const(s) <- parts)
1414
error(s, part.unseal.pos)
1515
}

tests/neg-macros/i6432b/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object Macro {
99
def impl(sc: Expr[StringContext])(using qctx: QuoteContext) : Expr[Unit] = {
1010
import qctx.tasty._
1111
sc match {
12-
case '{ StringContext(${ExprSeq(parts)}: _*) } =>
12+
case '{ StringContext(${Exprs(parts)}: _*) } =>
1313
for (part @ Const(s) <- parts)
1414
error(s, part.unseal.pos)
1515
}

tests/neg/i6436.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- Error: tests/neg/i6436.scala:5:9 ------------------------------------------------------------------------------------
2-
5 | case '{ StringContext(${ExprSeq(parts)}: _*) } => // error
2+
5 | case '{ StringContext(${Exprs(parts)}: _*) } => // error
33
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
| no implicit argument of type scala.quoted.QuoteContext was found
55
-- [E006] Unbound Identifier Error: tests/neg/i6436.scala:6:34 ---------------------------------------------------------

0 commit comments

Comments
 (0)