[NAME] ALL.dao.type.enum [TITLE] Enum or Symbol Type [DESCRIPTION] enum is a type that defines a set of symbols with associated integer values. It can be u sed to represent states and flags. A special type of enum called symbol is also supported to make the use of enum extremely convenient. 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 12 13 Symbol ::= '$' Identifier The only difference between Enum1 (EnumType1) and Enum2 (EnumType2) is the comma and semi colon. When comma(s) are used, the enum symbols are not combinable; but when semicolon(s ) are used, they can be combined as flags. For convenience, the enums with combinable sym bols may be referred to as flag enums, and those with non-combinable symbols as state enu ms. 0.2 State Enum Here is a simple example of state enum defined with C++ like syntax, 1 enum MyEnum 2 { 3 AA , # 0 4 BB = 3, # 3 5 CC # 4 6 } Like in C++, the first symbol will be automatically associated with zero integer, if its value is not specified explicitly, and for other symbols with unspecified values, their v alues will be simply increased by one from the values of their preceding symbols. These symbols are not exposed to the current namespace. So they have to be accessed as fi elds of the enum type, 1 var e = MyEnum::AA # Or: MyEnum.AA; Since MyEnum is a state enum, so the variable e can only take one value (symbol) of MyEnum. 0.3 Symbol Enum For convenience, symbol enums will be introduced before the flag enums. A symbol is compo sed of a dollar sign $ prefix with an ordinary identifier. Such symbols can be used freel y, but it becomes meaningful only when it is associated with a normal enum. For example, 1 enum E1 { AA=1, BB=2 } 2 enum E2 { AA=10, BB=20 } 3 4 var e1: E1 = $AA 5 var e2: E2 = $AA 6 7 io.writeln( e1 ) # Output: $AA(1) 8 io.writeln( e2 ) # Output: $AA(10) Here symbol $AA is assigned to both e1 and e2, and the symbol get interpreted properly ac cording the types of e1 and e2. So what a symbol represents actually depends on what enum type it become associated to. Note a symbol can be associated to any number of compatible enum types. 0.4 Flag Enum The definition of flag enums is almost the same as the definition of state enums, except that semi-colons should be used in place of commas. 1 enum MyEnum 2 { 3 AA ; # 1 4 BB = 3; # 3 5 CC # 6 6 } Besides the syntatical difference of commas and semi-colons, the unspecified values are a lso handled differently. Here the first symbol will be assigned with one, if not specifie d explicitly, and for other symbols with unspecified values, their values will be simply left-shifted by one bit from the values of their preceding symbols. It also worthes notic ing that the symbol values can be specified arbitrarily, so it is up to the users to assi gn meaningful values to them. As combinable enums, their symbols can be comibined freely, so they can be effectively us ed as flags: 1 enum Orientation 2 { 3 East ; 4 West ; 5 South ; 6 North 7 } 8 var orientation = Orientation::East + Orientation::South 9 io.writeln( orientation ) # Output: $East$South(5) 0.5 Enum Type Name Another way to use enum types is to use the enum type names: 1 var s1: enum<AA,BB> = $AA 2 var s2: enum<AA=10,BB=20> = $BB 3 var f1: enum<AA;BB;CC> = $AA + $BB Similarly, state enums and flag enums are distinguished by commas and semi-colons. Such type names are particularly handy for routine parameters. For example, 1 routine MySearch( values: list<int>, direction: enum<forward,backward> ) 2 { 3 ... 4 } 5 var values = { 1, 2, 3 } 6 var result = MySearch( values, $forward ) 0.6 Enum in Switch-Case Enum types can be used effectively the switch-case constructs, which can be optimized to table lookup, if the enums are explicitly typed or can be inferred. For example, 1 enum MyEnum 2 { 3 AA, 4 BB, 5 CC 6 } 7 8 switch( (any)e1 ){ 9 case MyEnum::AA : ... 10 case MyEnum::BB : ... 11 case MyEnum::CC : ... 12 } 13 14 switch( e1 ){ 15 case $AA : ... 16 case $BB : ... 17 case $CC : ... 18 } 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() ). B ut 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 symb ols in the cases are not well typed.