@@ -121,7 +121,7 @@ object QuoteMatcher {
121
121
122
122
private def withEnv [T ](env : Env )(body : Env ?=> T ): T = body(using env)
123
123
124
- def treeMatch (scrutineeTerm : Tree , patternTerm : Tree )(using Context ): Option [Tuple ] =
124
+ def treeMatch (scrutineeTerm : Tree , patternTerm : Tree )(using Context ): Option [Seq [ MatchResult ] ] =
125
125
given Env = Map .empty
126
126
scrutineeTerm =?= patternTerm
127
127
@@ -203,31 +203,12 @@ object QuoteMatcher {
203
203
// Matches an open term and wraps it into a lambda that provides the free variables
204
204
case Apply (TypeApply (Ident (_), List (TypeTree ())), SeqLiteral (args, _) :: Nil )
205
205
if pattern.symbol.eq(defn.QuotedRuntimePatterns_higherOrderHole ) =>
206
- def hoasClosure = {
207
- val names : List [TermName ] = args.map {
208
- case Block (List (DefDef (nme.ANON_FUN , _, _, Apply (Ident (name), _))), _) => name.asTermName
209
- case arg => arg.symbol.name.asTermName
210
- }
211
- val argTypes = args.map(x => x.tpe.widenTermRefExpr)
212
- val methTpe = MethodType (names)(_ => argTypes, _ => pattern.tpe)
213
- val meth = newAnonFun(ctx.owner, methTpe)
214
- def bodyFn (lambdaArgss : List [List [Tree ]]): Tree = {
215
- val argsMap = args.map(_.symbol).zip(lambdaArgss.head).toMap
216
- val body = new TreeMap {
217
- override def transform (tree : Tree )(using Context ): Tree =
218
- tree match
219
- case tree : Ident => summon[Env ].get(tree.symbol).flatMap(argsMap.get).getOrElse(tree)
220
- case tree => super .transform(tree)
221
- }.transform(scrutinee)
222
- TreeOps (body).changeNonLocalOwners(meth)
223
- }
224
- Closure (meth, bodyFn)
225
- }
206
+ val env = summon[Env ]
226
207
val capturedArgs = args.map(_.symbol)
227
208
val captureEnv = summon[Env ].filter((k, v) => ! capturedArgs.contains(v))
228
209
withEnv(captureEnv) {
229
210
scrutinee match
230
- case ClosedPatternTerm (scrutinee) => matched(hoasClosure )
211
+ case ClosedPatternTerm (scrutinee) => matchedOpen(scrutinee, pattern.tpe, args, env )
231
212
case _ => notMatched
232
213
}
233
214
@@ -452,20 +433,52 @@ object QuoteMatcher {
452
433
accumulator.apply(Set .empty, term)
453
434
}
454
435
436
+ enum MatchResult :
437
+ case ClosedTree (tree : Tree )
438
+ case OpenTree (tree : Tree , patternTpe : Type , args : List [Tree ], env : Env )
439
+
440
+ def toExpr (mapTypeHoles : TypeMap )(using Context ): Expr [Any ] = this match
441
+ case MatchResult .ClosedTree (tree) =>
442
+ new ExprImpl (tree, SpliceScope .getCurrent)
443
+ case MatchResult .OpenTree (tree, patternTpe, args, env) =>
444
+ def hoasClosure = {
445
+ val names : List [TermName ] = args.map {
446
+ case Block (List (DefDef (nme.ANON_FUN , _, _, Apply (Ident (name), _))), _) => name.asTermName
447
+ case arg => arg.symbol.name.asTermName
448
+ }
449
+ val paramTypes = args.map(x => mapTypeHoles(x.tpe.widenTermRefExpr))
450
+ val methTpe = MethodType (names)(_ => paramTypes, _ => mapTypeHoles(patternTpe))
451
+ val meth = newAnonFun(ctx.owner, methTpe)
452
+ def bodyFn (lambdaArgss : List [List [Tree ]]): Tree = {
453
+ val argsMap = args.map(_.symbol).zip(lambdaArgss.head).toMap
454
+ val body = new TreeMap {
455
+ override def transform (tree : Tree )(using Context ): Tree =
456
+ tree match
457
+ case tree : Ident => env.get(tree.symbol).flatMap(argsMap.get).getOrElse(tree)
458
+ case tree => super .transform(tree)
459
+ }.transform(tree)
460
+ TreeOps (body).changeNonLocalOwners(meth)
461
+ }
462
+ Closure (meth, bodyFn)
463
+ }
464
+ new ExprImpl (hoasClosure, SpliceScope .getCurrent)
465
+
455
466
/** Result of matching a part of an expression */
456
- private type Matching = Option [Tuple ]
467
+ private type Matching = Option [Seq [ MatchResult ] ]
457
468
458
469
private object Matching {
459
470
460
471
def notMatched : Matching = None
461
472
462
- val matched : Matching = Some (Tuple ())
473
+ val matched : Matching = Some (Seq ())
463
474
464
475
def matched (tree : Tree )(using Context ): Matching =
465
- Some (Tuple1 (new ExprImpl (tree, SpliceScope .getCurrent)))
476
+ Some (Seq (MatchResult .ClosedTree (tree)))
477
+
478
+ def matchedOpen (tree : Tree , patternTpe : Type , args : List [Tree ], env : Env )(using Context ): Matching =
479
+ Some (Seq (MatchResult .OpenTree (tree, patternTpe, args, env)))
466
480
467
481
extension (self : Matching )
468
- def asOptionOfTuple : Option [Tuple ] = self
469
482
470
483
/** Concatenates the contents of two successful matchings or return a `notMatched` */
471
484
def &&& (that : => Matching ): Matching = self match {
0 commit comments