@@ -9,15 +9,29 @@ object Matcher {
99
1010 private final val debug = false
1111
12- /**
12+ /** Pattern matches an the scrutineeExpr aquainsnt the patternExpr and returns a tuple
13+ * with the matched holes if successful.
1314 *
14- * @param scrutineeExpr
15- * @param patternExpr
16- * @param reflection
17- * @return None if it did not match, Some(tup) if it matched where tup contains Expr[_], Type[_] or Binding[_]
15+ * Examples:
16+ * - `Matcher.unapply('{ f(0, myInt) })('{ f(0, myInt) }, _)`
17+ * will return `Some(())` (where `()` is a tuple of arity 0)
18+ * - `Matcher.unapply('{ f(0, myInt) })('{ f(patternHole[Int], patternHole[Int]) }, _)`
19+ * will return `Some(Tuple2('{0}, '{ myInt }))`
20+ * - `Matcher.unapply('{ f(0, "abc") })('{ f(0, patternHole[Int]) }, _)`
21+ * will return `None` due to the missmatch of types in the hole
22+ *
23+ * Holes:
24+ * - scala.internal.Quoted.patternHole[T]: hole that matches an expression `x` of type `Expr[U]`
25+ * if `U <:< T` and returns `x` as part of the match.
26+ *
27+ * @param scrutineeExpr `Expr[_]` on which we are pattern matching
28+ * @param patternExpr `Expr[_]` containing the pattern tree
29+ * @param reflection instance of the reflection API (implicitly provided by the macro)
30+ * @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
1831 */
1932 def unapply [Tup <: Tuple ](scrutineeExpr : Expr [_])(implicit patternExpr : Expr [_], reflection : Reflection ): Option [Tup ] = {
2033 import reflection ._
34+ // TODO improve performance
2135
2236 def treeMatches (scrutinee : Tree , pattern : Tree )(implicit env : Set [(Symbol , Symbol )]): Option [Tuple ] = {
2337
@@ -38,15 +52,18 @@ object Matcher {
3852 case (Block (Nil , expr), _) => treeMatches(expr, pattern)
3953 case (_, Block (Nil , pat)) => treeMatches(scrutinee, pat)
4054
41- // Match
55+ // Match a scala.internal.Quoted.patternHole and return the scrutinee tree
4256 case (IsTerm (scrutinee), TypeApply (patternHole, tpt :: Nil ))
4357 if patternHole.symbol == kernel.Definitions_InternalQuoted_patternHole && scrutinee.tpe <:< tpt.tpe =>
4458 Some (Tuple1 (scrutinee.seal))
4559
46- case (Inlined (_, Nil , scr), _) =>
47- treeMatches(scr, pattern)
48- case (_, Inlined (_, Nil , pat)) =>
49- treeMatches(scrutinee, pat)
60+ // Normalize inline trees
61+ case (Inlined (_, Nil , scr), _) => treeMatches(scr, pattern)
62+ case (_, Inlined (_, Nil , pat)) => treeMatches(scrutinee, pat)
63+
64+ //
65+ // Match two equivalent trees
66+ //
5067
5168 case (Literal (constant1), Literal (constant2)) if constant1 == constant2 =>
5269 Some (())
@@ -150,6 +167,7 @@ object Matcher {
150167 val finalizerMatch = treeOptMatches(finalizer1, finalizer2)
151168 foldMatchings(bodyMacth, casesMatch, finalizerMatch)
152169
170+ // No Match
153171 case _ =>
154172 if (debug)
155173 println(
@@ -245,7 +263,11 @@ object Matcher {
245263 treeMatches(scrutineeExpr.unseal, patternExpr.unseal)(Set .empty).asInstanceOf [Option [Tup ]]
246264 }
247265
266+ /** Joins the mattchings into a single matching. If any matching is `None` the result is `None`.
267+ * Otherwise the result is `Some` of the concatenation of the tupples.
268+ */
248269 private def foldMatchings (matchings : Option [Tuple ]* ): Option [Tuple ] = {
270+ // TODO improve performance
249271 matchings.foldLeft[Option [Tuple ]](Some (())) {
250272 case (Some (acc), Some (holes)) => Some (acc ++ holes)
251273 case (_, _) => None
0 commit comments