package dotty.tools.dotc.core object Flags { /** A FlagSet represents a set of flags. Flags are encoded as follows: * The first two bits indicate whether a flagset applies to terms, * to types, or to both. Bits 2..63 are available for properties * and can be doubly used for terms and types. * Combining two FlagSets with `|` will give a FlagSet * that has the intersection of the applicability to terms/types * of the two flag sets. It is checked that the intersection is not empty. */ case class FlagSet(val bits: Long) extends AnyVal { /** The union of this flag set and the given flag set */ def | (that: FlagSet): FlagSet = if (bits == 0) that else if (that.bits == 0) this else { val tbits = bits & that.bits & KINDFLAGS assert(tbits != 0, s"illegal flagset combination: $this and $that") FlagSet(tbits | ((this.bits | that.bits) & ~KINDFLAGS)) } /** The intersection of this flag set and the given flag set */ def & (that: FlagSet) = FlagSet(bits & that.bits) /** The intersection of this flag set with the complement of the given flag set */ def &~ (that: FlagSet) = { val tbits = bits & KINDFLAGS if ((tbits & that.bits) == 0) this else FlagSet(tbits | ((this.bits & ~that.bits) & ~KINDFLAGS)) } /** Does this flag set have a non-empty intersection with the given flag set? * This means that both the kind flags and the carrier bits have non-empty intersection. */ def is(flags: FlagSet): Boolean = { val fs = bits & flags.bits (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0 } /** Does this flag set have a non-empty intersection with the given flag set, * and at the same time contain none of the flags in the `butNot` set? */ def is(flags: FlagSet, butNot: FlagSet): Boolean = is(flags) && !is(butNot) /** Does this flag set have all of the flags in given flag conjunction? * Pre: The intersection of the typeflags of both sets must be non-empty. */ def is(flags: FlagConjunction): Boolean = { val fs = bits & flags.bits (fs & KINDFLAGS) != 0 && (fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT) } /** Does this flag set have all of the flags in given flag conjunction? * and at the same time contain none of the flags in the `butNot` set? * Pre: The intersection of the typeflags of both sets must be non-empty. */ def is(flags: FlagConjunction, butNot: FlagSet): Boolean = is(flags) && !is(butNot) /** This flag set with all flags transposed to be type flags */ def toTypeFlags = FlagSet(bits & ~KINDFLAGS | TYPES) /** This flag set with all flags transposed to be term flags */ def toTermFlags = FlagSet(bits & ~KINDFLAGS | TERMS) /** This flag set with all flags transposed to be common flags */ def toCommonFlags = FlagSet(bits | KINDFLAGS) /** The number of non-kind flags in this set */ def numFlags: Int = java.lang.Long.bitCount(bits & ~KINDFLAGS) /** The list of non-empty names of flags with given index idx that are set in this FlagSet */ private def flagString(idx: Int): List[String] = if ((bits & (1L << idx)) == 0) Nil else { def halfString(kind: Int) = if ((bits & (1L << kind)) != 0) flagName(idx)(kind) else "" val termFS = halfString(TERMindex) val typeFS = halfString(TYPEindex) val strs = termFS :: (if (termFS == typeFS) Nil else typeFS :: Nil) strs filter (_.nonEmpty) } /** The list of non-empty names of flags that are set in this FlagSet */ def flagStrings: Seq[String] = (2 to MaxFlag).flatMap(flagString) /** The string representation of this flag set */ override def toString = flagStrings.mkString(" ") } /** A class representing flag sets that should be tested * conjunctively. I.e. for a flag conjunction `fc`, * `x is fc` tests whether `x` contains all flags in `fc`. */ case class FlagConjunction(bits: Long) { override def toString = FlagSet(bits).toString } private final val TYPESHIFT = 2 private final val TERMindex = 0 private final val TYPEindex = 1 private final val TERMS = 1 << TERMindex private final val TYPES = 1 << TYPEindex private final val KINDFLAGS = TERMS | TYPES private final val FirstFlag = 2 private final val FirstNotPickledFlag = 48 private final val MaxFlag = 63 private var flagName = Array.fill(64, 2)("") private def isDefinedAsFlag(idx: Int) = flagName(idx) exists (_.nonEmpty) /** The flag set containing all defined flags of either kind whose bits * lie in the given range */ private def flagRange(start: Int, end: Int) = FlagSet((KINDFLAGS.toLong /: (start until end)) ((bits, idx) => if (isDefinedAsFlag(idx)) bits | (1L << idx) else bits)) /** The flag with given index between 2 and 63 which applies to terms. * Installs given name as the name of the flag. */ private def termFlag(index: Int, name: String): FlagSet = { flagName(index)(TERMindex) = name FlagSet(TERMS | (1L << index)) } /** The flag with given index between 2 and 63 which applies to types. * Installs given name as the name of the flag. */ private def typeFlag(index: Int, name: String): FlagSet = { flagName(index)(TYPEindex) = name FlagSet(TYPES | (1L << index)) } /** The flag with given index between 2 and 63 which applies to both terms and types * Installs given name as the name of the flag. */ private def commonFlag(index: Int, name: String): FlagSet = { flagName(index)(TERMindex) = name flagName(index)(TYPEindex) = name FlagSet(TERMS | TYPES | (1L << index)) } /** The union of all flags in given flag set */ def union(flagss: FlagSet*) = (EmptyFlags /: flagss)(_ | _) /** The conjunction of all flags in given flag set */ def allOf(flagss: FlagSet*) = { assert(flagss forall (_.numFlags == 1)) FlagConjunction(union(flagss: _*).bits) } def commonFlags(flagss: FlagSet*) = union(flagss.map(_.toCommonFlags): _*) /** The empty flag set */ final val EmptyFlags = FlagSet(0) // Available flags: /** Labeled with `private` modifier */ final val Private = commonFlag(2, "private") /** Labeled with `protected` modifier */ final val Protected = commonFlag(3, "protected") /** Labeled with `override` modifier */ final val Override = commonFlag(4, "override") /** A declared, but not defined member */ final val Deferred = commonFlag(5, "") final val DeferredTerm = Deferred.toTermFlags final val DeferredType = Deferred.toTypeFlags /** Labeled with `final` modifier */ final val Final = commonFlag(6, "final") /** A method symbol. */ final val Method = termFlag(7, "") /** Labeled with `abstract` modifier (an abstract class) */ final val Abstract = typeFlag(7, "abstract") /** A (term or type) parameter to a class or method */ final val Param = commonFlag(8, "") final val TermParam = Param.toTermFlags final val TypeParam = Param.toTypeFlags /** Labeled with `implicit` modifier (implicit value) */ final val Implicit = termFlag(9, "implicit") /** A trait */ final val Trait = typeFlag(9, "") /** Labeled with `lazy` (a lazy val). */ final val Lazy = termFlag(10, "lazy") /** A trait that has only abstract methods as members * (and therefore can be represented by a Java interface */ final val Interface = typeFlag(10, "interface") /** A value or variable accessor (getter or setter) */ final val Accessor = termFlag(11, "") /** A covariant type variable */ final val Covariant = typeFlag(11, "") /** A mutable var */ final val Mutable = termFlag(12, "mutable") /** A contravariant type variable */ final val Contravariant = typeFlag(12, "") /** Symbol is local to current class (i.e. private[this] or protected[this] * pre: Private or Protected are also set */ final val Local = commonFlag(13, "") /** A field generated for a primary constructor parameter (no matter if it's a 'val' or not), * or an accessor of such a field. */ final val ParamAccessor = commonFlag(14, "") /** A value or class implementing a module */ final val Module = commonFlag(15, "module") final val ModuleVal = Module.toTermFlags final val ModuleClass = Module.toTypeFlags /** A value or class representing a package */ final val Package = commonFlag(16, "") final val PackageVal = Package.toTermFlags final val PackageClass = Package.toTypeFlags /** A package object or its module class */ final val PackageObject = commonFlag(17, "package") final val PackageObjectVal = PackageObject.toTermFlags final val PackageObjectClass = PackageObject.toTypeFlags /** A case class or its companion object */ final val Case = commonFlag(17, "case") final val CaseClass = Case.toTypeFlags final val CaseVal = Case.toTermFlags /** A compiler-generated symbol, which is visible for type-checking * (compare with artifact) */ final val Synthetic = commonFlag(18, "") /** Symbol's name is expanded */ final val ExpandedName = commonFlag(19, "") /** Method is a label. */ final val Label = termFlag(20, "