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
}

0 commit comments

Comments
 (0)