Skip to content

Commit 77d28da

Browse files
committed
Implement quoted type patterns
1 parent f032a19 commit 77d28da

File tree

8 files changed

+117
-7
lines changed

8 files changed

+117
-7
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ object PickledQuotes {
7575
unpickled match {
7676
case Block(aliases, tpt) =>
7777
// `@quoteTypeTag type` aliasses are not required after unpickling
78-
tpt
78+
// `@quoteTypeTag type` aliasses are not required after unpickling
79+
val aliases1 = aliases.filter(!_.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot))
80+
seq(aliases1, tpt)
7981
case tpt => tpt
8082
}
8183
}

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,16 @@ trait QuotesAndSplices { self: Typer =>
346346

347347
val splicePat = typed(untpd.Tuple(splices.map(x => untpd.TypedSplice(replaceBindingsInTree.transform(x)))).withSpan(quoted.span), patType)
348348

349+
val unapplySym = if (tree.quoted.isTerm) defn.InternalQuotedExpr_unapply else defn.InternalQuotedType_unapply
350+
val quoteClass = if (tree.quoted.isTerm) defn.QuotedExprClass else defn.QuotedTypeClass
351+
val quotedPattern =
352+
if (tree.quoted.isTerm) ref(defn.InternalQuoted_exprQuote.termRef).appliedToType(defn.AnyType).appliedTo(shape).select(nme.apply).appliedTo(qctx)
353+
else ref(defn.InternalQuoted_typeQuote.termRef).appliedToTypeTrees(shape :: Nil)
349354
UnApply(
350-
fun = ref(defn.InternalQuotedExpr_unapply.termRef).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
351-
implicits =
352-
ref(defn.InternalQuoted_exprQuote.termRef).appliedToType(defn.AnyType).appliedTo(shape).select(nme.apply).appliedTo(qctx) ::
353-
Literal(Constant(typeBindings.nonEmpty)) ::
354-
qctx :: Nil,
355+
fun = ref(unapplySym.termRef).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
356+
implicits = quotedPattern :: Literal(Constant(typeBindings.nonEmpty)) :: qctx :: Nil,
355357
patterns = splicePat :: Nil,
356-
proto = defn.QuotedExprClass.typeRef.appliedTo(replaceBindings(quoted1.tpe) & quotedPt))
358+
proto = quoteClass.typeRef.appliedTo(replaceBindings(quoted1.tpe) & quotedPt))
357359
}
358360

359361
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
%Int%
2+
%List[%Int%]%
3+
%Option[%Int%]%
4+
%%Int% => scala.Double%
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
5+
inline def lift[A]: String = ${ matchesExpr('[A]) }
6+
7+
private def matchesExpr(tp: Type[_]) given QuoteContext: Expr[String] = {
8+
def lift(tp: Type[_]): String = tp match {
9+
case '[Int] => "%Int%"
10+
case '[List[$t]] => s"%List[${lift(t)}]%"
11+
case '[Option[$t]] => s"%Option[${lift(t)}]%"
12+
case '[Function1[$t, $u]] => s"%${lift(t)} => ${lift(u)}%"
13+
case _ => tp.show
14+
}
15+
lift(tp).toExpr
16+
}
17+
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
import Macros._
3+
4+
import scala.internal.Quoted._
5+
6+
object Test {
7+
8+
def main(args: Array[String]): Unit = {
9+
10+
println(lift[Int])
11+
println(lift[List[Int]])
12+
println(lift[Option[Int]])
13+
println(lift[Int => Double])
14+
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Scrutinee: scala.Int
2+
Pattern: scala.Int
3+
Result: Some(List())
4+
5+
Scrutinee: 1
6+
Pattern: scala.Int
7+
Result: Some(List())
8+
9+
Scrutinee: scala.Int
10+
Pattern: 2
11+
Result: None
12+
13+
Scrutinee: scala.collection.immutable.List[scala.Int]
14+
Pattern: scala.collection.immutable.List[scala.Int]
15+
Result: Some(List())
16+
17+
Scrutinee: scala.collection.immutable.List[scala.Int]
18+
Pattern: scala.collection.immutable.List[scala.Double]
19+
Result: None
20+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import scala.quoted._
2+
import scala.quoted.matching._
3+
4+
5+
object Macros {
6+
7+
inline def matches[A, B]: Unit = ${ matchesExpr('[A], '[B]) }
8+
9+
private def matchesExpr[A, B](a: Type[A], b: Type[B]) given (qctx: QuoteContext): Expr[Unit] = {
10+
import qctx.tasty.{Bind => _, _}
11+
12+
val res = scala.internal.quoted.Type.unapply[Tuple, Tuple](a)(b, true, qctx).map { tup =>
13+
tup.toArray.toList.map {
14+
case r: quoted.Type[_] =>
15+
s"Type(${r.unseal.show})"
16+
case r: Bind[_] =>
17+
s"Bind(${r.name})"
18+
}
19+
}
20+
21+
'{
22+
println("Scrutinee: " + ${a.unseal.show.toExpr})
23+
println("Pattern: " + ${b.unseal.show.toExpr})
24+
println("Result: " + ${res.toString.toExpr})
25+
println()
26+
}
27+
}
28+
29+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
import Macros._
3+
4+
import scala.internal.Quoted._
5+
6+
object Test {
7+
8+
def main(args: Array[String]): Unit = {
9+
10+
matches[Int, Int]
11+
matches[1, Int]
12+
matches[Int, 2]
13+
14+
matches[List[Int], List[Int]]
15+
matches[List[Int], List[Double]]
16+
17+
}
18+
}
19+

0 commit comments

Comments
 (0)