aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/core/Flags.scala
blob: 1b1f2c61870b3db42261a3ba5fff2870b9d0eeac (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12



                             







                                                                             
                                                     
 


                                                         







                                                                           





                                                                         

                                                     










                                                                                      




                                




                                                                                


                                
                               

     



                                                                              




                                                    




                                                                              
                                                









                                                            
                                                     

                                                      
   
 











                                                             
 
                                




                                                     

                                                                        

                                                     
                   

   




                                                                           

                                                     
                   

   


                                                                           

                                                                                         
                                           
 

                                                         
 
                           
                              
 




































































































































                                                                                                
 

                                                                
 

























































                                                                                                   
 
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, "<deferred>")

  /** Labeled with `final` modifier */
  final val Final = commonFlag(6, "final")

  /** A method. !!! needed? */
  final val Method = termFlag(7, "<method>")

  /** 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, "<param>")
  final val TermParam = termFlag(15)
  final val TypeParam = typeFlag(15)

  /** A value or class representing a package */
  final val Package = commonFlag(16, "<package>")
  final val PackageObj = termFlag(16)
  final val PackageClass = typeFlag(16)

  /** A by-name parameter !!! needed? */
  final val ByNameParam = termFlag(17, "<by-name>")

  /** A covariant type variable */
  final val Covariant = typeFlag(17, "<covariant>")

  /** Method is a label. */
  final val Label = termFlag(18, "<label>")

  /** Symbol is a macro */
  final val Macro = commonFlag(???, "<macro>")

  /** A contravariant type variable */
  final val Contravariant = typeFlag(18, "<contravariant>")

  /** combination of abstract & override */
  final val AbsOverride = termFlag(19, "abstract override")

  /** Symbol is local to current class (i.e. private[this] or protected[this]
   *  pre: Private or Protected are also set
   */
  final val Local = commonFlag(20, "<local>")

  /** Symbol is defined by a Java class */
  final val Java = commonFlag(21, "<java>")

  /** A compiler-generated symbol. which is visible for type-checking
   *  (compare with artifact)
   */
  final val Synthetic = commonFlag(22, "<synthetic>")

  /** Method is assumed to be stable */
  final val Stable = termFlag(23, "<stable>")

  final val Static = commonFlag(24, "<static>")

  /** A value or variable accessor (getter or setter) */
  final val Accessor = termFlag(25, "<accessor>")

  /** A case parameter (or its accessor, or a GADT skolem) */
  final val CaseAccessor = termFlag(26, "<caseaccessor>")

  /** A super accessor */
  final val SuperAccessor = termFlag(27, "<superaccessor>")

  /** 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 = termFlag(28, "<paramaccessor>")

  /** A parameter with a default value */
  final val DefaultParam = termFlag(27, "<defaultparam>")

  /** A trait */
  final val Trait = typeFlag(27, "<trait>")

  /** A bridge method. Set by Erasure */
  final val Bridge = termFlag(28, "<bridge>")

  /** Symbol is initialized to the default value, e.g. var x: T = _ */
  final val DefaultInit = termFlag(29, "<defaultinit>")

  /** An error symbol */
  final val Erroneous = commonFlag(???, "<is-error>")

  /** Denotation has not yet been loaded */
  final val Unloaded = commonFlag(32, "??")

  /** Denotation is in train of being loaded and completed, flag to catch cyclic dependencies */
  final val Locked = commonFlag(???, "<locked>")

  /** Variable is accessed from nested function. */
  final val Captured = termFlag(???, "<captured>")

  /** Class symbol is defined in this/superclass constructor. */
  final val Inconstructor = typeFlag(???, "<in-constructor>")

  /** Class is not allowed to accept new members because fingerprint of subclass has been taken */
  final val Frozen = typeFlag(???, "<frozen>")

  /** Class has been lifted out to package level, local value has been lifted out to class level */
  final val Lifted = termFlag(???, "<lifted>")

  /** Term member has been mixed in */
  final val MixedIn = termFlag(???, "<mixedin>")

  /** Symbol is a generated specialized member */
  final val Specialized = commonFlag(???, "<specialized>")

  /** Symbol is a Java-style varargs method */
  final val JavaVarargs = termFlag(???, "<varargs>")

  /** Symbol is a Java varargs bridge */
  final val VBridge = termFlag(???, "<vbridge>")

  /** Symbol is a method which should be marked ACC_SYNCHRONIZED */
  final val Synchronized = termFlag(???, "<synchronized>")

  /** Symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode */
  final val Artifact = commonFlag(???, "<artifact>")

  /** Symbol is an implementation class */
  final val ImplClass = typeFlag(???, "<implclass>")

// --------- Combined Flag Sets and Conjunctions ----------------------

  /** Flags representing source modifiers */
  final val ModifierFlags =
    Private | Protected | Abstract | Final | Sealed |
    Override | Case | Implicit | AbsOverride | Lazy

  /** Flags representing access rights */
  final val AccessFlags    = Private | Protected | Local

  /** These flags are not pickled */
  final val FlagsNotPickled =
    Erroneous | Lifted | Unloaded | Frozen

  /** These flags are pickled */
  //final val PickledFlags  = InitialFlags & ~FlagsNotPickled


  /** A value that's unstable unless complemented with a Stable flag */
  final val UnstableValue = Mutable | Method | ByNameParam

  /** Labeled private[this] */
  final val PrivateLocal = allOf(Private | Local)

  /** Labeled `protected[this]` */
  final val ProtectedLocal = allOf(Protected | Local)

  /** Labeled `abstract` and `override`; only used in Parser,
   *  symbols are labeled AbsOverride instead
   */
  final val AbstractOverride = allOf(Abstract | Override)
}