@@ -48,9 +48,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
48
48
49
49
private var _id = 0 // left for debuging
50
50
51
+ // TODO: tpd._ is imported. Why not write (tree: Match)? (Same for the other occurrences of tpd below).
51
52
override def transformMatch (tree : tpd.Match )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
52
- val translated = new Translator ()(ctx).translator.translateMatch(tree)
53
- translated.ensureConforms(tree.tpe)
53
+ val translated = new Translator ()(ctx).translator.translateMatch(tree)
54
+ translated.ensureConforms(tree.tpe)
54
55
}
55
56
56
57
class Translator (implicit ctx : Context ) {
@@ -79,6 +80,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
79
80
def matcher (scrut : Tree , scrutSym : Symbol , restpe : Type )(cases : List [Casegen => Tree ], matchFailGen : Option [Symbol => Tree ]): Tree
80
81
81
82
// local / context-free
83
+ // TODO Would be good to have some comments what these methods do
82
84
def _asInstanceOf (b : Symbol , tp : Type ): Tree
83
85
def _equals (checker : Tree , binder : Symbol ): Tree
84
86
def _isInstanceOf (b : Symbol , tp : Type ): Tree
@@ -91,6 +93,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
91
93
trait Casegen extends AbsCodegen {
92
94
def one (res : Tree ): Tree
93
95
96
+ // TODO Would be good to have also some comments what these methods do
94
97
def flatMap (prev : Tree , b : Symbol , next : Tree ): Tree
95
98
def flatMapCond (cond : Tree , res : Tree , nextBinder : Symbol , next : Tree ): Tree
96
99
def flatMapGuard (cond : Tree , next : Tree ): Tree
@@ -102,7 +105,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
102
105
def codegen : AbsCodegen
103
106
104
107
abstract class CommonCodegen extends AbsCodegen {
105
- def tupleSel (binder : Symbol )(i : Int ): Tree = ref(binder).select(nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder
108
+ def tupleSel (binder : Symbol )(i : Int ): Tree = ref(binder).select(nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder // TODO move that comment to tupleSel in the base class
106
109
def index (tgt : Tree )(i : Int ): Tree = {
107
110
if (i > 0 ) tgt.select(defn.Seq_apply ).appliedTo(Literal (Constant (i)))
108
111
else tgt.select(defn.Seq_head ).appliedToNone
@@ -114,9 +117,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
114
117
// for name-based matching, but this was an expedient route for the basics.
115
118
def drop (tgt : Tree )(n : Int ): Tree = {
116
119
def callDirect = tgt.select(nme.drop).appliedTo(Literal (Constant (n)))
117
- def callRuntime = ref(ctx.definitions.traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
120
+ def callRuntime = ref(defn.traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
121
+ // TODO: Replace ctx.definitions elsewhere with just `defn`.
118
122
119
- def needsRuntime = (tgt.tpe ne null ) && tgt.tpe.baseTypeRef(ctx.definitions.SeqType .classSymbol).member(nme.drop).exists /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
123
+ def needsRuntime = /* Useless test: this is always true (tgt.tpe ne null) && */
124
+ tgt.tpe.baseTypeRef(defn.SeqClass ).member(nme.drop).exists /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
125
+ // TODO: I think the test above is the same as simply
126
+ // tgt.tpe derivesFrom defn.SeqClass
127
+ // If it derives from SeqClass, it will surely have a drop method, no?
120
128
121
129
if (needsRuntime) callRuntime else callDirect
122
130
}
@@ -135,7 +143,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
135
143
def apply (from : Symbol , to : Tree ) = new Substitution (List (from), List (to))
136
144
// requires sameLength(from, to)
137
145
def apply (from : List [Symbol ], to : List [Tree ]) =
138
- if (from nonEmpty) new Substitution (from, to) else EmptySubstitution
146
+ if (from. nonEmpty) new Substitution (from, to) else EmptySubstitution
139
147
}
140
148
141
149
class Substitution (val from : List [Symbol ], val to : List [Tree ]) {
@@ -149,12 +157,18 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
149
157
else*/
150
158
151
159
var replaced = 0
152
- val toAdapted = (from zip to) map {
153
- case (orig, nw) =>
154
- nw.ensureConforms(AndType (orig.info, nw.tpe))
160
+
161
+ // val toAdapted = (from zip to) map {
162
+ // case (orig, nw) =>
163
+ // nw.ensureConforms(AndType(orig.info, nw.tpe))
164
+ // TODO: Use orig.info & nw.tpe instead of the AndType. The former will do simplifications, the latter will not.
165
+ // But since this seems to be performance sensitive, we should use the code below.
166
+ // }
167
+ val toAdapted = to.zipWithConserve(from) { (nw, orig) =>
168
+ if (nw.tpe <:< orig.info) nw else nw.ensureConforms(orig.info & nw.tpe)
155
169
}
156
170
157
- val identReplace : tpd.Tree => tpd.Tree = _ match {
171
+ val identReplace : tpd.Tree => tpd.Tree = _ match { // TODO: Make identReplace a tpd.Ident => tpd.Tree
158
172
case t: Ident =>
159
173
def subst (from : List [Symbol ], to : List [Tree ]): Tree =
160
174
if (from.isEmpty) t
@@ -226,7 +240,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
226
240
// must compute catchAll after caseLabels (side-effects nextCase)
227
241
// catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
228
242
// if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd
229
- val catchAllDef = matchFailGen.map { matchFailGen => matchFailGen( scrutSym)}
243
+ val catchAllDef = matchFailGen.map(_( scrutSym))
230
244
.getOrElse(Throw (New (defn.MatchErrorType , List (ref(scrutSym)))))
231
245
232
246
val matchFail = newSynthCaseLabel(ctx.freshName(" matchFail" ), MethodType (Nil , restpe))
@@ -333,9 +347,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
333
347
def emitTypeSwitch (bindersAndCases : List [(Symbol , List [TreeMaker ])], pt : Type ): Option [List [CaseDef ]] =
334
348
None // todo
335
349
350
+ // TODO Would be good to have some explanation here what a TreeMaker is. What's it for? What are its attributes?
336
351
abstract class TreeMaker {
337
352
def pos : Position
338
353
354
+ private [this ] var currSub : Substitution = null
355
+
339
356
/** captures the scope and the value of the bindings in patterns
340
357
* important *when* the substitution happens (can't accumulate and do at once after the full matcher has been constructed)
341
358
*/
@@ -352,7 +369,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
352
369
}
353
370
else currSub = outerSubst >> substitution
354
371
}
355
- private [this ] var currSub : Substitution = null
356
372
357
373
/** The substitution that specifies the trees that compute the values of the subpattern binders.
358
374
*
@@ -419,6 +435,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
419
435
// unless we're optimizing, emit local variable bindings for all subpatterns of extractor/case class patterns
420
436
protected val debugInfoEmitVars = true // !settings.optimise.value
421
437
438
+ // TODO Explain what this is for, similarly to what's done for ExtractorTreeMaker
422
439
sealed trait PreserveSubPatBinders extends TreeMaker {
423
440
val subPatBinders : List [Symbol ]
424
441
val subPatRefs : List [Tree ]
@@ -932,15 +949,24 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
932
949
933
950
trait MatchTranslator extends TreeMakers with ScalacPatternExpanders {
934
951
952
+ /* I think the commented out code
935
953
def isBackquoted(x: Ident) = x.isInstanceOf[BackquotedIdent]
936
954
937
955
def isVarPattern(pat: Tree): Boolean = pat match {
938
956
case x: Ident => !isBackquoted(x) && nme.isVariableName(x.name)
939
957
case _ => false
940
958
}
959
+ is better written like this:
960
+ */
961
+ def isVarPattern (pat : Tree ): Boolean = pat match {
962
+ case x : BackquotedIdent => false
963
+ case x : Ident => nme.isVariableName(x.name)
964
+ case _ => false
965
+ }
941
966
942
967
/** A conservative approximation of which patterns do not discern anything.
943
968
* They are discarded during the translation.
969
+ * TODO: Why is x a wildcard pattern but x @ _ is not?
944
970
*/
945
971
object WildcardPattern {
946
972
def unapply (pat : Tree ): Boolean = pat match {
@@ -971,6 +997,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
971
997
}
972
998
973
999
// Always map repeated params to sequences
1000
+ // TODO But repeated params don't exist where PM is running. Why the method?
974
1001
private def setVarInfo (sym : Symbol , info : Type ) = {
975
1002
// setInfo debug.patmatResult(s"changing ${sym.defString} to")(repeatedToSeq(info))
976
1003
// if(info!= NoType && !(sym.info =:= info))
@@ -986,11 +1013,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
986
1013
case _ => BoundTree (freshSym(tree.pos, pt, prefix = " p" ), tree)
987
1014
}
988
1015
1016
+ // TODO: Again would be nice to document what this class is for.
989
1017
final case class BoundTree (binder : Symbol , tree : Tree ) {
990
1018
private lazy val extractor = ExtractorCall (tree, binder)
991
1019
992
1020
def pos = tree.pos
993
- def tpe = binder.info.dealias.widen // the type of the variable bound to the pattern
1021
+ def tpe = binder.info.widenDealias // the type of the variable bound to the pattern
994
1022
def pt = unbound match {
995
1023
// case Star(tpt) => this glbWith seqType(tpt.tpe) dd todo:
996
1024
case TypeBound (tpe) => tpe
@@ -1010,6 +1038,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1010
1038
object TypeBound {
1011
1039
def unapply (tree : Tree ): Option [Type ] = tree match {
1012
1040
case Typed (_, _) if tree.tpe != null => Some (tree.tpe)
1041
+ // Should be: if tree.hasType (tree.tpe is always != null, where a tree is untyped, you'd get an exception when calling .tpe)
1042
+ // But probably it's better to do without the extractor altogether. tree.typeOpt fulfils the same fucntion, and
1043
+ // is more efficient.
1013
1044
case _ => None
1014
1045
}
1015
1046
}
@@ -1088,6 +1119,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1088
1119
// accessors) TODO: get to the bottom of this -- I assume it happens when type checking
1089
1120
// infers a weird type for an unapply call. By going back to the parameterType for the
1090
1121
// extractor call we get a saner type, so let's just do that for now.
1122
+ // TODO: This is now just a more convoluted and cumbersome version of tpd.ensureConforms. We should use the latter.
1123
+ // All setInfo defs and calls can be dropped.
1091
1124
def ensureConformsTo (paramType : Type ): Boolean = (
1092
1125
(tpe =:= paramType)
1093
1126
|| (tpe <:< paramType) && setInfo(paramType)
@@ -1116,7 +1149,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1116
1149
1117
1150
def elimAnonymousClass (t : Type ) = t match {
1118
1151
case t: TypeRef if t.symbol.isAnonymousClass =>
1119
- t.symbol.asClass.typeRef.asSeenFrom(t.prefix, t.symbol.owner)
1152
+ val res =
1153
+ t.symbol.asClass.typeRef.asSeenFrom(t.prefix, t.symbol.owner)
1154
+ // what does this do? Is this not always the same as `t` itself?
1155
+ // It is in our test runs. See assertion below which never fires.
1156
+ assert(res =:= t)
1157
+ res
1120
1158
case _ =>
1121
1159
t
1122
1160
}
@@ -1131,6 +1169,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1131
1169
isDefaultCase(cdef)
1132
1170
}
1133
1171
1172
+ // TODO: This method is redundant. Use thiz.derivesFrom(that) instead.
1134
1173
def isNonBottomSubClass (thiz : Symbol , that : Symbol )(implicit ctx : Context ): Boolean = (
1135
1174
(thiz eq that) || thiz.isError || that.isError ||
1136
1175
thiz.info.baseClasses.contains(that)
@@ -1612,7 +1651,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1612
1651
* arbitrary types here, and NoPattern and NoType arbitrary values.
1613
1652
*/
1614
1653
def NoPattern : Pattern
1615
- def NoType : Type
1654
+ def NoType : Type // TODO Why parameterize over NoType? It looks like it is always core.Types.NoType.
1616
1655
1617
1656
/** It's not optimal that we're carrying both sequence and repeated
1618
1657
* type here, but the implementation requires more unraveling before
0 commit comments