diff options
author | Martin Odersky <odersky@gmail.com> | 2016-12-14 22:21:51 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-12-14 23:27:05 +0100 |
commit | 9bf58090c704a59d8735874c565200758bcea666 (patch) | |
tree | 705c77dc8cea85ecf0203ea710957542541c4bb5 /compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala | |
parent | ba06bf06721f1a8de7d68d22ad7eba27fff90c43 (diff) | |
download | dotty-9bf58090c704a59d8735874c565200758bcea666.tar.gz dotty-9bf58090c704a59d8735874c565200758bcea666.tar.bz2 dotty-9bf58090c704a59d8735874c565200758bcea666.zip |
Change by-name pattern matching.
New implementation following the scheme outlined in #1790.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala | 60 |
1 files changed, 27 insertions, 33 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 3e25cf82e..1252781e8 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -235,14 +235,20 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { // next: MatchMonad[U] // returns MatchMonad[U] def flatMap(prev: Tree, b: Symbol, next: Tree): Tree = { - - val getTp = extractorMemberType(prev.tpe, nme.get) - val isDefined = extractorMemberType(prev.tpe, nme.isDefined) - - if ((isDefined isRef defn.BooleanClass) && getTp.exists) { - // isDefined and get may be overloaded - val getDenot = prev.tpe.member(nme.get).suchThat(_.info.isParameterless) - val isDefinedDenot = prev.tpe.member(nme.isDefined).suchThat(_.info.isParameterless) + if (isProductMatch(prev.tpe)) { + val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null))) + ifThenElseZero( + nullCheck, + Block( + List(ValDef(b.asTerm, prev)), + next //Substitution(b, ref(prevSym))(next) + ) + ) + } + else { + val getDenot = extractorMember(prev.tpe, nme.get) + val isEmptyDenot = extractorMember(prev.tpe, nme.isEmpty) + assert(getDenot.exists && isEmptyDenot.exists, i"${prev.tpe}") val tmpSym = freshSym(prev.pos, prev.tpe, "o") val prevValue = ref(tmpSym).select(getDenot.symbol).ensureApplied @@ -251,20 +257,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { List(ValDef(tmpSym, prev)), // must be isEmpty and get as we don't control the target of the call (prev is an extractor call) ifThenElseZero( - ref(tmpSym).select(isDefinedDenot.symbol), + ref(tmpSym).select(isEmptyDenot.symbol).select(defn.Boolean_!), Block(List(ValDef(b.asTerm, prevValue)), next) ) ) - } else { - assert(defn.isProductSubType(prev.tpe)) - val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null))) - ifThenElseZero( - nullCheck, - Block( - List(ValDef(b.asTerm, prev)), - next //Substitution(b, ref(prevSym))(next) - ) - ) } } @@ -1431,12 +1427,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { case _ => or } - def resultInMonad = if (aligner.isBool) defn.UnitType else { - val getTp = extractorMemberType(resultType, nme.get) - if ((extractorMemberType(resultType, nme.isDefined) isRef defn.BooleanClass) && getTp.exists) - getTp + def resultInMonad = + if (aligner.isBool) defn.UnitType + else if (isProductMatch(resultType)) resultType + else if (isGetMatch(resultType)) extractorMemberType(resultType, nme.get) else resultType - } + def resultType: Type /** Create the TreeMaker that embodies this extractor call @@ -1632,13 +1628,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { //val spr = subPatRefs(binder) assert(go && go1) ref(binder) :: Nil - } else { - lazy val getTp = extractorMemberType(binderTypeTested, nme.get) - if ((aligner.isSingle && aligner.extractor.prodArity == 1) && ((extractorMemberType(binderTypeTested, nme.isDefined) isRef defn.BooleanClass) && getTp.exists)) - List(ref(binder)) - else - subPatRefs(binder) } + else if ((aligner.isSingle && aligner.extractor.prodArity == 1) && + !isProductMatch(binderTypeTested) && isGetMatch(binderTypeTested)) + List(ref(binder)) + else + subPatRefs(binder) } /*protected def spliceApply(binder: Symbol): Tree = { @@ -1890,9 +1885,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { else if (result.classSymbol is Flags.CaseClass) result.decls.filter(x => x.is(Flags.CaseAccessor) && x.is(Flags.Method)).map(_.info).toList else result.select(nme.get) :: Nil )*/ - if ((extractorMemberType(resultType, nme.isDefined) isRef defn.BooleanClass) && resultOfGet.exists) - getUnapplySelectors(resultOfGet, args) - else if (defn.isProductSubType(resultType)) productSelectorTypes(resultType) + if (isProductMatch(resultType)) productSelectorTypes(resultType) + else if (isGetMatch(resultType)) getUnapplySelectors(resultOfGet, args) else if (resultType isRef defn.BooleanClass) Nil else { ctx.error(i"invalid return type in Unapply node: $resultType") |