load help; ############################################################ #### Installation ############################################################ @[name] misc.installation @[name] @[title] Dao Installation @[title] @[text] @[subsection] Compiling and Building @[subsection] The recommended way to compile Dao is to run the following from the shell: @[code] $ make -f Makefile.daomake PLATFORM @[code] where PLATFORM can be one of the followings: @[list] -- linux -- macosx -- freebsd -- mingw -- minix -- haiku @[list] Dao uses DaoMake, which is a make tool based on Dao (see @[node]tool.standard.daomake@[node]), as the default building system. Running the above make command will make a bootstrap build of DaoMake, and then use the bootstrapped DaoMake to configure a full build of Dao and its modules and tools and generate appropriate make files for building and installation. @[subsection] Customized Building @[subsection] Build mode (release, debug or profile) and installation directory can be set by: @[code] $ make -f Makefile.daomake PLATFORM MODE=debug INSTALL=directory @[code] Out of source building can be done by executing the following from the build directory: @[code] $ make -f DAO-DIR/Makefile.daomake PLATFORM SRCDIR=DAO-DIR @[code] Please read Makefile.daomake for more options such as making static build and compiling to JavaScript etc. @[subsection] Installation @[subsection] Simply run the following to install, @[code] $ make install @[code] @[text] @[name] misc.changelog @[name] @[title] Dao Change Logs @[title] @[text] @[subsection]2013-11-26@[subsection] @[list] --@[red]CHANGED:@[red] Implementation of @[code]frame(){}@[code] from syntax construct to built-in method; --@[red]REMOVED:@[red] Support for the assertion @[code]??@[code] operator, use @[code]frame(){}@[code] instead. @[list] @[subsection]2013-11-23@[subsection] @[list] --@[red]CHANGED:@[red] Syntax for calling code section methods and syntax for data packing (function partial application, uniform initialization etc.) are @[red]swapped@[red]. Namely, there is no need for @[code]::@[code] before @[code]{@[code] for code sections, and it is required for data packing. For example, @[code] type MyTuple = tuple tup = MyTuple::{ 123, 'abc' } fut = mt::start { rand() } # no :: @[code] --@[red]CHANGED:@[red] Syntax for decorator declaration is improved to avoid implicit declaration of the variable for function parameters. Previously the variable @[code]__args__@[code] is automatically declared, now users can declare it to be any name by placing it in a pair of brackets right after the parameter name of the first parameter. @[code] routine @Decorator( func(args) : routine ) { io.writeln( 'Calling function:', std.about(func) ); return func( args, ... ); # ... for parameter expanding; } @[code] --@[red]REMOVED:@[red] Support for the @[code]:=@[code] operator. @[list] @[text] ############################################################ #### Comparisons ############################################################ @[name] misc.comparison @[name] @[title] Comparisons between Dao and Other Languages @[title] @[text] @[text] @[name] misc.comparison.typing @[name] @[title] Optional VS Duck Typing (Python) @[title] @[text] @[subsection] Type Checking @[subsection] Duck typing offers much flexibility in programming, but it lacks of compiling time type safety checking. As a result, even obvious type errors cannot be detected at compiling time by an interpreter or compiler for a duck typing language. This problem can be well illustrated by the following example in Python, @[code] def SomeFunction(a, b): return a * b SomeFunction( 'abc', 'def' ) # Running time error! @[code] Since not all the execution paths can be covered by testing, some bugs caused by such simple typing errors may go undetected. But such error can be easily detected with type inference and function specialization in an optional typing language such as Dao. For example, the following will raise a compiling error for the second function call, @[code] routine SomeFunction( a, b ) { return a * b } SomeFunction( 123, 456 ) # No error. SomeFunction( 'abc', 'def' ) # Compiling time error! @[code] In this example, even though the parameter types of @[green]SomeFunction()@[green] are not explicitly specified, but at its call sites, the types of the arguments for the calls can be inferred. Using these type information, Dao interpreter will specialize @[green]SomeFunction()@[green] into two functions, one for @[green]int@[green] and @[green]int@[green] parameters, the other for @[green]string@[green] and @[green]string@[green] parameters. The first call is valid because the specialized function will do integer-integer multiplication. But the second call is not, because it attempts to do string-string multiplication, which is not a valid operation. Because such function specialization and type checking is done at compiling time, such errors can be easily detected at compiling time. @[subsection] Explicit Typing @[subsection] Another problem with duck typing is that explicit types cannot be specified to make codes clearer and more readable. For example, in Python, without looking into the documentations for a function, or the implementation of the function, it may be very difficult to guess what are the correct parameter types for the function. But in Dao with optional typing, one can write a function in the following way, @[code] routine SomeFunction( a: float, b: float ) { return a * b } @[code] This will make it clear that this function will accept two floats as parameters. Such explicit parameter type specification is also very helpful in creating bindings for C/C++ functions, because this will guarantee that the parameters passed to the functions are of the expected types, so it can save a lot of boilerplate codes for type checking (and conversion in some cases). @[text] @[name] misc.comparison.enumsym @[name] @[title] Enum Symbols (C++,Ruby) @[title] @[text] Dao supports a data type that is roughly a combination of C++ enum and Ruby symbol types. Like in C++, enum symbol in Dao can be declared in the following way, @[code] enum Boolean { False, True } @[code] And zero will be associated with @[green]False@[green] and one will be associated with @[green]True@[green]. But unlike in C++, this will not add integer constants named @[green]False@[green] and @[green]True@[green] to the current namespace, so they have to be accessed in the following way, @[code] bl1 = Boolean::False bl2 = Boolean::True @[code] However, the more convenient way to use this type is to use them as symbols. A symbol is an identifier prefixed with a dollar symbol. A symbol is a like a "polymorphic" enum: it can be used freely without being fixed to a particular enum type, but its actually value will depend on the type of the variable that holds it. For example, @[code] enum EnumRF{ Real, False } A = $False B: Boolean = $False C: EnumRF = $False @[code] Here @[green]A@[green] will hold a free symbol @[green]$False@[green] with value @[green]zero@[green]. And @[green]B@[green] will hold a symbol @[green]$False@[green] of type @[green]Boolean@[green] with value @[green]zero@[green]. And @[green]C@[green] will hold a symbol @[green]$False@[green] of type @[green]EnumRF@[green] with value @[green]one@[green]. The main difference between Dao enum symbol and C++ enum and Ruby symbol is this polymophic behavior of Dao enum symbol. @[text] @[name] misc.comparison.codesect @[name] @[title] Code Block Method (Ruby) @[title] @[text] Ruby supports a special type of functions called @[green]code block method@[green], which can accept a block of codes as an additional and implicit parameter. Dao also supports such method in a similar way, and such method is often called @[green]code section method@[green] in Dao, that's because there is a significant difference between the implementation of such methods in Dao and in Ruby. In Ruby, the code block attached to a call is compiled and passed to the call as a closure. But in Dao, the code block is compile as a part (section) of the host (caller) function, and is not passed to the call. Instead, the call will locate the right code section in the caller and execute that section when necessary. There are advantages and disadvantages of both implementation, but the implementation as code sections should be more efficient. The following examples should demonstrate some syntactic differences. @[code] # Ruby def CodeBlock puts 'Starting CodeBlock' yield 123 puts 'Ending CodeBlock' end CodeBlock { |x| puts "#{x}" } @[code] @[code] # Dao routine CodeBlock() [ int ] # parameter type for the block; { io.writeln( 'Starting CodeBlock' ) yield( 123 ) io.writeln( 'Ending CodeBlock' ) } CodeBlock { [x] io.writeln( x ) } @[code] Note: code section method is not really inspired by Ruby, but it was evolved from the previous functional method in Dao. Only the syntax was eventually settled down and converged to something similar to Ruby code block method, whose syntax seems quite appropriate for such feature. @[text] @[name] misc.comparison.decorator @[name] @[title] Function Decorator (Python) @[title] @[text] Decorators are a special type of functions that can be used to enhance the functionalities of other functions by decorating them. @[subsection] Decorators for Single Functions @[subsection] In Python, a decorator is just a callable that can take a function as an input argument and return a replacement function as output. For example, @[code] def Decorator( func ): def newfunc(): ret = func() return ret + 123 return newfunc def Foo(): return 456 deco = Decorator( Foo ) deco() @[code] Dao decorators are quite different from Python decorators. Dao decorators do not return replacement functions, instead, they are defined as the templates from which the replacement functions can be created. Such replacement functions may or may not call the original function, this is the same as Python decorators, but Dao decorators are typed and can be strictly typed. So all the static type checking that can be applied to normal functions can also be applied to decorators as well. An equivalent Dao decorator for the above Python example is, @[code] routine @Decorator( func(args): routine< =>int > ) { ret = func( args, ... ) # call the original function; return ret + 123 } routine Foo() { return 456 } deco = @Decorator( Foo ) deco() @[code] Where the parameter type @[green]routine< =>int >@[green] of @[green]@Decorator()@[green] indicates that this decorator can only be applied to functions that can take no parameter and return an integer. @[green]args@[green] is a specially defined variable of tuple type to hold the parameters that will be passed to the decorated function. The @[green]...@[green] in the end of the argument list indicates that the call must expand the previous tuple argument in the argument list, namely, removing the tuple and placing its items in the argument list. In both Python and Dao, decorators can be applied at function definition sites in the same way. @[subsection] Decorators for Any Functions @[subsection] If one wants to define a decorator that can be applied to any functions. In Python, one might do, @[code] def Decorator( func ): def newfunc( *args, **kwargs ): print "Calling with: %s, %s" % (args, kwargs) return func( *args, **kwargs ) return newfunc def Foo( a ): return a + 456 deco = Decorator( Foo ) deco( 123 ) @[code] The equivalent in Dao would be, @[code] routine @Decorator( func(args): routine ) { io.writeln( 'Calling with:', args, ... ) return func( args, ... ) # call the original function; } routine Foo( a ) { return a + 456 } deco = @Decorator( Foo ) deco( 123 ) @[code] @[subsection] Overloaded Decorators @[subsection] If one wants to write a decorator for multiple type of functions, in Python one would have to create decorators as in the above Python examples and check the argument types to handle different types of functions. Because Python does not support function overloading. In Dao, one could simply create different decorators for different target functions, and overload them with the same name. For example, @[code] routine @Decorator( func(args): routineint> ) { return func( args, ... ) + 123 } routine @Decorator( func(args): routinestring> ) { return func( args, ... ) + 'abc' } @Decorator # the first decorator will be applied; routine Foo( a: int ) { return a * 100 } @Decorator # the second decorator will be applied; routine Foo( a: string ) { return a + '##'; } f = @Decorator( Foo ) f( 123 ) f( 'xyz' ) @[code] When the target function is also overloaded, the decorator will be applied to each of the overloaded functions, and create a new (and possible also overloaded as well) function. @[text] @[name] misc.comparison.overloading @[name] @[title] Operator Overloading (Python) @[title] @[text] This help entry will demonstrate a few examples to compare Dao and Python in operator overloading for field accessing, subindexing and binary operator etc. @[subsection] Field Getter and Setter @[subsection] @[code] # Python class Something: def __init__(self): self.thing = {} def __getattr__(self, name): if name == "something": return self.thing return None def __setattr__(self, name, value): if name == "something": self.thing = value; @[code] @[code] # Dao class Something { var thing = {} routine .something() { return thing } routine .something=( value ){ thing = value; } } @[code] Or alternatively in Dao, @[code] # Dao class Something { var thing = {} routine .( name : string ) { if( name == "something" ) return thing return none; } routine .=( name : string, value ){ if( name == "something" ) thing = value; } } @[code] @[subsection] Item Getter and Setter @[subsection] @[code] # Python class UserDict: def __init__(self): self.data = {} def __getitem__(self, key): return self.data[key] def __setitem__(self, key, item): self.data[key] = item @[code] @[code] # Dao class UserDict { var data = {=>} routine []( key ){ return data[key] } routine []=( item, key ){ data[key] = item } } @[code] Please note that in @[green]routine[]=@[green], @[green]item@[green] is the first parameter. It is arranged in this way to naturally support multiple keys/indices. For example, for a multidimensional array, one may define, @[code] class UserMatrix { var data = [] routine UserArray( N: int, M: int ){ data = array(N,M){ [index] index } } routine []( index1, index2 ){ return data[ index1, index2 ] } routine []=( item, index1, index2 ){ data[ index1, index2 ] = item } } @[code] @[subsection] Arithmetic Operators @[subsection] @[code] # Python class MyNumber: def __init__(self, value): self.value = value def __add__(self, other): return MyNumber( self.value + other.value ) @[code] @[code] # Dao class MyNumber { var value = 0 routine MyNumber( value = 0 ) { self.value = value } routine +( other: MyNumber ) { return MyNumber( value + other.value ) } } @[code] @[text] @[name] misc.comparison.tasklet @[name] @[title] Concurrency Tasklet (Go) @[title] @[text] In Go, lightweight threads or tasklets can be created by starting goroutines: @[code] func Sum( ch chan int ){ sum = 0 for index := 0; index < 100; index++ { sum += index } ch <- sum } ch := make(chan int, 1) go Sum( ch ) # Start goroutine; sum = <-ch # Wait for the result; @[code] In Dao, they can be created by using Asynchronous Function Calls: @[code] routine Sum(){ sum = 0 for( index = 0; index < 100; ++index ){ sum += index } return sum } fut = Sum() !! # Asynchronous Function Call (returns a future value); sum = fut.value() # Wait for the result; @[code] There are other ways to create tasklet in Dao, please see @[node]dao.concurrent@[node] for details. @[text] @[name] misc.comparison.channel @[name] @[title] Communication Channel (Go) @[title] @[text] The main differences between Go channel and Dao channel are: @[list] -- Go has syntax support for channels; But Dao doesn't; -- Dao channel has builtin support for timeout for both sending and receiving; But Go channel doesn't; -- Data receive from Dao channel has an additional attribute to indicate whether the channel has been closed; But Go channel doesn't support this; @[list] @[code] # Go package main const N = 1000000; var c1 = make(chan int, 1) var c2 = make(chan int, 1) func Producer( ch chan int ){ for index := 0; index < N; index++ { if index % 100000 == 0 { println( "sending", index ) } ch <- index } c1 <- 1 } func Consumer( ch chan int ){ println( "Consumer" ) for index := 0; index < N; index++ { var data = <-ch if int(data) % 100000 == 0 { println( "received", data ) } } c2 <- 1 } func main() { ch := make(chan int, 1) go Producer( ch ) go Consumer( ch ) <-c1 <-c2 } @[code] @[code] # Dao const N = 1000000 routine Producer( chan: mt::channel ) { index = 0; while( ++index <= N ){ if( index % 10000 == 0 ) io.writeln( "sending", index ) chan.send( index ) # Or chan.send( index, 1.5 ) for a 1.5 second timeout; } chan.cap(0) # set channel buffer size to zero to close the channel; } routine Consumer( chan: mt::channel ) { while(1){ data = chan.receive() # Or chan.receive( 1.5 ) for a 1.5 second timeout; if( (int)data.data % 10000 == 0 ) io.writeln( "received", data ); if( data.status == $finished ) break } } routine main() { chan = mt::channel(1) Producer( chan ) !! Consumer( chan ) !! # Tasklets are automatically joined at the end of the program; } @[code] @[text] @[name] misc.comparison.binding @[name] @[title] C/C++ Function Binding (Python, Lua) @[title] @[text] The followings are simple examples to demostrate the differences in building C/C++ function bindings for Python, Lua and Dao. The main advantage of Dao for interfacing C/C++ functions is that, the C/C++ functions can be registered with Dao function signatures, so that Dao can guarantee that only parameters with correct types can be passed to the functions. This can save much boilerplate code and overheads for parameter type checking and conversion, as well as codes for error handling for incorrect parameters. @[subsubsection] Python @[subsubsection] @[code(cxx)] #include /* Function to be called from Python */ static PyObject* py_MySum(PyObject* self, PyObject* args) { double x, y; PyArg_ParseTuple( args, "dd", &x, &y ); return Py_BuildValue( "d", x + y ); } /* Bind Python function names to C function(s) */ static PyMethodDef MyModule_Methods[] = { { "MySum", py_MySum, METH_VARARGS }, { NULL, NULL } }; /* Module entry function: */ void initMyModule() { (void) Py_InitModule("MyModule", MyModule_Methods); } @[code(cxx)] @[subsubsection] Lua @[subsubsection] @[code(cxx)] #define LUA_LIB #include "lua.h" #include "lauxlib.h" static int lua_MySum(lua_State *L) { double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); lua_pushnumber( L, x + y ); return 1; } static const luaL_reg myfuncs[] = { { "MySum", lua_MySum }, { NULL, NULL } }; /* Module entry function: */ LUALIB_API int luaopen_MyModule( lua_State *L ) { luaL_register( L, "MyModule", myfuncs ); return 1; } @[code(cxx)] @[subsubsection] Dao @[subsubsection] @[code(cxx)] #include "dao.h" #include "daoValue.h" static void dao_MySum( DaoProcess *proc, DaoValue *pars[], int npar ) { /* // No need to check parameter types here, they are guaranteed to be // two doubles when this function is registered as: // MySum( x: float, y: float ) => float // // So the parameter values can be retrieved directly if "daoValue.h" // has been included, otherwise, one may use "DaoValue_TryGetFloat()". */ double x = pars[0]->xFloat.value; double y = pars[1]->xFloat.value; DaoProcess_PutFloat( proc, x + y ); } static const DaoFuncItem myfuncs[] = { /* A function signature must be provided for each function: */ { dao_MySum, "MySum( x: float, y: float ) => float" }, { NULL, NULL } }; /* Module entry function: */ DAO_DLL int DaoMyModule_OnLoad( DaoVmSpace *vmSpace, DaoNamespace *ns ) { DaoNamespace_WrapFunctions( ns, myfuncs ); return 0; } @[code(cxx)] @[text] #{ In Python, @[code] from MyModule import * print "Result from MySum(2.0, 3.0):", MySum(2.0, 3.0) @[code] #} ############################################################ #### Benchmarking ############################################################ @[name] misc.benchmarks @[name] @[title] Benchmarks @[title] ##Program ## Argument ## Dao ## Dao+JIT ## Speedup ## ## Lua ## Python ## Go ## C ##nbody && 10000000 && 41.2 && 12.1 && 3.4X && && 103.9 && 279.8 && 2.6 && 1.8 ##fannkuch && 11 && 57.4 && 16.5 && 3.6X && && 151.4 && 284.0 && 4.4 && 2.9 ##mandelbrot && 4000 && 25.9 && 4.3 && 6.0X && && 63.7 && 137.2 && 1.3* && 2.3 ##spectral-norm && 3000 && 21.7 && 2.1 && 10.2X && && 78.2 && 305.7 && 1.5* && 1.9 ##binary-trees && 16 && 55.9 && 57.7 && 1.0X && && 21.2 && 20.1 && 4.5 && 4.7 @[text] Here are some random benchmarks which shouldn't be taken too seriously. They are presented to give developers some rough idea what one can expect from Dao regarding its efficiency. @[red]These benchmarks by no means indicate the performance of these languages in real applications.@[red] Some of the benchmarks are taken from the @[link]The Computer Language Benchmarks Game@@http://benchmarksgame.alioth.debian.org@[link]. All the tested benchmarks are available here @[link]benchmarks@@/projects/DaoBenchmarks/dir?ci=tip@[link]; The following languages are chosen for comparison, @[table] ##Language ##Version/Compiler ##Dao &&2.0-beta2 ##Lua &&5.1.5 ##Python &&2.7.2 ##Go &&1.1.1 ##Java &&1.6 ##C &&Apple Clang V4.0 (-O2) @[table] The benchmarks are executed on Mac OS X 10.8.4 with 1.8GHz Intel Core i5. In these tests, time is measured in seconds (S), and memory is measured in Mega-Bytes (M). @[table] ##Program ## Argument ## Dao ## Dao+JIT ## Speedup ## ## Lua ## Python ## Java ## C ##nbody && 10000000 && 33.9 && 10.5 && 3.2X && && 93.2 && 261.4 && 2.0 && 1.7 ##fannkuch && 11 && 62.0 && 13.4 && 4.6X && && 135.1 && 279.0 && 3.1 && 2.9 ##mandelbrot && 4000 && 27.7 && 6.1 && 4.5X && && 55.8 && 132.1 && 2.7 && 2.3 ##spectral-norm && 3000 && 20.7 && 3.4 && 6.1X && && 69.4 && 287.1 && 2.6 && 1.9 ##binary-trees && 16 && 26.4 && 26.3 && 1.0X && && 20.7 && 19.7 && 0.6 && 4.5 ##pidigits && 5000 && 11.4 && 11.2 && 1.0X && && 40.8 && 2.7 && 6.2 && -- ##meteor && 2098 && 5.5 && 5.5 && 1.0X && && 2.1 && 9.6 && 0.4 && 0.1 ##meteor2 && 2098 && 1.9 && 1.9 && 1.0X && && 2.1 && 9.6 && 0.4 && 0.1 @[table] Note: @[green]meteor@[green] is a port of the Python @[green]meteor@[green] program; @[green]meteor2@[green] is a port of the C @[green]meteor@[green] program. The followings are a couple of benchmarks to compare Dao to Go. Time: @[table] ##Program ## Test Case ## Dao ## Dao+JIT ## Go ##massive-tasklets && 100000 tasklets && 113.2 S && 43.0 S && 156.7 S ##massive-messages && 1000000 messages && 80.5 S && 82.8 S && 0.7 S @[table] Memory: @[table] ##Program ## Test Case ## Dao ## Dao+JIT ## Go ##massive-tasklets && 100000 tasklets && 136.0 M && 143.0 M && 533.0 M ##massive-messages && 1000000 messages && 2.2 M && 5.3 M && 7.3 M @[table] @[text]