diff options
Diffstat (limited to 'src/compiler/scala/reflect/internal/SymbolFlags.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/SymbolFlags.scala | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/internal/SymbolFlags.scala b/src/compiler/scala/reflect/internal/SymbolFlags.scala new file mode 100644 index 0000000000..0b49ee2505 --- /dev/null +++ b/src/compiler/scala/reflect/internal/SymbolFlags.scala @@ -0,0 +1,237 @@ + /* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect +package internal + +import scala.collection.{ mutable, immutable } +import scala.collection.mutable.ListBuffer +import util.Statistics._ +import Flags._ +import api.Modifier +import scala.tools.util.StringOps.{ ojoin } + +trait SymbolFlags { + self: SymbolTable => + + import definitions._ + + /** Not mixed in under normal conditions; a powerful debugging aid. + */ + trait FlagVerifier extends SymbolFlagLogic { + this: Symbol => + + private def assert0(cond: Boolean, message: => Any) { + if (!cond) { + Console.err.println("[flag verification failure]\n%s\n%s\n".format(atPhaseStackMessage, message)) + (new Throwable).getStackTrace.take(13).drop(3).foreach(println) + println("") + } + } + + protected def verifyChange(isAdd: Boolean, mask: Long, before: Long) { + val after = if (isAdd) before | mask else before & ~mask + val added = after & ~before + val removed = before & ~after + val ignored = mask & ~added & ~removed + val error = ( + (added & OverloadedFlagsMask) != 0 || (removed & OverloadedFlagsMask) != 0 + // || (ignored != 0) + ) + val addString = if (added == 0) "" else "+(" + flagsToString(added) + ")" + val removeString = if (removed == 0) "" else "-(" + flagsToString(removed) + ")" + val changeString = if (added == 0 && removed == 0) "no change" else addString + " " + removeString + + if (error) { + val templ = ( + """| symbol: %s %s in %s + | call: %s(%s) + | flags: %s + | result: %s""".stripMargin + ) + + assert0(false, templ.format( + shortSymbolClass, + name.decode, + owner, + if (isAdd) "+" else "-", + flagsToString(mask), + flagsToString(before), + changeString + )) + } + } + + protected def verifyFlags(what: String) { + assert0(this hasAllFlags alwaysHasFlags, symbolCreationString + "\n always=%s, what=%s\n".format(flagsToString(alwaysHasFlags), what)) + if (this hasFlag neverHasFlags) { + val hasRaw = (rawflags & neverHasFlags) != 0 + assert0(!hasRaw, symbolCreationString + "\n never=%s, what=%s".format(flagsToString(neverHasFlags), what)) + } + } + override def initFlags(mask: Long): this.type = { + super.initFlags(mask) + verifyFlags("initFlags(" + flagsToString(mask) + ")") + this + } + override def setFlag(mask: Long): this.type = { + verifyChange(true, mask, rawflags) + super.setFlag(mask) + verifyFlags("setFlag(" + flagsToString(mask) + ")") + this + } + override def resetFlag(mask: Long): this.type = { + verifyChange(false, mask, rawflags) + super.resetFlag(mask) + verifyFlags("resetFlag(" + flagsToString(mask) + ")") + this + } + override def flags_=(fs: Long) { + if ((fs & ~rawflags) != 0) + verifyChange(true, fs & ~rawflags, rawflags) + if ((rawflags & ~fs) != 0) + verifyChange(false, rawflags & ~fs, rawflags) + + super.flags_=(fs) + verifyFlags("flags_=(" + flagsToString(fs) + ")") + } + } + + /** A distinguishing flag is one which the mixing class must always + * have, and which no other symbol class is allowed to have. + */ + trait DistinguishingFlag extends SymbolFlagLogic { + this: Symbol => + + def distinguishingFlag: Long + override protected def alwaysHasFlags = super.alwaysHasFlags | distinguishingFlag + override protected def neverHasFlags = super.neverHasFlags & ~distinguishingFlag + } + + trait SymbolFlagLogic { + this: Symbol => + + protected def alwaysHasFlags: Long = 0L + protected def neverHasFlags: Long = METHOD | MODULE + + def flagStringFn(flag: Long): String = { + val res = flag match { + // "<bynameparam/captured/covariant>" + case BYNAMEPARAM => + if (this.isValueParameter) "<bynameparam>" + else if (this.isTypeParameter) "<covariant>" + else "<captured>" + // "<contravariant/inconstructor/label>" + case CONTRAVARIANT => + if (this.isLabel) "<label>" + else if (this.isTypeParameter) "<contravariant>" + else "<inconstructor>" + // "<defaultparam/trait>" + case DEFAULTPARAM => + if (this.isTerm && (this hasFlag PARAM)) "<defaultparam>" + else "<trait>" + // "<existential/mixedin>" + case EXISTENTIAL => + if (this.isType) "<existential>" + else "<mixedin>" + // "<implclass/presuper>" + case IMPLCLASS => + if (this.isClass) "<implclass>" + else "<presuper>" + case _ => "" + } + if (res == "") Flags.flagToString(flag) + else res + ":overloaded-flag" + } + + private def calculateFlagString(basis: Long): String = { + val nonAccess = nonAccessString(basis)(flagStringFn) + val access = Flags.accessString(basis, pwString) + + ojoin(nonAccess, access) + } + + def flagString(mask: Long): String = calculateFlagString(flags & mask) + def flagString: String = flagString(defaultFlagMask) + def rawFlagString(mask: Long): String = calculateFlagString(rawflags & mask) + def rawFlagString: String = rawFlagString(defaultFlagMask) + def flaggedString(mask: Long): String = flagString(mask) + def flaggedString: String = flaggedString(defaultFlagMask) + + def accessString = calculateFlagString(flags & AccessFlags) + def debugFlagString = flaggedString(AllFlags) + def defaultFlagString = flaggedString(defaultFlagMask) + + def hasFlagsToString(mask: Long) = flagString(mask) + + /** String representation of symbol's variance */ + def varianceString: String = + if (variance == 1) "+" + else if (variance == -1) "-" + else "" + + def defaultFlagMask = + if (settings.debug.value && !isAbstractType) AllFlags + else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE + else ExplicitFlags + + // make the error message more googlable + def flagsExplanationString = + if (isGADTSkolem) " (this is a GADT skolem)" + else "" + + private def pwString = if (hasAccessBoundary) privateWithin.toString else "" + private var _rawflags: FlagsType = 0L + protected def rawflags_=(x: FlagsType) { _rawflags = x } + def rawflags = _rawflags + + final def flags: Long = { + val fs = rawflags & phase.flagMask + (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) + } + def flags_=(fs: Long) = rawflags = fs + + /** Set the symbol's flags to the given value, asserting + * that the previous value was 0. + */ + def initFlags(mask: Long): this.type = { + assert(rawflags == 0L, symbolCreationString) + rawflags = mask + this + } + def reinitFlags(mask: Long): this.type = { + rawflags = mask + this + } + def setFlag(mask: Long): this.type = { rawflags |= mask ; this } + def resetFlag(mask: Long): this.type = { rawflags &= ~mask ; this } + def resetFlags() { rawflags &= (TopLevelCreationFlags | alwaysHasFlags) } + + def getFlag(mask: Long): Long + def hasFlag(mask: Long): Boolean + def hasAllFlags(mask: Long): Boolean + + /** If the given flag is set on this symbol, also set the corresponding + * notFLAG. For instance if flag is PRIVATE, the notPRIVATE flag will + * be set if PRIVATE is currently set. + */ + final def setNotFlag(flag: Int) = if (hasFlag(flag)) setFlag((flag: @annotation.switch) match { + case PRIVATE => notPRIVATE + case PROTECTED => notPROTECTED + case OVERRIDE => notOVERRIDE + case _ => abort("setNotFlag on invalid flag: " + flag) + }) + + protected def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$") + def symbolCreationString: String = ( + "%s%25s | %-40s | %s".format( + if (settings.uniqid.value) "%06d | ".format(id) else "", + shortSymbolClass, + name.decode + " in " + owner, + rawFlagString + ) + ) + } +} |