@@ -96,18 +96,18 @@ object PatternMatcher {
96
96
LetPlan (vble, body(vble))
97
97
}
98
98
99
- /** The plan `let l = labelled in body (l)` where `l` is a fresh label */
100
- private def labeledAbstract (next : Plan )( expr : (=> Plan ) => Plan ): Plan = {
99
+ /** The plan `l: { expr (l) } ` where `l` is a fresh label */
100
+ private def labeledAbstract (expr : (=> Plan ) => Plan ): Plan = {
101
101
val label = ctx.newSymbol(ctx.owner, PatMatCaseName .fresh(), Synthetic | Label ,
102
102
defn.UnitType )
103
- LabeledPlan (label, expr(ReturnPlan (label)), next )
103
+ LabeledPlan (label, expr(ReturnPlan (label)))
104
104
}
105
105
106
- /** The plan `let l = labelled in body (l)` where `l` is a fresh label */
107
- private def labeledAbstract2 (next : Plan )( expr : TermSymbol => Plan ): Plan = {
106
+ /** The plan `l: { expr (l) } ` where `l` is a fresh label */
107
+ private def labeledAbstract2 (expr : TermSymbol => Plan ): Plan = {
108
108
val label = ctx.newSymbol(ctx.owner, PatMatCaseName .fresh(), Synthetic | Label ,
109
109
defn.UnitType )
110
- LabeledPlan (label, expr(label), next )
110
+ LabeledPlan (label, expr(label))
111
111
}
112
112
113
113
/** Test whether a type refers to a pattern-generated variable */
@@ -138,7 +138,7 @@ object PatternMatcher {
138
138
sealed abstract class Plan { val id = nxId; nxId += 1 }
139
139
140
140
case class TestPlan (test : Test , var scrutinee : Tree , pos : Position ,
141
- var onSuccess : Plan , var onFailure : Plan ) extends Plan {
141
+ var onSuccess : Plan ) extends Plan {
142
142
override def equals (that : Any ) = that match {
143
143
case that : TestPlan => this .scrutinee === that.scrutinee && this .test == that.test
144
144
case _ => false
@@ -147,13 +147,14 @@ object PatternMatcher {
147
147
}
148
148
149
149
case class LetPlan (sym : TermSymbol , var body : Plan ) extends Plan
150
- case class LabeledPlan (sym : TermSymbol , var expr : Plan , var next : Plan ) extends Plan
150
+ case class LabeledPlan (sym : TermSymbol , var expr : Plan ) extends Plan
151
151
case class ReturnPlan (var label : TermSymbol ) extends Plan
152
+ case class SeqPlan (var head : Plan , var tail : Plan ) extends Plan
152
153
case class ResultPlan (var tree : Tree ) extends Plan
153
154
154
155
object TestPlan {
155
- def apply (test : Test , sym : Symbol , pos : Position , ons : Plan , onf : Plan ): TestPlan =
156
- TestPlan (test, ref(sym), pos, ons, onf )
156
+ def apply (test : Test , sym : Symbol , pos : Position , ons : Plan ): TestPlan =
157
+ TestPlan (test, ref(sym), pos, ons)
157
158
}
158
159
159
160
/** The different kinds of tests */
@@ -218,7 +219,7 @@ object PatternMatcher {
218
219
}
219
220
220
221
/** Plan for matching `scrutinee` symbol against `tree` pattern */
221
- private def patternPlan (scrutinee : Symbol , tree : Tree , onSuccess : Plan , onFailure : Plan ): Plan = {
222
+ private def patternPlan (scrutinee : Symbol , tree : Tree , onSuccess : Plan ): Plan = {
222
223
223
224
/** Plan for matching `selectors` against argument patterns `args` */
224
225
def matchArgsPlan (selectors : List [Tree ], args : List [Tree ], onSuccess : Plan ): Plan = {
@@ -247,7 +248,7 @@ object PatternMatcher {
247
248
args match {
248
249
case arg :: args1 =>
249
250
val sym :: syms1 = syms
250
- patternPlan(sym, arg, matchArgsPatternPlan(args1, syms1), onFailure )
251
+ patternPlan(sym, arg, matchArgsPatternPlan(args1, syms1))
251
252
case Nil =>
252
253
assert(syms.isEmpty)
253
254
onSuccess
@@ -262,7 +263,7 @@ object PatternMatcher {
262
263
val selectors = args.indices.toList.map(idx =>
263
264
ref(seqSym).select(nme.apply).appliedTo(Literal (Constant (idx))))
264
265
TestPlan (LengthTest (args.length, exact), seqSym, seqSym.pos,
265
- matchArgsPlan(selectors, args, onSuccess), onFailure )
266
+ matchArgsPlan(selectors, args, onSuccess))
266
267
}
267
268
268
269
/** Plan for matching the sequence in `getResult` against sequence elements
@@ -272,13 +273,13 @@ object PatternMatcher {
272
273
case Some (VarArgPattern (arg)) =>
273
274
val matchRemaining =
274
275
if (args.length == 1 )
275
- patternPlan(getResult, arg, onSuccess, onFailure )
276
+ patternPlan(getResult, arg, onSuccess)
276
277
else {
277
278
val dropped = ref(getResult)
278
279
.select(defn.Seq_drop .matchingMember(getResult.info))
279
280
.appliedTo(Literal (Constant (args.length - 1 )))
280
281
letAbstract(dropped) { droppedResult =>
281
- patternPlan(droppedResult, arg, onSuccess, onFailure )
282
+ patternPlan(droppedResult, arg, onSuccess)
282
283
}
283
284
}
284
285
matchElemsPlan(getResult, args.init, exact = false , matchRemaining)
@@ -297,7 +298,7 @@ object PatternMatcher {
297
298
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length)
298
299
matchArgsPlan(caseAccessors.map(ref(scrutinee).select(_)), args, onSuccess)
299
300
else if (unapp.tpe.widenSingleton.isRef(defn.BooleanClass ))
300
- TestPlan (GuardTest , unapp, unapp.pos, onSuccess, onFailure )
301
+ TestPlan (GuardTest , unapp, unapp.pos, onSuccess)
301
302
else {
302
303
letAbstract(unapp) { unappResult =>
303
304
val isUnapplySeq = unapp.symbol.name == nme.unapplySeq
@@ -320,7 +321,7 @@ object PatternMatcher {
320
321
matchArgsPlan(selectors, args, onSuccess)
321
322
}
322
323
}
323
- TestPlan (NonEmptyTest , unappResult, unapp.pos, argsPlan, onFailure )
324
+ TestPlan (NonEmptyTest , unappResult, unapp.pos, argsPlan)
324
325
}
325
326
}
326
327
}
@@ -332,54 +333,58 @@ object PatternMatcher {
332
333
TestPlan (TypeTest (tpt), scrutinee, tree.pos,
333
334
letAbstract(ref(scrutinee).asInstance(tpt.tpe)) { casted =>
334
335
nonNull += casted
335
- patternPlan(casted, pat, onSuccess, onFailure)
336
- },
337
- onFailure)
336
+ patternPlan(casted, pat, onSuccess)
337
+ })
338
338
case UnApply (extractor, implicits, args) =>
339
339
val mt @ MethodType (_) = extractor.tpe.widen
340
340
var unapp = extractor.appliedTo(ref(scrutinee).ensureConforms(mt.paramInfos.head))
341
341
if (implicits.nonEmpty) unapp = unapp.appliedToArgs(implicits)
342
342
val unappPlan = unapplyPlan(unapp, args)
343
343
if (scrutinee.info.isNotNull || nonNull(scrutinee)) unappPlan
344
- else TestPlan (NonNullTest , scrutinee, tree.pos, unappPlan, onFailure )
344
+ else TestPlan (NonNullTest , scrutinee, tree.pos, unappPlan)
345
345
case Bind (name, body) =>
346
- if (name == nme.WILDCARD ) patternPlan(scrutinee, body, onSuccess, onFailure )
346
+ if (name == nme.WILDCARD ) patternPlan(scrutinee, body, onSuccess)
347
347
else {
348
348
// The type of `name` may refer to val in `body`, therefore should come after `body`
349
349
val bound = tree.symbol.asTerm
350
350
initializer(bound) = ref(scrutinee)
351
- patternPlan(scrutinee, body, LetPlan (bound, onSuccess), onFailure )
351
+ patternPlan(scrutinee, body, LetPlan (bound, onSuccess))
352
352
}
353
353
case Alternative (alts) =>
354
- labeledAbstract(onSuccess) { ons =>
355
- (alts :\ onFailure) { (alt, onf) =>
356
- labeledAbstract(onf) { onf1 =>
357
- patternPlan(scrutinee, alt, ons, onf1)
358
- }
359
- }
354
+ labeledAbstract { onf =>
355
+ SeqPlan (
356
+ labeledAbstract { ons =>
357
+ alts.foldRight(onf) { (alt, next) =>
358
+ SeqPlan (patternPlan(scrutinee, alt, ons), next)
359
+ }
360
+ },
361
+ onSuccess
362
+ )
360
363
}
361
364
case WildcardPattern () =>
362
365
onSuccess
363
366
case SeqLiteral (pats, _) =>
364
367
matchElemsPlan(scrutinee, pats, exact = true , onSuccess)
365
368
case _ =>
366
- TestPlan (EqualTest (tree), scrutinee, tree.pos, onSuccess, onFailure )
369
+ TestPlan (EqualTest (tree), scrutinee, tree.pos, onSuccess)
367
370
}
368
371
}
369
372
370
- private def caseDefPlan (scrutinee : Symbol , cdef : CaseDef , onFailure : Plan ): Plan =
371
- labeledAbstract(onFailure) { onf =>
372
- var onSuccess : Plan = ResultPlan (cdef.body)
373
- if (! cdef.guard.isEmpty)
374
- onSuccess = TestPlan (GuardTest , cdef.guard, cdef.guard.pos, onSuccess, onf)
375
- patternPlan(scrutinee, cdef.pat, onSuccess, onf)
376
- }
373
+ private def caseDefPlan (scrutinee : Symbol , cdef : CaseDef ): Plan = {
374
+ var onSuccess : Plan = ResultPlan (cdef.body)
375
+ if (! cdef.guard.isEmpty)
376
+ onSuccess = TestPlan (GuardTest , cdef.guard, cdef.guard.pos, onSuccess)
377
+ patternPlan(scrutinee, cdef.pat, onSuccess)
378
+ }
377
379
378
- private def matchPlan (tree : Match ): Plan =
380
+ private def matchPlan (tree : Match ): Plan = {
379
381
letAbstract(tree.selector) { scrutinee =>
380
382
val matchError : Plan = ResultPlan (Throw (New (defn.MatchErrorType , ref(scrutinee) :: Nil )))
381
- (tree.cases :\ matchError)(caseDefPlan(scrutinee, _, _))
383
+ tree.cases.foldRight(matchError) { (cdef, next) =>
384
+ SeqPlan (caseDefPlan(scrutinee, cdef), next)
385
+ }
382
386
}
387
+ }
383
388
384
389
// ----- Optimizing plans ---------------
385
390
@@ -392,7 +397,6 @@ object PatternMatcher {
392
397
def apply (plan : TestPlan ): Plan = {
393
398
plan.scrutinee = apply(plan.scrutinee)
394
399
plan.onSuccess = apply(plan.onSuccess)
395
- plan.onFailure = apply(plan.onFailure)
396
400
plan
397
401
}
398
402
def apply (plan : LetPlan ): Plan = {
@@ -402,15 +406,20 @@ object PatternMatcher {
402
406
}
403
407
def apply (plan : LabeledPlan ): Plan = {
404
408
plan.expr = apply(plan.expr)
405
- plan.next = apply(plan.next)
406
409
plan
407
410
}
408
411
def apply (plan : ReturnPlan ): Plan = plan
412
+ def apply (plan : SeqPlan ): Plan = {
413
+ plan.head = apply(plan.head)
414
+ plan.tail = apply(plan.tail)
415
+ plan
416
+ }
409
417
def apply (plan : Plan ): Plan = plan match {
410
418
case plan : TestPlan => apply(plan)
411
419
case plan : LetPlan => apply(plan)
412
420
case plan : LabeledPlan => apply(plan)
413
421
case plan : ReturnPlan => apply(plan)
422
+ case plan : SeqPlan => apply(plan)
414
423
case plan : ResultPlan => plan
415
424
}
416
425
}
@@ -426,7 +435,6 @@ object PatternMatcher {
426
435
object refCounter extends RefCounter {
427
436
override def apply (plan : LabeledPlan ): Plan = {
428
437
apply(plan.expr)
429
- apply(plan.next)
430
438
plan
431
439
}
432
440
override def apply (plan : ReturnPlan ): Plan = {
@@ -500,6 +508,7 @@ object PatternMatcher {
500
508
* We use some tricks to identify a let pointing to an unapply and the
501
509
* NonEmptyTest that follows it as a single `UnappTest` test.
502
510
*/
511
+ /*
503
512
def mergeTests(plan: Plan): Plan = {
504
513
def isUnapply(sym: Symbol) = sym.name == nme.unapply || sym.name == nme.unapplySeq
505
514
@@ -570,6 +579,7 @@ object PatternMatcher {
570
579
}
571
580
new MergeTests()(plan)
572
581
}
582
+ */
573
583
574
584
/** Eliminate tests that are redundant (known to be true or false).
575
585
* Two parts:
@@ -894,6 +904,7 @@ object PatternMatcher {
894
904
* a switch, including a last default case, by starting with this
895
905
* plan and following onSuccess plans.
896
906
*/
907
+ /*
897
908
private def collectSwitchCases(plan: TestPlan): List[Plan] = {
898
909
def isSwitchableType(tpe: Type): Boolean =
899
910
(tpe isRef defn.IntClass) ||
@@ -919,14 +930,17 @@ object PatternMatcher {
919
930
if (isSwitchableType(scrutinee.tpe.widen)) recur(plan)
920
931
else Nil
921
932
}
933
+ */
922
934
923
935
/** Emit cases of a switch */
936
+ /*
924
937
private def emitSwitchCases(cases: List[Plan]): List[CaseDef] = (cases: @unchecked) match {
925
938
case (default: Plan) :: Nil =>
926
939
CaseDef(Underscore(defn.IntType), EmptyTree, emit(default)) :: Nil
927
940
case TestPlan(EqualTest(tree), _, _, ons, _) :: cases1 =>
928
941
CaseDef(tree, EmptyTree, emit(ons)) :: emitSwitchCases(cases1)
929
942
}
943
+ */
930
944
931
945
/** If selfCheck is `true`, used to check whether a tree gets generated twice */
932
946
private val emitted = mutable.Set [Int ]()
@@ -939,10 +953,10 @@ object PatternMatcher {
939
953
}
940
954
plan match {
941
955
case plan : TestPlan =>
942
- val switchCases = collectSwitchCases(plan)
956
+ /* val switchCases = collectSwitchCases(plan)
943
957
if (switchCases.lengthCompare(MinSwitchCases) >= 0) // at least 3 cases + default
944
958
Match(plan.scrutinee, emitSwitchCases(switchCases))
945
- else {
959
+ else*/ {
946
960
/** Merge nested `if`s that have the same `else` branch into a single `if`.
947
961
* This optimization targets calls to label defs for case failure jumps to next case.
948
962
*
@@ -966,7 +980,7 @@ object PatternMatcher {
966
980
def emitWithMashedConditions (plans : List [TestPlan ]): Tree = {
967
981
val plan = plans.head
968
982
plan.onSuccess match {
969
- case plan2 : TestPlan if plan.onFailure == plan2.onFailure =>
983
+ case plan2 : TestPlan =>
970
984
emitWithMashedConditions(plan2 :: plans)
971
985
case _ =>
972
986
def emitCondWithPos (plan : TestPlan ) = emitCondition(plan).withPos(plan.pos)
@@ -975,19 +989,19 @@ object PatternMatcher {
975
989
if (acc.isEmpty) emitCondWithPos(otherPlan)
976
990
else acc.select(nme.ZAND ).appliedTo(emitCondWithPos(otherPlan))
977
991
}
978
- If (conditions, emit(plan.onSuccess), emit(plan.onFailure) )
992
+ If (conditions, emit(plan.onSuccess), unitLiteral )
979
993
}
980
-
981
994
}
982
995
emitWithMashedConditions(plan :: Nil )
983
996
}
984
997
case LetPlan (sym, body) =>
985
998
seq(ValDef (sym, initializer(sym).ensureConforms(sym.info)) :: Nil , emit(body))
986
- case LabeledPlan (label, expr, next) =>
987
- val labeledBlock = Labeled (label, emit(expr))
988
- seq(labeledBlock :: Nil , emit(next))
999
+ case LabeledPlan (label, expr) =>
1000
+ Labeled (label, emit(expr))
989
1001
case ReturnPlan (label) =>
990
1002
Return (Literal (Constant (())), ref(label))
1003
+ case SeqPlan (head, tail) =>
1004
+ seq(emit(head) :: Nil , emit(tail))
991
1005
case ResultPlan (tree) =>
992
1006
Return (tree, ref(resultLabel))
993
1007
}
@@ -1009,21 +1023,23 @@ object PatternMatcher {
1009
1023
seen += plan.id
1010
1024
sb append s " \n ${plan.id}: "
1011
1025
plan match {
1012
- case TestPlan (test, scrutinee, _, ons, onf ) =>
1013
- sb.append(i " $scrutinee ? ${showTest(test)}( ${ons.id}, ${onf.id} ) " )
1026
+ case TestPlan (test, scrutinee, _, ons) =>
1027
+ sb.append(i " $scrutinee ? ${showTest(test)}( ${ons.id}) " )
1014
1028
showPlan(ons)
1015
- showPlan(onf)
1016
1029
case LetPlan (sym, body) =>
1017
1030
sb.append(i " Let( $sym = ${initializer(sym)}}, ${body.id}) " )
1018
1031
sb.append(s " , refcount = ${vrefCount(sym)}" )
1019
1032
showPlan(body)
1020
- case LabeledPlan (label, expr, next ) =>
1021
- sb.append(i " Labeled( $label: { ${expr.id} }; ${next.id} ) " )
1033
+ case LabeledPlan (label, expr) =>
1034
+ sb.append(i " Labeled( $label: { ${expr.id} }) " )
1022
1035
sb.append(s " , refcount = ${lrefCount(label)}" )
1023
1036
showPlan(expr)
1024
- showPlan(next)
1025
1037
case ReturnPlan (label) =>
1026
1038
sb.append(s " Return( $label) " )
1039
+ case SeqPlan (head, tail) =>
1040
+ sb.append(s " ${head.id}; ${tail.id}" )
1041
+ showPlan(head)
1042
+ showPlan(tail)
1027
1043
case ResultPlan (tree) =>
1028
1044
sb.append(tree.show)
1029
1045
}
@@ -1075,12 +1091,12 @@ object PatternMatcher {
1075
1091
def translateMatch (tree : Match ): Tree = {
1076
1092
var plan = matchPlan(tree)
1077
1093
// patmatch.println(i"Plan for $tree: ${show(plan)}")
1078
- System .err.println(i " Plan for $tree: ${show(plan)}" )
1094
+ // System.err.println(i"Plan for $tree: ${show(plan)}")
1079
1095
if (! ctx.settings.YnoPatmatOpt .value)
1080
1096
for ((title, optimization) <- optimizations) {
1081
1097
plan = optimization(plan)
1082
1098
// patmatch.println(s"After $title: ${show(plan)}")
1083
- System .err.println(s " After $title: ${show(plan)}" )
1099
+ // System.err.println(s"After $title: ${show(plan)}")
1084
1100
}
1085
1101
val result = emit(plan)
1086
1102
// checkSwitch(tree, result)
0 commit comments