Skip to content

Commit 7783f73

Browse files
committed
wip
1 parent a7fc7ac commit 7783f73

File tree

4 files changed

+50
-19
lines changed

4 files changed

+50
-19
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: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,13 @@ class Typer extends Namer
19581958

19591959
def splitQuotePattern(quoted: Tree)(implicit ctx: Context): (Tree, List[Tree]) = {
19601960
val ctx0 = ctx
1961+
1962+
def bindExpr(name: Name, tpe: Type, span: Span): Tree = {
1963+
val exprTpe = AppliedType(defn.QuotedMatchingBindingType, tpe :: Nil)
1964+
val sym = ctx0.newPatternBoundSymbol(name, exprTpe, span)
1965+
Bind(sym, untpd.Ident(nme.WILDCARD).withType(exprTpe)).withSpan(span)
1966+
}
1967+
19611968
object splitter extends tpd.TreeMap {
19621969
val patBuf = new mutable.ListBuffer[Tree]
19631970
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
@@ -1967,18 +1974,27 @@ class Typer extends Namer
19671974
case Splice(pat) =>
19681975
try patternHole(tree)
19691976
finally patBuf += pat
1970-
case vdef: ValDef =>
1971-
if (vdef.symbol.annotations.exists(_.symbol == defn.InternalQuoted_patternBindHoleAnnot)) {
1972-
val tpe = AppliedType(defn.QuotedMatchingBindingType, vdef.tpt.tpe :: Nil)
1973-
val sym = ctx0.newPatternBoundSymbol(vdef.name, tpe, vdef.span)
1974-
patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(tpe)).withSpan(vdef.span)
1975-
}
1977+
case tree @ UnApply(_, _, (bind: Bind) :: Nil) if tree.fun.symbol == defn.InternalQuoted_patternMatchBindHole_unapply =>
1978+
patBuf += bindExpr(bind.name, bind.tpe.widen, bind.span)
1979+
super.transform(tree)
1980+
case vdef: ValDef if vdef.symbol.annotations.exists(_.symbol == defn.InternalQuoted_patternBindHoleAnnot) =>
1981+
patBuf += bindExpr(vdef.name, vdef.tpt.tpe, vdef.span)
19761982
super.transform(tree)
19771983
case _ =>
19781984
super.transform(tree)
19791985
}
19801986
}
1987+
19811988
val result = splitter.transform(quoted)
1989+
println()
1990+
println(quoted.show)
1991+
println()
1992+
println(result.show)
1993+
println()
1994+
println(splitter.patBuf.toList)
1995+
println()
1996+
println()
1997+
println()
19821998
(result, splitter.patBuf.toList)
19831999
}
19842000

tests/pos/quotedPatterns.scala

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@ object Test {
66
def g(x: Int, y: Int) = x * y
77

88
def res given tasty.Reflection: quoted.Expr[Int] = x match {
9-
case '{1 + 2} => '{0}
10-
case '{f($y)} => y
11-
case '{g($y, $z)} => '{$y * $z}
12-
case '{ ((a: Int) => 3)($y) } => y
13-
case '{ 1 + ($y: Int)} => y
14-
case '{ val a = 1 + ($y: Int); 3 } => y
15-
// currently gives an unreachable case warning
16-
// but only when used in conjunction with the others.
17-
// I believe this is because implicit arguments are not taken
18-
// into account when checking whether we have already seen an `unapply` before.
19-
case '{ val $y: Int = $z; 1 } => z
20-
case '{ ((`$y`: Int) => 1 + y + ($z: Int))(2) } => z
9+
// case '{1 + 2} => '{0}
10+
// case '{f($y)} => y
11+
// case '{g($y, $z)} => '{$y * $z}
12+
// case '{ ((a: Int) => 3)($y) } => y
13+
// case '{ 1 + ($y: Int)} => y
14+
// case '{ val a = 1 + ($y: Int); 3 } => y
15+
// // currently gives an unreachable case warning
16+
// // but only when used in conjunction with the others.
17+
// // I believe this is because implicit arguments are not taken
18+
// // into account when checking whether we have already seen an `unapply` before.
19+
// case '{ val $y: Int = $z; 1 } => z
20+
// case '{ ((`$y`: Int) => 1 + y + ($z: Int))(2) } => z
21+
case '{ Option(1) match { case Some($n) => $z } } => z
2122
// TODO support syntax
2223
// case '{ (($y: Int) => 1 + y + ($z: Int))(2) } => z
2324
case _ => '{1}

0 commit comments

Comments
 (0)