diff options
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/generic/HasFlags.scala | 83 | ||||
-rwxr-xr-x | src/library/scala/reflect/generic/Symbols.scala | 35 | ||||
-rwxr-xr-x | src/library/scala/reflect/generic/Trees.scala | 46 | ||||
-rwxr-xr-x | src/library/scala/reflect/generic/UnPickler.scala | 9 |
4 files changed, 118 insertions, 55 deletions
diff --git a/src/library/scala/reflect/generic/HasFlags.scala b/src/library/scala/reflect/generic/HasFlags.scala index 00566995e2..7dfb3506f6 100644 --- a/src/library/scala/reflect/generic/HasFlags.scala +++ b/src/library/scala/reflect/generic/HasFlags.scala @@ -1,6 +1,76 @@ package scala.reflect package generic +/** ISSUE #1: Flag names vs. Test method names + * + * The following methods from Symbol have a name of + * the form isFoo where FOO is the name of a flag, but where the method + * body tests for more than whether the flag is set. + * + * There are two possibilities with such methods. Either the extra + * tests are strictly to partition among overloaded flags (which is + * the case we can live with in the short term, if each such flag's + * partitioning assumptions are documented) or they aren't. + * + * The second case implies that "x hasFlag FOO" and "x.isFoo" have + * different semantics, and this we can't live with, because even if + * we're smart enough to avoid being tripped up by that, the next guy isn't. + * + * No extreme measures necessary, only renaming isFoo to something + * which hews more closely to its implementation. (Or renaming the flag.) + * + // Defined in the compiler Symbol + // + final def isLabel = isMethod && !hasFlag(ACCESSOR) && hasFlag(LABEL) + final def isLocal: Boolean = owner.isTerm + final def isModuleVar: Boolean = isVariable && hasFlag(MODULEVAR) + final def isStable = + isTerm && + !hasFlag(MUTABLE) && + (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) && + !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass)) + final def isStatic: Boolean = + hasFlag(STATIC) || isRoot || owner.isStaticOwner + override final def isTrait: Boolean = + isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE) + + // Defined in the library Symbol + // + def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes. + final def isContravariant = isType && hasFlag(CONTRAVARIANT) + final def isCovariant = isType && hasFlag(COVARIANT) + final def isMethod = isTerm && hasFlag(METHOD) + final def isModule = isTerm && hasFlag(MODULE) + final def isPackage = isModule && hasFlag(PACKAGE) + * + */ + +/** ISSUE #2: Implicit flag relationships must be made explicit. + * + * For instance, every time the MODULE flag is set, the FINAL flag is + * set along with it: + * + .setFlag(FINAL | MODULE | PACKAGE | JAVA) + .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader) + new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) + new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) + val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) + setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL) + sourceModule.flags = MODULE | FINAL + + * However the same is not true of when the MODULE flag is cleared: + + sym.resetFlag(MODULE) + .setFlag(sym.flags | STABLE).resetFlag(MODULE) + sym.resetFlag(MODULE | FINAL | CASE) + + * It's not relevant whether this example poses any issues: we must + * not tolerate these uncertainties. If the flags are to move together + * then both setting and clearing have to be encapsulated. If there + * is a useful and used distinction between the various permutations + * of on and off, then it must be documented. It's the only way! + */ + import Flags._ /** Common code utilized by Modifiers (which carry the flags associated @@ -63,6 +133,10 @@ trait HasFlags { */ def hasAllFlags(mask: Long): Boolean + /** Whether this entity has NONE of the flags in the given mask. + */ + def hasNoFlags(mask: Long): Boolean = !hasFlag(mask) + // Tests which come through cleanly: both Symbol and Modifiers use these // identically, testing for a single flag. def isCase = hasFlag(CASE ) @@ -97,11 +171,16 @@ trait HasFlags { // Problematic: // DEFAULTPARAM overloaded with TRAIT - def hasDefault = isParameter && hasFlag(DEFAULTPARAM) - def hasDefaultFlag = hasFlag(DEFAULTPARAM) + def hasDefault = isParameter && hasFlag(DEFAULTPARAM) + def hasDefaultFlag = hasFlag(DEFAULTPARAM) // def isTrait = hasFlag(TRAIT ) // def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes. + // Straightforwardly named accessors already being used differently + def hasStaticFlag = hasFlag(STATIC) + def hasLocalFlag = hasFlag(LOCAL) + def hasModuleFlag = hasFlag(MODULE) + // Problematic: // ABSTRACT and DEFERRED too easy to confuse, and // ABSTRACT + OVERRIDE ==> ABSOVERRIDE adds to it. diff --git a/src/library/scala/reflect/generic/Symbols.scala b/src/library/scala/reflect/generic/Symbols.scala index a1c9a0c18d..75e1c05d49 100755 --- a/src/library/scala/reflect/generic/Symbols.scala +++ b/src/library/scala/reflect/generic/Symbols.scala @@ -7,7 +7,12 @@ trait Symbols { self: Universe => type Symbol >: Null <: AbsSymbol - abstract class AbsSymbol { this: Symbol => + abstract class AbsSymbol extends HasFlags { + this: Symbol => + + type FlagsType = Long + type AccessBoundaryType = Symbol + type AnnotationType = AnnotationInfo /** The owner of this symbol. */ @@ -56,6 +61,8 @@ trait Symbols { self: Universe => */ def privateWithin: Symbol + final def hasAccessBoundary = (privateWithin != null) && (privateWithin != NoSymbol) + /** The raw info of the type */ def rawInfo: Type @@ -122,47 +129,27 @@ trait Symbols { self: Universe => private[scala] def isSkolem = false // to be overridden def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes. - final def hasDefault = isParameter && hasFlag(DEFAULTPARAM) final def isAbstractClass = isClass && hasFlag(ABSTRACT) - // XXX This is unlikely to be correct: it's not looking for the ABSOVERRIDE flag? - final def isAbstractOverride = isTerm && hasFlag(ABSTRACT) && hasFlag(OVERRIDE) + final def isAbstractOverride = isTerm && hasFlag(ABSOVERRIDE) final def isBridge = hasFlag(BRIDGE) - final def isCase = hasFlag(CASE) - final def isCaseAccessor = hasFlag(CASEACCESSOR) final def isContravariant = isType && hasFlag(CONTRAVARIANT) final def isCovariant = isType && hasFlag(COVARIANT) - final def isDeferred = hasFlag(DEFERRED) && !isClass final def isEarlyInitialized: Boolean = isTerm && hasFlag(PRESUPER) final def isExistentiallyBound = isType && hasFlag(EXISTENTIAL) - final def isFinal = hasFlag(FINAL) final def isGetterOrSetter = hasFlag(ACCESSOR) final def isImplClass = isClass && hasFlag(IMPLCLASS) // Is this symbol an implementation class for a mixin? - final def isImplicit = hasFlag(IMPLICIT) final def isInterface = hasFlag(INTERFACE) final def isJavaDefined = hasFlag(JAVA) - final def isLazy = hasFlag(LAZY) + final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol final def isMethod = isTerm && hasFlag(METHOD) final def isModule = isTerm && hasFlag(MODULE) final def isModuleClass = isClass && hasFlag(MODULE) - final def isMutable = hasFlag(MUTABLE) final def isOverloaded = hasFlag(OVERLOADED) - final def isOverride = hasFlag(OVERRIDE) - final def isParamAccessor = hasFlag(PARAMACCESSOR) - final def isParameter = hasFlag(PARAM) final def isRefinementClass = isClass && name == mkTypeName(nme.REFINE_CLASS_NAME) - final def isSealed = isClass && (hasFlag(SEALED) || definitions.isValueClass(this)) - final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD // exclude all accessors!!! + final def isSourceMethod = isMethod && !hasFlag(STABLE) // exclude all accessors!!! final def isSuperAccessor = hasFlag(SUPERACCESSOR) - final def isSynthetic = hasFlag(SYNTHETIC) final def isTypeParameter = isType && isParameter && !isSkolem - /** Access tests */ - final def isPrivate = hasFlag(PRIVATE) - final def isPrivateLocal = hasFlag(PRIVATE) && hasFlag(LOCAL) - final def isProtected = hasFlag(PROTECTED) - final def isProtectedLocal = hasFlag(PROTECTED) && hasFlag(LOCAL) - final def isPublic = !hasFlag(PRIVATE | PROTECTED) && privateWithin == NoSymbol - /** Package tests */ final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME final def isEmptyPackageClass = isPackageClass && name == mkTypeName(nme.EMPTY_PACKAGE_NAME) diff --git a/src/library/scala/reflect/generic/Trees.scala b/src/library/scala/reflect/generic/Trees.scala index 87ce15dd24..7ab4cf882b 100755 --- a/src/library/scala/reflect/generic/Trees.scala +++ b/src/library/scala/reflect/generic/Trees.scala @@ -1,7 +1,7 @@ package scala.reflect package generic -import java.io.{PrintWriter, StringWriter} +import java.io.{ PrintWriter, StringWriter } import Flags._ trait Trees { self: Universe => @@ -15,33 +15,29 @@ trait Trees { self: Universe => private[scala] var nodeCount = 0 + protected def flagsIntoString(flags: Long, privateWithin: String): String + /** @param privateWithin the qualifier for a private (a type name) * or nme.EMPTY.toTypeName, if none is given. * @param annotations the annotations for the definition. * <strong>Note:</strong> the typechecker drops these annotations, * use the AnnotationInfo's (Symbol.annotations) in later phases. */ - case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) { - def isAbstract = hasFlag(ABSTRACT ) - def isAccessor = hasFlag(ACCESSOR ) - def isArgument = hasFlag(PARAM ) - def isCase = hasFlag(CASE ) - def isContravariant = hasFlag(CONTRAVARIANT) // marked with `-' - def isCovariant = hasFlag(COVARIANT ) // marked with `+' - def isDeferred = hasFlag(DEFERRED ) - def isFinal = hasFlag(FINAL ) - def isImplicit = hasFlag(IMPLICIT ) - def isLazy = hasFlag(LAZY ) - def isOverride = hasFlag(OVERRIDE ) - def isPrivate = hasFlag(PRIVATE ) - def isProtected = hasFlag(PROTECTED) - def isPublic = !isPrivate && !isProtected - def isSealed = hasFlag(SEALED ) - def isSynthetic = hasFlag(SYNTHETIC) - def isTrait = hasFlag(TRAIT ) - def isVariable = hasFlag(MUTABLE ) + case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) extends HasFlags { + /* Abstract types from HasFlags. */ + type FlagsType = Long + type AccessBoundaryType = Name + type AnnotationType = Tree + + private val emptyTypeName = mkTypeName(nme.EMPTY) + def hasAccessBoundary = privateWithin != emptyTypeName + def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask def hasFlag(flag: Long) = (flag & flags) != 0L + def hasFlagsToString(mask: Long): String = flagsToString( + flags & mask, + if (hasAccessBoundary) privateWithin.toString else "" + ) def & (flag: Long): Modifiers = { val flags1 = flags & flag if (flags1 == flags) this @@ -62,6 +58,8 @@ trait Trees { self: Universe => else copy(annotations = annotations ::: annots) def withPosition(flag: Long, position: Position) = copy(positions = positions + (flag -> position)) + + override def toString = "Modifiers(%s, %s, %s)".format(hasFlagsToString(-1L), annotations mkString ", ", positions) } def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), Map.empty) @@ -101,6 +99,8 @@ trait Trees { self: Universe => def isDef = false def isEmpty = false + def hasSymbolWhich(f: Symbol => Boolean) = hasSymbol && f(symbol) + /** The direct child trees of this tree * EmptyTrees are always omitted. Lists are collapsed. */ @@ -181,14 +181,14 @@ trait Trees { self: Universe => def mods: Modifiers def keyword: String = this match { case TypeDef(_, _, _, _) => "type" - case ClassDef(mods, _, _, _) => if (mods.isTrait) "trait" else "class" + case ClassDef(mods, _, _, _) => if (mods hasFlag TRAIT) "trait" else "class" case DefDef(_, _, _, _, _, _) => "def" case ModuleDef(_, _, _) => "object" case PackageDef(_, _) => "package" - case ValDef(mods, _, _, _) => if (mods.isVariable) "var" else "val" + case ValDef(mods, _, _, _) => if (mods.isMutable) "var" else "val" case _ => "" } - final def hasFlag(mask: Long): Boolean = (mods.flags & mask) != 0L + // final def hasFlag(mask: Long): Boolean = mods hasFlag mask } /** Package clause diff --git a/src/library/scala/reflect/generic/UnPickler.scala b/src/library/scala/reflect/generic/UnPickler.scala index 80818ac62a..8a370e44fa 100755 --- a/src/library/scala/reflect/generic/UnPickler.scala +++ b/src/library/scala/reflect/generic/UnPickler.scala @@ -196,11 +196,8 @@ abstract class UnPickler { tag match { case EXTMODCLASSref => val moduleVar = owner.info.decl(nme.moduleVarName(name)) - if (moduleVar.hasFlag(LAZY)) { - val lazyAcc = moduleVar.lazyAccessor - if (lazyAcc != NoSymbol) - sym = lazyAcc.lazyAccessor - } + if (moduleVar.isLazyAccessor) + sym = moduleVar.lazyAccessor.lazyAccessor case _ => } @@ -255,7 +252,7 @@ abstract class UnPickler { sym.flags = flags & PickledFlags sym.privateWithin = privateWithin if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR), sym) - if (sym hasFlag SUPERACCESSOR) assert(readIndex != end) + if (sym.isSuperAccessor) assert(readIndex != end) sym.info = if (readIndex != end) newLazyTypeRefAndAlias(inforef, readNat()) else newLazyTypeRef(inforef) |