Skip to content

Commit 43a2673

Browse files
committed
Add regression test
ConstructExpr and DestructExpr are used to construct and destruct case classes into and from tuples containing the expressions of their elements.
1 parent f215817 commit 43a2673

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package scala.quoted
2+
package util
3+
4+
trait ConstructExpr[T] {
5+
6+
type Elems <: Tuple
7+
8+
def from(x: Elems)(using Quotes): Expr[T]
9+
// def from(x: Tuple.Map[Elems, Expr])(using Quotes): Expr[T] // alternative
10+
11+
}
12+
13+
object ConstructExpr {
14+
15+
def apply[T](using ce: ConstructExpr[T]): ce.type = ce
16+
17+
/** Default implementation of `ConstructExpr[Tuple1[T]]` */
18+
given EmptyTupleConstructExpr[T: Type]: ConstructExpr[EmptyTuple] with {
19+
type Elems = EmptyTuple
20+
def from(x: Elems)(using Quotes): Expr[EmptyTuple] =
21+
'{ EmptyTuple }
22+
}
23+
24+
/** Default implementation of `ConstructExpr[Tuple1[T]]` */
25+
given Tuple1ConstructExpr[T: Type]: ConstructExpr[Tuple1[T]] with {
26+
type Elems = Tuple1[Expr[T]]
27+
def from(x: Elems)(using Quotes): Expr[Tuple1[T]] =
28+
'{ Tuple1[T](${x._1}) }
29+
}
30+
31+
/** Default implementation of `ConstructExpr[Tuple2[T1, T2]]` */
32+
given Tuple2ConstructExpr[T1: Type, T2: Type]: ConstructExpr[Tuple2[T1, T2]] with {
33+
type Elems = (Expr[T1], Expr[T2])
34+
def from(x: Elems)(using Quotes): Expr[Tuple2[T1, T2]] =
35+
'{ Tuple2[T1, T2](${x._1}, ${x._2}) }
36+
}
37+
38+
/** Default implementation of `ConstructExpr[Tuple3[T1, T2, T3]]` */
39+
given Tuple3ConstructExpr[T1: Type, T2: Type, T3: Type]: ConstructExpr[Tuple3[T1, T2, T3]] with {
40+
type Elems = (Expr[T1], Expr[T2], Expr[T3])
41+
def from(x: Elems)(using Quotes): Expr[Tuple3[T1, T2, T3]] =
42+
'{ Tuple3[T1, T2, T3](${x._1}, ${x._2}, ${x._3}) }
43+
}
44+
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package scala.quoted
2+
package util
3+
4+
trait DestructExpr[T] {
5+
6+
type Elems <: Tuple
7+
8+
def unapply(x: Expr[T])(using Quotes): Option[Elems]
9+
// def unapply(x: Expr[T])(using Quotes): Option[Tuple.Map[Elems, Expr]] // alternative
10+
11+
}
12+
13+
/** Default given instances of `DestructExpr` */
14+
object DestructExpr {
15+
16+
def unapply[T](x: Expr[T])(using de: DestructExpr[T])(using Quotes): Option[de.Elems] =
17+
de.unapply(x)
18+
19+
20+
/** Default implementation of `DestructExpr[Tuple1[...]]`
21+
* - Transform `'{Tuple1(x1)}` into `Some(Tuple1('{x1}))`
22+
* - Otherwise returns `None`
23+
*/
24+
given DestructTuple1[T1](using Type[T1]): DestructExpr[Tuple1[T1]] with {
25+
type Elems = Tuple1[Expr[T1]]
26+
def unapply(x: Expr[Tuple1[T1]])(using Quotes) = x match {
27+
case '{ new Tuple1[T1]($y) } => Some(Tuple1(y))
28+
case '{ Tuple1[T1]($y) } => Some(Tuple1(y))
29+
case _ => None
30+
}
31+
}
32+
33+
/** Default implementation of `DestructExpr[Tuple2[...]]`
34+
* - Transform `'{Tuple2(x1, x2)}` into `Some(Tuple2('{x1}, '{x2}))`
35+
* - Otherwise returns `None`
36+
*/
37+
given DestructTuple2[T1, T2](using Type[T1], Type[T2]): DestructExpr[Tuple2[T1, T2]] with {
38+
type Elems = (Expr[T1], Expr[T2])
39+
def unapply(x: Expr[Tuple2[T1, T2]])(using Quotes) = x match {
40+
case '{ new Tuple2[T1, T2]($y1, $y2) } => Some(Tuple2(y1, y2))
41+
case '{ Tuple2[T1, T2]($y1, $y2) } => Some(Tuple2(y1, y2))
42+
case '{ ($y1: T1) -> ($y2: T2) } => Some(Tuple2(y1, y2))
43+
case _ => None
44+
}
45+
}
46+
47+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted.*
2+
import scala.quoted.util.*
3+
4+
def test(using Quotes) =
5+
'{ Tuple2(1, 2) } match
6+
case DestructExpr((a, b)) =>
7+
ConstructExpr[(Int, Int)].from((a, b))

0 commit comments

Comments
 (0)