@@ -1930,17 +1930,51 @@ class Typer extends Namer
19301930 * while tracking the quotation level in the context.
19311931 */
19321932 def typedQuote (tree : untpd.Quote , pt : Type )(implicit ctx : Context ): Tree = track(" typedQuote" ) {
1933- tree.t match {
1933+ tree.quoted match {
19341934 case untpd.Splice (innerExpr) =>
19351935 ctx.warning(" Canceled splice directly inside a quote. '{ ${ XYZ } } is equivalent to XYZ." , tree.sourcePos)
19361936 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+ }
19411971 }
1972+ val result = splitter.transform(quoted)
1973+ (result, splitter.patBuf.toList)
19421974 }
19431975
1976+ def givenReflection (implicit ctx : Context ): Tree = Literal (Constant (null )) // FIXME: fill in
1977+
19441978 /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
19451979 def typedSplice (tree : untpd.Splice , pt : Type )(implicit ctx : Context ): Tree = track(" typedSplice" ) {
19461980 checkSpliceOutsideQuote(tree)
@@ -1949,7 +1983,14 @@ class Typer extends Namer
19491983 ctx.warning(" Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ." , tree.sourcePos)
19501984 typed(innerExpr, pt)
19511985 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)
19531994 }
19541995 }
19551996
0 commit comments