@@ -74,20 +74,23 @@ object PatternMatcher {
74
74
private val initializer = mutable.Map [Symbol , Tree ]()
75
75
private val labelled = mutable.Map [Symbol , Plan ]()
76
76
77
+ private def newVar (rhs : Tree , flags : FlagSet ): TermSymbol =
78
+ ctx.newSymbol(ctx.owner, PatMatStdBinderName .fresh(), Synthetic | Case | flags,
79
+ sanitize(rhs.tpe), coord = rhs.pos)
80
+
77
81
/** The plan `let x = rhs in body(x)` where `x` is a fresh variable */
78
82
private def letAbstract (rhs : Tree )(body : Symbol => Plan ): Plan = {
79
- val vble = ctx.newSymbol(ctx.owner, PatMatStdBinderName .fresh(), Synthetic | Case ,
80
- sanitize(rhs.tpe), coord = rhs.pos)
83
+ val vble = newVar(rhs, EmptyFlags )
81
84
initializer(vble) = rhs
82
85
LetPlan (vble, body(vble))
83
86
}
84
87
85
88
/** The plan `let l = labelled in body(l)` where `l` is a fresh label */
86
- private def labelAbstract (labeld : Plan )(body : Plan => Plan ): Plan = {
89
+ private def labelAbstract (labeld : Plan )(body : ( => Plan ) => Plan ): Plan = {
87
90
val label = ctx.newSymbol(ctx.owner, PatMatCaseName .fresh(), Synthetic | Label | Method ,
88
91
MethodType (Nil , resultType))
89
92
labelled(label) = labeld
90
- LabelledPlan (label, body(CallPlan (label)) )
93
+ LabelledPlan (label, body(CallPlan (label, Nil )), Nil )
91
94
}
92
95
93
96
/** Was symbol generated by pattern matcher? */
@@ -127,9 +130,10 @@ object PatternMatcher {
127
130
}
128
131
129
132
case class LetPlan (sym : TermSymbol , var body : Plan ) extends Plan
130
- case class LabelledPlan (sym : TermSymbol , var body : Plan ) extends Plan
133
+ case class LabelledPlan (sym : TermSymbol , var body : Plan , var params : List [ TermSymbol ] ) extends Plan
131
134
case class CodePlan (var tree : Tree ) extends Plan
132
- case class CallPlan (label : TermSymbol ) extends Plan
135
+ case class CallPlan (label : TermSymbol ,
136
+ var args : List [(/* formal*/ TermSymbol , /* actual*/ TermSymbol )]) extends Plan
133
137
134
138
object TestPlan {
135
139
def apply (test : Test , sym : Symbol , pos : Position , ons : Plan , onf : Plan ): TestPlan =
@@ -368,16 +372,36 @@ object PatternMatcher {
368
372
}
369
373
}
370
374
375
+ private class RefCounter extends PlanTransform {
376
+ val count = new mutable.HashMap [Symbol , Int ] {
377
+ override def default (key : Symbol ) = 0
378
+ }
379
+ }
380
+
371
381
/** Reference counts for all variables and labels */
372
- def referenceCount (plan : Plan ): collection.Map [Symbol , Int ] = {
373
- object RefCount extends PlanTransform {
374
- val count = new mutable.HashMap [Symbol , Int ] {
375
- override def default (key : Symbol ) = 0
382
+ private def labelRefCount (plan : Plan ): collection.Map [Symbol , Int ] = {
383
+ object refCounter extends RefCounter {
384
+ override def apply (plan : LabelledPlan ): Plan = {
385
+ apply(plan.body)
386
+ if (count(plan.sym) != 0 ) apply(labelled(plan.sym))
387
+ plan
388
+ }
389
+ override def apply (plan : CallPlan ): Plan = {
390
+ count(plan.label) += 1
391
+ plan
376
392
}
393
+ }
394
+ refCounter(plan)
395
+ refCounter.count
396
+ }
397
+
398
+ /** Reference counts for all variables and labels */
399
+ private def varRefCount (plan : Plan ): collection.Map [Symbol , Int ] = {
400
+ object refCounter extends RefCounter {
377
401
override val treeMap = new TreeMap {
378
402
override def transform (tree : Tree )(implicit ctx : Context ) = tree match {
379
403
case tree : Ident =>
380
- if (initializer contains tree.symbol) count(tree.symbol) += 1
404
+ if (isPatmatGenerated( tree.symbol) ) count(tree.symbol) += 1
381
405
tree
382
406
case _ =>
383
407
super .transform(tree)
@@ -390,18 +414,18 @@ object PatternMatcher {
390
414
plan
391
415
}
392
416
override def apply (plan : LabelledPlan ): Plan = {
417
+ apply(labelled(plan.sym))
393
418
apply(plan.body)
394
- if (count(plan.sym) != 0 )
395
- apply(labelled(plan.sym))
396
419
plan
397
420
}
398
421
override def apply (plan : CallPlan ): Plan = {
399
- count(plan.label) += 1
422
+ for ((formal, actual) <- plan.args)
423
+ if (count(formal) != 0 ) count(actual) += 1
400
424
plan
401
425
}
402
426
}
403
- RefCount (plan)
404
- RefCount .count
427
+ refCounter (plan)
428
+ refCounter .count
405
429
}
406
430
407
431
/** Rewrite everywhere
@@ -421,13 +445,13 @@ object PatternMatcher {
421
445
object hoistLabels extends PlanTransform {
422
446
override def apply (plan : TestPlan ): Plan =
423
447
plan.onSuccess match {
424
- case lp @ LabelledPlan (sym, body) =>
448
+ case lp @ LabelledPlan (sym, body, _ ) =>
425
449
plan.onSuccess = body
426
450
lp.body = plan
427
451
apply(lp)
428
452
case _ =>
429
453
plan.onFailure match {
430
- case lp @ LabelledPlan (sym, body) =>
454
+ case lp @ LabelledPlan (sym, body, _ ) =>
431
455
plan.onFailure = body
432
456
lp.body = plan
433
457
apply(lp)
@@ -552,7 +576,7 @@ object PatternMatcher {
552
576
* Drop all labels that are not referenced anymore after this.
553
577
*/
554
578
private def inlineLabelled (plan : Plan ) = {
555
- val refCount = referenceCount (plan)
579
+ val refCount = labelRefCount (plan)
556
580
def toDrop (sym : Symbol ) = labelled.contains(sym) && refCount(sym) <= 1
557
581
class Inliner extends PlanTransform {
558
582
override def apply (plan : LabelledPlan ): Plan =
@@ -575,8 +599,17 @@ object PatternMatcher {
575
599
}
576
600
override def hashCode : Int = tree.hash
577
601
}
602
+ type SeenVars = Map [RHS , TermSymbol ]
578
603
579
- class Merge (seenVars : Map [RHS , Symbol ]) extends PlanTransform {
604
+ /** The variables known at entry to label */
605
+ val seenAtLabel = mutable.HashMap [Symbol , SeenVars ]()
606
+
607
+ /** Parameters of label; these are passed additional variables
608
+ * which are known at all callsites.
609
+ */
610
+ val paramsOfLabel = mutable.HashMap [Symbol , SeenVars ]()
611
+
612
+ class Merge (seenVars : SeenVars ) extends PlanTransform {
580
613
override val treeMap = new TreeMap {
581
614
override def transform (tree : Tree )(implicit ctx : Context ) = tree match {
582
615
case tree : Ident =>
@@ -593,21 +626,49 @@ object PatternMatcher {
593
626
}
594
627
595
628
override def apply (plan : LetPlan ): Plan = {
629
+ initializer(plan.sym) = apply(initializer(plan.sym))
596
630
val seenVars1 =
597
631
if (isPatmatGenerated(plan.sym)) {
598
632
val thisRhs = new RHS (initializer(plan.sym))
599
633
seenVars.get(thisRhs) match {
600
634
case Some (seen) =>
601
635
initializer(plan.sym) = ref(seen)
636
+ seenVars
602
637
case none =>
638
+ seenVars.updated(thisRhs, plan.sym)
603
639
}
604
- seenVars.updated(thisRhs, plan.sym)
605
640
}
606
641
else seenVars
607
- initializer(plan.sym) = apply(initializer(plan.sym))
608
642
plan.body = new Merge (seenVars1)(plan.body)
609
643
plan
610
644
}
645
+
646
+ override def apply (plan : LabelledPlan ): Plan = {
647
+ seenAtLabel(plan.sym) = seenVars
648
+ plan.body = apply(plan.body)
649
+ val paramsMap = paramsOfLabel.getOrElse(plan.sym, Map ())
650
+ plan.params = paramsMap.values.toList.sortBy(_.name.toString)
651
+ val seenVars1 = seenVars ++ paramsMap
652
+ labelled(plan.sym) = new Merge (seenVars1)(labelled(plan.sym))
653
+ plan
654
+ }
655
+
656
+ override def apply (plan : CallPlan ): Plan = {
657
+ paramsOfLabel(plan.label) = paramsOfLabel.get(plan.label) match {
658
+ case Some (params) =>
659
+ params.filter { case (rhs, _) => seenVars.contains(rhs) }
660
+ case none =>
661
+ for ((rhs, _) <- seenVars if ! seenAtLabel(plan.label).contains(rhs))
662
+ yield (rhs, newVar(rhs.tree, Param ))
663
+ }
664
+ plan.args =
665
+ for {
666
+ (rhs, actual) <- seenVars.toList
667
+ formal <- paramsOfLabel(plan.label).get(rhs)
668
+ }
669
+ yield (formal -> actual)
670
+ plan
671
+ }
611
672
}
612
673
(new Merge (Map ()))(plan)
613
674
}
@@ -617,7 +678,7 @@ object PatternMatcher {
617
678
* Also: hoist cases out of tests using `hoistLabelled`.
618
679
*/
619
680
private def inlineVars (plan : Plan ): Plan = {
620
- val refCount = referenceCount (plan)
681
+ val refCount = varRefCount (plan)
621
682
val LetPlan (topSym, _) = plan
622
683
623
684
def toDrop (sym : Symbol ) =
@@ -628,7 +689,8 @@ object PatternMatcher {
628
689
override def transform (tree : Tree )(implicit ctx : Context ) = tree match {
629
690
case tree : Ident =>
630
691
val sym = tree.symbol
631
- if (toDrop(sym)) transform(initializer(sym)) else tree
692
+ if (toDrop(sym)) transform(initializer(sym))
693
+ else tree
632
694
case _ =>
633
695
super .transform(tree)
634
696
}
@@ -641,6 +703,16 @@ object PatternMatcher {
641
703
plan
642
704
}
643
705
}
706
+ override def apply (plan : LabelledPlan ): Plan = {
707
+ plan.params = plan.params.filter(refCount(_) != 0 )
708
+ super .apply(plan)
709
+ }
710
+ override def apply (plan : CallPlan ): Plan = {
711
+ plan.args = plan.args
712
+ .filter(formalActual => refCount(formalActual._1) != 0 )
713
+ .sortBy(_._1.name.toString)
714
+ plan
715
+ }
644
716
}
645
717
Inliner (plan)
646
718
}
@@ -758,18 +830,21 @@ object PatternMatcher {
758
830
If (emitCondition(plan).withPos(plan.pos), emit(plan.onSuccess), emit(plan.onFailure))
759
831
case LetPlan (sym, body) =>
760
832
seq(ValDef (sym, initializer(sym).ensureConforms(sym.info)) :: Nil , emit(body))
761
- case LabelledPlan (label, body) =>
762
- seq(DefDef (label, emit(labelled(label))) :: Nil , emit(body))
833
+ case LabelledPlan (label, body, params) =>
834
+ label.info = MethodType .fromSymbols(params, resultType)
835
+ val labelDef = DefDef (label, Nil , params :: Nil , resultType, emit(labelled(label)))
836
+ seq(labelDef :: Nil , emit(body))
763
837
case CodePlan (tree) =>
764
838
tree
765
- case CallPlan (label) =>
766
- ref(label).ensureApplied
839
+ case CallPlan (label, args ) =>
840
+ ref(label).appliedToArgs(args.map { case (_, actual) => ref(actual) })
767
841
}
768
842
}
769
843
770
844
/** Pretty-print plan; used for debugging */
771
845
def show (plan : Plan ): String = {
772
- val refCount = referenceCount(plan)
846
+ val lrefCount = labelRefCount(plan)
847
+ val vrefCount = varRefCount(plan)
773
848
val sb = new StringBuilder
774
849
val seen = mutable.Set [Int ]()
775
850
def showTest (test : Test ) = test match {
@@ -788,18 +863,20 @@ object PatternMatcher {
788
863
showPlan(onf)
789
864
case LetPlan (sym, body) =>
790
865
sb.append(i " Let( $sym = ${initializer(sym)}}, ${body.id}) " )
791
- sb.append(s " , refcount = ${refCount (sym)}" )
866
+ sb.append(s " , refcount = ${vrefCount (sym)}" )
792
867
showPlan(body)
793
- case LabelledPlan (label, body) =>
868
+ case LabelledPlan (label, body, params ) =>
794
869
val labeld = labelled(label)
795
- sb.append(i " Labelled( $label = ${labeld.id}, ${body.id}) " )
796
- sb.append(s " , refcount = ${refCount(label)}" )
870
+ def showParam (param : Symbol ) =
871
+ i " $param: ${param.info}, refCount = ${vrefCount(param)}"
872
+ sb.append(i " Labelled( $label( ${params.map(showParam)}%, %) = ${labeld.id}, ${body.id}) " )
873
+ sb.append(s " , refcount = ${lrefCount(label)}" )
797
874
showPlan(body)
798
875
showPlan(labeld)
799
876
case CodePlan (tree) =>
800
877
sb.append(tree.show)
801
- case CallPlan (label) =>
802
- sb.append(s " Call( $label) " )
878
+ case CallPlan (label, params ) =>
879
+ sb.append(s " Call( $label( ${params.map(_._2)} %, % )" )
803
880
}
804
881
}
805
882
showPlan(plan)
0 commit comments