@@ -1930,17 +1930,51 @@ class Typer extends Namer
1930
1930
* while tracking the quotation level in the context.
1931
1931
*/
1932
1932
def typedQuote (tree : untpd.Quote , pt : Type )(implicit ctx : Context ): Tree = track(" typedQuote" ) {
1933
- tree.t match {
1933
+ tree.quoted match {
1934
1934
case untpd.Splice (innerExpr) =>
1935
1935
ctx.warning(" Canceled splice directly inside a quote. '{ ${ XYZ } } is equivalent to XYZ." , tree.sourcePos)
1936
1936
typed(innerExpr, pt)
1937
- case t if t.isType =>
1938
- typedTypeApply(untpd.TypeApply (untpd.ref(defn.InternalQuoted_typeQuoteR ), List (tree.t)), pt)(quoteContext).withSpan(tree.span)
1939
- case t=>
1940
- typedApply(untpd.Apply (untpd.ref(defn.InternalQuoted_exprQuoteR ), tree.t), pt)(quoteContext).withSpan(tree.span)
1937
+ case quoted if quoted.isType =>
1938
+ typedTypeApply(untpd.TypeApply (untpd.ref(defn.InternalQuoted_typeQuoteR ), quoted :: Nil ), pt)(quoteContext).withSpan(tree.span)
1939
+ case quoted =>
1940
+ if (ctx.mode.is(Mode .Pattern )) {
1941
+ val exprPt = pt.baseType(defn.QuotedExprClass )
1942
+ val quotedPt = if (exprPt.exists) exprPt.argTypesHi.head else defn.AnyType
1943
+ val quoted1 = typedExpr(quoted, quotedPt)(quoteContext.addMode(Mode .QuotedPattern ))
1944
+ val (shape, splices) = splitQuotePattern(quoted1)
1945
+ val splicePat = typed(untpd.Tuple (splices.map(untpd.TypedSplice (_))).withSpan(quoted.span))
1946
+ val patType = TypeOps .tupleOf(splices.tpes)
1947
+ UnApply (
1948
+ ref(defn.QuotedMatcher_unapplyR ).appliedToType(patType),
1949
+ ref(defn.InternalQuoted_exprQuoteR ).appliedToType(shape.tpe).appliedTo(shape) :: givenReflection :: Nil ,
1950
+ splicePat :: Nil ,
1951
+ pt)
1952
+ }
1953
+ else
1954
+ typedApply(untpd.Apply (untpd.ref(defn.InternalQuoted_exprQuoteR ), quoted), pt)(quoteContext).withSpan(tree.span)
1955
+ }
1956
+ }
1957
+
1958
+ def splitQuotePattern (quoted : Tree )(implicit ctx : Context ): (Tree , List [Tree ]) = {
1959
+ object splitter extends tpd.TreeMap {
1960
+ val patBuf = new mutable.ListBuffer [Tree ]
1961
+ override def transform (tree : Tree )(implicit ctx : Context ) = tree match {
1962
+ case Typed (Splice (pat), tpt) =>
1963
+ val exprTpt = ref(defn.QuotedExprType ).appliedToTypeTrees(tpt :: Nil )
1964
+ transform(Splice (Typed (pat, exprTpt)))
1965
+ case Splice (pat) =>
1966
+ try tasty.TreePickler .Hole (patBuf.length, Nil )
1967
+ finally patBuf += pat
1968
+ case _ =>
1969
+ super .transform(tree)
1970
+ }
1941
1971
}
1972
+ val result = splitter.transform(quoted)
1973
+ (result, splitter.patBuf.toList)
1942
1974
}
1943
1975
1976
+ def givenReflection (implicit ctx : Context ): Tree = Literal (Constant (null )) // FIXME: fill in
1977
+
1944
1978
/** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
1945
1979
def typedSplice (tree : untpd.Splice , pt : Type )(implicit ctx : Context ): Tree = track(" typedSplice" ) {
1946
1980
checkSpliceOutsideQuote(tree)
@@ -1949,7 +1983,14 @@ class Typer extends Namer
1949
1983
ctx.warning(" Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ." , tree.sourcePos)
1950
1984
typed(innerExpr, pt)
1951
1985
case expr =>
1952
- typedApply(untpd.Apply (untpd.ref(defn.InternalQuoted_exprSpliceR ), tree.expr), pt)(spliceContext).withSpan(tree.span)
1986
+ if (ctx.mode.is(Mode .QuotedPattern )) {
1987
+ fullyDefinedType(pt, " quoted pattern selector" , tree.span)
1988
+ val pat = typedPattern(expr, defn.QuotedExprType .appliedTo(pt))(
1989
+ spliceContext.retractMode(Mode .QuotedPattern ))
1990
+ Splice (pat)
1991
+ }
1992
+ else
1993
+ typedApply(untpd.Apply (untpd.ref(defn.InternalQuoted_exprSpliceR ), tree.expr), pt)(spliceContext).withSpan(tree.span)
1953
1994
}
1954
1995
}
1955
1996
0 commit comments