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 & TYPEFLAGS assert(tbits != 0, s"illegal flagset combination: $this and $that") FlagSet(tbits | ((this.bits | that.bits) & ~TYPEFLAGS)) } /** The union of this flag set and the given flag conjunction seen as * a flag set. */ def | (that: FlagConjunction): FlagSet = this | FlagSet(that.bits) /** 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 & that.bits & TYPEFLAGS assert(tbits != 0, s"illegal flagset combination: $this and $that") FlagSet(tbits | ((this.bits & ~that.bits) & ~TYPEFLAGS)) } /** Does this flag set have a non-empty intersection with the given flag set? * Pre: The intersection of the typeflags of both sets must be non-empty. */ def is(flags: FlagSet) = { val fs = bits & flags.bits (fs & TYPEFLAGS) != 0 && fs > TYPEFLAGS } /** 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? * Pre: The intersection of the typeflags of both sets must be non-empty. */ def is(flags: FlagSet, butNot: FlagSet) = { val fs = bits & flags.bits (fs & TYPEFLAGS) != 0 && fs > TYPEFLAGS && (bits & butNot.bits) == 0 } /** 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) = { val fs = bits & flags.bits (fs & TYPEFLAGS) != 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) = { val fs = bits & (flags.bits | butNot.bits) (fs & TYPEFLAGS) != 0 && (fs >> TYPESHIFT) == (flags.bits >> TYPESHIFT) } /** The set of all non-empty strings that are associated * as term or type flags with this index */ private def flagString(idx: Int): Set[String] = kindIndices.map(flagName(idx)).filterNot(_.isEmpty) /** The string representation of this flag set */ override def toString = (2 to MaxFlag).flatMap(flagString).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) private final val TYPEFLAGS = 3L 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 MaxFlag = 63 private var flagName = Array.fill(64, 2)("") private val kindIndices = Set(TERMindex, TYPEindex) /** The flag with given index between 2 and 63 which applies to terms. * Installs given name as the name of the flag. */ def termFlag(index: Int, name: String): FlagSet = { flagName(index)(TERMindex) = name termFlag(index) } /** The flag with given index between 2 and 63 which applies to terms. */ def termFlag(index: Int) = 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. */ def typeFlag(index: Int, name: String): FlagSet = { flagName(index)(TYPEindex) = name typeFlag(index) } /** The flag with given index between 2 and 63 which applies to terms. */ def typeFlag(index: Int) = FlagSet(TYPES | (1L << index)) /** The flag with given index between 2 and 63 which applies to both terms and types */ def commonFlag(index: Int, name: String): FlagSet = termFlag(index, name) | typeFlag(index) /** The conjunction of all flags in given flag set */ def allOf(flags: FlagSet) = FlagConjunction(flags.bits) /** The empty flag set */ final val Empty = 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, "") /** Labeled with `final` modifier */ final val Final = commonFlag(6, "final") /** A method. !!! needed? */ final val Method = termFlag(7, "") /** An abstract class */ final val Abstract = typeFlag(8, "abstract") /** A trait that has only abstract methods as members * (and therefore can be represented by a Java interface */ final val Interface = typeFlag(9, "interface") /** A value or class implementing a module */ final val Module = commonFlag(10, "module") final val ModuleObj = termFlag(10) final val ModuleClass = typeFlag(10) /** Labeled with `implicit` modifier */ final val Implicit = termFlag(11, "implicit") /** Labeled with `sealed` modifier */ final val Sealed = typeFlag(12, "sealed") /** A case class or its companion object */ final val Case = commonFlag(13, "case") final val CaseClass = typeFlag(13) final val CaseObj = termFlag(13) /** A lazy val */ final val Lazy = termFlag(14, "lazy") /** A mutable var */ final val Mutable = termFlag(14, "mutable") /** A (term or type) parameter to a class or method */ final val Param = commonFlag(15, "") final val TermParam = termFlag(15) final val TypeParam = typeFlag(15) /** A value or class representing a package */ final val Package = commonFlag(16, "") final val PackageObj = termFlag(16) final val PackageClass = typeFlag(16) /** A by-name parameter !!! needed? */ final val ByNameParam = termFlag(17, "") /** A covariant type variable */ final val Covariant = typeFlag(17, "") /** Method is a label. */ final val Label = termFlag(18, "