Enumeration types
Enumeration types define a new type whose values consist of the ones specified. The values are ordered. Example:
type
Direction = enum
north, east, south, west
Now the following holds:
ord(north) == 0
ord(east) == 1
ord(south) == 2
ord(west) == 3
# Also allowed:
ord(Direction.west) == 3
The implied order is: north < east < south < west. The comparison operators can be used with enumeration types. Instead of north etc., the enum value can also be qualified with the enum type that it resides in, Direction.north.
For better interfacing to other programming languages, the fields of enum types can be assigned an explicit ordinal value. However, the ordinal values have to be in ascending order. A field whose ordinal value is not explicitly given is assigned the value of the previous field + 1.
An explicit ordered enum can have holes:
type
TokenType = enum
a = 2, b = 4, c = 89 # holes are valid
However, it is then not ordinal anymore, so it is impossible to use these enums as an index type for arrays. The procedures inc, dec, succ and pred are not available for them either.
The compiler supports the built-in stringify operator $ for enumerations. The stringify’s result can be controlled by explicitly giving the string values to use:
type
MyEnum = enum
valueA = (0, "my value A"),
valueB = "value B",
valueC = 2,
valueD = (3, "abc")
As can be seen from the example, it is possible to both specify a field’s ordinal value and its string value by using a tuple. It is also possible to only specify one of them.
An enum can be marked with the pure pragma so that its fields are added to a special module-specific hidden scope that is only queried as the last attempt. Only non-ambiguous symbols are added to this scope. But one can always access these via type qualification written as MyEnum.value:
type
MyEnum {.pure.} = enum
valueA, valueB, valueC, valueD, amb
OtherEnum {.pure.} = enum
valueX, valueY, valueZ, amb
echo valueA # MyEnum.valueA
echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb
echo MyEnum.amb # OK.
Enum value names are overloadable, much like routines. If both of the enums T and U have a member named foo, then the identifier foo corresponds to a choice between T.foo and U.foo. During overload resolution, the correct type of foo is decided from the context. If the type of foo is ambiguous, a static error will be produced.
type
E1 = enum
value1,
value2
E2 = enum
value1,
value2 = 4
const
Lookuptable = [
E1.value1: "1",
# no need to qualify value2, known to be E1.value2
value2: "2"
]
proc p(e: E1) =
# disambiguation in 'case' statements:
case e
of value1: echo "A"
of value2: echo "B"
p value2
In some cases, ambiguity of enums is resolved depending on the relation between the current scope and the scope the enums were defined in.
# a.nim
type Foo* = enum abc
# b.nim
import a
type Bar = enum abc
echo abc is Bar # true
block:
type Baz = enum abc
echo abc is Baz # true
To implement bit fields with enums see Bit fields.