Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed May 22, 2019
1 parent 5501e37 commit a5374ae
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,7 @@ class Typer extends Namer
fun = ref(defn.InternalQuotedMatcher_unapplyR).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
implicits =
ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) ::
Literal(Constant(typeBindings.nonEmpty)) ::
implicitArgTree(defn.TastyReflectionType, tree.span) :: Nil,
patterns = splicePat :: Nil,
proto = pt)
Expand Down
37 changes: 23 additions & 14 deletions library/src-3.x/scala/internal/quoted/Matcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@ object Matcher {
*
* @param scrutineeExpr `Expr[_]` on which we are pattern matching
* @param patternExpr `Expr[_]` containing the pattern tree
* @param hasTypeSplices `Boolean` notify if the pattern has type splices (if so we use a GADT context)
* @param reflection instance of the reflection API (implicitly provided by the macro)
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
*/
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = {
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], hasTypeSplices: Boolean, reflection: Reflection): Option[Tup] = {
// TODO improve performance
import reflection.{Bind => BindPattern, _}
import Matching._

type Env = Set[(Symbol, Symbol)]

class SymBinding(val sym: Symbol)
class SymBinding(val sym: Symbol, val fromBellow: Boolean)

inline def withEnv[T](env: Env)(body: => given Env => T): T = body given env

Expand Down Expand Up @@ -140,7 +141,8 @@ object Matcher {

case (Block(stats1, expr1), Block(binding :: stats2, expr2)) if isTypeBinding(binding) =>
reflection.kernel.Context_GADT_addToConstraint(the[Context])(binding.symbol :: Nil)
matched(new SymBinding(binding.symbol)) && Block(stats1, expr1) =#= Block(stats2, expr2)
val fromBellow = true // TODO
matched(new SymBinding(binding.symbol, fromBellow)) && Block(stats1, expr1) =#= Block(stats2, expr2)

case (Block(stat1 :: stats1, expr1), Block(stat2 :: stats2, expr2)) =>
withEnv(the[Env] + (stat1.symbol -> stat2.symbol)) {
Expand All @@ -150,7 +152,8 @@ object Matcher {
case (scrutinee, Block(typeBindings, expr2)) if typeBindings.forall(isTypeBinding) =>
val bindingSymbols = typeBindings.map(_.symbol)
reflection.kernel.Context_GADT_addToConstraint(the[Context])(bindingSymbols)
bindingSymbols.foldRight(scrutinee =#= expr2)((x, acc) => matched(new SymBinding(x)) && acc)
val fromBellow = true // TODO
bindingSymbols.foldRight(scrutinee =#= expr2)((x, acc) => matched(new SymBinding(x, fromBellow)) && acc)

case (If(cond1, thenp1, elsep1), If(cond2, thenp2, elsep2)) =>
cond1 =#= cond2 && thenp1 =#= thenp2 && elsep1 =#= elsep2
Expand Down Expand Up @@ -335,18 +338,24 @@ object Matcher {

implied for Env = Set.empty

{
// TODO only set GADT context when needed
implicit val ctx2 = reflection.kernel.Context_GADT_setFreshGADTBounds(rootContext)
val matchings = scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
val res = matchings.asOptionOfTuple.map { tup =>
Tuple.fromArray(tup.toArray.map { // TODO improve code
case x: SymBinding => reflection.kernel.Context_GADT_approximation(ctx2)(x.sym, true).seal
case x => x
})
val res = {
if (hasTypeSplices) {
implied for Context = reflection.kernel.Context_GADT_setFreshGADTBounds(rootContext)
val matchings = scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
// After matching and doing all subtype check, we have to aproximate all the type bindings
// that we have found and seal them in a quoted.Type
matchings.asOptionOfTuple.map { tup =>
Tuple.fromArray(tup.toArray.map { // TODO improve performace
case x: SymBinding => kernel.Context_GADT_approximation(the[Context])(x.sym, x.fromBellow).seal
case x => x
})
}
}
else {
scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
}
res.asInstanceOf[Option[Tup]]
}
res.asInstanceOf[Option[Tup]]
}

/** Result of matching a part of an expression */
Expand Down
2 changes: 1 addition & 1 deletion tests/run-macros/quote-matcher-runtime/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Macros {
private def impl[A, B](a: Expr[A], b: Expr[B])(implicit reflect: Reflection): Expr[Unit] = {
import reflect.{Bind => _, _}

val res = scala.internal.quoted.Matcher.unapply[Tuple, Tuple](a)(b, reflect).map { tup =>
val res = scala.internal.quoted.Matcher.unapply[Tuple, Tuple](a)(b, true, reflect).map { tup =>
tup.toArray.toList.map {
case r: Expr[_] =>
s"Expr(${r.unseal.show})"
Expand Down

0 comments on commit a5374ae

Please sign in to comment.