Skip to content

Commit 7b5cdba

Browse files
Merge pull request #10189 from dotty-staging/simplify-compiler-interface-abstraction
Simplify CompilerInterface abstraction
2 parents 0cbefb4 + 5cc810e commit 7b5cdba

File tree

11 files changed

+84
-94
lines changed

11 files changed

+84
-94
lines changed

compiler/src/dotty/tools/dotc/quoted/Matcher.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import scala.annotation.internal.sharable
44
import scala.annotation.{Annotation, compileTimeOnly}
55

66
import scala.quoted._
7-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
87

98
/** Matches a quoted tree against a quoted pattern tree.
109
* A quoted pattern tree may have type and term holes in addition to normal terms.
@@ -98,7 +97,7 @@ import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
9897
*/
9998
object Matcher {
10099

101-
abstract class QuoteMatcher[QCtx <: QuoteContext { val reflect: scala.internal.tasty.CompilerInterface } & Singleton](val qctx: QCtx) {
100+
abstract class QuoteMatcher[QCtx <: QuoteContext & scala.internal.quoted.CompilerInterface & Singleton](val qctx: QCtx) {
102101

103102
// TODO improve performance
104103

compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ object QuoteContextImpl {
4545

4646
}
4747

48-
class QuoteContextImpl private (ctx: Context) extends QuoteContext:
48+
class QuoteContextImpl private (ctx: Context) extends QuoteContext, scala.internal.quoted.CompilerInterface:
4949

50-
object reflect extends scala.tasty.Reflection, scala.internal.tasty.CompilerInterface:
50+
object reflect extends scala.tasty.Reflection:
5151

5252
def rootContext: Context = ctx
5353

@@ -2615,70 +2615,74 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext:
26152615
private def withDefaultPos[T <: Tree](fn: Context ?=> T): T =
26162616
fn(using ctx.withSource(Position.ofMacroExpansion.source)).withSpan(Position.ofMacroExpansion.span)
26172617

2618-
def unpickleTerm(pickledQuote: PickledQuote): Term =
2619-
PickledQuotes.unpickleTerm(pickledQuote)
2620-
2621-
def unpickleTypeTree(pickledQuote: PickledQuote): TypeTree =
2622-
PickledQuotes.unpickleTypeTree(pickledQuote)
2618+
end reflect
26232619

2624-
def termMatch(scrutinee: Term, pattern: Term): Option[Tuple] =
2625-
treeMatch(scrutinee, pattern)
2620+
def unpickleExpr(pickledQuote: PickledQuote): scala.quoted.Expr[Any] =
2621+
val tree = PickledQuotes.unpickleTerm(pickledQuote)(using reflect.rootContext)
2622+
new scala.internal.quoted.Expr(tree, hash)
26262623

2627-
def typeTreeMatch(scrutinee: TypeTree, pattern: TypeTree): Option[Tuple] =
2628-
treeMatch(scrutinee, pattern)
2624+
def unpickleType(pickledQuote: PickledQuote): scala.quoted.Type[?] =
2625+
val tree = PickledQuotes.unpickleTypeTree(pickledQuote)(using reflect.rootContext)
2626+
new scala.internal.quoted.Type(tree, hash)
26292627

2630-
private def treeMatch(scrutinee: Tree, pattern: Tree): Option[Tuple] = {
2631-
def isTypeHoleDef(tree: Tree): Boolean =
2632-
tree match
2633-
case tree: TypeDef =>
2634-
tree.symbol.hasAnnotation(dotc.core.Symbols.defn.InternalQuotedPatterns_patternTypeAnnot)
2635-
case _ => false
2636-
2637-
def extractTypeHoles(pat: Term): (Term, List[Symbol]) =
2638-
pat match
2639-
case tpd.Inlined(_, Nil, pat2) => extractTypeHoles(pat2)
2640-
case tpd.Block(stats @ ((typeHole: TypeDef) :: _), expr) if isTypeHoleDef(typeHole) =>
2641-
val holes = stats.takeWhile(isTypeHoleDef).map(_.symbol)
2642-
val otherStats = stats.dropWhile(isTypeHoleDef)
2643-
(tpd.cpy.Block(pat)(otherStats, expr), holes)
2644-
case _ =>
2645-
(pat, Nil)
2628+
def exprMatch(scrutinee: scala.quoted.Expr[Any], pattern: scala.quoted.Expr[Any]): Option[Tuple] =
2629+
treeMatch(scrutinee.unseal(using this), pattern.unseal(using this))
26462630

2647-
val (pat1, typeHoles) = extractTypeHoles(pattern)
2631+
def typeMatch(scrutinee: scala.quoted.Type[?], pattern: scala.quoted.Type[?]): Option[Tuple] =
2632+
treeMatch(scrutinee.unseal(using this), pattern.unseal(using this))
26482633

2649-
val ctx1 =
2650-
if typeHoles.isEmpty then ctx
2651-
else
2652-
val ctx1 = ctx.fresh.setFreshGADTBounds.addMode(dotc.core.Mode.GadtConstraintInference)
2653-
ctx1.gadt.addToConstraint(typeHoles)
2654-
ctx1
2655-
2656-
val qctx1 = dotty.tools.dotc.quoted.QuoteContextImpl()(using ctx1)
2657-
.asInstanceOf[QuoteContext { val reflect: QuoteContextImpl.this.reflect.type }]
2634+
private def treeMatch(scrutinee: reflect.Tree, pattern: reflect.Tree): Option[Tuple] = {
2635+
import reflect._
2636+
given Context = rootContext
2637+
def isTypeHoleDef(tree: Tree): Boolean =
2638+
tree match
2639+
case tree: TypeDef =>
2640+
tree.symbol.hasAnnotation(dotc.core.Symbols.defn.InternalQuotedPatterns_patternTypeAnnot)
2641+
case _ => false
26582642

2659-
val matcher = new Matcher.QuoteMatcher[qctx1.type](qctx1) {
2660-
def patternHoleSymbol: Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_patternHole
2661-
def higherOrderHoleSymbol: Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_higherOrderHole
2662-
}
2643+
def extractTypeHoles(pat: Term): (Term, List[Symbol]) =
2644+
pat match
2645+
case tpd.Inlined(_, Nil, pat2) => extractTypeHoles(pat2)
2646+
case tpd.Block(stats @ ((typeHole: TypeDef) :: _), expr) if isTypeHoleDef(typeHole) =>
2647+
val holes = stats.takeWhile(isTypeHoleDef).map(_.symbol)
2648+
val otherStats = stats.dropWhile(isTypeHoleDef)
2649+
(tpd.cpy.Block(pat)(otherStats, expr), holes)
2650+
case _ =>
2651+
(pat, Nil)
2652+
2653+
val (pat1, typeHoles) = extractTypeHoles(pattern)
2654+
2655+
val ctx1 =
2656+
if typeHoles.isEmpty then ctx
2657+
else
2658+
val ctx1 = ctx.fresh.setFreshGADTBounds.addMode(dotc.core.Mode.GadtConstraintInference)
2659+
ctx1.gadt.addToConstraint(typeHoles)
2660+
ctx1
2661+
2662+
val qctx1 = dotty.tools.dotc.quoted.QuoteContextImpl()(using ctx1)
2663+
.asInstanceOf[QuoteContext & scala.internal.quoted.CompilerInterface]
2664+
2665+
val matcher = new Matcher.QuoteMatcher[qctx1.type](qctx1) {
2666+
def patternHoleSymbol: qctx1.reflect.Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_patternHole.asInstanceOf
2667+
def higherOrderHoleSymbol: qctx1.reflect.Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_higherOrderHole.asInstanceOf
2668+
}
26632669

2664-
val matchings =
2665-
if pat1.isType then matcher.termMatch(scrutinee, pat1)
2666-
else matcher.termMatch(scrutinee, pat1)
2667-
2668-
// val matchings = matcher.termMatch(scrutinee, pattern)
2669-
if typeHoles.isEmpty then matchings
2670-
else {
2671-
// After matching and doing all subtype checks, we have to approximate all the type bindings
2672-
// that we have found, seal them in a quoted.Type and add them to the result
2673-
def typeHoleApproximation(sym: Symbol) =
2674-
ctx1.gadt.approximation(sym, !sym.hasAnnotation(dotc.core.Symbols.defn.InternalQuotedPatterns_fromAboveAnnot)).seal
2675-
matchings.map { tup =>
2676-
Tuple.fromIArray(typeHoles.map(typeHoleApproximation).toArray.asInstanceOf[IArray[Object]]) ++ tup
2677-
}
2670+
val matchings =
2671+
if pat1.isType then matcher.termMatch(scrutinee.asInstanceOf[matcher.qctx.reflect.Term], pat1.asInstanceOf[matcher.qctx.reflect.Term])
2672+
else matcher.termMatch(scrutinee.asInstanceOf[matcher.qctx.reflect.Term], pat1.asInstanceOf[matcher.qctx.reflect.Term])
2673+
2674+
// val matchings = matcher.termMatch(scrutinee, pattern)
2675+
if typeHoles.isEmpty then matchings
2676+
else {
2677+
// After matching and doing all subtype checks, we have to approximate all the type bindings
2678+
// that we have found, seal them in a quoted.Type and add them to the result
2679+
def typeHoleApproximation(sym: Symbol) =
2680+
ctx1.gadt.approximation(sym, !sym.hasAnnotation(dotc.core.Symbols.defn.InternalQuotedPatterns_fromAboveAnnot)).asInstanceOf[qctx1.reflect.TypeRepr].seal
2681+
matchings.map { tup =>
2682+
Tuple.fromIArray(typeHoles.map(typeHoleApproximation).toArray.asInstanceOf[IArray[Object]]) ++ tup
26782683
}
26792684
}
2680-
2681-
end reflect
2685+
}
26822686

26832687
private[this] val hash = QuoteContextImpl.scopeId(using ctx)
26842688
override def hashCode: Int = hash

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package scala.internal.quoted
22

33
import scala.quoted._
4-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
4+
import scala.internal.quoted.CompilerInterface.quoteContextWithCompilerInterface
55

66
/** An Expr backed by a tree. Only the current compiler trees are allowed.
77
*
@@ -54,7 +54,7 @@ object Expr {
5454
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: scala.quoted.Expr[Any])
5555
(using patternExpr: scala.quoted.Expr[Any], qctx: QuoteContext): Option[Tup] = {
5656
val qctx1 = quoteContextWithCompilerInterface(qctx)
57-
qctx1.reflect.termMatch(scrutineeExpr.unseal, patternExpr.unseal).asInstanceOf[Option[Tup]]
57+
qctx1.exprMatch(scrutineeExpr, patternExpr).asInstanceOf[Option[Tup]]
5858
}
5959

6060
/** Returns a null expresssion equivalent to `'{null}` */

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package scala.internal.quoted
22

33
import scala.quoted._
4-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
4+
import scala.internal.quoted.CompilerInterface.quoteContextWithCompilerInterface
55

66
/** Quoted type (or kind) `T` backed by a tree */
77
final class Type[Tree](val typeTree: Tree, val scopeId: Int) extends scala.quoted.Type[Any] {
@@ -37,7 +37,7 @@ object Type {
3737
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeType: scala.quoted.Type[_])
3838
(using patternType: scala.quoted.Type[_], qctx: QuoteContext): Option[Tup] = {
3939
val qctx1 = quoteContextWithCompilerInterface(qctx)
40-
qctx1.reflect.typeTreeMatch(scrutineeType.unseal, patternType.unseal).asInstanceOf[Option[Tup]]
40+
qctx1.typeMatch(scrutineeType, patternType).asInstanceOf[Option[Tup]]
4141
}
4242

4343

library/src-bootstrapped/scala/quoted/Expr.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package scala.quoted
22

3-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
4-
53
/** Quoted expression of type `T` */
64
abstract class Expr[+T] private[scala] {
75

library/src-non-bootstrapped/scala/internal/quoted/Expr.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package scala.internal.quoted
22

33
import scala.quoted._
4-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
54

65
/** An Expr backed by a tree. Only the current compiler trees are allowed.
76
*

library/src-non-bootstrapped/scala/internal/quoted/Type.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package scala.internal.quoted
22

33
import scala.quoted._
4-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
54

65
/** Quoted type (or kind) `T` backed by a tree */
76
final class Type[Tree](val typeTree: Tree, val scopeId: Int) extends scala.quoted.Type[Any] {
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1-
package scala.internal.tasty
1+
package scala.internal.quoted
22

33
import scala.quoted.QuoteContext
44
import scala.tasty.reflect._
55
import scala.internal.quoted.PickledQuote
66

77
/** Part of the reflection interface that needs to be implemented by the compiler */
8-
trait CompilerInterface { self: scala.tasty.Reflection =>
8+
trait CompilerInterface { self: scala.quoted.QuoteContext =>
99

10-
//////////////////////
11-
// QUOTE UNPICKLING //
12-
//////////////////////
10+
import self.reflect._
1311

1412
/** Unpickle `repr` which represents a pickled `Expr` tree,
1513
* replacing splice nodes with `holes`
1614
*/
17-
def unpickleTerm(pickledQuote: PickledQuote): Term
15+
def unpickleExpr(pickledQuote: PickledQuote): scala.quoted.Expr[Any]
1816

1917
/** Unpickle `repr` which represents a pickled `Type` tree,
2018
* replacing splice nodes with `holes`
2119
*/
22-
def unpickleTypeTree(pickledQuote: PickledQuote): TypeTree
20+
def unpickleType(pickledQuote: PickledQuote): scala.quoted.Type[?]
2321

2422
/** Pattern matches the scrutinee against the pattern and returns a tuple
2523
* with the matched holes if successful.
@@ -36,27 +34,27 @@ trait CompilerInterface { self: scala.tasty.Reflection =>
3634
* - scala.internal.Quoted.patternHole[T]: hole that matches an expression `x` of type `Expr[U]`
3735
* if `U <:< T` and returns `x` as part of the match.
3836
*
39-
* @param scrutinee `Term` on which we are pattern matching
40-
* @param pattern `Term` containing the pattern tree
37+
* @param scrutinee `Expr` on which we are pattern matching
38+
* @param pattern `Expr` containing the pattern tree
4139
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Term``
4240
*/
43-
def termMatch(scrutinee: Term, pattern: Term): Option[Tuple]
41+
def exprMatch(scrutinee: scala.quoted.Expr[Any], pattern: scala.quoted.Expr[Any]): Option[Tuple]
4442

4543
/** Pattern matches the scrutineeType against the patternType and returns a tuple
4644
* with the matched holes if successful.
4745
*
48-
* @param scrutinee `TypeTree` on which we are pattern matching
49-
* @param pattern `TypeTree` containing the pattern tree
50-
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `quoted.Type[Ti]``
46+
* @param scrutinee `Type` on which we are pattern matching
47+
* @param pattern `Type` containing the pattern tree
48+
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `scala.quoted.Type[Ti]``
5149
*/
52-
def typeTreeMatch(scrutinee: TypeTree, pattern: TypeTree): Option[Tuple]
50+
def typeMatch(scrutinee: scala.quoted.Type[?], pattern: scala.quoted.Type[?]): Option[Tuple]
5351

5452
}
5553

5654

5755
object CompilerInterface {
5856

59-
private[scala] def quoteContextWithCompilerInterface(qctx: QuoteContext): qctx.type { val reflect: qctx.reflect.type & scala.internal.tasty.CompilerInterface } =
60-
qctx.asInstanceOf[qctx.type { val reflect: qctx.reflect.type & scala.internal.tasty.CompilerInterface }]
57+
private[scala] def quoteContextWithCompilerInterface(qctx: QuoteContext): qctx.type { val reflect: qctx.reflect.type } & CompilerInterface =
58+
qctx.asInstanceOf[qctx.type { val reflect: qctx.reflect.type } & CompilerInterface]
6159

6260
}

library/src/scala/internal/quoted/PickledQuote.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package scala.internal.quoted
22

33
import scala.quoted._
4-
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface
54

65
/** Pickled representation of a quoted expression or type */
76
trait PickledQuote:
@@ -18,14 +17,12 @@ trait PickledQuote:
1817
object PickledQuote:
1918

2019
def unpickleExpr[T](pickledQuote: PickledQuote): QuoteContext ?=> Expr[T] =
21-
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext])
22-
val tree = qctx.reflect.unpickleTerm(pickledQuote)
23-
new scala.internal.quoted.Expr(tree, qctx.hashCode).asInstanceOf[Expr[T]]
20+
val qctx = CompilerInterface.quoteContextWithCompilerInterface(summon[QuoteContext])
21+
qctx.unpickleExpr(pickledQuote).asInstanceOf[Expr[T]]
2422

2523
def unpickleType[T](pickledQuote: PickledQuote): QuoteContext ?=> Type[T] =
26-
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext])
27-
val tree = qctx.reflect.unpickleTypeTree(pickledQuote)
28-
new scala.internal.quoted.Type(tree, qctx.hashCode).asInstanceOf[Type[T]]
24+
val qctx = CompilerInterface.quoteContextWithCompilerInterface(summon[QuoteContext])
25+
qctx.unpickleType(pickledQuote).asInstanceOf[Type[T]]
2926

3027
/** Create an instance of PickledExpr from encoded tasty and sequence of labmdas to fill holes
3128
*

library/src/scala/tasty/Reflection.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package scala.tasty
22

3-
import scala.internal.tasty.CompilerInterface
4-
53
import scala.quoted.QuoteContext
64
import scala.tasty.reflect._
75

tests/run-macros/quote-matcher-runtime/quoted_1.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ object Macros {
1313
s"Expr(${r.unseal.show})"
1414
case r: Type[_] =>
1515
s"Type(${r.unseal.show})"
16-
case r: String =>
17-
s"String($r)"
1816
}
1917
}
2018

0 commit comments

Comments
 (0)