[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  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  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  values = { 1, 2, 3 }
   6  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.