
load help;

@[name]
module.core.sys
@[name]

@[title]
System Dependent Core Functions
@[title]

@[text]

@[code(syntax)]
shell( command :string )
popen( cmd :string, mode :string )=>io::stream
sleep( seconds :float )
exit( code=0 )
clock()=>float
ctime( time=0 )=>tuple<year:int,month:int,day:int,wday:int,hour:int,minute:int,second:int>
ctimef( time=0, format='%Y-%M-%D, %H:%I:%S', names : map<string,list<string>> = {=>} )=>string
time(  )=>int
time( tm : tuple<year:int,month:int,day:int,wday:int,hour:int,minute:int,second:int> )=>int
setlocale( category: enum<all,collate,ctype,monetary,numeric,time> = $all, locale = '' )=>string
getenv( name: string )=>string
putenv( name: string, value = '' )
@[code(syntax)]

@[text]



@[name]
module.core.aux
@[name]

@[title]
Aux Module
@[title]


@[name]
module.core.math
@[name]

@[title]
Math Module
@[title]





@[name]
module.core.coroutine
@[name]

@[title]
Coroutine and Generator
@[title]

@[text]

Coroutine is a generic data type that can turn a routine into coroutine or generator.
It has the following type form,
@[code]
coroutine<@RESUME,@YIELD>
@[code]
where @[green]@RESUME@[green] is the type holder for the type
that can be passed to its @[green]resume()@[green] method,
and @[green]@YIELD@[green] is the type holder for the type
that can be passed to its @[green]yeild()@[green] method.


To create a coroutine that can be resume with a integer value,
and yield a string value, the coroutine type should be created in following way,
@[code]
co = coroutine<int,string>()
@[code]


The routine that will be used to create the coroutine need to be defined
with the first parameter named @[green]self@[green] with the coroutine type,
@[code]
routine Test( self :coroutine<int,string>, initpar : string )
{
	for( i = 1 : 5 ) io.writeln( self.yield( initpar + 'abc' ) )
}
@[code]
In such routine, @[green]self.yield()@[green] can be used yield the
control of the execution and pass its parameter to the caller of
@[green]self.yield()@[green] or @[green]self.resume()@[green].


Then the coroutine can be started by,
@[code]
a = co.start( Test, 'test' )
@[code]
which will start the coroutine and execute it until the first yield (if any).
It will return the first yielded value.


The coroutie can be resumed using,
@[code]
a = co.resume( 100 )
@[code]
The parameter passed to resume() will become the returned value of yield().
And the parameter passed to yield() will become the returned value of resume().


The status of coroutine can be checked with,
@[code]
status = co.status()
@[code]


A complete example,
@[code]
load coroutine

routine Test( self :coroutine<int,string>, par : int )
{
	for( i = 1 : 5 ) io.writeln( i, self.yield( 'index_' + (string) (par*i) ) )
	return 'done'
}

co = coroutine<int,string>()

io.writeln( co )

a = co.start( Test, 100 )
io.writeln( a )

for( i = 1 : 6 ) io.writeln( co.resume( 100*i ), co.status() )
@[code]

@[text]




@[name]
module.core.protobject
@[name]

@[title]
Protobject
@[title]

@[text]

@[green]Protobject@[green] is a data type to provide support for prototype-based OOP.
Arbitrary fields can be set to or gotten from a @[green]Protobject@[green] object.
A delegator can also be set for such object.
When a @[green]Protobject@[green] has a delegator, setting a field for this
object will only affect this object, not the delegator.

@[code]
load protobject

obj = Protobject()

obj.name = 'FirstObject'  # set a field;

io.writeln( obj.name )    # get a field;

obj2 = Protobject()
obj2.__proto__ = obj  # set a delegator;

io.writeln( obj2.name )


obj2.name = 'SecondObject'

io.writeln( obj.name, obj2.name )
@[code]

@[text]




@[name]
module.core.meta
@[name]

@[title]
Meta
@[title]


@[text]
TODO
@[text]





@[name]
module.core.serializer
@[name]

@[title]
Serializer
@[title]


@[text]

Serializer is the module to provide methods for serializing data structures into strings
and deserializing from strings. It also provide methods to serialize and deserialize
an entire namespace. These methods include:
@[list]
--@[code]serialize(value:any)=>string@[code]

Serialize a value to string. Primitive types (such as int, string)
and container types (such as array, list, map and tuple) are directly
serialized. Objects of C data types and Dao classes can be serialized
if they define method named @[green]serialize()@[green] that return
data that can be directly serialized.


--@[code]deserialize(text:string)=>any@[code]

Deserialize a string into a value. Serializations from primitive types
(such as int, string) and container types (such as array, list, map and tuple)
can be directly deserialized into values.
Serializations from objects of C data types and Dao classes will be deserialized into
primitive values or container values first. If the C data types and Dao classes has
defined constructors that can take these values as parameters, such constrcuts will
be used to construct proper C data objects and Dao objects as the deserialized values.


--@[code]backup(tofile='backup.sdo',limit=0)@[code]

Backup the current namespace by serialization to a file.


--@[code]restore(fromfile='backup.sdo')@[code]

Restore a namespace from a backup file.

@[list]
Upon loading this module, these methods are imported to the @[green]std@[green] namespace.


Examples,
@[code]
load serializer;

list1 = { 1.3, 2.5, 3.6 }
list2 = { (any)(name=>'dao',year=>2006), (123+456C, 'abc'), [1.2, 3.4; 5.6, 7.8] }

s1 = std.serialize( list1 );
s2 = std.serialize( list2 );

io.writeln( s2 )
io.writeln( s1, std.deserialize( s1 ) )
io.writeln( s2, std.deserialize( s2 ) )

map1 = { 'abc'->123, 'def'->{} }
s3 = std.serialize( map1 );
io.writeln( s3, std.deserialize( s3 ) )

class Klass
{
	var index = 123;
	var name = 'abc';

	routine Klass( ){ index = 789; }
	routine Klass( i : int, s : string ){ index = i; name = s; }
	routine Klass( tup : tuple<int,string> ){index = tup[0]; name = tup[1]; }
	routine serialize(){ return index, name }
}
object = Klass( 456, 'def' );
io.writeln( object.serialize() );

ss = std.serialize( object );
io.writeln( ss );
object = (Klass)std.deserialize( ss )
io.writeln( object, object.index, object.name );
@[code]

@[text]






@[name]
module.core.dataframe
@[name]

@[title]
Data Frame
@[title]


@[text]

A data frame is a matrix-like data structure that organizes data values into table(s).
But unlike a matrix, a data frame can contain any types of values, though the values
of the same column are required to be the same.
Also, the rows and columns can be attached with arbitrary sets of labels,
and such labels can be used to retrieve the rows or columns.


Dao data frame supports both 2D and 3D data frames. A 2D data frame contains only one
data table, with data items indexed by row and column indices or labels.
A 3D data frame contains multiple data tables, where each table is indexed by a depth
index or multiple depth labels.


Here is a simple example to create and print a data frame:
@[code]
load DataFrame

matrix = [ [ -1.0D : -1 : 4] : 1.5 : 5 ] 
dframe = DataFrame( matrix )
io.writeln( dframe );
@[code]
which will print something like the following:
@[code]
DataFrame[0x7f82f34a1700]
Dimensions: Rows=5; Cols=4; Deps=1;
Depth: 0;
| Columns from 0 to 3:
|       0     1     2     3
|--------------------------|
0:   -1.0  -2.0  -3.0  -4.0
1:    0.5  -0.5  -1.5  -2.5
2:    2.0   1.0   0.0  -1.0
3:    3.5   2.5   1.5   0.5
4:    5.0   4.0   3.0   2.0
@[code]


More on data frame creation:
@[code]
# Create a 2D matrix:
matrix = [ [ -1.0D : -1 : 8] : 1.51 : 16 ]

# Create a 2D dataframe from the matrix:
dframe2d = DataFrame( matrix )

# Create a 3D matrix:
matrix3d = [ matrix : 1 : 3 ]
matrix3d.permute( [ 2, 1, 0 ] )

# Create 3D dataframe:
dframe3d = DataFrame( matrix3d )
@[code]


Attaching labels to data frames:
@[code]
# Add row labels:
dframe2d.AddLabels( $row, { 'RR1' => 0, 'R2' => 1, 'RRRR5' => 5 } )
dframe2d.AddLabels( $row, { 'RR1' => 0, 'R2' => 1, 'RRRR5' => 6 } )

# Add column labels:
dframe2d.AddLabels( $column, { 'CC1' => 0, 'C2' => 1, 'CCCCCCCCC3' => 4 } )
@[code]


Adding additional columns:
@[code]
# Add string column:
dframe2d.AddColumn( { 'ABC', 'DEF', 'SSSS', 'Hello\t world!' }, 'String' )

# Add column of arbitrary type:
dframe2d.AddColumn( { {'ABC'}, {'DEF', 'SSSS'}, 'Hello\n world!' }, 'Any' )

# Add integer column:
dframe2d.AddColumn( [ 123, 456, 7890], 'Number' )
@[code]


Operation on data frame:
@[code]
# Update one cell:
dframe2d[0,1] = 1000000.23

# Update one column:
dframe2d[:,2] += [[0]:100:9]

# Add the first column to the second:
dframe2d[:,1] += dframe2d[:,0]
@[code]


Using code section methods of data frame:
@[code]
# Scan cells:
dframe2d[1:5,:3].ScanCells { [value,row,column]
	io.writeln( row, column, value )
}

# Scan rows:
dframe2d[1:5,:3].ScanRows { [value,row]
	io.writeln( row, value )
}

# Scan columns:
dframe2d[1:5,:3].ScanColumns { [value,column]
	io.writeln( column, value )
}
@[code]

@[text]



