Skip to content

Commit c214949

Browse files
committed
wip
1 parent 77f4c68 commit c214949

37 files changed

+129
-69
lines changed

compiler/src/dotty/tools/dotc/transform/Splicer.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ object Splicer {
159159
case tree: Ident if tree.symbol.is(Inline) || summon[Env].contains(tree.symbol) =>
160160
// OK
161161

162+
// TODO remove case
163+
case Apply(Select(TypeApply(unsafeExpr, _), nme.apply), List(expr))
164+
if unsafeExpr.symbol.showFullName == "scala.quoted.QuoteScope.unsafeExpr" =>
165+
checkIfValidArgument(expr)
166+
162167
case _ =>
163168
val extra = if tree.span.isZeroExtent then ": " + tree.show else ""
164169
ctx.error(
@@ -242,6 +247,11 @@ object Splicer {
242247
if unsafe.symbol == defn.QuotedExprModule_unsafeExpr || unsafe.symbol == defn.QuotedTypeModule_unsafeType =>
243248
interpretTree(expr)
244249

250+
// TODO remove case
251+
case Apply(Select(TypeApply(unsafeExpr, _), nme.apply), List(expr))
252+
if unsafeExpr.symbol.showFullName == "scala.quoted.QuoteScope.unsafeExpr" =>
253+
interpretTree(expr)
254+
245255
case TypeApply(aio @ Select(expr, _), _) if aio.symbol == defn.Any_typeCast =>
246256
interpretTree(expr)
247257

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package dotty.internal
33
import scala.quoted._
44

55
object CompileTimeMacros:
6-
def codeExpr(using qctx: QuoteContext)(sc: Expr[StringContext], args: Expr[Seq[Any]]): Expr[String] =
6+
def codeExpr(using s: QuoteScope)(sc: s.Expr[StringContext], args: s.Expr[Seq[Any]]): s.Expr[String] =
77
(sc, args) match
8-
case (Expr.StringContext(Consts(parts)), Varargs(args2)) =>
8+
case (s.Expr.StringContext(Consts(parts)), s.Varargs(args2)) =>
99
Expr(StringContext(parts: _*).s(args2.map(_.show): _*))
1010
case _ =>
1111
Reporting.throwError("compiletime.code must be used as a string interpolator `code\"...\"`")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ object Expr {
187187
/** Given a tuple of the form `(Expr[A1], ..., Expr[An])`, outputs a tuple `Expr[(A1, ..., An)]`. */
188188
def ofTuple[T <: Tuple](tup: T)(using s: QuoteScope)(using s.Type[T], Tuple.IsMappedBy[s.Expr][T]): s.Expr[Tuple.InverseMap[T, s.Expr]] = {
189189
val elems: Seq[s.Expr[Any]] = tup.asInstanceOf[Product].productIterator.toSeq.asInstanceOf[Seq[s.Expr[Any]]]
190-
ofTupleFromSeq(elems).asInstanceOf[s.Expr[Tuple.InverseMap[T, s.Expr]]]
190+
ofTupleFromSeq(elems.asInstanceOf[Seq[Expr[Any]]]).asInstanceOf[s.Expr[Tuple.InverseMap[T, s.Expr]]] // TODO remove asInstanceOf[Seq[Expr[Any]]]
191191
}
192192

193193
/** Find an implicit of type `T` in the current scope given by `qctx`.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ object Lambda {
1515
* body('{3}) // returns '{ println(3) }
1616
* ```
1717
*/
18-
def unapply[F, Args <: Tuple, Res, G](using s: QuoteScope)(expr: s.Expr[F])(using tf: TupledFunction[F, Args => Res], tg: TupledFunction[G, Tuple.Map[Args, s.Expr] => Expr[Res]], functionType: Type[F]): Option[/*QuoteContext ?=>*/ G] = {
18+
def unapply[F, Args <: Tuple, Res, G](using s: QuoteScope)(expr: s.Expr[F])(using tf: TupledFunction[F, Args => Res], tg: TupledFunction[G, Tuple.Map[Args, s.Expr] => s.Expr[Res]], functionType: Type[F]): Option[/*QuoteContext ?=>*/ G] = {
1919
import qctx.tasty._
2020
val argTypes = functionType.unseal.tpe match
2121
case AppliedType(_, functionArguments) => functionArguments.init.asInstanceOf[List[Type]]
2222
qctx.tasty.internal.lambdaExtractor(expr.unseal, argTypes).map { fn =>
2323
def f(args: Tuple.Map[Args, s.Expr]): s.Expr[Res] =
2424
fn(args.toArray.toList.map(_.asInstanceOf[s.Expr[Any]].unseal)).seal.asInstanceOf[s.Expr[Res]]
25-
tg.untupled(f)
25+
tg.untupled(f) // TODO remove asInstanceOf
2626
}
2727

2828
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ object Liftable {
110110

111111
given [T: Type: Liftable] as Liftable[Seq[T]] = new Liftable[Seq[T]] {
112112
def toExpr(xs: Seq[T]): (s: QuoteScope) ?=> s.Expr[Seq[T]] =
113-
Expr.ofSeq(xs.map(summon[Liftable[T]].toExpr))
113+
Expr.ofSeq[T](xs.map(x => summon[Liftable[T]].toExpr(x).asInstanceOf[Expr[T]]))
114114
}
115115

116116
given [T: Type: Liftable] as Liftable[List[T]] = new Liftable[List[T]] {
117117
def toExpr(xs: List[T]): (s: QuoteScope) ?=> s.Expr[List[T]] =
118-
Expr.ofList(xs.map(summon[Liftable[T]].toExpr))
118+
Expr.ofList(xs.map(x => summon[Liftable[T]].toExpr(x).asInstanceOf[Expr[T]]))
119119
}
120120

121121
given [T: Type: Liftable] as Liftable[Set[T]] = new Liftable[Set[T]] {

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

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ import scala.quoted.show.SyntaxHighlight
1313
trait QuoteScope { self =>
1414

1515
/** Quoted expression of type `T` */
16-
type Expr[+T] <: scala.quoted.Expr[T] // TODO replace `<: scala.quoted.Expr[T]` with `<: tasty.Term`
16+
type Expr[+T] // TODO replace `<: scala.quoted.Expr[T]` with `<: tasty.Term`
1717

18-
object Expr {
18+
/** Show a source code like representation of this expression without syntax highlight */
19+
def [T](expr: Expr[T]).show(using QuoteScope): String =
20+
expr.unseal.showWith(SyntaxHighlight.plain)
21+
22+
/** View this expression `Expr[T]` as a `Term` */
23+
def [T](expr: Expr[T]).unseal: self.tasty.Term =
24+
self.tasty.internal.QuotedExpr_unseal(expr.asInstanceOf[scala.quoted.Expr[T]])(using self.tasty.rootContext)
1925

20-
// /** Show a source code like representation of this expression without syntax highlight */
21-
// def [T](expr: Expr[T]).show(using QuoteScope): String =
22-
// expr.unseal.showWith(SyntaxHighlight.plain)
26+
object Expr {
2327

2428
// /** Show a source code like representation of this expression */
2529
// def show(syntaxHighlight: SyntaxHighlight)(using qctx: QuoteContext): String =
@@ -56,14 +60,29 @@ trait QuoteScope { self =>
5660
// def cast[U](using tp: scala.quoted.Type[U])(using qctx: QuoteContext): scala.quoted.Expr[U] =
5761
// qctx.tasty.internal.QuotedExpr_cast[U](expr)(using tp, qctx.tasty.rootContext)
5862

59-
/** View this expression `Expr[T]` as a `Term` */
60-
def [T](expr: Expr[T]).unseal: self.tasty.Term =
61-
self.tasty.internal.QuotedExpr_unseal(expr.asInstanceOf[scala.quoted.Expr[T]])(using self.tasty.rootContext)
63+
object StringContext {
64+
/** Matches a `StringContext(part0, part1, ...)` and extracts the parts of a call to if the
65+
* parts are passed explicitly. Returns the equvalent to `Seq('{part0}, '{part1}, ...)`.
66+
*/
67+
def unapply(sc: Expr[StringContext]): Option[Seq[Expr[String]]] =
68+
val qctx = self.asInstanceOf[QuoteContext & self.type] // FIXME remove
69+
given qctx.type = qctx
70+
sc.asInstanceOf[scala.quoted.Expr[StringContext]] match
71+
case '{ scala.StringContext(${scala.quoted.Varargs(parts)}: _*) } => Some(parts.asInstanceOf[Seq[Expr[String]]])
72+
case '{ new scala.StringContext(${scala.quoted.Varargs(parts)}: _*) } => Some(parts.asInstanceOf[Seq[Expr[String]]])
73+
case _ => None
74+
}
75+
76+
6277
}
6378

6479
/** Quoted type (or kind) `T` */
6580
type Type[T <: AnyKind] <: scala.quoted.Type[T] // TODO replace `<: scala.quoted.Type[T]` with `<: tasty.Type`
6681

82+
/** View this expression `Type[T]` as a `tasty.TypeTree` */
83+
def [T <: AnyKind](tpe: Type[T]).unseal: self.tasty.TypeTree =
84+
self.tasty.internal.QuotedType_unseal(tpe.asInstanceOf[scala.quoted.Type[T]])(using self.tasty.rootContext)
85+
6786
object Type {
6887
// /** Show a source code like representation of this type without syntax highlight */
6988
// def show(using qctx: QuoteContext): String =
@@ -73,9 +92,6 @@ trait QuoteScope { self =>
7392
// def show(syntaxHighlight: SyntaxHighlight)(using qctx: QuoteContext): String =
7493
// this.unseal.showWith(syntaxHighlight)
7594

76-
/** View this expression `Type[T]` as a `tasty.TypeTree` */
77-
def [T <: AnyKind](tpe: Type[T]).unseal: self.tasty.TypeTree =
78-
self.tasty.internal.QuotedType_unseal(tpe.asInstanceOf[scala.quoted.Type[T]])(using self.tasty.rootContext)
7995
}
8096

8197
/** Low-level Typed AST API `tasty` meta-programming API.
@@ -102,4 +118,51 @@ trait QuoteScope { self =>
102118
val tasty: self.tasty.type
103119
}
104120

121+
/** Literal sequence of expressions */
122+
object Varargs {
123+
124+
/** Lifts this sequence of expressions into an expression of a sequence
125+
*
126+
* Transforms a sequence of expression
127+
* `Seq(e1, e2, ...)` where `ei: Expr[T]`
128+
* to an expression equivalent to
129+
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
130+
*
131+
* Usage:
132+
* ```scala
133+
* '{ List(${Varargs(List(1, 2, 3))}: _*) } // equvalent to '{ List(1, 2, 3) }
134+
* ```
135+
*/
136+
def apply[T](xs: Seq[Expr[T]])(using tp: Type[T]): Expr[Seq[T]] = {
137+
import tasty._
138+
Repeated(xs.map[Term](_.unseal).toList, self.unseal(tp)).seal.asInstanceOf[Expr[Seq[T]]] // cast OK
139+
}
140+
141+
/** Matches a literal sequence of expressions and return a sequence of expressions.
142+
*
143+
* Usage:
144+
* ```scala
145+
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
146+
* def sumExpr(argsExpr: Expr[Seq[Int]])(using QuoteContext): Expr[Int] = argsExpr match
147+
* case Varargs(argVarargs) =>
148+
* // argVarargs: Seq[Expr[Int]]
149+
* ...
150+
* }
151+
* ```
152+
*/
153+
def unapply[T](expr: Expr[Seq[T]]): Option[Seq[Expr[T]]] = {
154+
import tasty._
155+
def rec(tree: Term): Option[Seq[Expr[T]]] = tree match {
156+
case Typed(Repeated(elems, _), _) => Some(elems.map(x => x.seal.asInstanceOf[Expr[T]])) // ccast OK
157+
case Block(Nil, e) => rec(e)
158+
case Inlined(_, Nil, e) => rec(e)
159+
case _ => None
160+
}
161+
rec(expr.unseal)
162+
}
163+
164+
}
165+
166+
given unsafeExpr[T] as Conversion[Expr[T], scala.quoted.Expr[T]] = _.asInstanceOf
167+
105168
}

tests/run-staging/shonan-hmm/Lifters.scala renamed to tests/disabled/run-staging/shonan-hmm/Lifters.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object Lifters {
2626

2727
private def initArray[T : Liftable : Type](arr: Array[T], array: Expr[Array[T]])(using QuoteContext): Expr[Array[T]] = {
2828
UnrolledExpr.block(
29-
arr.zipWithIndex.map {
29+
arr.zipWithIndex.map[Expr[Unit]] {
3030
case (x, i) => '{ $array(${i}) = ${x} }
3131
}.toList,
3232
array)

tests/run-staging/shonan-hmm/Vmults.scala renamed to tests/disabled/run-staging/shonan-hmm/Vmults.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object Vmults {
2020
}
2121

2222
def vmultCA(using QuoteContext): Expr[(Array[Complex[Int]], Array[Complex[Int]], Array[Complex[Int]]) => Unit] = '{
23-
(vout, v1, v2) => {
23+
(vout: Array[Complex[Int]], v1: Array[Complex[Int]], v2: Array[Complex[Int]]) => {
2424
val n = vout.length
2525
${
2626
val vout_ = OVec[Expr[Int], Complex[Expr[Int]], Expr[Unit]]('n, (i, v) => '{vout($i) = ${Complex.of_expr_complex(v)}})

tests/neg-macros/i7142.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package macros
2+
import scala.quoted._
3+
import scala.util.control.NonLocalReturns._
4+
5+
def oops(using s: QuoteScope): s.Expr[Int] =
6+
returning('{ { (x: Int) => ${ throwReturn('x) }} apply 0 }) // error

tests/neg-macros/i7142b/Macro_1.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/neg-macros/i7142b/Test_2.scala

Lines changed: 0 additions & 4 deletions
This file was deleted.

tests/neg-macros/splice-in-top-level-splice-2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import scala.quoted._
22

33
object Foo {
44
inline def foo(): Int = ${$x} // error
5-
def x(using QuoteContext): Expr[Expr[Int]] = '{ '{1} }
5+
def x(using QuoteContext): Expr[Expr[Int]] = '{ '{1} } // error
66
}

tests/pos/i7046.scala renamed to tests/pos-macros/i7046.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import scala.quoted._
22

33
inline def mcr: Any = ${mcrImpl}
44
def mcrImpl(using ctx: QuoteContext): Expr[Any] = {
5-
val tpl: Expr[1] = '{1}
5+
val tpl: Expr[1] = '{1}.asInstanceOf[Expr[1]] // FIXME: remove asInstanceOf
66
'{()}
77
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
import scala.quoted._
3+
4+
def f(using s: QuoteScope) = {
5+
val x: s.Expr[Double] = '{5: Double} // FIXME remove ascription
6+
}

tests/pos/quote-this.scala renamed to tests/pos-macros/quote-this.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Foo {
66
${ this.a }
77
}
88

9-
def d(using QuoteContext): Expr[QuoteContext ?=> Expr[Int]] = '{ '{1} }
9+
def d(using QuoteContext): Expr[QuoteContext ?=> Expr[Int]] = '{ (using q: QuoteContext) => '{1} } // FIXME
1010

1111
def foo[T](x: T): T = x
1212

tests/run-macros/inferred-repeated-result/test_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ object Macros {
1717
s"$name : $returnType"
1818
}.sorted
1919

20-
methods.foldLeft('{}) { (res, m) => '{ $res; println(${m}) } }
20+
methods.foldLeft[Expr[Unit]]('{}) { (res, m) => '{ $res; println(${m}) } }
2121
}
2222
}

tests/run-macros/string-context-implicits/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ inline def (sc: StringContext) showMe(inline args: Any*): String = ${ showMeExpr
66
private def showMeExpr(sc: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using qctx: QuoteContext): Expr[String] = {
77
argsExpr match {
88
case Varargs(argExprs) =>
9-
val argShowedExprs = argExprs.map {
9+
val argShowedExprs = argExprs.map[Expr[Any]] {
1010
case '{ $arg: $tp } =>
1111
val showTp = '[Show[$tp]]
1212
Expr.summon[Show[$tp]] match {

tests/run-staging/i5152.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import scala.quoted.staging._
33

44
object Test {
55
given Toolbox = Toolbox.make(getClass.getClassLoader)
6-
def eval1(ff: Expr[Int => Int])(using QuoteContext): Expr[Int => Int] = '{identity}
6+
def eval1(ff: Expr[Int => Int])(using QuoteContext): Expr[Int => Int] = '{identity[Int]}
77

88
def peval1()(using QuoteContext): Expr[Unit] = '{
99
lazy val f: Int => Int = ${eval1('{(y: Int) => f(y)})}

tests/run-staging/i7142.scala

Lines changed: 0 additions & 13 deletions
This file was deleted.

tests/run-staging/quote-ackermann-1.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ object Test {
1212
println(ack3(4))
1313
}
1414

15-
def ackermann(m: Int)(using QuoteContext): Expr[Int => Int] = {
16-
if (m == 0) '{ n => n + 1 }
17-
else '{ n =>
15+
def ackermann(m: Int)(using s: QuoteScope): s.Expr[Int => Int] = {
16+
if (m == 0) '{ (n: Int) => n + 1 } // FIXME infer parameter type
17+
else '{ (n: Int) =>
1818
def `ackermann(m-1)`(n: Int): Int = ${Expr.betaReduce(ackermann(m - 1))('n)} // Expr[Int => Int] applied to Expr[Int]
1919
def `ackermann(m)`(n: Int): Int =
2020
if (n == 0) `ackermann(m-1)`(1) else `ackermann(m-1)`(`ackermann(m)`(n - 1))

tests/run-staging/quote-fun-app-1.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ object Test {
1212
println(f(43))
1313
}
1414

15-
def f1(using QuoteContext): Expr[Int => Int] = '{ n => ${Expr.betaReduce(f2)('n)} }
16-
def f2(using QuoteContext): Expr[Int => Int] = '{ n => ${Expr.betaReduce(f3)('n)} }
17-
def f3(using QuoteContext): Expr[Int => Int] = '{ n => ${Expr.betaReduce(f4)('n)} }
18-
def f4(using QuoteContext): Expr[Int => Int] = '{ n => n }
15+
def f1(using QuoteContext): Expr[Int => Int] = '{ (n: Int) => ${Expr.betaReduce(f2)('n)} } // FIXME infer parameter type
16+
def f2(using QuoteContext): Expr[Int => Int] = '{ (n: Int) => ${Expr.betaReduce(f3)('n)} }
17+
def f3(using QuoteContext): Expr[Int => Int] = '{ (n: Int) => ${Expr.betaReduce(f4)('n)} }
18+
def f4(using QuoteContext): Expr[Int => Int] = '{ (n: Int) => n }
1919
}

tests/run-staging/quote-run-2.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ object Test {
1111
else if (n % 2 == 0) '{ { val y = $x * $x; ${powerCode(n / 2, 'y)} } }
1212
else '{ $x * ${powerCode(n - 1, x)} }
1313

14-
println(powerCode(0, '{5}).show)
15-
println(powerCode(1, '{5}).show)
16-
println(powerCode(2, '{5}).show)
17-
println(powerCode(3, '{5}).show)
18-
println(powerCode(22, '{5}).show)
14+
println(powerCode(0, '{5.0}).show)
15+
println(powerCode(1, '{5.0}).show)
16+
println(powerCode(2, '{5.0}).show)
17+
println(powerCode(3, '{5.0}).show)
18+
println(powerCode(22, '{5.0}).show)
1919
}
2020
}

tests/run-staging/quote-unrolled-foreach.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object Test {
1818
println(code1Tpe2.show)
1919
println()
2020

21-
def code2(using QuoteContext) = '{ (arr: Array[Int]) => ${ foreach1('arr, '{i => System.out.println(i)}) } }
21+
def code2(using QuoteContext) = '{ (arr: Array[Int]) => ${ foreach1('arr, '{(i: Int) => System.out.println(i)}) } }
2222
println(code2.show)
2323
println()
2424

@@ -37,7 +37,7 @@ object Test {
3737

3838
def printAll(arr: Array[Int]) = '{
3939
val arr1 = ${ arr }
40-
${ foreach1('arr1, '{x => println(x)}) }
40+
${ foreach1('arr1, '{(x: Int) => println(x)}) }
4141
}
4242

4343
println(printAll(Array(1, 3, 4, 5)).show)

tests/run-staging/quoted-show-name.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object Test {
1010
}
1111

1212
def powerCode(n: Long)(using QuoteContext): Expr[Double => Double] =
13-
'{ x1 => ${powerCode(n, 2, 'x1)} }
13+
'{ (x1: Double) => ${powerCode(n, 2, 'x1)} }
1414

1515
def powerCode(n: Long, idx: Int, x: Expr[Double])(using QuoteContext): Expr[Double] =
1616
if (n == 0) '{1.0}

0 commit comments

Comments
 (0)