@@ -13,13 +13,17 @@ import scala.quoted.show.SyntaxHighlight
13
13
trait QuoteScope { self =>
14
14
15
15
/** 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`
17
17
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)
19
25
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 {
23
27
24
28
// /** Show a source code like representation of this expression */
25
29
// def show(syntaxHighlight: SyntaxHighlight)(using qctx: QuoteContext): String =
@@ -56,14 +60,29 @@ trait QuoteScope { self =>
56
60
// def cast[U](using tp: scala.quoted.Type[U])(using qctx: QuoteContext): scala.quoted.Expr[U] =
57
61
// qctx.tasty.internal.QuotedExpr_cast[U](expr)(using tp, qctx.tasty.rootContext)
58
62
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
+
62
77
}
63
78
64
79
/** Quoted type (or kind) `T` */
65
80
type Type [T <: AnyKind ] <: scala.quoted.Type [T ] // TODO replace `<: scala.quoted.Type[T]` with `<: tasty.Type`
66
81
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
+
67
86
object Type {
68
87
// /** Show a source code like representation of this type without syntax highlight */
69
88
// def show(using qctx: QuoteContext): String =
@@ -73,9 +92,6 @@ trait QuoteScope { self =>
73
92
// def show(syntaxHighlight: SyntaxHighlight)(using qctx: QuoteContext): String =
74
93
// this.unseal.showWith(syntaxHighlight)
75
94
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)
79
95
}
80
96
81
97
/** Low-level Typed AST API `tasty` meta-programming API.
@@ -102,4 +118,51 @@ trait QuoteScope { self =>
102
118
val tasty : self.tasty.type
103
119
}
104
120
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
+
105
168
}
0 commit comments