load help; @[name] dao.guide @[name] @[title] The Quick and Simple Guide @[title] @[text] This quick and simple guide will cover some basics of Dao programming. @[section] Basics @[section] We will start with the traditional @[green]hello world@[green] example. @[subsection] Hello World! @[subsection] To simply write "Hello world!" to the screen, one can use, @[code] io.write( "Hello world!" ) @[code] In this simple example, the built-in @[green]io@[green] module is used to access the IO functionalities of the module. @[green]write()@[green] is a method provided by the @[green]io@[green] module to write outputs on to the standard output (the screen in this case). In Dao, string can be quoted with a pair of single quotation marks or with a pair of double quotation marks. Semicolons are optional at the end of statements. @[subsection] Running Scripts @[subsection] There are three ways to run codes in Dao. The most typical way is to create a script file (e.g. @[cyan]hello_world.dao@[cyan]), and put the codes into this file, and then run @[green]dao@[green] using this file as argument, @[code] $$ dao hello_world.dao @[code] But if you just want to run the codes once, you can simple run them from command line using, @[code] $$ dao -e "io.write( 'Hello world!' )" @[code] For learning Dao, it may be the best to run codes in interactive mode. Invoking @[green]dao@[green] without any argument will start an interactive shell, @[code] $$ dao Dao Virtual Machine 2.0 Built date: Jun 12 2014 Changeset ID: FOS.4d5eb15f0e53 Copyright(C) 2006-2014, Fu Limin Dao is released under the terms of the Simplified BSD License Dao Language website: http://daoscript.org (dao) @[code] @[subsection] Accessing Online Help @[subsection] If you have the Dao @[green]help@[green] properly installed, starting @[green]dao@[green] in interactive mode will automatically load the help files and print out the following information, @[code] Module Help is loaded. Now you may run "help()" to list all the available help entries; or run "help('help')" for detailed information about the help system. @[code] If you are reading this tutorial from a webpage, and want to access it from the interactive command line, you can simple run, @[code(dao)] (dao) help( "dao.guide" ) @[code(dao)] Such online helps come in two languages: English and Chinese. To choose the language, @[code(dao)] (dao) help::set_language("en"); # choose english; (dao) help::set_language("zh"); # choose chinese; @[code(dao)] @[subsection] Commenting Codes @[subsection] It is always a good idea to comment your codes. Dao supports both single line comments and multiple line comments. A single comment starts at a @[code]#@[code] (not followed by a left curly bracket @[code]{@[code]), and ends at the end of the current line. And a multiple line comment (or just part of a single line) opens by @[code]#{@[code] and closes by @[code]#}@[code]. For example, @[code] # This is a simple demo: io.write( "Hello World!" #{ comment inside codes #} ); #{ Here are multi-lines comments. Here are multi-lines comments. #} @[code] @[subsection] Constants, Variables and Invariables @[subsection] Dao supports the explicit declaration of constants, local variables, static variables, global variables and invariables. Constants are declared with keyword @[code]const@[code], @[code] const DEFAULT_INDEX = 123 const DEFAULT_NAME = 'abc' @[code] Constants can only be initialized with constant expression. Constants that are declared at the top lexical scope are global constants. Keyword @[code]var@[code] can be used to declare local and global variables. If used at the top lexical scope, it will declare global variables, otherwise the declared variables will be local. @[code] var current_index = 456 # global variable; var current_name = 'def' # global variable; if( current_index ) { var temp_index = current_index # local variable; } @[code] In every places where @[code]var@[code] can be used, @[code]invar@[code] can be used as well, to declare local, global or member invariables. Invariables are special kind of variables that cannot be modified once initialized. @[code] var varlist = { 123 } invar invlist = varlist invlist.append( 456 ) # Error! @[code] Please see @[node]dao.data.invar@[node] for more information. Another type of variable is the static variable which can be declared with the @[code]static@[code] keyword. Outside class body, a static variable is a global variable with strictly local visibility within its declaration scope. So if a routine with static variables is executed multiple times, all the executions will access the same static variables. Static variables must be initialized with constant expressions. Without the above specifiers, newly declared symbols in the form of @[code]name=expression@[code] will be automatically declared as local variables. But if the symbol was defined as variable, such statements will simply reinitialize the existing variable. To avoid this, one must the keyword @[code]var@[code] to explicitly declare the variable as local, @[code] var index = 789 for(var i = 1 : 3 ){ var index = 123 # Local to the loop; } @[code] Please read @[node]dao.data@[node] for more information. @[red] Note: in interactve mode, all top level variables are automatically declared as global variables. @[red] @[subsection] Type Annotation @[subsection] In the above examples, no type information is declared for the constants, variables and invariables. Their types are automatically inferred from the values that were used to initialize them. In many cases, it is better to provide type annotations to the constant, variable and invariable declarations. In general, programs with good type annotations are more readable them programs without them. It also makes error detection in such programs easier. Type annotations are usually placed after the constant/variable/invariable names with a colon sparating them. @[code] const vector: array = [ 12.5, 34.6 ] invar invlist: list = { 12.5, 34.6 } var varlist: list @[code] Here without type annotation, "vector" will become a constant of type "array". And "varlist" is declared without initializing expression, so its type cannot be inferred here. As you will see, type annotations can also be used in routine/function signatures and class member fields. Please read @[node]dao.type@[node] for more information. @[section] Data Types @[section] Dao supports a good number of data types to facilitate programming. These include, boolean type, several number types, enum symbol, string, numeric array, tuple, list and map etc. types. @[subsection] Boolean @[subsection] Boolean (@[code]bool@[code]) is a simple logical data type representing true and false. @[code] var B1 = true var B2 = false var B3 = 3 > 2 var B4 = B1 and B2 @[code] @[subsection] Numbers @[subsection] Dao has native supports for the following number types: @[code]int@[code], @[code]float@[code], and @[code]complex@[code]. Both @[code]int@[code] and @[code]float@[code] are stored in 64 bits. Integer and floating point numbers can be expressed in the same ways as in most other languages. Number literals suffixed with @[code]C@[code] represent the imaginary parts of double precision complex numbers. Examples, @[code] var I1 = 123 # Base-10 integer; var I2 = 0xabc # Base-16 integer; var F1 = 456.7 # Double precision; var F2 = 123e4 # Double precision; var F3 = 123E4 # Double precision; var C1 = 123C # Double precision complex number with 0.0 real part and 123 imag part; var C2 = 456.6C # Double precision complex number; @[code] These types support most of the common operators that are meaningful for them. For example, all the basic arithmetic operators such as: @[code]+@[code] (addition, unary plus), @[code]-@[code] (subtraction, unary minus), @[code]*@[code] (multiplication) and @[code]/@[code] (division). are supported. @[code] var I1 = 123 + 456 var I2 = 789 % 123 var F1 = 123.5 ** 3 var F2 = 789.5 / 123 var C1 = 12.3 + 45.6C @[code] Please see @[node]dao.type.int@[node], @[node]dao.type.float@[node] and @[node]dao.type.complex@[node] for more information. @[subsection] Enum Symbols @[subsection] An @[code]enum@[code] defines a set of symbols with associated integer values. It is particularly useful to represent states and flags. @[code] enum MyEnum { AA , # 0 BB = 3, # 3 CC # 4 } @[code] These symbols are not exposed to the current namespace. So they have to be accessed as fields of the enum type, @[code] var a = MyEnum::AA # Or: MyEnum.AA; @[code] There is a special type of enum called @[code]symbol@[code], which appears as an ordinary identifier prefixed with a dollar sign @[code]$@[code]. Such symbols are often used in conjunction with normal enum types. @[code] enum E1 { AA=1, BB=2 } enum E2 { AA=10, BB=20 } var e1: E1 = $AA var e2: E2 = $AA io.writeln( e1 ) # Output: $AA(1) io.writeln( e2 ) # Output: $AA(10) @[code] Here symbol "$AA" is assigned to both "e1" and "e2", and the symbol get interpreted properly according the types of "e1" and "e2". So what a symbol represents actually depends on the variable type to which is assigned. Another way to use enum types is to use the enum type names: @[code] var e1: enum = $AA var e2: enum = $BB @[code] There are different types of enum types to support different operations. Please see @[node]dao.type.enum@[node] for more information. @[subsection] Strings @[subsection] A Dao string is simply a sequence of bytes, which can contain arbitrary data. But when processed as text, it is usually assumed to be encoded in UTF-8. Strings can be expressed as string literals quoted with double or single quotation marks. @[code] var S1 = 'Something' var S2 = "道语言" var S3 = 'It\'s green' var S4 = "\u9053\u8bed\u8a00" # the same as S2: "道语言"; @[code] Inside string lieterals, some characters need to be escaped with backslashes. Some others such as @[code]\u@[code] are used to instruct Dao parser to interprete the following byte sequences specially. To use strings as it is written without special treatment of the characters, they can be expressed as @[code]verbatim@[code] string, which are quoted with a pair of identical compound marks in the forms of @[code]@[]@[code]. 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. @[code] # C++ codes as verbatim string: var cpp = @[cpp x] class AA { int index; }; struct BB{}; @[cpp x] @[code] The content of a string can be accessed or altered using sub-indexing or slicing: @[code] var str = "ABCDEFGHIJK"; io.writeln( str[1] ) # the second character; io.writeln( str[:4] ) # the substring from the start to the 4th character; io.writeln( str[6:] ) # the substring from the 6th character to the end; io.writeln( str[3:8] ) # the substring from the 3rd to the 8th character; str[1] = "X"; # Change a single byte: str = "AXCDEFGHIJK"; str[2:5] = "123456" # Change a substring: str = "AB123456GHIJK"; @[code] String can be concaternated using @[code]+@[code] or @[code]+=@[code], @[code] var str = "ABCDEFGHIJK"; str2 = str + "123" # str2 = ABCDEFGHIJK123 str += "123" # Append a string: str = ABCDEFGHIJK123 str += 88 # Append a character: str = ABCDEFGHIJK123X @[code] The string type supports a number of builtin methods for handling its data. Among these methods, there are also string pattern matching methods. Please read @[node]dao.type.string@[node] for more information. @[subsection] Numeric Arrays @[subsection] Dao has built-in support for multi-dimensional numeric arrays. Such arrays can be defined by using the squared brackets @[code][]@[code] or @[code]array{}@[code]. 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. @[code] var vec1 = [1, 2, 3] # array vector, or 1x3 matrix; var vec2 = [1.0; 2; 3] # array 3x1 matrix, or transposed vector; var mat1 = [1.0, 2; 3, 4] # array 2x2 matrix; var mat2 = [ [1, 2], [3, 4] ] # 2x2 matrix var mat3 = array{ 1, 2; 3, 4 } # 2x2 matrix @[code] Like string, array support sub-indexing and slicing: @[code] var mat = [ 1, 2, 3; 4, 5, 6; 7, 8, 9 ]; # 3x3 matrix; var rowvec = mat[1,:] # the second row; var colvec = mat[:,1] # the second column; var submat1 = mat[:1,:] # the first two rows; var submat2 = mat[:,1:] # the last two columns; var submat3 = mat[:1,1:] # intersection between the first two rows and the last two columns; mat[0,:] = [11, 22, 33] # set the first row to [11, 22, 33]; mat[:,1] += [11, 22, 33] # add [11, 22, 33] to the second column; mat[:,1] += 100 # add 100 to the second column; mat[:1,1:] += [10, 20; 30, 40] # add [10, 20; 30, 40] to sub-matrix of mat; @[code] Please see @[node]dao.type.array@[node] for more information. @[subsection] Lists @[subsection] List can be created in similar ways as array, by enumerating elements or specifying an arithmetic progression, but using @[code]{}@[code] or @[code]list{}@[code] instead of @[code][]@[code] or @[code]array{}@[code]. @[code] var list1 = { 1, 2, 3 } # list var list2 = { 1.0, 2, 3 } # list var list3 = { 1 : 2 : 5 } # list var list4 = { 'abc', 'def' } # list var list5 = { 123, 'abc' } # list @[code] List also supports sub-indexing and slicing: @[code] var alist = { 0, 1, 2, 3, 4, 5 } var item = alist[1] var sublist = alist[2:4] alist[3] = 10 alist[4] += 10 @[code] @[subsection] Maps and Hash Maps (Associative Arrays) @[subsection] 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 @[code]{key=>value...}@[code] or @[code]map{key=>value...}@[code]. Replacing the @[code]=>@[code] with colon @[code]->@[code] will create hash maps. Map and hash map can be used in identical ways. @[code] var amap = { 'abc' => 123, 'def' => 456 } var ahash = { 'abc' -> 123, 'def' -> 456 } var amap = map{ 'abc' => 123, 'def' => 456 } var ahash = map{ 'abc' -> 123, 'def' -> 456 } @[code] Sub-scripting and slicing are also supported for map to access value(s) through key(s). @[code] var amap = { 'abc' => 123, 'def' => 456, 'ghi' => 789 } var value = amap[ 'abc' ]; var submap = amap[ 'abc' : 'def' ]; @[code] @[subsection] Tuples @[subsection] Tuple is a data type that can store a fixed number of items with individual type annotation for each item. Each item may optionally have a field name. They can be created in similar ways as creating lists and maps, but using @[code]()@[code] instead. @[code] var tup1 = ( 123, 'abc' ) # tuple with unnamed items; var tup2 = ( index = 123, 'abc' ) # the first item is named as "index"; var tup3 = tuple{ 123, name = 'abc' } # the second item is named as "name"; @[code] 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. @[code] var tup = ( index = 123, 'abc', [1,2,3] ) var id = tup[0] id = tup.index tup.index = 456 var tup2 = tup[:1] # ( index = 123, 'abc' ) @[code] @[section] Control Constructs @[section] The logic of a program is mostly expressed with constrol constructs. Dao supports the commonly used controls such as: @[green]if-else@[green], @[green]for@[green], @[green]while@[green], @[green]do-while@[green], @[green]switch-case@[green], @[green]break@[green] and @[green]skip@[green] etc. @[subsection] If-Else Conditional Construct @[subsection] The @[green]if-else@[green] control allows the program to branch and execute different blocks of codes, based on the results of the condition expressions. When the execution reachs an @[green]if-else@[green] block, the condition in the @[code]if()@[code] clause will be tested first, if the test is successful, the block associated with the @[code]if@[code] clause will be execute. Otherwise the next @[code]else if()@[code] clauses (if any) will be tested one by one, until one succeeds the test, then the block of the succeeded @[code]else if()@[code] clause will be executed. If none of the conditions suceeds and there is an @[code]else@[code] clause, its block will be executed instead. @[code] if( sin(10) > 0.7 ){ io.writeln( "greater than 0.7" ) }else if( sin(10) > 0.5 ){ io.writeln( "greater than 0.5" ) }else if( sin(10) > 0.3 ){ io.writeln( "greater than 0.3" ) }else{ io.writeln( "not greater than 0.3" ) } @[code] Before each condition expression, there can be an optional expression or variable declaration, for example, @[code] if(var a = sin(100); a > 0.0 ) io.writeln( "positive sine:", a ); @[code] @[subsection] For Looping Construct @[subsection] Dao supports three different styles of for loops: @[list] -- For-in loop; -- Range for loop; -- C style for loop; @[list] For-in loop can normally used to iterate over the items of a container object. It is probably most useful with list. @[code] var numbers = { 1, 2, 3, 4, 5 } for( num in numbers ) io.writeln( num ) @[code] A range for loop uses an arithmetic progression condition to control the loop. The arithmetic progression condition usually consists of an initial value, an optional step value and a stopping value. @[code] for(var index = 1 : 2 : 10 ) { # step value = 2; io.writeln( index ) } for(var index = 1 : 10 ) { # step value = 1; io.writeln( index ) } @[code] The loops will start with "index=1", and with each loop cycle, "index" is increased by two or one, when "index" become greater than 10, the loop will stop. C-style for loop is the most flexible for loop construct. @[code] for( init; condition; step ){ block; } @[code] The essential execution logic or steps of @[code]for@[code] statement is the following, @[list] == Execute the initial expression @[code]init@[code]; == Check the condition expression @[code]condition@[code]; == If true continue to the next step, otherwise exit the loop; == Execute the code block @[code]block@[code]; == Execute the step expression @[code]step@[code] and go to 2; @[list] The detailed steps may depends on the implementation but the basic execution logic is the same. Example, @[code(dao)] for(var i=0; i<3; ++i){ io.writeln( i ); } @[code(dao)] @[subsection] While Looping Construct @[subsection] @[code]while@[code] is a simple looping construct that executes a block if the looping condition is true, and repeats the execution as long as the condition is true. @[code] while( expression ){ block; } @[code] If @[code]expression@[code] is true, @[code]block@[code] is executed and repeated until @[code]expression@[code] becomes false, namely, while @[code]expression@[code] is true, execute @[code]block@[code]. @[code] var i = 0; while( i < 5 ){ io.writeln( i ); i += 1; } @[code] @[subsection] Do-While Looping Construct @[subsection] @[code]Do-while@[code] is a simple looping construct that executes a block and repeats the execution until its looping condition become false. @[code] do { block; } while ( condition ) @[code] Execute @[code]block@[code], and then repeat executing it until the @[code]condition@[code] become false. @[subsection] Switch-Case Construct @[subsection] Switch-case control provides a convenient way to branch the code and choose a block of code to execute based on the value of an expression. @[code] switch( expresssion ){ case C_1 : block_1 case C_2 : block_2 case C_3 : block_3 ... default: block0 } @[code] If the value of @[code]expresssion@[code] equals to @[code]C_i@[code], @[code]block_i@[code] will be executed. Here @[code]C_i@[code] must be a constant, but they can be of different types, that means, you can mix numbers and strings as case values. Unlike in C/C++, no @[code]break@[code] statement is required to get out of the @[code]switch@[code]. If you want to execute the same block of codes for different case values, you just need to put them together in the same case: @[code] switch( expresssion ){ case C1, C2, C3 : block3 ... default: block0 } @[code] As a simple example, @[code(dao)] var a = "a"; switch( a ){ case 1, "a" : io.write("case 1 or a"); default : io.write("case default"); } @[code(dao)] @[subsection] Break and Skip @[subsection] @[code]break@[code] can be used to exit a loop, and @[code]skip@[code] can be used to skip the rest part of script and start the next cycle of a loop. @[code]skip@[code] is equivalent to @[code]continue@[code] in C/C++. @[code] for(var i=0; i<5; ++i ){ io.writeln( i ); if( i == 3 ) break; } @[code] @[section] Routines (Functions) @[section] Routine (function) is a relative independent block of code that can be repeatedly executed by invoking it when and where it is needed. It can accept parameters to changes its behaviour. It may also return results to its caller. @[subsection] Definition @[subsection] Dao routines are declared with keyword @[code]routine@[code] For example, @[code(dao)] routine func( first, second ) { first += 10; second += "test"; return first, second; # return more than one results. } var (ret1, ret2) = func( 111, "AAA" ); var ret3 = func( ret1, ret2 ); @[code(dao)] defines a function that can take two parameters as inputs, and return two values as outputs. @[subsection]Parameter Type and Default Value@[subsection] Routine parameters can have type annotations, and a default value can also be specified for a parameter. @[code] routine MyRout( name: string, index = 0 ) { io.writeln( "NAME = ", name ) io.writeln( "INDEX = ", index ) } @[code] Here @[code]name@[code] is annotated as type string, and @[code]index@[code] is specified as an integer with default value 0. Any parameter after a parameter with default value must have default values as well. @[subsection]Routine Overloading@[subsection] Routine overloading by parameter types is also supported in Dao, which means that multiple routines can be defined with the same name, but different parameter signatures. @[code] routine MyRout( index: int, name = "ABC" ) { io.writeln( "INDEX = ", index ) io.writeln( "NAME = ", name ) } MyRout( "DAO", 123 ) # invoke the first MyRout() MyRout( 456, "script" ) # invoke the second MyRout() @[code] @[subsection]Anonymous Routine and Closure@[subsection] Dao supports routines as first class objects. So they can be created as anonymous routines or closures, and used just like other objects. The syntax to create anonymous routine or closure is nearly identical to the definition of a normal function, except the following differences: @[list] == No need for a function name; == Default parameter values do not need to be constant; == Its function body may access the local variables of the outer function; @[list] When such function accesses local variables from its outer/upper scope, it is created as a closure, otherwise as an anonymous function. Here is a simple example, @[code] var abc = "ABC"; rout = routine( x, y: string, z = abc + abc ){ abc += y; io.writeln( "lambda ", abc ) io.writeln( "lambda ", y ) io.writeln( "lambda ", z ) } rout( 123, "XXX" ); io.writeln( abc ) # Output: ABCXXX @[code] For code section routines, please see @[node]dao.routine.section@[node]. For coroutine and generator, please see @[node]module.core.coroutine@[node]. @[section] Classes @[section] Class is a user-defined data structure that supports data abstraction, encapsulation, polymorphism and inheritance etc. It is commonly used to do Object-Oriented Programming (OOP). @[subsection]Class Definition@[subsection] A @[code]class@[code] data strucutre is defined by composing data fields and member methods in a meaningful way that defines the states and behaviours for the instances of the class. Dao class supports four types of fields: @[list] --@[code]constant@[code]: declared with keyword @[code]const@[code]; --@[code]static variable@[code]: declared with keyword @[code]static@[code]; --@[code]instance variable@[code]: declared with keyword @[code]var@[code]; --@[code]instance invariable@[code]: declared with keyword @[code]invar@[code]; @[list] Such fields can be declared with or without explicit types, and with or without default initialization values, in the same way as specifying types and/or default values for function parameters. For example, the following can be used for instance variables, @[code] var variable; var variable = init_value; var variable: typename; var variable: typename = init_value; @[code] Class constructors and ordinary methods must be declared with keyword @[code]routine@[code]. Methods for overloading operators must use keyword @[code]operator@[code]. The visibilities of class fields and methods can be restricted by three permission keywords: @[list] --@[code]public@[code]: publically accessible without restriction; --@[code]protected@[code]: accessible from the class and its derived classes; --@[code]private@[code]: only accessible from the class; @[list] Here is a simple class, @[code] class ClassOne { var index = 0; var name : string var words : list = {} routine ClassOne( name :string, index = 0 ){ self.name = name; self.index = index; } } @[code] Within class methods, the special variable @[code]self@[code] represents the current class instance. Class methods may be declared inside class body and defined outside in the same way as in C++, but in Dao, one should make sure that, the parameter list must be exactly the same in the places for declaration and definition. @[subsection]Class Instance@[subsection] Class constructors are the methods that have name the same as the class name. A class instance can be created by invoking a constructor of the class in the same way as a function call, @[code] var object = ClassOne( 'abc' ) @[code] Note that, the constructors are not used to create class instances, instead, an instance is created before, and then the constructor is called after to initialize the instance. For a class without parent classes and without constructors, its instances may also be created by enumerating the members of the class, @[code] class Point3D { var x = 0.0; var y = 0.0; var z = 0.0; } var point = Point3D.{ 1, 2, 3 }; @[code] The names of instance variables may also be specified in enumeration, @[code] var point = Point3D.{ y = 2, x = 1, z = 3 }; @[code] @[subsection]Methods and Properties@[subsection] There are three typical types of methods for Dao classes: static method, instance method and invariable/const instance method. Static methods can be invoked without class instance objects, so they cannot access instance variables. The other two types of methods requires class instances to invoke. Instance methods can modify the instance variables, but invariable methods cannot. Invariable methods can be declared by specifying "invar" after the brackets for the parameters. @[code(dao)] class ClassTwo { private static state = 0 var value = 0 public static routine Stat() { state += 1 # OK! state += value # Error! Cannot access "value"! } routine Meth() { state += 1 # OK! value += 2 # OK! } routine InvarMeth() invar { state += value # OK! Can access "value"! value += 2 # Error! Cannot modify "value"! } } @[code(dao)] In order to provide access to the variables such as "value" in the above example, one can define ordinary methods such @[code]GetValue()@[code] and @[code]SetValue()@[code]. But the better way is to use properties. A property is a method that provides access to a field in a way that syntatically looks like direct access. In Dao, this can be done by overloading name specific operators such as @[code].Name@[code] and @[code].Name=@[code]. For example, @[code(dao)] class MyNumber { private var value = 0; public routine MyNumber( init = 0 ){ value = init; } operator .value(){ return value } operator .value=( newval: int ) { value = newval; io.writeln( "value is set" ) } } var num = MyNumber( 123 ) num.value = 456 io.writeln( num.value ) @[code(dao)] @[subsection]Inheritance@[subsection] @[code] class ColorRBG { var red = 0.0; var green = 0.0; var blue = 0.0; routine ColorRBG( R = 0.0, G = 0.0, B = 0.0 ){ red = R; green = G; blue = B; } } var yellow = ColorRBG( 1, 1, 0 ); # create an instance. @[code] The following will define a derived class of @[code]ColorRBG@[code], @[code] class ColorRGBA : ColorRBG { var alpha = 0.0; # alpha component for tranparency. routine ColorRGBA( R = 0.0, G = 0.0, B = 0.0, A = 0.0 ) : ColorRBG( R, G, B ){ alpha = A; } } magenta = ColorRGBA( 1, 0, 1, 0 ); # not tranparent. magenta.alpha = 0.5; # change to half tranparency. @[code] In the definition of derived class, the parent class @[code]ColorRBG@[code] should be put after the derived class and be separated with @[code]:@[code]. The constructor parameters for derived class can be passed to parent classes in the way as shown in the example. There are several more advanced features based on class, please see @[node]dao.class@[node] for more information. @[text]