@@ -68,10 +68,10 @@ object PatternMatcher {
6868 * - emit the translated tree, using methods `emit`, `collectSwitchCases`,
6969 * `emitSwitchCases`, and `emitCondition`.
7070 *
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.
7575 */
7676 class Translator (resultType : Type , thisPhase : MiniPhase )(implicit ctx : Context ) {
7777
@@ -104,13 +104,6 @@ object PatternMatcher {
104104 LabeledPlan (label, expr(ReturnPlan (label)))
105105 }
106106
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-
114107 /** Test whether a type refers to a pattern-generated variable */
115108 private val refersToInternal = new TypeAccumulator [Boolean ] {
116109 def apply (x : Boolean , tp : Type ) =
@@ -505,6 +498,9 @@ object PatternMatcher {
505498 * }
506499 *
507500 * 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.
508504 */
509505 def mergeTests (plan : Plan ): Plan = {
510506 class SubstituteIdent (from : TermSymbol , to : TermSymbol ) extends PlanTransform {
@@ -574,95 +570,6 @@ object PatternMatcher {
574570 new MergeTests ()(plan)
575571 }
576572
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-
666573 /** Inline let-bound trees that are referenced only once.
667574 * Drop all variables that are not referenced anymore after this.
668575 */
@@ -782,6 +689,7 @@ object PatternMatcher {
782689 case _ => false
783690 }
784691
692+ // An extractor to recover the shape of plans that can become alternatives
785693 object AlternativesPlan {
786694 def unapply (plan : LabeledPlan ): Option [(List [Tree ], Plan )] = {
787695 plan.expr match {
@@ -951,7 +859,7 @@ object PatternMatcher {
951859 case ReturnPlan (label) =>
952860 sb.append(s " Return( $label) " )
953861 case SeqPlan (head, tail) =>
954- sb.append(s " ${head.id}; ${tail.id}" )
862+ sb.append(s " Seq( ${head.id}, ${tail.id}) " )
955863 showPlan(head)
956864 showPlan(tail)
957865 case ResultPlan (tree) =>
@@ -993,22 +901,16 @@ object PatternMatcher {
993901 val optimizations : List [(String , Plan => Plan )] = List (
994902 " mergeTests" -> mergeTests,
995903 " inlineVars" -> inlineVars
996- /*
997- "mergeVars" -> mergeVars,
998- "inlineVars" -> inlineVars
999- */
1000904 )
1001905
1002906 /** Translate pattern match to sequence of tests. */
1003907 def translateMatch (tree : Match ): Tree = {
1004908 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)}" )
1007910 if (! ctx.settings.YnoPatmatOpt .value)
1008911 for ((title, optimization) <- optimizations) {
1009912 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)}" )
1012914 }
1013915 val result = emit(plan)
1014916 checkSwitch(tree, result)
0 commit comments