Enum declaration

Grammar§

EnumDeclaration ::= Attribute* "enum" Identifier ( ":" Type)? "{" (EnumMember ",")* EnumMember ","? "}" | Attribute* "enum" Identifier ( ":" Type)? "=" Expression ";" EnumMember ::= Identifier ( "=" Expression )?

Semantics§

An EnumDeclaration allows to declare constant expressions in a named group.

If the Type is not specified then each member is of type u32. If specified then it must be one of the integer type, bool, TypeAuto, or another enum.

When the Expression used to define the value of a member is not specified then the member value is set to its rank, starting from the last member that was initialized.

enum EnumA: u8
{
    a0,     // 0
    a1,     // 1
    a2 = 8, // 8
    a3      // 9
}

When the Type is another enum it extends it.

enum Foo
{
     a0 = 1,
     a1
}

enum Bar: Foo
{
    a2 // 3
}

function extendedEnum()
{
    Bar bar;
    assert(bar.a0 == 1);
    assert(bar.a1 == 2);
    assert(bar.a2 == 3);
}

When the Type is auto the smaller unsigned integer type allowing to contain the member with the highest value is selected.

enum Bar: auto
{
    member1 = (1 << 16) - 1;
}

function autoEnum()
{
    Bar b;
    assert(echo(is, b, u16));
}

Members implicitly convert to the enumeration type.

const u8 a = EnumA.a0;

Variables typed as enum take the enum .min property as initializer.

enum E { e = 1 }
var E e;
assert(e == 1);

Enumerations are not generated as a whole by the backend. Their members, however, when used in other expressions, are replaced by the rvalue they represent.

In several contexts, the members can be used without using the declaration name. Supported contexts are

unit enum_name_inference;

enum E { e1, e2 }

alias ESet = bool[E];

function testParam(E p){}

function main(): s32
{
    // decl type -> init
    var ESet es = [e1];
    var E e = e1;
    // set type -> subscript
    assert(es[e1]);

    // binary left -> binary right
    const auto n = E.e1 + e2;
    e   = e2;
    e   &= e1;
    es  += e1;

    // straight call, fd is available early -> passed argument
    testParam(e2);

    // switch condition -> on match expression
    switch e do
    {
        on e1 do {}
        on e2 do {}
    }

    // foreach var type -> foreach aggregate exp
    foreach (const E el) in e1 .. e2 do {}

    return 0;
}

Normal IdentExpression resolution rules are not affected. The parent enum is only tried as last resort.

If the enum contains a single member then a shorthand syntax is available.

enum Enum : u8
{
    Enum = 8;
}

is equivalent to

enum Enum : u8 = 8:

and the single member value is obtained using the enum identifier.

enum MAX_PATH = 255;
assert(MAX_PATH + 1 == 256);