    [NAME]
    ALL.dao.type.enum

    [TITLE]
    Enum or Symbol Type

    [DESCRIPTION]

    enum is a type hybriding C++ enum and Ruby symbol types to offer the advantages of both
    types. It can be used as enumerated constant in C++ or as symbol in Ruby.

     0.1  Definition

       1  EnumEntry ::= Identifier [ = ConstExpr ]
       2
       3  Enum1 ::= 'enum' Identifier '{' EnumEntry { ',' EnumEntry } '}'
       4  Enum2 ::= 'enum' Identifier '{' EnumEntry { ';' EnumEntry } '}'
       5
       6  Enum ::= Enum1 | Enum2
       7
       8  EnumType1 ::= 'enum' '<' EnumEntry { ',' EnumEntry } '>'
       9  EnumType2 ::= 'enum' '<' EnumEntry { ';' EnumEntry } '>'
      10
      11  EnumType ::= EnumType1 | EnumType2

    The only difference between Enum1 and Enum2, EnumType1 and EnumType2 is the comma and
    semicolon. When comma(s) are used, the enum items are not combinable; but when
    semicolon(s) are used, they can be combined as flags.

     0.2  Examples

    Enum types can be declared in the same way as C++ enum:

       1  enum MyEnum
       2  {
       3      AA,
       4      BB,
       5      CC
       6  }

    Then it can be used in the following way:

       1  e1 = MyEnum::BB   # with constant folding;
       2  e2 = MyEnum.BB    # without constant folding;
       3  e3 : MyEnum = $BB # with auto conversion;

    All e1, e2 and e3 will be an enum value with integer value equal to 1 and string symbol
    equal to "BB". The last is equivalent to:

       1  # Use enum type on the fly:
       2  e3 : enum<AA,BB,CC> = $BB

    Enum values can be used in switch-case statements, which can be optimized to table
    lookup, if the enums are explicitly typed or can be inferred. For example,

       1  switch( (any)e1 ){
       2  case MyEnum::AA : ...
       3  case MyEnum::BB : ...
       4  case MyEnum::CC : ...
       5  }
       6
       7  switch( e1 ){
       8  case $AA : ...
       9  case $BB : ...
      10  case $CC : ...
      11  }

    Both will be optimized into table lookup, because the case values have well defined types
    (the cases in the second example have types inferred from the expression in switch() ).
    But not the following example,

       1  switch( (any)e1 ){
       2  case $AA : ...
       3  case $BB : ...
       4  case $CC : ...
       5  }

    because the value type of the expression inside switch() is not well defined, so the
    symbols in the cases are not well typed.

    Enum can be very useful function parameter list. For example, if you want a parameter can
    only accept three different values representing red, green and blue, you can simply use
    color :enum<red,green,blue>!