summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Modes.scala
blob: d942d080cb05ff2cabb3e963940b8b8883c1cecd (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
/* NSC -- new Scala compiler
 * Copyright 2005-2012 LAMP/EPFL
 * @author  Martin Odersky
 */

package scala.tools.nsc
package typechecker

/** Mode constants.
 */
trait Modes {
  /** NOmode, EXPRmode and PATTERNmode are mutually exclusive.
   */
  final val NOmode        = 0x000
  final val EXPRmode      = 0x001
  final val PATTERNmode   = 0x002

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

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

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

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

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

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

  /** SUPERCONSTRmode is set for the super
   *  in a superclass constructor call super.<init>.
   */
  final val SUPERCONSTRmode = 0x100

  /** SNDTRYmode indicates that an application is typed for the 2nd time.
   *  In that case functions may no longer be coerced with implicit views.
   */
  final val SNDTRYmode    = 0x200

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

  /** STARmode is set when star patterns are allowed.
   *  (This was formerly called REGPATmode.)
   */
  final val STARmode      = 0x1000

  /** ALTmode is set when we are under a pattern alternative.
   */
  final val ALTmode       = 0x2000

  /** HKmode is set when we are typing a higher-kinded type.
   *  adapt should then check kind-arity based on the prototypical type's
   *  kind arity.  Type arguments should not be inferred.
   */
  final val HKmode        = 0x4000 // @M: could also use POLYmode | TAPPmode

  /** 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     = 0x8000

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

  /** RETmode is set when we are typing a return expression.
   */
  final val RETmode       = 0x20000

  final private val StickyModes   = EXPRmode | PATTERNmode | TYPEmode | ALTmode

  final def onlyStickyModes(mode: Int) =
    mode & StickyModes

  final def forFunMode(mode: Int) =
    mode & (StickyModes | SCCmode) | FUNmode | POLYmode | BYVALmode

  final def forTypeMode(mode: Int) =
    if (inAnyMode(mode, PATTERNmode | TYPEPATmode)) TYPEmode | TYPEPATmode
    else TYPEmode

  final def inAllModes(mode: Int, required: Int)  = (mode & required) == required
  final def inAnyMode(mode: Int, required: Int)   = (mode & required) != 0
  final def inNoModes(mode: Int, prohibited: Int) = (mode & prohibited) == 0
  final def inHKMode(mode: Int)                   = (mode & HKmode) != 0
  final def inFunMode(mode: Int)                  = (mode & FUNmode) != 0
  final def inPolyMode(mode: Int)                 = (mode & POLYmode) != 0
  final def inPatternMode(mode: Int)              = (mode & PATTERNmode) != 0
  final def inExprModeOr(mode: Int, others: Int)  = (mode & (EXPRmode | others)) != 0
  final def inExprModeButNot(mode: Int, prohibited: Int) =
    (mode & (EXPRmode | prohibited)) == EXPRmode

  /** Translates a mask of mode flags into something readable.
   */
  private val modeNameMap = Map[Int, String](
    (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)  -> "SUPERCONSTRmode",
    (1 << 9)  -> "SNDTRYmode",
    (1 << 10) -> "LHSmode",
    (1 << 11) -> "<DOES NOT EXIST mode>",
    (1 << 12) -> "STARmode",
    (1 << 13) -> "ALTmode",
    (1 << 14) -> "HKmode",
    (1 << 15) -> "BYVALmode",
    (1 << 16) -> "TYPEPATmode"
  )
  def modeString(mode: Int): String =
    if (mode == 0) "NOmode"
    else (modeNameMap filterKeys (bit => inAllModes(mode, bit))).values mkString " "
}