@@ -72,24 +72,18 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
7272 Annotated (Ident (nme.synthSwitch), expr)
7373 }
7474
75- // must be kept in synch with the codegen in PatMatVirtualiser
76- object VirtualCaseDef {
77- def unapply (b : Block ): Option [(Assign , Tree , Tree )] = b match {
78- case Block (List (assign@ Assign (keepGoingLhs, falseLit), matchRes), zero) => Some ((assign, matchRes, zero)) // TODO: check tree annotation
79- case _ => None
80- }
81- }
82-
8375 def hasSynthCaseSymbol (t : Tree ) = (t.symbol ne null ) && (t.symbol hasFlag (CASE | SYNTHETIC ))
8476
8577 // TODO: would be so much nicer if we would know during match-translation (i.e., type checking)
8678 // whether we should emit missingCase-style apply (and isDefinedAt), instead of transforming trees post-factum
8779 class MatchMatcher {
8880 def caseMatch (orig : Tree , selector : Tree , cases : List [CaseDef ], wrap : Tree => Tree ): Tree = unknownTree(orig)
8981 def caseVirtualizedMatch (orig : Tree , _match : Tree , targs : List [Tree ], scrut : Tree , matcher : Tree ): Tree = unknownTree(orig)
90- def caseVirtualizedMatchOpt (orig : Tree , zero : ValDef , x : ValDef , matchRes : ValDef , keepGoing : ValDef , stats : List [Tree ], epilogue : Tree , wrap : Tree => Tree ): Tree = unknownTree(orig)
82+ def caseVirtualizedMatchOpt (orig : Tree , prologue : List [ Tree ], cases : List [Tree ], matchEndDef : Tree , wrap : Tree => Tree ): Tree = unknownTree(orig)
9183
92- def apply (matchExpr : Tree ): Tree = (matchExpr : @ unchecked) match {
84+ def genVirtualizedMatch (prologue : List [Tree ], cases : List [Tree ], matchEndDef : Tree ): Tree = Block (prologue ++ cases, matchEndDef)
85+
86+ def apply (matchExpr : Tree ): Tree = matchExpr match {
9387 // old-style match or virtpatmat switch
9488 case Match (selector, cases) => // println("simple match: "+ (selector, cases) + "for:\n"+ matchExpr )
9589 caseMatch(matchExpr, selector, cases, identity)
@@ -100,11 +94,15 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
10094 case Apply (Apply (TypeApply (Select (tgt, nme.runOrElse), targs), List (scrut)), List (matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
10195 caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher)
10296 // optimized version of virtpatmat
103- case Block ((zero : ValDef ) :: (x : ValDef ) :: (matchRes : ValDef ) :: (keepGoing : ValDef ) :: stats, epilogue) if opt.virtPatmat => // TODO: check tree annotation // println("virtopt match: "+ (zero, x, matchRes, keepGoing, stats) + "for:\n"+ matchExpr )
104- caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, identity)
97+ case Block (stats, matchEndDef) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
98+ // the assumption is once we encounter a case, the remainder of the block will consist of cases
99+ // the prologue may be empty, usually it is the valdef that stores the scrut
100+ val (prologue, cases) = stats span (s => ! s.isInstanceOf [LabelDef ])
101+ caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity)
105102 // optimized version of virtpatmat
106- case Block (outerStats, orig@ Block ((zero : ValDef ) :: (x : ValDef ) :: (matchRes : ValDef ) :: (keepGoing : ValDef ) :: stats, epilogue)) if opt.virtPatmat => // TODO: check tree annotation // println("virt opt block match: "+ (zero, x, matchRes, keepGoing, stats, outerStats) + "for:\n"+ matchExpr )
107- caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, m => copyBlock(matchExpr, outerStats, m))
103+ case Block (outerStats, orig@ Block (stats, matchEndDef)) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
104+ val (prologue, cases) = stats span (s => ! s.isInstanceOf [LabelDef ])
105+ caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m))
108106 case other =>
109107 unknownTree(other)
110108 }
@@ -120,35 +118,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
120118 }
121119 }
122120
123- def withDefaultCase (matchExpr : Tree , defaultAction : Tree /* scrutinee*/ => Tree ): Tree = {
124- object withDefaultTransformer extends MatchMatcher {
125- override def caseMatch (orig : Tree , selector : Tree , cases : List [CaseDef ], wrap : Tree => Tree ): Tree = {
126- val casesNoSynthCatchAll = dropSyntheticCatchAll(cases)
127- if (casesNoSynthCatchAll exists treeInfo.isDefaultCase) orig
128- else {
129- val defaultCase = CaseDef (Ident (nme.WILDCARD ), EmptyTree , defaultAction(selector.duplicate))
130- wrap(Match (selector, casesNoSynthCatchAll :+ defaultCase))
131- }
132- }
133- override def caseVirtualizedMatch (orig : Tree , _match : Tree , targs : List [Tree ], scrut : Tree , matcher : Tree ): Tree = { import CODE ._
134- ((matcher APPLY (scrut)) DOT nme.getOrElse) APPLY (defaultAction(scrut.duplicate)) // TODO: pass targs
135- }
136- override def caseVirtualizedMatchOpt (orig : Tree , zero : ValDef , x : ValDef , matchRes : ValDef , keepGoing : ValDef , stats : List [Tree ], epilogue : Tree , wrap : Tree => Tree ): Tree = { import CODE ._
137- wrap(Block (
138- zero ::
139- x ::
140- matchRes ::
141- keepGoing ::
142- stats,
143- // replace `if (keepGoing) throw new MatchError(...) else matchRes` by `if (keepGoing) ${defaultAction(`x`)} else matchRes`
144- (IF (REF (keepGoing.symbol)) THEN defaultAction(x.rhs.duplicate) ELSE REF (matchRes.symbol))
145- ))
146- }
147- }
148- withDefaultTransformer(matchExpr)
149- }
150-
151-
152121 def mkCached (cvar : Symbol , expr : Tree ): Tree = {
153122 val cvarRef = mkUnattributedRef(cvar)
154123 Block (
0 commit comments