diff options
author | Paul Phillips <paulp@improving.org> | 2013-08-18 09:29:44 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-08-18 13:23:21 -0700 |
commit | 6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8 (patch) | |
tree | 672e9dfa0343526c77f68d45c7a4698a9dc832dc /src/reflect | |
parent | a905d0e7e49bf92f119b2fdcd2b9d15b71d64ca2 (diff) | |
download | scala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.tar.gz scala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.tar.bz2 scala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.zip |
Refined name-based patmat methods.
This fleshes out some of the slightly unfinished corners
of the adventure, especially for unapplySeq. There's still
an unhealthy amount of duplication and a paucity of
specification, but I think it's in eminently good shape
for a milestone.
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index f1480c6cbd..19458361e1 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -681,41 +681,23 @@ trait Definitions extends api.StandardDefinitions { def isExactProductType(tp: Type): Boolean = isProductNSymbol(tp.typeSymbol) /** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */ - def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match { + @deprecated("No longer used", "2.11.0") def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match { case Some(x) => tpe.baseType(x).typeArgs case _ => Nil } - def getNameBasedProductSelectors(tpe: Type): List[Symbol] = { - def loop(n: Int): List[Symbol] = tpe member TermName("_" + n) match { - case NoSymbol => Nil - case m if m.paramss.nonEmpty => Nil - case m => m :: loop(n + 1) - } - loop(1) - } - def getNameBasedProductSelectorTypes(tpe: Type): List[Type] = getProductArgs(tpe) match { - case xs if xs.nonEmpty => xs - case _ => getterMemberTypes(tpe, getNameBasedProductSelectors(tpe)) + + @deprecated("No longer used", "2.11.0") def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match { + case RefinedType(p :: _, _) => p.dealiasWiden + case tp => tp } def getterMemberTypes(tpe: Type, getters: List[Symbol]): List[Type] = getters map (m => dropNullaryMethod(tpe memberType m)) - def getNameBasedProductSeqElementType(tpe: Type) = getNameBasedProductSelectorTypes(tpe) match { - case _ :+ elem => unapplySeqElementType(elem) - case _ => NoType - } - def dropNullaryMethod(tp: Type) = tp match { case NullaryMethodType(restpe) => restpe case _ => tp } - - def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match { - case RefinedType(p :: _, _) => p.dealiasWiden - case tp => tp - } - def abstractFunctionForFunctionType(tp: Type) = { assert(isFunctionType(tp), tp) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) @@ -738,13 +720,54 @@ trait Definitions extends api.StandardDefinitions { def scalaRepeatedType(arg: Type) = appliedType(RepeatedParamClass, arg) def seqType(arg: Type) = appliedType(SeqClass, arg) - def typeOfMemberNamedGet(tp: Type) = resultOfMatchingMethod(tp, nme.get)() - - def unapplySeqElementType(seqType: Type) = ( - resultOfMatchingMethod(seqType, nme.apply)(IntTpe) - orElse resultOfMatchingMethod(seqType, nme.head)() + // FYI the long clunky name is because it's really hard to put "get" into the + // name of a method without it sounding like the method "get"s something, whereas + // this method is about a type member which just happens to be named get. + def typeOfMemberNamedGet(tp: Type) = resultOfMatchingMethod(tp, nme.get)() + def typeOfMemberNamedHead(tp: Type) = resultOfMatchingMethod(tp, nme.head)() + def typeOfMemberNamedApply(tp: Type) = resultOfMatchingMethod(tp, nme.apply)() + def typeOfMemberNamedGetOrSelf(tp: Type) = typeOfMemberNamedGet(tp) orElse tp + def typesOfSelectors(tp: Type) = getterMemberTypes(tp, productSelectors(tp)) + def typesOfCaseAccessors(tp: Type) = getterMemberTypes(tp, tp.typeSymbol.caseFieldAccessors) + + /** If this is a case class, the case field accessors (which may be an empty list.) + * Otherwise, if there are any product selectors, that list. + * Otherwise, a list containing only the type itself. + */ + def typesOfSelectorsOrSelf(tp: Type): List[Type] = ( + if (tp.typeSymbol.isCase) + typesOfCaseAccessors(tp) + else typesOfSelectors(tp) match { + case Nil => tp :: Nil + case tps => tps + } ) + /** If the given type has one or more product selectors, the type of the last one. + * Otherwise, the type itself. + */ + def typeOfLastSelectorOrSelf(tp: Type) = typesOfSelectorsOrSelf(tp).last + + def elementTypeOfLastSelectorOrSelf(tp: Type) = { + val last = typeOfLastSelectorOrSelf(tp) + ( typeOfMemberNamedHead(last) + orElse typeOfMemberNamedApply(last) + orElse elementType(ArrayClass, last) + ) + } + + /** Returns the method symbols for members _1, _2, ..., _N + * which exist in the given type. + */ + def productSelectors(tpe: Type): List[Symbol] = { + def loop(n: Int): List[Symbol] = tpe member TermName("_" + n) match { + case NoSymbol => Nil + case m if m.paramss.nonEmpty => Nil + case m => m :: loop(n + 1) + } + loop(1) + } + /** If `tp` has a term member `name`, the first parameter list of which * matches `paramTypes`, and which either has no further parameter * lists or only an implicit one, then the result type of the matching |