All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.dotc.core.Flags.scala Maven / Gradle / Ivy

The newest version!
package dotty.tools.dotc
package core

object Flags {

  object opaques {

    /** A FlagSet represents a set of flags. Flags are encoded as follows:
    *  The first two bits indicate whether a flag set applies to terms,
    *  to types, or to both.  Bits 2..63 are available for properties
    *  and can be doubly used for terms and types.
    */
    opaque type FlagSet = Long
    def FlagSet(bits: Long): FlagSet = bits
    def toBits(fs: FlagSet): Long = fs

    /** A flag set consisting of a single flag */
    opaque type Flag <: FlagSet = Long
    private[Flags] def Flag(bits: Long): Flag = bits
  }
  export opaques.FlagSet

  type Flag = opaques.Flag

  delegate FlagOps {

    def (x: FlagSet) bits: Long = opaques.toBits(x)

    /** The union of the given flag sets.
     *  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.
     */
    def (x: FlagSet) | (y: FlagSet): FlagSet =
      if (x.bits == 0) y
      else if (y.bits == 0) x
      else {
        val tbits = x.bits & y.bits & KINDFLAGS
        if (tbits == 0)
          assert(false, s"illegal flagset combination: $x and $y")
        FlagSet(tbits | ((x.bits | y.bits) & ~KINDFLAGS))
      }

    /** The intersection of the given flag sets */
    def (x: FlagSet) & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits)

    /** The intersection of a flag set with the complement of another flag set */
    def (x: FlagSet) &~ (y: FlagSet): FlagSet = {
      val tbits = x.bits & KINDFLAGS
      if ((tbits & y.bits) == 0) x
      else FlagSet(tbits | ((x.bits & ~y.bits) & ~KINDFLAGS))
    }

    def (x: FlagSet) ^ (y: FlagSet) =
      FlagSet((x.bits | y.bits) & KINDFLAGS | (x.bits ^ y.bits) & ~KINDFLAGS)

    /** Does the given flag set contain the given flag?
     *  This means that both the kind flags and the carrier bits have non-empty intersection.
     */
    def (x: FlagSet) is (flag: Flag): Boolean = {
      val fs = x.bits & flag.bits
      (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
    }

    /** Does the given flag set contain the given flag
     *  and at the same time contain none of the flags in the `butNot` set?
     */
    def (x: FlagSet) is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot)

    /** Does the given flag set have a non-empty intersection with another flag set?
     *  This means that both the kind flags and the carrier bits have non-empty intersection.
     */
    def (x: FlagSet) isOneOf (flags: FlagSet): Boolean = {
      val fs = x.bits & flags.bits
      (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
    }

   /** Does the given flag set have a non-empty intersection with another flag set,
    *  and at the same time contain none of the flags in the `butNot` set?
    */
   def (x: FlagSet) isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot)

    /** Does a given flag set have all of the flags of another flag set?
     *  Pre: The intersection of the term/type flags of both sets must be non-empty.
     */
    def (x: FlagSet) isAllOf (flags: FlagSet): Boolean = {
      val fs = x.bits & flags.bits
      ((fs & KINDFLAGS) != 0 || flags.bits == 0) &&
      (fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT)
    }

    /** Does a given flag set have all of the flags in another flag set
     *  and at the same time contain none of the flags in the `butNot` set?
     *  Pre: The intersection of the term/type flags of both sets must be non-empty.
     */
    def (x: FlagSet) isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot)

    def (x: FlagSet) isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0

    /** Is a given flag set a subset of another flag set? */
    def (x: FlagSet) <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits

    /** Does the given flag set apply to terms? */
    def (x: FlagSet) isTermFlags: Boolean = (x.bits & TERMS) != 0

    /** Does the given flag set apply to terms? */
    def (x: FlagSet) isTypeFlags: Boolean = (x.bits & TYPES) != 0

    /** The given flag set with all flags transposed to be type flags */
    def (x: FlagSet) toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES)

    /** The given flag set with all flags transposed to be term flags */
    def (x: FlagSet) toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS)

    /** The given flag set with all flags transposed to be common flags */
    def (x: FlagSet) toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS)

    /** The number of non-kind flags in the given flag set */
    def (x: FlagSet) numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS)

    /** The lowest non-kind bit set in the given flag set */
    def (x: FlagSet) firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS)

    /** The  list of non-empty names of flags with given index idx that are set in the given flag set */
    private def (x: FlagSet) flagString(idx: Int): List[String] =
      if ((x.bits & (1L << idx)) == 0) Nil
      else {
        def halfString(kind: Int) =
          if ((x.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 teh given flag set */
    def (x: FlagSet) flagStrings(privateWithin: String): Seq[String] = {
      var rawStrings = (2 to MaxFlag).flatMap(x.flagString(_)) // DOTTY problem: cannot drop with (_)
      if (!privateWithin.isEmpty && !x.is(Protected))
      	rawStrings = rawStrings :+ "private"
      val scopeStr = if (x.is(Local)) "this" else privateWithin
      if (scopeStr != "")
        rawStrings.filter(_ != "").map {
          case "private" => s"private[$scopeStr]"
          case "protected" => s"protected[$scopeStr]"
          case str => str
        }
      else rawStrings
    }

    /** The string representation of the given flag set */
    def (x: FlagSet) flagsString: String = x.flagStrings("").mkString(" ")
  }

  def termFlagSet(x: Long) = FlagSet(TERMS | x)

  private inline val TYPESHIFT = 2
  private inline val TERMindex = 0
  private inline val TYPEindex = 1
  private inline val TERMS = 1 << TERMindex
  private inline val TYPES = 1 << TYPEindex
  private inline val KINDFLAGS = TERMS | TYPES

  private inline val FirstFlag = 2
  private inline val FirstNotPickledFlag = 48
  private inline val MaxFlag = 63

  private val 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 union of all flags in given flag set */
  def union(flagss: FlagSet*): FlagSet = {
    var flag = EmptyFlags
    for (f <- flagss)
      flag |= f
    flag
  }

  def commonFlags(flagss: FlagSet*): FlagSet = union(flagss.map(_.toCommonFlags): _*)

  /** The empty flag set */
  val EmptyFlags: FlagSet = FlagSet(0)

  /** The undefined flag set */
  val UndefinedFlags: FlagSet = FlagSet(~KINDFLAGS)

  /** Three flags with given index between 2 and 63.
   *  The first applies to both terms and types. the second is a term flag, and
   *  the third is a type flag. Installs given name(s) as the name(s) of the flags.
   *  @param name     The name to be used for the term flag
   *  @param typeName The name to be used for the type flag, if it is different from `name`.
   */
  private def newFlags(index: Int, name: String, typeName: String = ""): (Flag, Flag, Flag) = {
    flagName(index)(TERMindex) = name
    flagName(index)(TYPEindex) = if (typeName.isEmpty) name else typeName
    val bits = 1L << index
    (opaques.Flag(KINDFLAGS | bits), opaques.Flag(TERMS | bits), opaques.Flag(TYPES | bits))
  }

  // ----------------- Available flags -----------------------------------------------------

  /** Labeled with `private` modifier */
  val (Private @ _, PrivateTerm @ _, PrivateType @ _) = newFlags(2, "private")

  /** Labeled with `protected` modifier */
  val (Protected @ _, _, _) = newFlags(3, "protected")

  /** Labeled with `override` modifier */
  val (Override @ _, _, _) = newFlags(4, "override")

  /** A declared, but not defined member */
  val (Deferred @ _, DeferredTerm @ _, DeferredType @ _) = newFlags(5, "")

  /** Labeled with `final` modifier */
  val (Final @ _, _, _) = newFlags(6, "final")

  /** A method symbol */
  val (_, Method @ _, HigherKinded @ _) = newFlags(7, "", "") // TODO drop HigherKinded

  /** A (term or type) parameter to a class or method */
  val (Param @ _, TermParam @ _, TypeParam @ _) = newFlags(8, "")

  /** Labeled with `implicit` modifier (implicit value) */
  val (Implicit @ _, ImplicitTerm @ _, _) = newFlags(9, "implicit")

  /** Labeled with `lazy` (a lazy val) / a trait */
  val (LazyOrTrait @ _, Lazy @ _, Trait @ _) = newFlags(10, "lazy", "")

  /** A value or variable accessor (getter or setter) */
  val (AccessorOrSealed @ _, Accessor @ _, Sealed @ _) = newFlags(11, "", "sealed")

  /** A mutable var */
  val (_, Mutable @ _, _) = newFlags(12, "mutable")

  /** Symbol is local to current class (i.e. private[this] or protected[this]
   *  pre: Private or Protected are also set
   */
  val (Local @ _, _, _) = newFlags(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.
   */
  val (_, ParamAccessor @ _, _) = newFlags(14, "")

  /** A value or class implementing a module */
  val (Module @ _, ModuleVal @ _, ModuleClass @ _) = newFlags(15, "module")

   /** A value or class representing a package */
  val (Package @ _, PackageVal @ _, PackageClass @ _) = newFlags(16, "")

  /** A case class or its companion object
   *  Note: Case is also used to indicate that a symbol is bound by a pattern.
   */
  val (Case @ _, CaseVal @ _, CaseClass @ _) = newFlags(17, "case")

  /** A compiler-generated symbol, which is visible for type-checking
   *  (compare with artifact)
   */
  val (Synthetic @ _, _, _) = newFlags(18, "")

  /** Labelled with `inline` modifier */
  val (Inline @ _, _, _) = newFlags(19, "inline")

  /** An outer accessor / a covariant type variable */
  val (OuterOrCovariant @ _, OuterAccessor @ _, Covariant @ _) = newFlags(20, "", "")

  /** The label of a labeled block / a contravariant type variable */
  val (LabelOrContravariant @ _, Label @ _, Contravariant @ _) = newFlags(21, "




© 2015 - 2025 Weber Informatics LLC | Privacy Policy