Skip to content

Commit 02e67ff

Browse files
authored
Merge pull request #7076 from dotty-staging/improve-toExprOfTuple
Make toExprOfTuple produce tuples with precise types
2 parents 6f6751d + 49c6626 commit 02e67ff

File tree

4 files changed

+240
-123
lines changed

4 files changed

+240
-123
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package scala
2+
3+
package object quoted {
4+
5+
/** Evaluate the contents of this expression and return the result.
6+
* It provides a new QuoteContext that is only valid within the scope the argument.
7+
*
8+
* Usage:
9+
* ```
10+
* val e: T = run { // (given qctx: QuoteContext) =>
11+
* expr
12+
* }
13+
* ```
14+
* where `expr: Expr[T]`
15+
*
16+
* This method should not be called in a context where there is already has a `QuoteContext`
17+
* such as within a `run` or a `withQuoteContext`.
18+
*/
19+
def run[T](expr: given QuoteContext => Expr[T]) given (toolbox: Toolbox): T = toolbox.run(expr given _)
20+
21+
/** Provide a new quote context within the scope of the argument that is only valid within the scope the argument.
22+
* Return the result of the argument.
23+
*
24+
* Usage:
25+
* ```
26+
* val e: T = withQuoteContext { // (given qctx: QuoteContext) =>
27+
* thunk
28+
* }
29+
* ```
30+
* where `thunk: T`
31+
*
32+
* This method should not be called in a context where there is already has a `QuoteContext`
33+
* such as within a `run` or a `withQuoteContext`.
34+
*/
35+
def withQuoteContext[T](thunk: given QuoteContext => T) given (toolbox: Toolbox): T = {
36+
var result: T = NoResult.asInstanceOf[T]
37+
def dummyRun given QuoteContext: Expr[Unit] = {
38+
result = thunk
39+
Expr.unitExpr
40+
}
41+
toolbox.run(dummyRun given _)
42+
assert(result != NoResult) // toolbox.run should have thrown an exception
43+
result
44+
}
45+
46+
private object NoResult
47+
48+
object autolift {
49+
given autoToExpr[T] as Conversion[T, Expr[T]] given Liftable[T], QuoteContext = _.toExpr
50+
}
51+
52+
implicit object ExprOps {
53+
def (x: T) toExpr[T: Liftable] given QuoteContext: Expr[T] = the[Liftable[T]].toExpr(x)
54+
55+
/** Lifts this sequence of expressions into an expression of a sequence
56+
*
57+
* Transforms a sequence of expression
58+
* `Seq(e1, e2, ...)` where `ei: Expr[T]`
59+
* to an expression equivalent to
60+
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
61+
*
62+
* Usage:
63+
* ```scala
64+
* '{ List(${List(1, 2, 3).toExprOfSeq}: _*) } // equvalent to '{ List(1, 2, 3) }
65+
* ```
66+
*/
67+
def (seq: Seq[Expr[T]]) toExprOfSeq[T] given (tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
68+
import qctx.tasty._
69+
Repeated(seq.map(_.unseal).toList, tp.unseal).seal.asInstanceOf[Expr[Seq[T]]]
70+
}
71+
72+
/** Lifts this list of expressions into an expression of a list
73+
*
74+
* Transforms a list of expression
75+
* `List(e1, e2, ...)` where `ei: Expr[T]`
76+
* to an expression equivalent to
77+
* `'{ List($e1, $e2, ...) }` typed as an `Expr[List[T]]`
78+
*/
79+
def (list: List[Expr[T]]) toExprOfList[T] given Type[T], QuoteContext: Expr[List[T]] =
80+
if (list.isEmpty) '{ Nil } else '{ List(${list.toExprOfSeq}: _*) }
81+
82+
/** Lifts this sequence of expressions into an expression of a tuple
83+
*
84+
* Transforms a sequence of expression
85+
* `Seq(e1, e2, ...)` where `ei: Expr[_]`
86+
* to an expression equivalent to
87+
* `'{ ($e1, $e2, ...) }` typed as an `Expr[Tuple]`
88+
*/
89+
def (seq: Seq[Expr[_]]) toExprOfTuple given QuoteContext: Expr[Tuple] = {
90+
seq match {
91+
case Seq() =>
92+
Expr.unitExpr
93+
case Seq('{ $x1: $t1 }) =>
94+
'{ Tuple1($x1) }
95+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }) =>
96+
'{ Tuple2($x1, $x2) }
97+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }) =>
98+
'{ Tuple3($x1, $x2, $x3) }
99+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }) =>
100+
'{ Tuple4($x1, $x2, $x3, $x4) }
101+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }) =>
102+
'{ Tuple5($x1, $x2, $x3, $x4, $x5) }
103+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }) =>
104+
'{ Tuple6($x1, $x2, $x3, $x4, $x5, $x6) }
105+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }) =>
106+
'{ Tuple7($x1, $x2, $x3, $x4, $x5, $x6, $x7) }
107+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }, '{ $x8: $t8 }) =>
108+
'{ Tuple8($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8) }
109+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }, '{ $x8: $t8 }, '{ $x9: $t9 }) =>
110+
'{ Tuple9($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9) }
111+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }, '{ $x8: $t8 }, '{ $x9: $t9 }, '{ $x10: $t10 }) =>
112+
'{ Tuple10($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10) }
113+
case Seq('{ $x1: $t1 }, '{ $x2: $t2 }, '{ $x3: $t3 }, '{ $x4: $t4 }, '{ $x5: $t5 }, '{ $x6: $t6 }, '{ $x7: $t7 }, '{ $x8: $t8 }, '{ $x9: $t9 }, '{ $x10: $t10 }, '{ $x11: $t11 }) =>
114+
'{ Tuple11($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11) }
115+
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 }) =>
116+
'{ Tuple12($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12) }
117+
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 }) =>
118+
'{ Tuple13($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13) }
119+
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 }) =>
120+
'{ Tuple14($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14) }
121+
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 }) =>
122+
'{ Tuple15($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15) }
123+
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 }) =>
124+
'{ Tuple16($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16) }
125+
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 }) =>
126+
'{ Tuple17($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17) }
127+
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 }) =>
128+
'{ Tuple18($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18) }
129+
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 }) =>
130+
'{ Tuple19($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19) }
131+
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 }) =>
132+
'{ Tuple20($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20) }
133+
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 }) =>
134+
'{ Tuple21($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21) }
135+
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 }) =>
136+
'{ Tuple22($x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22) }
137+
case _ =>
138+
'{ Tuple.fromIArray(IArray(${seq.toExprOfSeq}: _*)) }
139+
}
140+
}
141+
}
142+
143+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package scala
2+
3+
package object quoted {
4+
5+
/** Evaluate the contents of this expression and return the result.
6+
* It provides a new QuoteContext that is only valid within the scope the argument.
7+
*
8+
* Usage:
9+
* ```
10+
* val e: T = run { // (given qctx: QuoteContext) =>
11+
* expr
12+
* }
13+
* ```
14+
* where `expr: Expr[T]`
15+
*
16+
* This method should not be called in a context where there is already has a `QuoteContext`
17+
* such as within a `run` or a `withQuoteContext`.
18+
*/
19+
def run[T](expr: given QuoteContext => Expr[T]) given (toolbox: Toolbox): T = toolbox.run(expr given _)
20+
21+
/** Provide a new quote context within the scope of the argument that is only valid within the scope the argument.
22+
* Return the result of the argument.
23+
*
24+
* Usage:
25+
* ```
26+
* val e: T = withQuoteContext { // (given qctx: QuoteContext) =>
27+
* thunk
28+
* }
29+
* ```
30+
* where `thunk: T`
31+
*
32+
* This method should not be called in a context where there is already has a `QuoteContext`
33+
* such as within a `run` or a `withQuoteContext`.
34+
*/
35+
def withQuoteContext[T](thunk: given QuoteContext => T) given (toolbox: Toolbox): T = {
36+
var result: T = NoResult.asInstanceOf[T]
37+
def dummyRun given QuoteContext: Expr[Unit] = {
38+
result = thunk
39+
Expr.unitExpr
40+
}
41+
toolbox.run(dummyRun given _)
42+
assert(result != NoResult) // toolbox.run should have thrown an exception
43+
result
44+
}
45+
46+
private object NoResult
47+
48+
object autolift {
49+
given autoToExpr[T] as Conversion[T, Expr[T]] given Liftable[T], QuoteContext = _.toExpr
50+
}
51+
52+
implicit object ExprOps {
53+
def (x: T) toExpr[T: Liftable] given QuoteContext: Expr[T] = the[Liftable[T]].toExpr(x)
54+
55+
/** Lifts this sequence of expressions into an expression of a sequence
56+
*
57+
* Transforms a sequence of expression
58+
* `Seq(e1, e2, ...)` where `ei: Expr[T]`
59+
* to an expression equivalent to
60+
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
61+
*
62+
* Usage:
63+
* ```scala
64+
* '{ List(${List(1, 2, 3).toExprOfSeq}: _*) } // equvalent to '{ List(1, 2, 3) }
65+
* ```
66+
*/
67+
def (seq: Seq[Expr[T]]) toExprOfSeq[T] given (tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
68+
import qctx.tasty._
69+
Repeated(seq.map(_.unseal).toList, tp.unseal).seal.asInstanceOf[Expr[Seq[T]]]
70+
}
71+
72+
/** Lifts this list of expressions into an expression of a list
73+
*
74+
* Transforms a list of expression
75+
* `List(e1, e2, ...)` where `ei: Expr[T]`
76+
* to an expression equivalent to
77+
* `'{ List($e1, $e2, ...) }` typed as an `Expr[List[T]]`
78+
*/
79+
def (list: List[Expr[T]]) toExprOfList[T] given Type[T], QuoteContext: Expr[List[T]] =
80+
throw new Exception("running on non bootstrapped library")
81+
82+
/** Lifts this sequence of expressions into an expression of a tuple
83+
*
84+
* Transforms a sequence of expression
85+
* `Seq(e1, e2, ...)` where `ei: Expr[_]`
86+
* to an expression equivalent to
87+
* `'{ ($e1, $e2, ...) }` typed as an `Expr[Tuple]`
88+
*/
89+
def (seq: Seq[Expr[_]]) toExprOfTuple given QuoteContext: Expr[Tuple] =
90+
throw new Exception("running on non bootstrapped library")
91+
92+
}
93+
94+
}

library/src/scala/quoted/package.scala

-120
This file was deleted.

0 commit comments

Comments
 (0)