@@ -68,10 +68,10 @@ object PatternMatcher {
68
68
* - emit the translated tree, using methods `emit`, `collectSwitchCases`,
69
69
* `emitSwitchCases`, and `emitCondition`.
70
70
*
71
- * A plan represents the underlying decision graph. It consists
72
- * of tests, let and label bindings, calls to labels and code blocks.
73
- * It's represented by its own data type. Plans are optimized by
74
- * inlining, hoisting, and the elimination of redundant tests and dead code.
71
+ * A plan represents the underlying decision graph. It consists of tests,
72
+ * let bindings, labeled blocks, return from said labeled blocks and code blocks.
73
+ * It's represented by its own data type. Plans are optimized by merging common
74
+ * tests and eliminating dead code.
75
75
*/
76
76
class Translator (resultType : Type , thisPhase : MiniPhase )(implicit ctx : Context ) {
77
77
@@ -104,13 +104,6 @@ object PatternMatcher {
104
104
LabeledPlan (label, expr(ReturnPlan (label)))
105
105
}
106
106
107
- /** The plan `l: { expr(l) }` where `l` is a fresh label */
108
- private def labeledAbstract2 (expr : TermSymbol => Plan ): Plan = {
109
- val label = ctx.newSymbol(ctx.owner, PatMatCaseName .fresh(), Synthetic | Label ,
110
- defn.UnitType )
111
- LabeledPlan (label, expr(label))
112
- }
113
-
114
107
/** Test whether a type refers to a pattern-generated variable */
115
108
private val refersToInternal = new TypeAccumulator [Boolean ] {
116
109
def apply (x : Boolean , tp : Type ) =
@@ -505,6 +498,9 @@ object PatternMatcher {
505
498
* }
506
499
*
507
500
* where plan2[x1/x2] means substituting x1 for x2 in plan2.
501
+ *
502
+ * There are some tricks to "ignore" non-patmat-generated let bindings, i.e.,
503
+ * captures written in the source code, while identifying common subplans.
508
504
*/
509
505
def mergeTests (plan : Plan ): Plan = {
510
506
class SubstituteIdent (from : TermSymbol , to : TermSymbol ) extends PlanTransform {
@@ -574,95 +570,6 @@ object PatternMatcher {
574
570
new MergeTests ()(plan)
575
571
}
576
572
577
- /** Merge variables that have the same right hand side.
578
- * Propagate common variable bindings as parameters into case labels.
579
- */
580
- /*
581
- private def mergeVars(plan: Plan): Plan = {
582
- class RHS(val tree: Tree) {
583
- override def equals(that: Any) = that match {
584
- case that: RHS => this.tree === that.tree
585
- case _ => false
586
- }
587
- override def hashCode: Int = tree.hash
588
- }
589
- type SeenVars = Map[RHS, TermSymbol]
590
-
591
- /** The variables known at entry to label */
592
- val seenAtLabel = newMutableSymbolMap[SeenVars]
593
-
594
- /** Parameters of label; these are passed additional variables
595
- * which are known at all callsites.
596
- */
597
- val paramsOfLabel = newMutableSymbolMap[SeenVars]
598
-
599
- class Merge(seenVars: SeenVars) extends PlanTransform {
600
- override val treeMap = new TreeMap {
601
- override def transform(tree: Tree)(implicit ctx: Context) = tree match {
602
- case tree: Ident =>
603
- val sym = tree.symbol
604
- initializer.get(sym) match {
605
- case Some(id: Ident @unchecked)
606
- if isPatmatGenerated(sym) && isPatmatGenerated(id.symbol) =>
607
- transform(id)
608
- case none => tree
609
- }
610
- case _ =>
611
- super.transform(tree)
612
- }
613
- }
614
-
615
- override def apply(plan: LetPlan): Plan = {
616
- initializer(plan.sym) = apply(initializer(plan.sym))
617
- val seenVars1 =
618
- if (isPatmatGenerated(plan.sym)) {
619
- val thisRhs = new RHS(initializer(plan.sym))
620
- seenVars.get(thisRhs) match {
621
- case Some(seen) =>
622
- initializer(plan.sym) = ref(seen)
623
- seenVars
624
- case none =>
625
- seenVars.updated(thisRhs, plan.sym)
626
- }
627
- }
628
- else seenVars
629
- plan.body = new Merge(seenVars1)(plan.body)
630
- plan
631
- }
632
-
633
- override def apply(plan: LabelledPlan): Plan = {
634
- seenAtLabel(plan.sym) = seenVars
635
- plan.body = apply(plan.body)
636
- val paramsMap = paramsOfLabel.getOrElse(plan.sym, Map())
637
- plan.params = paramsMap.values.toList.sortBy(_.name.toString)
638
- val seenVars1 = seenVars ++ paramsMap
639
- labelled(plan.sym) = new Merge(seenVars1)(labelled(plan.sym))
640
- plan
641
- }
642
-
643
- override def apply(plan: CallPlan): Plan = {
644
- paramsOfLabel(plan.label) = paramsOfLabel.get(plan.label) match {
645
- case Some(params) =>
646
- params.filter { case (rhs, _) => seenVars.contains(rhs) }
647
- case none =>
648
- for ((rhs, _) <- seenVars if !seenAtLabel(plan.label).contains(rhs))
649
- yield (rhs, newVar(rhs.tree, Param))
650
- }
651
- val newArgs =
652
- for {
653
- (rhs, actual) <- seenVars.toList
654
- formal <- paramsOfLabel(plan.label).get(rhs)
655
- }
656
- yield (formal -> actual)
657
- if (plan.args.isEmpty) { plan.args = newArgs; plan }
658
- else if (newArgs == plan.args) plan
659
- else CallPlan(plan.label, newArgs)
660
- }
661
- }
662
- (new Merge(Map()))(plan)
663
- }
664
- */
665
-
666
573
/** Inline let-bound trees that are referenced only once.
667
574
* Drop all variables that are not referenced anymore after this.
668
575
*/
@@ -782,6 +689,7 @@ object PatternMatcher {
782
689
case _ => false
783
690
}
784
691
692
+ // An extractor to recover the shape of plans that can become alternatives
785
693
object AlternativesPlan {
786
694
def unapply (plan : LabeledPlan ): Option [(List [Tree ], Plan )] = {
787
695
plan.expr match {
@@ -951,7 +859,7 @@ object PatternMatcher {
951
859
case ReturnPlan (label) =>
952
860
sb.append(s " Return( $label) " )
953
861
case SeqPlan (head, tail) =>
954
- sb.append(s " ${head.id}; ${tail.id}" )
862
+ sb.append(s " Seq( ${head.id}, ${tail.id}) " )
955
863
showPlan(head)
956
864
showPlan(tail)
957
865
case ResultPlan (tree) =>
@@ -993,22 +901,16 @@ object PatternMatcher {
993
901
val optimizations : List [(String , Plan => Plan )] = List (
994
902
" mergeTests" -> mergeTests,
995
903
" inlineVars" -> inlineVars
996
- /*
997
- "mergeVars" -> mergeVars,
998
- "inlineVars" -> inlineVars
999
- */
1000
904
)
1001
905
1002
906
/** Translate pattern match to sequence of tests. */
1003
907
def translateMatch (tree : Match ): Tree = {
1004
908
var plan = matchPlan(tree)
1005
- // patmatch.println(i"Plan for $tree: ${show(plan)}")
1006
- // System.err.println(i"Plan for $tree: ${show(plan)}")
909
+ patmatch.println(i " Plan for $tree: ${show(plan)}" )
1007
910
if (! ctx.settings.YnoPatmatOpt .value)
1008
911
for ((title, optimization) <- optimizations) {
1009
912
plan = optimization(plan)
1010
- // patmatch.println(s"After $title: ${show(plan)}")
1011
- // System.err.println(s"After $title: ${show(plan)}")
913
+ patmatch.println(s " After $title: ${show(plan)}" )
1012
914
}
1013
915
val result = emit(plan)
1014
916
checkSwitch(tree, result)
0 commit comments