aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/core/Flags.scala
blob: f4a1116321573f42ba16a618f98ed7fd4c2d1640 (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 {

    def | (that: 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))
      }

    def & (that: FlagSet) = FlagSet(bits & that.bits)

    def intersects(flags: FlagSet) = {
      val fs = bits & flags.bits
      (fs & TYPEFLAGS) != 0 &&
      fs > TYPEFLAGS
    }

    def intersects(flags: FlagSet, butNot: FlagSet) = {
      val fs = bits & flags.bits
      (fs & TYPEFLAGS) != 0 &&
      fs > TYPEFLAGS &&
      (bits & butNot.bits) == 0
    }

    def contains(flags: FlagSet) = {
      val fs = bits & flags.bits
      (fs & TYPEFLAGS) != 0 &&
      (fs >> TYPESHIFT) == (flags.bits >> TYPESHIFT)
    }

    def contains(flags: FlagSet, 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)

    override def toString =
      (2 to MaxFlag).flatMap(flagString).mkString(" ")
  }

  final val TYPEFLAGS = 3L
  final val TYPESHIFT = 2
  final val TERMindex = 0
  final val TYPEindex = 1
  final val TERMS = 1 << TERMindex
  final val TYPES = 1 << TYPEindex

  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 */
  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 */
  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 */
  def commonFlag(index: Int, name: String): FlagSet =
    termFlag(index, name) | typeFlag(index, name)

  // Available flags:

  final val Empty = FlagSet(0)

  final val Private = commonFlag(3, "private")
  final val Accessor = termFlag(4, "<accessor>")

  final val Error = FlagSet(1 << 32)
  final val Frozen = FlagSet(???)
  final val Package = FlagSet(???)

}