diff options
author | Martin Odersky <odersky@gmail.com> | 2013-02-21 14:08:39 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-02-21 14:08:39 +0100 |
commit | 58b7b61fb8ffda09dbec4427476a47b4e3a505bc (patch) | |
tree | 10179fe6510d9d059cd8767f05ea0e4fe7f60e70 /src/dotty/tools | |
parent | 3c2d0d752dcb690bd37622cf8593bc359d6b35aa (diff) | |
download | dotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.tar.gz dotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.tar.bz2 dotty-58b7b61fb8ffda09dbec4427476a47b4e3a505bc.zip |
More utility methods and split up filter
More utility methods in types. Also replaced Denotation#filter with a set of more useful operations.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 49 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 51 |
4 files changed, 91 insertions, 28 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 924057935..c7c257f5c 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -157,18 +157,31 @@ object Denotations { def orElse(that: => Denotation) = if (this.exists) this else that - /** The part of this denotation that satisfies the predicate, or NoDenotation is none exists */ - def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation + /** The set of alternative single-denotations making up this denotation */ + def alts(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = + altsWith(scala.Function.const(true)) + + /** The alternatives of this denotation that satisfy the predicate `p`. */ + def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] + + /** The unique alternative of this denotation that satisfies the predicate `p`, + * or NoDenotation if no satisfying alternative exists. + * @throws TypeError if there is at more than one alternative that satisfies `p`. + */ + def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation + + /** Does this denotation have an alternative that satisfies the predicate `p`? */ + def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean /** If this denotation is overloaded, filter with given predicate. - * If result is still overloaded throw a TypeError + * If result is still overloaded throw a TypeError. + * Note: disambiguate is slightly different from suchThat in that + * single-denotations that do not satisfy the predicate are left alone + * (whereas suchThat would map them to NoDenotation). */ def disambiguate(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = this match { case sdenot: SingleDenotation => sdenot - case mdenot => this filter p match { - case sdenot: SingleDenotation => sdenot - case mdenot => throw new TypeError(s"failure to disambiguate overloaded reference $mdenot") - } + case mdenot => suchThat(p) } /** Return symbol in this denotation that satisfies the given predicate. @@ -279,8 +292,18 @@ object Denotations { def info = unsupported("info") def signature = unsupported("signature") def firstSym(implicit ctx: Context): Symbol = denot1.firstSym orElse denot2.firstSym - def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation = - (denot1 filter p) & (denot2 filter p) + def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = + denot1.altsWith(p) ++ denot2.altsWith(p) + def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = { + val sd1 = denot1.suchThat(p) + val sd2 = denot2.suchThat(p) + if (sd1.exists) + if (sd2.exists) throw new TypeError(s"failure to disambiguate overloaded reference $this") + else sd1 + else sd2 + } + def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean = + denot1.hasAltWith(p) || denot2.hasAltWith(p) def atSignature(sig: Signature): SingleDenotation = denot1.atSignature(sig) orElse denot2.atSignature(sig) def validFor = denot1.validFor & denot2.validFor @@ -311,9 +334,15 @@ object Denotations { def orElse(that: => SingleDenotation) = if (this.exists) this else that - def filter(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = + def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = + if (p(symbol)) this :: Nil else Nil + + def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = if (p(symbol)) this else NoDenotation + def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean = + p(symbol) + def atSignature(sig: Signature): SingleDenotation = if (sig == signature) this else NoDenotation diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 73d14141c..2bafb7732 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -198,12 +198,13 @@ object SymDenotations { || (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath) ) - /** Is this a denotation of a stable term? */ - final def isStable(implicit ctx: Context) = !( - isTerm && - this.is(UnstableValue, butNot = Stable) || - info.isVolatile && !hasAnnotation(defn.uncheckedStableClass) - ) + /** Is this a denotation of a stable term (or an arbitrary type)? */ + final def isStable(implicit ctx: Context) = { + val isUnstable = + this.is(UnstableValue, butNot = Stable) || + info.isVolatile && !hasAnnotation(defn.uncheckedStableClass) + !(isTerm && isUnstable) + } /** Is this a subclass of the given class `base`? */ def isSubClass(base: Symbol)(implicit ctx: Context) = false @@ -382,7 +383,7 @@ object SymDenotations { */ def companionModule(implicit ctx: Context): Symbol = { owner.info.decl(name.toTermName) - .filter(sym => sym.isModule && sym.isCoDefinedWith(symbol)) + .suchThat(sym => sym.isModule && sym.isCoDefinedWith(symbol)) .symbol } @@ -392,7 +393,7 @@ object SymDenotations { */ def companionClass(implicit ctx: Context): Symbol = owner.info.decl(name.toTypeName) - .filter(sym => sym.isClass && sym.isCoDefinedWith(symbol)) + .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol)) .symbol /** If this is a class, the module class of its companion object. diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index f3193a95f..77038816e 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -73,7 +73,7 @@ trait TypeOps { this: Context => case tp: RefinedType => tp.parent.isVolatile || isAbstractIntersection(tp.parent) && - (tp.abstractMemberNames(tp) contains tp.name) + (tp.abstractMemberNames contains tp.name) case tp: TypeProxy => tp.underlying.isVolatile case AndType(l, r) => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 9b7a26dfe..60facee3c 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -93,18 +93,30 @@ object Types { */ final def abstractTypeNames(pre: Type)(implicit ctx: Context): Set[Name] = memberNames(pre, abstractTypeNameFilter) + final def abstractTypeNames(implicit ctx: Context): Set[Name] = + abstractTypeNames(this) /** The set of names that denote an abstract term member of this type * which is also an abstract term member of `pre` */ final def abstractTermNames(pre: Type)(implicit ctx: Context): Set[Name] = memberNames(pre, abstractTermNameFilter) + final def abstractTermNames(implicit ctx: Context): Set[Name] = + abstractTermNames(this) /** The set of names that denote an abstract member of this type * which is also an abstract member of `pre` */ final def abstractMemberNames(pre: Type)(implicit ctx: Context): Set[Name] = abstractTypeNames(pre) | abstractTermNames(pre) + final def abstractMemberNames(implicit ctx: Context): Set[Name] = + abstractMemberNames(this) + + final def abstractTermMembers(pre: Type)(implicit ctx: Context): Set[SingleDenotation] = + abstractTermNames.flatMap(name => + pre.member(name).altsWith(_ is Deferred)) + final def abstractTermMembers(implicit ctx: Context): Set[SingleDenotation] = + abstractTermMembers(this) /** The set of names of members of this type that pass the given name filter * when seen as members of `pre`. More precisely, these are all @@ -127,6 +139,19 @@ object Types { Set() } + /** Is this type a value type */ + final def isValueType: Boolean = this match { + case NoPrefix + | NoType + | WildcardType + | _: TypeBounds + | _: MethodType + | _: PolyType + | _: ExprType + | _: ClassInfo => false + case _ => true + } + /** Is this type a TypeBounds instance, with lower and upper bounds * that are not identical? */ @@ -240,12 +265,20 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - def paramTypess(implicit ctx: Context): List[List[Type]] = this match { + def paramTypess: List[List[Type]] = this match { case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess case pt: PolyType => pt.paramTypess case _ => Nil } + /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */ + def resultType: Type = this match { + case et: ExprType => et.resultType + case mt: MethodType => mt.resultType + case pt: PolyType => pt.resultType + case _ => this + } + /** Map function over elements of an AndType, rebuilding with & */ def mapAnd(f: Type => Type)(implicit ctx: Context): Type = this match { case AndType(tp1, tp2) => tp1.mapAnd(f) & tp2.mapAnd(f) @@ -387,14 +420,16 @@ object Types { /** Widen from singleton type to its underlying non-singleton * base type by applying one or more `underlying` dereferences, - * identity for all other types. Example: + * Also go from => T to T. + * Identity for all other types. Example: * * class Outer { class C ; val x: C } - * val o: Outer + * def o: Outer * <o.x.type>.widen = o.C */ final def widen(implicit ctx: Context): Type = this match { case tp: SingletonType => tp.underlying.widen + case tp: ExprType => tp.underlying.widen case _ => this } @@ -406,8 +441,6 @@ object Types { case _ => this } - //def resultType: Type = ??? - /** The base classes of this type as determined by ClassDenotation * in linearization order, with the class itself as first element. * Inherited by all type proxies. `Nil` for all other types. @@ -883,7 +916,7 @@ object Types { // and therefore two different poly types would never be equal. abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType { - lazy val resultType = resultTypeExp(this) + override lazy val resultType = resultTypeExp(this) def isJava = false def isImplicit = false @@ -954,7 +987,7 @@ object Types { unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp)) } - abstract case class ExprType(resultType: Type) extends CachedProxyType { + abstract case class ExprType(override val resultType: Type) extends CachedProxyType { override def underlying(implicit ctx: Context): Type = resultType override def signature: Signature = Nil def derivedExprType(rt: Type)(implicit ctx: Context) = @@ -972,7 +1005,7 @@ object Types { case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) extends UncachedGroundType with BindingType { lazy val paramBounds = paramBoundsExp(this) - lazy val resultType = resultTypeExp(this) + override lazy val resultType = resultTypeExp(this) override def signature = resultType.signature @@ -1272,7 +1305,7 @@ object Types { /** A filter for names of deferred term definitions of a given type */ object abstractTermNameFilter extends NameFilter { def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = - name.isTermName && ((pre member name).symbol is Deferred) + name.isTermName && (pre member name).hasAltWith(_ is Deferred) } // ----- Exceptions ------------------------------------------------------------- |