Skip to content

Commit ecdaa4e

Browse files
Define ordinal and name for enums
1 parent 9116ecb commit ecdaa4e

File tree

5 files changed

+43
-30
lines changed

5 files changed

+43
-30
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,11 @@ object desugar {
545545
yield syntheticProperty(nme.selectorName(i), caseParams(i).tpt,
546546
Select(This(EmptyTypeIdent), caseParams(i).name))
547547
}
548-
def enumTagMeths = if (isEnumCase) enumTagMeth(CaseKind.Class)._1 :: Nil else Nil
548+
def ordinalMeths =
549+
if (isEnumCase)
550+
ordinalMethLit(nextOrdinal(CaseKind.Class)._1) ::
551+
nameMethLit(className.toString) :: Nil
552+
else Nil
549553
def copyMeths = {
550554
val hasRepeatedParam = constrVparamss.exists(_.exists {
551555
case ValDef(_, tpt, _) => isRepeated(tpt)
@@ -582,7 +586,7 @@ object desugar {
582586
}
583587

584588
if (isCaseClass)
585-
productElemNameMeth :: copyMeths ::: enumTagMeths ::: productElemMeths
589+
productElemNameMeth :: copyMeths ::: ordinalMeths ::: productElemMeths
586590
else Nil
587591
}
588592

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,29 +102,27 @@ object DesugarEnums {
102102

103103
/** A creation method for a value of enum type `E`, which is defined as follows:
104104
*
105-
* private def $new(tag: Int, name: String) = new E {
106-
* def enumTag = tag
105+
* private def $new(tag: Int, name_: String) = new E {
106+
* override def ordinal = tag
107+
* override def name = name_
107108
* override def toString = name
108109
* $values.register(this)
109110
* }
110111
*/
111112
private def enumValueCreator(implicit ctx: Context) = {
112113
def param(name: TermName, typ: Type) =
113114
ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param)
114-
val enumTagDef =
115-
DefDef(nme.enumTag, Nil, Nil, TypeTree(), Ident(nme.tag))
116-
val toStringDef =
117-
DefDef(nme.toString_, Nil, Nil, TypeTree(), Ident(nme.name))
118-
.withFlags(Override)
115+
val ordinalDef = ordinalMeth(Ident(nme.tag))
116+
val nameDef = nameMeth(Ident(nme.name_))
119117
val creator = New(Template(
120118
constr = emptyConstructor,
121119
parents = enumClassRef :: Nil,
122120
derived = Nil,
123121
self = EmptyValDef,
124-
body = List(enumTagDef, toStringDef) ++ registerCall
122+
body = List(ordinalDef, nameDef, toStringMethAsName) ++ registerCall
125123
).withAttachment(ExtendsSingletonMirror, ()))
126124
DefDef(nme.DOLLAR_NEW, Nil,
127-
List(List(param(nme.tag, defn.IntType), param(nme.name, defn.StringType))),
125+
List(List(param(nme.tag, defn.IntType), param(nme.name_, defn.StringType))),
128126
TypeTree(), creator).withFlags(Private | Synthetic)
129127
}
130128

@@ -232,7 +230,7 @@ object DesugarEnums {
232230
* - scaffolding containing the necessary definitions for singleton enum cases
233231
* unless that scaffolding was already generated by a previous call to `nextEnumKind`.
234232
*/
235-
def nextEnumTag(kind: CaseKind.Value)(implicit ctx: Context): (Int, List[Tree]) = {
233+
def nextOrdinal(kind: CaseKind.Value)(implicit ctx: Context): (Int, List[Tree]) = {
236234
val (count, seenKind) = ctx.tree.removeAttachment(EnumCaseCount).getOrElse((0, CaseKind.Class))
237235
val minKind = if (kind < seenKind) kind else seenKind
238236
ctx.tree.pushAttachment(EnumCaseCount, (count + 1, minKind))
@@ -244,14 +242,23 @@ object DesugarEnums {
244242
(count, scaffolding)
245243
}
246244

247-
/** A pair consisting of
248-
* - a method returning the next enum tag
249-
* - scaffolding as defined in `nextEnumTag`
250-
*/
251-
def enumTagMeth(kind: CaseKind.Value)(implicit ctx: Context): (DefDef, List[Tree]) = {
252-
val (tag, scaffolding) = nextEnumTag(kind)
253-
(DefDef(nme.enumTag, Nil, Nil, TypeTree(), Literal(Constant(tag))), scaffolding)
254-
}
245+
def ordinalMeth(body: Tree)(implicit ctx: Context): DefDef =
246+
DefDef(nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body).withFlags(Override)
247+
248+
def nameMeth(body: Tree)(implicit ctx: Context): DefDef =
249+
DefDef(nme.name, Nil, Nil, TypeTree(defn.StringType), body).withFlags(Override)
250+
251+
def toStringMeth(body: Tree)(implicit ctx: Context): DefDef =
252+
DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), body).withFlags(Override)
253+
254+
def ordinalMethLit(ord: Int)(implicit ctx: Context): DefDef =
255+
ordinalMeth(Literal(Constant(ord)))
256+
257+
def nameMethLit(name: String)(implicit ctx: Context): DefDef =
258+
nameMeth(Literal(Constant(name)))
259+
260+
def toStringMethAsName(implicit ctx: Context): DefDef =
261+
toStringMeth(Ident(nme.name))
255262

256263
/** Expand a module definition representing a parameterless enum case */
257264
def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, span: Span)(implicit ctx: Context): Tree = {
@@ -260,11 +267,10 @@ object DesugarEnums {
260267
else if (impl.parents.isEmpty)
261268
expandSimpleEnumCase(name, mods, span)
262269
else {
263-
def toStringMeth =
264-
DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), Literal(Constant(name.toString)))
265-
.withFlags(Override)
266-
val (tagMeth, scaffolding) = enumTagMeth(CaseKind.Object)
267-
val impl1 = cpy.Template(impl)(body = List(tagMeth, toStringMeth) ++ registerCall)
270+
val (tag, scaffolding) = nextOrdinal(CaseKind.Object)
271+
val ordinalDef = ordinalMethLit(tag)
272+
val nameDef = nameMethLit(name.toString)
273+
val impl1 = cpy.Template(impl)(body = List(ordinalDef, nameDef, toStringMethAsName) ++ registerCall)
268274
.withAttachment(ExtendsSingletonMirror, ())
269275
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | Final)
270276
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)
@@ -280,7 +286,7 @@ object DesugarEnums {
280286
expandEnumModule(name, impl, mods, span)
281287
}
282288
else {
283-
val (tag, scaffolding) = nextEnumTag(CaseKind.Simple)
289+
val (tag, scaffolding) = nextOrdinal(CaseKind.Simple)
284290
val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString))))
285291
val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final)
286292
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,6 @@ object StdNames {
417417
val elem: N = "elem"
418418
val emptyValDef: N = "emptyValDef"
419419
val ensureAccessible : N = "ensureAccessible"
420-
val enumTag: N = "enumTag"
421420
val eq: N = "eq"
422421
val eqInstance: N = "eqInstance"
423422
val equalsNumChar : N = "equalsNumChar"
@@ -482,6 +481,7 @@ object StdNames {
482481
val mirror : N = "mirror"
483482
val moduleClass : N = "moduleClass"
484483
val name: N = "name"
484+
val name_ : N = "name_"
485485
val ne: N = "ne"
486486
val newFreeTerm: N = "newFreeTerm"
487487
val newFreeType: N = "newFreeType"

library/src/scala/Enum.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ package scala
44
trait Enum {
55

66
/** A number uniquely identifying a case of an enum */
7-
def enumTag: Int
7+
def ordinal: Int
8+
9+
/** Name of the enum's case */
10+
def name: String
811
}

library/src/scala/runtime/EnumValues.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class EnumValues[E <: Enum] {
77
private[this] var fromNameCache: Map[String, E] = null
88

99
def register(v: E) = {
10-
require(!myMap.contains(v.enumTag))
11-
myMap = myMap.updated(v.enumTag, v)
10+
require(!myMap.contains(v.ordinal))
11+
myMap = myMap.updated(v.ordinal, v)
1212
fromNameCache = null
1313
}
1414

0 commit comments

Comments
 (0)