@@ -47,7 +47,24 @@ object PatternMatcher {
4747
4848 final val selfCheck = true // debug option, if on we check that no case gets generated twice
4949
50- /** The pattern matching translator. */
50+ /** The pattern matching translator.
51+ * Its general structure is a pipeline:
52+ *
53+ * Match tree ---matchPlan---> Plan ---optimize---> Plan ---emit---> Tree
54+ *
55+ * The pipeline consists of three steps:
56+ *
57+ * - build a plan, using methods `matchPlan`, `caseDefPlan`, `patternPlan`.
58+ * - optimize the plan, using methods `optimize`, `hoistLabelled`, `referenceCount`.
59+ * - emit the translated tree, using methods `emit`, `collectSwitchCases`,
60+ * `emitSwitchCases`, and `emitCondition`.
61+ *
62+ * A plan represents the underlying decision graph. It consists
63+ * of tests, let and label bindings, calls to labels and code blocks.
64+ * It's represented by its own data type. Plans are optimized by
65+ * inlining, hoisting, and dead code elimination. We should also
66+ * do common test elimination but right now this is missing.
67+ */
5168 class Translator (resultType : Type , trans : TreeTransform )(implicit ctx : Context , info : TransformerInfo ) {
5269
5370 // ------- Bindings for variables and labels ---------------------
@@ -356,17 +373,17 @@ object PatternMatcher {
356373 *
357374 * The rewrite is useful to group cases that can form a switch together.
358375 */
359- private def hoistCases (plan : TestPlan ): Plan = plan.onFailure match {
376+ private def hoistLabelled (plan : TestPlan ): Plan = plan.onFailure match {
360377 case LetPlan (sym, body) if sym.is(Label ) =>
361378 plan.onFailure = body
362- LetPlan (sym, hoistCases (plan))
379+ LetPlan (sym, hoistLabelled (plan))
363380 case _ =>
364381 plan
365382 }
366383
367384 /** Inline let-bound trees and labelled blocks that are referenced only once.
368385 * Drop all variables and labels that are not referenced anymore after this.
369- * Also: hoist cases out of tests using `hoistCases `.
386+ * Also: hoist cases out of tests using `hoistLabelled `.
370387 */
371388 private def optimize (plan : Plan ): Plan = {
372389 val refCount = referenceCount(plan)
@@ -387,7 +404,7 @@ object PatternMatcher {
387404 plan.scrutinee = treeMap.transform(plan.scrutinee)
388405 plan.onSuccess = transform(plan.onSuccess)
389406 plan.onFailure = transform(plan.onFailure)
390- hoistCases (plan)
407+ hoistLabelled (plan)
391408 case plan @ LetPlan (sym, body) =>
392409 val body1 = transform(body)
393410 if (toDrop(sym)) body1
@@ -412,15 +429,8 @@ object PatternMatcher {
412429
413430 // ----- Generating trees from plans ---------------
414431
415- /** The position to be used for the tree generated from a plan */
416- private def position (plan : TestPlan ) = plan.test match {
417- case TypeTest (tpt) => tpt.pos
418- case EqualTest (tree) => tree.pos
419- case _ => plan.scrutinee.pos
420- }
421-
422432 /** The condition a test plan rewrites to */
423- private def condition (plan : TestPlan ): Tree = {
433+ private def emitCondition (plan : TestPlan ): Tree = {
424434 val scrutinee = plan.scrutinee
425435 plan.test match {
426436 case NonEmptyTest =>
@@ -526,7 +536,7 @@ object PatternMatcher {
526536 if (switchCases.lengthCompare(4 ) >= 0 ) // at least 3 cases + default
527537 Match (plan.scrutinee, emitSwitchCases(switchCases))
528538 else
529- If (condition (plan).withPos(position( plan) ), emit(plan.onSuccess), emit(plan.onFailure))
539+ If (emitCondition (plan).withPos(plan.pos ), emit(plan.onSuccess), emit(plan.onFailure))
530540 case plan @ LetPlan (sym, body) =>
531541 val symDef =
532542 if (sym.is(Label )) DefDef (sym, emit(labelled(sym)))
0 commit comments