summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Mode.scala
blob: 557ec9c16287069d571fa678dad139b77c628a65 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Martin Odersky
 */

package scala
package reflect
package internal

import scala.language.implicitConversions

object Mode {
  private implicit def liftIntBitsToMode(bits: Int): Mode = apply(bits)
  def apply(bits: Int): Mode = new Mode(bits)

  /** NOmode, EXPRmode and PATTERNmode are mutually exclusive.
   */
  final val NOmode: Mode        = 0x000
  final val EXPRmode: Mode      = 0x001
  final val PATTERNmode: Mode   = 0x002

  /** TYPEmode needs a comment. <-- XXX.
   */
  final val TYPEmode: Mode      = 0x004

  /** SCCmode is orthogonal to above. When set we are
   *  in the this or super constructor call of a constructor.
   */
  final val SCCmode: Mode       = 0x008

  /** FUNmode is orthogonal to above.
   *  When set we are looking for a method or constructor.
   */
  final val FUNmode: Mode       = 0x010

  /** POLYmode is orthogonal to above.
   *  When set expression types can be polymorphic.
   */
  final val POLYmode: Mode      = 0x020

  /** QUALmode is orthogonal to above. When set
   *  expressions may be packages and Java statics modules.
   */
  final val QUALmode: Mode      = 0x040

  /** TAPPmode is set for the function/type constructor
   *  part of a type application. When set we do not decompose PolyTypes.
   */
  final val TAPPmode: Mode      = 0x080

  /** LHSmode is set for the left-hand side of an assignment.
   */
  final val LHSmode: Mode       = 0x400

  /** BYVALmode is set when we are typing an expression
   *  that occurs in a by-value position. An expression e1 is in by-value
   *  position within expression e2 iff it will be reduced to a value at that
   *  position during the evaluation of e2.  Examples are by-value function
   *  arguments or the conditional of an if-then-else clause.
   *  This mode has been added to support continuations.
   */
  final val BYVALmode: Mode     = 0x8000

  /** TYPEPATmode is set when we are typing a type in a pattern.
   */
  final val TYPEPATmode: Mode   = 0x10000

  private val StickyModes: Mode       = EXPRmode | PATTERNmode | TYPEmode
  private val StickyModesForFun: Mode = StickyModes | SCCmode
  final val MonoQualifierModes: Mode  = EXPRmode | QUALmode
  final val PolyQualifierModes: Mode  = EXPRmode | QUALmode | POLYmode
  final val OperatorModes: Mode       = EXPRmode |            POLYmode | TAPPmode | FUNmode

  /** Translates a mask of mode flags into something readable.
   */
  private val modeNameMap = Map[Int, String]( // TODO why duplicate the bitmasks here, rather than just referring to this.EXPRmode etc?
    (1 << 0)  -> "EXPRmode",
    (1 << 1)  -> "PATTERNmode",
    (1 << 2)  -> "TYPEmode",
    (1 << 3)  -> "SCCmode",
    (1 << 4)  -> "FUNmode",
    (1 << 5)  -> "POLYmode",
    (1 << 6)  -> "QUALmode",
    (1 << 7)  -> "TAPPmode",
    (1 << 8)  -> "<>",      // formerly SUPERCONSTRmode
    (1 << 9)  -> "<>",      // formerly SNDTRYmode
    (1 << 10) -> "LHSmode",
    (1 << 11) -> "<>",
    (1 << 12) -> "<>",      // formerly STARmode
    (1 << 13) -> "<>",      // formerly ALTmode
    (1 << 14) -> "<>",      // formerly HKmode
    (1 << 15) -> "BYVALmode",
    (1 << 16) -> "TYPEPATmode"
  ).map({ case (k, v) => Mode(k) -> v })
}
import Mode._

final class Mode private (val bits: Int) extends AnyVal {
  def &(other: Mode): Mode  = new Mode(bits & other.bits)
  def |(other: Mode): Mode  = new Mode(bits | other.bits)
  def &~(other: Mode): Mode = new Mode(bits & ~(other.bits))

  def onlyTypePat = this & TYPEPATmode
  def onlySticky  = this & Mode.StickyModes
  def forFunMode  = this & Mode.StickyModesForFun | FUNmode | POLYmode | BYVALmode
  def forTypeMode = if (typingPatternOrTypePat) TYPEmode | TYPEPATmode else TYPEmode

  def inAll(required: Mode)    = (this & required) == required
  def inAny(required: Mode)    = (this & required) != NOmode
  def inNone(prohibited: Mode) = (this & prohibited) == NOmode

  /** True if this mode matches every mode in the 'all' Mode,
   *  and no modes in the 'none' Mode.
   */
  def in(all: Mode = NOmode, none: Mode = NOmode) = inAll(all) && inNone(none)

  def inByValMode   = inAll(BYVALmode)
  def inExprMode    = inAll(EXPRmode)
  def inFunMode     = inAll(FUNmode)
  def inPatternMode = inAll(PATTERNmode)
  def inPolyMode    = inAll(POLYmode)
  def inQualMode    = inAll(QUALmode)
  def inSccMode     = inAll(SCCmode)
  def inTappMode    = inAll(TAPPmode)
  def inTypeMode    = inAll(TYPEmode)

  def typingExprByValue           = inAll(EXPRmode | BYVALmode)
  def typingExprFun               = inAll(EXPRmode | FUNmode)
  def typingExprNotFun            = in(all = EXPRmode, none = FUNmode)
  def typingExprNotFunNotLhs      = in(all = EXPRmode, none = FUNmode | LHSmode)
  def typingExprNotLhs            = in(all = EXPRmode, none = LHSmode)
  def typingExprNotValue          = in(all = EXPRmode, none = BYVALmode)
  def typingMonoExprByValue       = in(all = EXPRmode | BYVALmode, none = POLYmode)
  def typingConstructorPattern    = inAll(PATTERNmode | FUNmode)
  def typingPatternNotConstructor = in(all = PATTERNmode, none = FUNmode)
  def typingPatternOrTypePat      = inAny(PATTERNmode | TYPEPATmode)

  override def toString =
    if (this == NOmode) "NOmode"
    else (modeNameMap filterKeys inAll).values.toList.sorted mkString "-"
}