-
Notifications
You must be signed in to change notification settings - Fork 20
/
MatchTreeTransform.scala
91 lines (72 loc) · 3.43 KB
/
MatchTreeTransform.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// transform for match
// (C) Ruslan Shevchenko, 2019-2023
// , Kiev, Ukraine
package cps.macros.forest
import scala.quoted._
import cps._
import cps.macros._
import cps.macros.common._
import cps.macros.misc._
trait MatchTreeTransform[F[_], CT, CC<:CpsMonadContext[F]]:
thisScope: TreeTransformScope[F, CT, CC] =>
import qctx.reflect._
// case selectTerm @ Select(qualifier,name)
def runMatch( matchTerm: Match )(owner: Symbol): CpsTree =
if (cpsCtx.flags.debugLevel >= 15) then
cpsCtx.log(s"matchTransform: matchTerm.tpe=${matchTerm.tpe}")
cpsCtx.log(s"matchTransform: matchTerm.tpe.widen=${matchTerm.tpe.widen}")
cpsCtx.log(s"matchTransform: veryWiden(matchTerm.tpe)=${TransformUtil.veryWiden(matchTerm.tpe)}")
val widenOtpe = TransformUtil.veryWiden(matchTerm.tpe)
//val otpe = widenOtpe
val otpe = matchTerm.tpe
val scrutinee = matchTerm.scrutinee
val cpsScrutinee = runRoot(scrutinee)(owner)
val cpsCases = matchTerm.cases.map( caseDef => runRoot(caseDef.rhs)(owner) )
val asyncCases = cpsCases.exists( _.isAsync )
val changedCases = cpsCases.exists( _.isChanged )
if (cpsCtx.flags.debugLevel >= 15) then
cpsCtx.log(s"matchTransform: asyncCases=${asyncCases}, changedCases=${changedCases}")
val nCases = if (asyncCases) {
(matchTerm.cases zip cpsCases).map{(old,cpstree) =>
CaseDef.copy(old)(old.pattern, old.guard, cpstree.castOtpe(widenOtpe).transformed)
}
} else if (changedCases) {
(matchTerm.cases zip cpsCases).map{(old,cpstree) =>
CaseDef.copy(old)(old.pattern, old.guard, cpstree.syncOrigin.get)
}
} else {
matchTerm.cases
}
if (!cpsScrutinee.isAsync) then
if (!asyncCases) then
if (!changedCases) then
CpsTree.pure(owner,matchTerm)
else
CpsTree.pure(owner,Match.copy(matchTerm)(scrutinee, nCases))
else
val nTree = Match.copy(matchTerm)(scrutinee, nCases)
CpsTree.impure(owner,nTree, otpe)
else
if (!asyncCases)
cpsScrutinee.monadMap( x => Match.copy(matchTerm)(x, nCases), otpe )
else
cpsScrutinee.monadFlatMap( x => Match.copy(matchTerm)(x, nCases), otpe )
object MatchTreeTransform:
def run[F[_]:Type,T:Type, C<:CpsMonadContext[F]:Type](using qctx1: Quotes)(cpsCtx1: TransformationContext[F,T,C],
matchTerm: qctx1.reflect.Match): CpsExpr[F,T] = {
val tmpFType = summon[Type[F]]
val tmpCTType = summon[Type[T]]
val tmpCCType = summon[Type[C]]
class Bridge(tc:TransformationContext[F,T,C]) extends
TreeTransformScope[F,T,C]
with TreeTransformScopeInstance[F,T,C](tc) {
implicit val fType: quoted.Type[F] = tmpFType
implicit val ctType: quoted.Type[T] = tmpCTType
implicit val ccType: quoted.Type[C] = tmpCCType
def bridge(): CpsExpr[F,T] =
val origin = matchTerm.asInstanceOf[quotes.reflect.Match]
val owner = quotes.reflect.Symbol.spliceOwner
runMatch(origin)(owner).toResult[T]
}
(new Bridge(cpsCtx1)).bridge()
}