summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/SymbolFlags.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/reflect/internal/SymbolFlags.scala')
-rw-r--r--src/compiler/scala/reflect/internal/SymbolFlags.scala237
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
+ )
+ )
+ }
+}