[NAME]
ALL.dao.tutorial.types

[TITLE]
Essential Types

[DESCRIPTION]

Dao supports a number of essential types as built-in types to allow flexible use of 
them. These types include several number types, enum symbol, string, numeric array, list
and map etc.

 0.1   Numbers  

Dao has native supports for the following number types: int, float, double, complex and 
long.

Integer and floating point numbers can be expressed in the same ways as in most other
languages. Floating point numbers in Dao are parsed as double precision floating point
numbers double by default. To explicitly express a single (double) precision floating 
point number float ( double), it is necessary to append a suffix F ( D) to a normally 
expressed number.

The imaginary part of a complex number can be expressed as an int or float number with a
C suffix. A general complex number can be expressed by combining an integer or a 
floating point number as the real part and an imginary part, which are both stored as
double precision floating point numbers.

long type represents arbitrary precision integers. They can be expressed as an int 
number with a L or a Lx suffix, where x is an integer between 2 and 16 (inclusive), 
representing the base of the number (used for parsing and printing only).

Examples,
     
   1  I1 = 123
   2  I2 = 0xabc
   3  
   4  F1 = 456.7F
   5  F2 = 123e4F
   6  
   7  D1 = 123D
   8  D2 = 456.7
   9  D2 = 456.7D
  10  D3 = 123E4
  11  D3 = 123E4D
  12  
  13  C1 = 123C
  14  C2 = 456.6C
  15  
  16  L1 = 123456789L
  17  L2 = 10001001110L2
  18  L3 = 0x123abc456L16
     


These types support most of the common operators that are meaningful for them. For
example, all the basic arithmetic operators such as: + (addition, unary plus), - 
(subtraction, unary minus), * (multiplication), / (division), % (modulo) and ** (power) 
are supported.
     
   1  I1 = 123 + 456
   2  I2 = 789 % 123
   3  F1 = 123.5 ** 3
   4  D1 = 789.5D / 123
   5  L1 = 123456789L ** 123L
     

Please see dao.type.int, dao.type.float, dao.type.double, dao.type.complex and dao.type.long
for more information.

 0.2   Enum Symbols  

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.

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 into 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 inside switch()
).

 0.3   Strings  

In Dao, a string can be expressed as a sequence of characters enclosed by a pair of
single qutotation marks or a pair of double quotation marks. The characters placed
between the quotation marks must be formated according some rules (such as escaping
quotation marks and other special characters and using numeric encodings of characters
etc.). Please see dao.type.string for more information. 
     
   1  mbs = 'str'
   2  wcs = "道语言"
   3  mbs2 = 'It\'s green'
   4  wcs2 = "\u9053\u8bed\u8a00" # the same as wcs: "道语言";
     


To use strings as it is written without special treatment of the characters, they can be
expressed as verbatim string, which are quoted with a pair of identical compound marks 
in the forms of @[] and @@[]. Any number of letters, digits, underscores, blank spaces, 
dots, colons, dashes and assignment marks can be placed in between the squared brackets
to make sure the marks will not appear inside the string. The difference between using 
@[] and @@[] is the same as the difference between using single quotation marks and 
double quotation marks. Please see dao.type.string for more information. 
     
   1  # C++ codes in MBS:
   2  cpp =
   3  @[cpp x]
   4  class AA
   5  {
   6  	int index;
   7  };
   8  struct BB{};
   9  @[cpp x]
  10  
  11  
  12  # Lua codes in WCS:
  13  lua =
  14  @@[lua]
  15  local a = 1;
  16  function Test()
  17  	io.write( 'Hello' )
  18  end
  19  @@[lua]
     

The content of a string can be accessed or altered using sub-indexing or slicing:
     
   1  str = 'ABCDEFGHIJK';
   2  
   3  io.writeln( str[1] )    # the second character;
   4  io.writeln( str[:4] )   # the substring from the start to the 4th character;
   5  io.writeln(  str[6:] )  # the substring from the 6th character to the end;
   6  io.writeln(  str[3:8] ) # the substring from the 3rd to the 8th character;
   7  
   8  # Set single character:
   9  str[1] = 'X';
  10  str[1] = 'X'[0];
  11  
  12  # Set a substring:
  13  str[2:5] = '1234'   # str = 'AB1234GHIJK'
  14  str[2:5] = '123456' # str = 'AB123456GHIJK'
  15  str[2:5] = '12'     # str = 'AB12GHIJK'
  16  
  17  # Using negative index:
  18  io.writeln( str[-1] )    # the last character;
  19  io.writeln( str[-2] )    # the second last character;
  20  io.writeln( str[-2:] )   # the last two characters;
     

String can be concaternated using + or +=, 
     
   1  str = 'ABCDEFGHIJK';
   2  
   3  str2 = str + '123'  # str2 = ABCDEFGHIJK123
   4  
   5  # Append a string:
   6  str += '123' # str = ABCDEFGHIJK123
   7  
   8  # Append a character:
   9  str += 88    # str = ABCDEFGHIJK123X
     


 0.4   Arrays  

Dao has built-in support for multi-dimensional numeric arrays. Such arrays can be defined
by using the squared brackets [] or array{}. Using such constructs, one can either 
enumerate all the elements as a vector/matrix, or specify an arithmetic progression with
a start value, a step value and the number of steps. If the step value is omitted, it
will be assumed to be zero.
     
   1  vec1 = [1, 2, 3]  # array<int> vector, or 1x3 matrix;
   2  vec2 = [1.0; 2; 3]  # array<float> 3x1 matrix, or transposed vector;
   3  mat1 = [1D, 2; 3, 4]  # array<double> 2x2 matrix;
   4  mat2 = [ [1, 2], [3, 4] ]  # 2x2 matrix
   5  mat3 = [ [1, 2, 3] : 5 ]   # 5x3 matrix;
   6  mat4 = array{ 1, 2; 3, 4 }  # 2x2 matrix
     

Like string, array support sub-indexing, slicing and negative indices:
     
   1  mat = [ 1, 2, 3; 4, 5, 6; 7, 8, 9 ];  # 3x3 matrix;
   2  
   3  rowvec = mat[1,:]  # the second row;
   4  colvec = mat[:,1]  # the second column;
   5  
   6  submat1 = mat[:1,:]  # the first two rows;
   7  submat2 = mat[:,1:]  # the last two columns;
   8  submat3 = mat[:1,1:] # intersection between the first two rows and the last two columns;
   9  
  10  mat[0,:]  = [11, 22, 33]  # set the first row to [11, 22, 33];
  11  mat[:,1] += [11, 22, 33]  # add [11, 22, 33] to the second column;
  12  mat[:,1] += 100           # add 100 to the second column;
  13  
  14  mat[:1,1:] += [10, 20; 30, 40]  # add [10, 20; 30, 40] to sub-matrix of mat;
     

Please see dao.type.array for more information.

 0.5   Lists  

List can be created in similar ways as array, by enumerating elements or specifying an
arithmetic progression, but using {} or list{} instead of [] or array{}.
     
   1  list1 = { 1, 2, 3 }    # list<int>
   2  list2 = { 1.0, 2, 3 }  # list<float>
   3  list3 = { 1 : 2 : 5 }  # list<int>
   4  
   5  list4 = { 'abc', 'def' }  # list<string>
   6  list5 = { 123, 'abc' }    # list<any>
   7  
   8  list6 = list{ 'a' : 3 }    # { 'a', 'a', 'a' }
   9  list7 = { 'a' : 'b' : 3 }  # { 'a', 'ab', 'abb' }
     

List also supports sub-indexing, slicing and negative indices:
     
   1  alist = { 0, 1, 2, 3, 4, 5 }
   2  
   3  item = alist[1]
   4  item = alist[-2]
   5  
   6  sublist = alist[2:4]
   7  
   8  alist[3]  = 10
   9  alist[4] += 10
     


 0.6   Maps and Hash Maps  

A map or hash map organizes a set of key/value pairs into a structure for efficient
lookup. The keys in a map are ordered, while the keys in a hash map are unordered. A map
can be created using {key=>value...} or map{key=>value...}. Replacing the => with colon 
-> will create hash maps. Map and hash map can be used in identical ways. 
     
   1  amap  = { 'abc' => 123, 'def' => 456 }
   2  ahash = { 'abc' -> 123, 'def' -> 456 }
   3  
   4  amap  = map{ 'abc' => 123, 'def' => 456 }
   5  ahash = map{ 'abc' -> 123, 'def' -> 456 }
     

Sub-scripting and slicing are also supported for map to access value(s) through key(s).
     
   1  amap = { 'abc' => 123, 'def' => 456, 'ghi' => 789 }
   2  
   3  value  = amap[ 'abc' ];
   4  submap = amap[ 'abc' : 'def' ];
     


 0.7   Tuples  

Tuple is a very handy type, which can be used to hold a fixed number of items, with type
information recorded for each of them. In a tuple, each item can have a name, which can 
be used to access the item as field. They can be created in similar ways as creating
lists and maps, but use () instead. 
     
   1  tup1 = ( 123, 'abc' )               # tuple with unnamed items;
   2  tup2 = ( index => 123, 'abc' )      # the first item is named as "index";
   3  tup3 = tuple{ 123, name => 'abc' }  # the second item is named as "name";
     

Each item of a tuple can be accessed using its index or field (item name). New tuples can
be created from other tuples by slicing.
     
   1  tup = ( index => 123, 'abc', [1,2,3] )
   2  
   3  id = tup[0]
   4  id = tup.index
   5  tup.index = 456
   6  
   7  tup2 = tup[:1]  # ( index => 123, 'abc' )