Skip to content

Commit 3ed077b

Browse files
committed
Add section on enum translation
1 parent bb004eb commit 3ed077b

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

docs/docs/reference/desugarEnums.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Translation of Enums and ADTs
2+
3+
The compiler expands enum classes and cases to code that only uses
4+
Scala's other language features. As such, enums in Scala are
5+
convenient _syntactic sugar_, but they are not essential to understand
6+
Scala's core.
7+
8+
We now explain the expansion of enums is explained in detail. First,
9+
some terminology and notational conventions:
10+
11+
- We use `E` as a name of an enum class, and `C` as a name of an enum case that appears in the companion object of `E`.
12+
- We use `<...>` for syntactic constructs that in some circumstances might be empty. For instance `<body>` represents either the body of a case between `{...}` or nothing at all.
13+
14+
- Enum cases fall into three categories:
15+
16+
- _Class cases_ are those cases that are parameterized, either with a type parameter section `[...]` or with one or more (possibly empty) parameter sections `(...)`.
17+
- _Simple cases_ are cases of a non-generic enum class that have neither parameters nor an extends clause or body. That is, they consist of a name only.
18+
- _Value cases_ are all cases that do not have a parameter section but that do have a (possibly generated) extends clause and/or a body.
19+
20+
Simple cases and value cases are called collectively _singleton cases_.
21+
22+
The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val` definitions.
23+
24+
There are eight desugaring rules. Rules (1) and (2) desugar enums and
25+
enum classes. Rules (3) and (4) define extends clauses for cases that
26+
are missing them. Rules (5 - 7) define how such expanded cases map
27+
into case classes, case objects or vals. Finally, rule (8) expands
28+
comma separated simple cases into a sequence of cases.
29+
30+
1. An `enum` definition
31+
32+
enum E ... { <cases> }
33+
34+
expands to an enum class and a companion object
35+
36+
enum class E ...
37+
object E { <cases> }
38+
39+
2. An enum class definition
40+
41+
enum class E ... extends <parents> ...
42+
43+
expands to a `sealed` `abstract` class that extends the `scala.Enum` trait:
44+
45+
sealed abstract class E ... extends <parents> with scala.Enum ...
46+
47+
3. If `E` is an enum class without type parameters, then a case in its companion object without an extends clause
48+
49+
case C <params> <body>
50+
51+
expands to
52+
53+
case C <params> <body> extends E
54+
55+
4. If `E` is an enum class with type parameters `Ts`, then a case in its companion object without an extends clause
56+
57+
case C <params> <body>
58+
59+
expands according to two alternatives, depending whether `C` has type parameters or not. If `C` has type parameters, they must have the same names and appear in the same order as the enum type parameters `Ts` (variances may be different, however). In this case
60+
61+
case C [Ts] <params> <body>
62+
63+
expands to
64+
65+
case C[Ts] <params> extends E[Ts] <body>
66+
67+
For the case where `C` does not have type parameters, assume `E`'s type parameters are
68+
69+
V1 T1 > L1 <: U1 , ... , Vn Tn >: Ln <: Un (n > 0)
70+
71+
where each of the variances `Vi` is either `'+'` or `'-'`. Then the case expands to
72+
73+
case C <params> extends E[B1, ..., Bn] <body>
74+
75+
where `Bi` is `Li` if `Vi = '+'` and `Ui` if `Vi = '-'`. It is an error if `Bi` refers to some other type parameter `Tj (j = 0,..,n-1)`. It is also an error if `E` has type parameters that are non-variant.
76+
77+
5. A class case
78+
79+
case C <params> ...
80+
81+
expands analogous to a case class:
82+
83+
final case class C <params> ...
84+
85+
However, unlike for a regular case class, the return type of the associated `apply` method is a fully parameterized type instance of the enum class `E` itself instead of `C`. Also the enum case defines an `enumTag` method of the form
86+
87+
def enumTag = n
88+
89+
where `n` is the ordinal number of the case in the companion object, starting from 0.
90+
91+
6. A value case
92+
93+
case C extends <parents> <body>
94+
95+
expands to a value definition
96+
97+
val C = new <parents> { <body>; def enumTag = n; $values.register(this) }
98+
99+
where `n` is the ordinal number of the case in the companion object, starting from 0.
100+
The statement `$values.register(this)` registers the value as one of the `enumValues` of the
101+
enumeration (see below). `$values` is a compiler-defined private value in
102+
the companion object.
103+
104+
7. A simple case
105+
106+
case C
107+
108+
of an enum class `E` that does not take type parameters expands to
109+
110+
val C = $new(n, "C")
111+
112+
Here, `$new` is a private method that creates an instance of of `E` (see below).
113+
114+
8. A simple case consisting of a comma-separated list of enum names
115+
116+
case C_1, ..., C_n
117+
118+
expands to
119+
120+
case C_1; ...; case C_n
121+
122+
Any modifiers or annotations on the original case extend to all expanded cases.
123+
124+
## Translation of Enumerations
125+
126+
Non-generic enum classes `E` that define one or more singleton cases
127+
are called _enumerations_. Companion objects of enumerations define
128+
the following additional members.
129+
130+
- A method `enumValue` of type `scala.collection.immutable.Map[Int, E]`. `enumValue(n)` returns the singleton case value with ordinal number `n`.
131+
- A method `enumValueNamed` of type `scala.collection.immutable.Map[String, E]`. `enumValueNamed(s)` returns the singleton case value whose `toString` representation is `s`.
132+
- A method `enumValues` which returns an `Iterable[E]` of all singleton case values in `E`, in the order of their definitions.
133+
134+
Companion objects that contain at least one simple case define in addition:
135+
136+
- A private method `$new` which defines a new simple case value with given ordinal number and name. This method can be thought as being defined as follows.
137+
138+
def $new(tag: Int, name: String): ET = new E {
139+
def enumTag = tag
140+
def toString = name
141+
$values.register(this) // register enum value so that `valueOf` and `values` can return it.
142+
}
143+

0 commit comments

Comments
 (0)