fpp/docs/users-guide/Defining-Enums.adoc
2025-10-29 09:06:44 -07:00

201 lines
5.3 KiB
Plaintext

== Defining Enums
An FPP model may contain one or more *enum definitions*.
Enum is short for enumeration.
An FPP enum is similar to an enum in C or {cpp}.
It defines a named type called an *enum type* and a set of named constants
called *enumerated constants*.
The enumerated constants are the values associated with the type.
An enum definition may appear at the top level or inside a
<<Defining-Modules,module definition>>.
An enum definition is an
<<Writing-Comments-and-Annotations_Annotations,annotatable element>>.
=== Writing an Enum Definition
Here is an example:
[source,fpp]
----
enum Decision {
YES
NO
MAYBE
}
----
This code defines an enum type `Decision` with three
enumerated constants: `YES`, `NO`, and `MAYBE`.
In general, to write an enum definition, you write the following:
* The keyword `enum`.
* The name of the enum.
* A sequence of enumerated constants enclosed in curly braces `{` ... `}`.
The enumerated constants form an
<<Defining-Constants_Multiple-Definitions-and-Element-Sequences,element
sequence>>
in which the optional terminating punctuation is a comma.
For example, this definition is equivalent to the one above:
[source,fpp]
----
enum Decision { YES, NO, MAYBE }
----
There must be at least one enumerated constant.
=== Using an Enum Definition
Once you have defined an enum, you can use the enum as a type and the
enumerated constants as constants of that type.
The name of each enumerated constant is qualified by the enum name.
Here is an example:
[source,fpp]
----
enum State { ON, OFF }
constant initialState = State.OFF
----
The constant `s` has type `State` and value `State.ON`.
Here is another example:
[source,fpp]
----
enum Decision { YES, NO, MAYBE }
array Decisions = [3] Decision default Decision.MAYBE
----
Here we have used the enum type as the type of the array member,
and we have used the value `Decision.MAYBE` as the default
value of an array member.
=== Numeric Values
As in C and {cpp}, each enumerated constant has an associated
numeric value.
By default, the values start at zero and go up by one.
For example, in the enum `Decision` defined above,
`YES` has value 0, `NO` has value 1, and `MAYBE` has value 2.
You can optionally assign explicit values to the enumerated
constants.
To do this, you write an equals sign and an expression after
each of the constant definitions.
Here is an example:
[source,fpp]
----
enum E { A = 1, B = 2, C = 3 }
----
This definition creates an enum type `E` with three enumerated constants `E.A`,
`E.B`, and `E.C`. The constants have 1, 2, and 3 as their associated numeric
values.
If you provide an explicit numeric value for any of the enumerated constants,
then you must do so for all of them.
For example, this code is not allowed:
[source,fpp]
--------
# Error: cannot provide a value for just one enumerated constant
enum E { A = 1, B, C }
--------
Further, the values must be distinct.
For example, this code is not allowed, because
the enumerated constants `A` and `B` both have the value 2:
[source,fpp]
--------
# Error: enumerated constant values must be distinct
enum E { A = 2, B = 1 + 1 }
--------
You may convert an enumerated constant to its associated numeric value.
For example, this code is allowed:
[source,fpp]
----
enum E { A = 5 }
constant c = E.A + 1
----
The constant `c` has the value 6.
However, you may not convert a numeric value to an enumerated constant.
This is for type safety reasons: a value of enumeration type should have
one of the numeric values specified in the type.
Assigning an arbitrary number to an enum type would violate this rule.
For example, this code is not allowed:
[source,fpp]
--------
enum E { A, B, C }
# Error: cannot assign integer 10 to type E
array A = [3] E default 10
--------
=== The Representation Type
Each enum definition has an associated *representation type*.
This is the primitive integer type used to represent the numeric
values associated with the enumerated constants when generating code.
If you don't specify a representation type, then the default
type is `I32`.
For example, in the enumerations defined in the previous sections,
the representation type is `I32`.
To specify an explicit representation type, you write it after
the enum name, separated from the name by a colon, like this:
[source,fpp]
----
enum Small : U8 { A, B, C }
----
This code defines an enum `Small` with three enumerated constants
`Small.A`, `Small.B`, and `Small.C`.
Each of the enumerated constants is represented as a `U8` value
in {cpp}.
=== The Default Value
Every type in FPP has an associated default value.
For enum types, if you don't specify a default value explicitly,
then the default value is the first enumerated constant
in the definition.
For example, given this definition
[source,fpp]
----
enum Decision { YES, NO, MAYBE }
----
the default value for the type `Decision` is `Decision.YES`.
That may be too permissive, say if `Decision` represents
a decision on a bank loan.
Perhaps the default value should be `Decision.MAYBE`.
To specify an explicit default value, write the keyword `default`
and the enumerated constant after the enumerated constant
definitions, like this:
[source,fpp]
----
enum Decision { YES, NO, MAYBE } default MAYBE
----
Notice that when using the constant `MAYBE` as a default value, we
don't need to qualify it with the enum name, because the
use appears inside the enum where it is defined.