Skip to content

Commit ff9070a

Browse files
committed
wip
1 parent 87f7d52 commit ff9070a

File tree

8 files changed

+80
-8
lines changed

8 files changed

+80
-8
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,10 @@ class Definitions {
723723
lazy val InternalQuoted_patternHoleR: TermRef = InternalQuotedModule.requiredMethodRef("patternHole")
724724
def InternalQuoted_patternHole(implicit ctx: Context): Symbol = InternalQuoted_patternHoleR.symbol
725725
lazy val InternalQuoted_patternBindHoleAnnot: ClassSymbol = InternalQuotedModule.requiredClass("patternBindHole")
726+
lazy val InternalQuoted_patternMatchBindHoleModuleR: TermRef = InternalQuotedModule.requiredValueRef("patternMatchBindHole".toTermName)
727+
def InternalQuoted_patternMatchBindHoleModule: Symbol = InternalQuoted_patternMatchBindHoleModuleR.symbol
728+
lazy val InternalQuoted_patternMatchBindHole_unapplyR: TermRef = InternalQuoted_patternMatchBindHoleModule.requiredMethodRef("unapply")
729+
def InternalQuoted_patternMatchBindHole_unapply(implicit ctx: Context): Symbol = InternalQuoted_patternMatchBindHole_unapplyR.symbol
726730

727731
lazy val InternalQuotedMatcherModuleRef: TermRef = ctx.requiredModuleRef("scala.internal.quoted.Matcher")
728732
def InternalQuotedMatcherModule(implicit ctx: Context): Symbol = InternalQuotedMatcherModuleRef.symbol

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,17 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
10131013
tree
10141014
}
10151015

1016-
def typedUnApply(tree: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = track("typedUnApply") {
1016+
def typedUnApply(tree0: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = track("typedUnApply") {
1017+
val tree =
1018+
if (ctx.mode.is(Mode.QuotedPattern)) { // TODO move to desugar
1019+
val Apply(qual0, args0) = tree0
1020+
val args1 = args0 map {
1021+
case arg: untpd.Ident if arg.name.startsWith("$") =>
1022+
untpd.Apply(untpd.ref(defn.InternalQuoted_patternMatchBindHoleModuleR), untpd.Ident(arg.name.toString.substring(1).toTermName) :: Nil)
1023+
case arg => arg
1024+
}
1025+
untpd.cpy.Apply(tree0)(qual0, args1)
1026+
} else tree0
10171027
val Apply(qual, args) = tree
10181028

10191029
def notAnExtractor(tree: Tree) =

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,10 @@ class Typer extends Namer
14161416
}
14171417

14181418
def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") {
1419+
if (ctx.mode.is(Mode.QuotedPattern) && tree.name.startsWith("$")) {
1420+
val bind1 = untpd.cpy.Bind(tree)(tree.name.toString.substring(1).toTermName, tree.body)
1421+
return typed(untpd.Apply(untpd.ref(defn.InternalQuoted_patternMatchBindHoleModuleR), bind1 :: Nil).withSpan(tree.span), pt)
1422+
}
14191423
val pt1 = fullyDefinedType(pt, "pattern variable", tree.span)
14201424
val body1 = typed(tree.body, pt1)
14211425
body1 match {
@@ -1960,6 +1964,13 @@ class Typer extends Namer
19601964

19611965
def splitQuotePattern(quoted: Tree)(implicit ctx: Context): (Tree, List[Tree]) = {
19621966
val ctx0 = ctx
1967+
1968+
def bindExpr(name: Name, tpe: Type, span: Span): Tree = {
1969+
val exprTpe = AppliedType(defn.QuotedMatchingBindingType, tpe :: Nil)
1970+
val sym = ctx0.newPatternBoundSymbol(name, exprTpe, span)
1971+
Bind(sym, untpd.Ident(nme.WILDCARD).withType(exprTpe)).withSpan(span)
1972+
}
1973+
19631974
object splitter extends tpd.TreeMap {
19641975
val patBuf = new mutable.ListBuffer[Tree]
19651976
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
@@ -1990,6 +2001,9 @@ class Typer extends Namer
19902001
patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(exprTpe)).withSpan(ddef.span)
19912002
}
19922003
super.transform(tree)
2004+
case tree @ UnApply(_, _, (bind: Bind) :: Nil) if tree.fun.symbol == defn.InternalQuoted_patternMatchBindHole_unapply =>
2005+
patBuf += bindExpr(bind.name, bind.tpe.widen, bind.span)
2006+
cpy.UnApply(tree)(patterns = untpd.Ident(nme.WILDCARD).withType(bind.tpe.widen) :: Nil)
19932007
case _ =>
19942008
super.transform(tree)
19952009
}

library/src-bootstrapped/scala/internal/Quoted.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ object Quoted {
2121
def patternHole[T]: T =
2222
throw new Error("Internal error: this method call should have been replaced by the compiler")
2323

24-
/** A splice of a name in a quoted pattern is desugared by wrapping getting this annotation */
24+
/** A splice of a name in a quoted pattern is desugared by adding this annotation */
2525
class patternBindHole extends Annotation
2626

27+
/** A splice of a name in a quoted pattern in pattern position is desugared by wrapping it in this extractor */
28+
object patternMatchBindHole {
29+
def unapply(x: Any): Some[x.type] =
30+
throw new Error("Internal error: this method call should have been replaced by the compiler")
31+
}
32+
2733
}

library/src-bootstrapped/scala/internal/quoted/Matcher.scala

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ object Matcher {
3535

3636
// TODO improve performance
3737

38+
/** Create a new matching with the resulting binding for the symbol */
39+
def bindingMatched(sym: Symbol) =
40+
Some(Tuple1(new Binding(sym.name, sym)))
41+
3842
/** Check that the trees match and return the contents from the pattern holes.
3943
* Return None if the trees do not match otherwise return Some of a tuple containing all the contents in the holes.
4044
*
@@ -253,9 +257,19 @@ object Matcher {
253257
* `None` if it did not match or `Some(tup: Tuple)` if it matched where `tup` contains the contents of the holes.
254258
*/
255259
def patternMatches(scrutinee: Pattern, pattern: Pattern)(implicit env: Set[(Symbol, Symbol)]): (Set[(Symbol, Symbol)], Option[Tuple]) = (scrutinee, pattern) match {
256-
case (Pattern.Value(v1), Pattern.Unapply(TypeApply(Select(patternHole @ Ident("patternHole"), "unapply"), List(tpt)), Nil, Nil))
257-
if patternHole.symbol.owner.fullName == "scala.runtime.quoted.Matcher$" =>
258-
(env, Some(Tuple1(v1.seal)))
260+
// case (Pattern.Value(v1), Pattern.Unapply(TypeApply(Select(patternHole @ Ident("patternHole"), "unapply"), List(tpt)), Nil, Nil))
261+
// if patternHole.symbol.owner.fullName == "scala.runtime.quoted.Matcher$" =>
262+
// (env, Some(Tuple1(v1.seal)))
263+
264+
case (Pattern.Bind(name1, pat1), Pattern.Unapply(Select(Ident("patternMatchBindHole"), "unapply"), Nil, List(Pattern.Bind(name2, pat2))))
265+
// TODO if pattern.symbol == ... =>
266+
=>
267+
val (env1, patMatch) = patternMatches(pat1, pat2)
268+
(env1, foldMatchings(bindingMatched(scrutinee.symbol), patMatch))
269+
270+
case (Pattern.Value(Ident("_")), Pattern.Value(Ident("_"))) => // TODO add Wildcard to patterns
271+
val bindEnv = env + (scrutinee.symbol -> pattern.symbol)
272+
(bindEnv, Some(()))
259273

260274
case (Pattern.Value(v1), Pattern.Value(v2)) =>
261275
(env, treeMatches(v1, v2))

tests/pos/quotedPatterns.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ object Test {
3434
case '{ def $ff[T](i: T): Int = $z; 2 } =>
3535
val a: quoted.matching.Bind[[T] => T => Int] = ff
3636
z
37+
case '{ Option(1) match { case $a @ Some(_) => $z } } => z
38+
case '{ Option(1) match { case $b: Some[_] => $z } } => z
39+
// case '{ Option(1) match { case Some($n @ _) => $z } } => z
40+
// case '{ Option(1) match { case $c => $z } } => z
3741
case _ => '{1}
3842
}
3943
}

tests/run-with-compiler/quote-matcher-runtime.check

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,26 @@ Pattern: scala.Predef.??? match {
622622
}
623623
Result: Some(List())
624624

625+
Scrutinee: scala.Predef.??? match {
626+
case scala.Some(n) =>
627+
2
628+
}
629+
Pattern: scala.Predef.??? match {
630+
case scala.Some(scala.internal.Quoted.patternMatchBindHole(n)) =>
631+
2
632+
}
633+
Result: Some(List(Binding(n)))
634+
635+
Scrutinee: scala.Predef.??? match {
636+
case scala.Some(n @ scala.Some(m)) =>
637+
2
638+
}
639+
Pattern: scala.Predef.??? match {
640+
case scala.Some(scala.internal.Quoted.patternMatchBindHole(n @ scala.Some(scala.internal.Quoted.patternMatchBindHole(m)))) =>
641+
2
642+
}
643+
Result: Some(List(Binding(n), Binding(m)))
644+
625645
Scrutinee: try 1 catch {
626646
case _ =>
627647
2

tests/run-with-compiler/quote-matcher-runtime/quoted_2.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Macros._
33

44
import scala.internal.quoted.Matcher._
55

6-
import scala.internal.Quoted.{patternHole, patternBindHole}
6+
import scala.internal.Quoted.{patternHole, patternBindHole, patternMatchBindHole}
77

88
object Test {
99

@@ -123,8 +123,8 @@ object Test {
123123
matches(??? match { case None => 2 }, ??? match { case None => 2 })
124124
matches(??? match { case Some(1) => 2 }, ??? match { case Some(1) => 2 })
125125
// matches(??? match { case Some(1) => 2 }, ??? match { case Some(patternMatchHole()) => 2 })
126-
// matches(??? match { case Some(n) => 2 }, ??? match { case Some(patternMatchBindHole(n)) => 2 })
127-
// matches(??? match { case Some(n @ Some(m)) => 2 }, ??? match { case Some(patterMatchBindHole(n @ Some(patternMatchBindHole(m)))) => 2 })
126+
matches(??? match { case Some(n) => 2 }, ??? match { case Some(patternMatchBindHole(n)) => 2 })
127+
matches(??? match { case Some(n @ Some(m)) => 2 }, ??? match { case Some(patternMatchBindHole(n @ Some(patternMatchBindHole(m)))) => 2 })
128128
matches(try 1 catch { case _ => 2 }, try 1 catch { case _ => 2 })
129129
matches(try 1 finally 2, try 1 finally 2)
130130
matches(try 1 catch { case _ => 2 }, try patternHole[Int] catch { case _ => patternHole[Int] })

0 commit comments

Comments
 (0)