

The Luban Programming 
Language

Peter X. Huang
8/6/2004





Contents
1	WHAT IS LUBAN	4
2	START SCRIPTING LUBAN	5
2.1	HELLO WORLD	5
2.2	PROCEDURAL STATEMENTS	5
2.2.1	Expression and Assignment	5
2.2.2	Flow Control	6
2.2.3	Compound Statement:	6
2.2.4	Component Property Batch Setting	6
2.2.5	Comments	7
2.3	LUBAN BUILT-IN DATA TYPES	7
2.3.1	Double and Integer:	7
2.3.2	Boolean	7
2.3.3	Character	7
2.3.4	String	7
2.3.5	Vector, Map and Set	7
2.4	NULL AND ERROR	8
2.5	PARALLEL COMPUTING: THREADING AND SYNCHRONIZATION	9
2.6	EVERYTHING IS OBJECT	9
3	INTRODUCTION TO LUBAN COMPONENT STRUCTURE	10
3.1	DEFINE A LUBAN STRUCTURE	10
3.2	HELLO WORLD STRUCTURE WITH INPUT AND OUTPUT	11
3.3	MORE ON USE OF LUBAN STRUCTURE	12
3.4	PASS BY VALUE SEMANTICS	13
3.5	NAME SPACE BASICS AND PROGRAM ENTRY POINT	13
4	STRUCTURE INTERFACE AND INHERITANCE	14
4.1	STRUCTURE INTERFACE: PROPERTY FLOW TYPE AND EXTERNAL ACCESS PERMISSION	14
4.2	STRUCTURE INTERFACE INHERITANCE	16
4.3	LUBAN INHERITANCE IS ONLY FOR INTERFACE	17
5	THE DYNAMIC TYPE SYSTEM OF LUBAN	18
5.1	NAME OF DATA TYPE AND STRUCTURE TYPE	18
5.2	CONSTRUCTION OF DATA TYPE AND STRUCTURE TYPE	19
5.3	EXPLICIT TYPE CASTING	19
5.4	DYNAMIC TYPE CHECKING: ISA AND TYPEOF OPERATORS	20
5.5	TYPE EXPRESSION	20
5.6	GATE KEEPER: TYPED PROPERTY AND VARIABLE	21
6	COMPONENT COMPOSITION	23
6.1	COMPOSITION 101	23
6.2	DIFFERENT COMPONENT CELLS	24
6.2.1	Ad hoc Cell	24
6.2.2	Typed Cell	24
6.3	DEPENDENCY SPECIFICATION RULES	25
6.3.1	Change Nothing But Yourself, But Do Read Your Surrounding	25
6.3.2	No Tail Chasing	26
6.4	INHERITANCE AND COMPOSITION	26
6.5	COMPOSITION VS. PROCESS	26
7	ASYNCHRONOUS STRUCTURE: IMPLICIT THREAD AND QUEUE	27
7.1	THE FIRST ASYNCHRONOUS STRUCTURE EXAMPLE	27
7.2	ASYNCHRONOUS STRUCTURE IN COMPOSITION	29
7.3	AD HOC ASYNCHRONOUS CELL IN COMPOSITION	30
7.4	ASYNCHRONOUS COMPONENT AND CYCLE IN COMPOSITION	30
8	ERROR HANDLING OF LUBAN	32
8.1	SO LONG TRY AND CATCH MADNESS	32
8.2	ERROR VALUE GENERATION AND PROPAGATION	32
8.3	ERRORS THAT STOP THE SHOW	32
9	UTILITY DATA TYPES AND STRUCTURES	34
9.1	CONSOLE, FILE AND SOCKET	34
9.2	HOW TO CREATE, READ AND WRITE FILE	34
9.3	SOCKET ROUTINE, SERVER AND CLIENT	35
9.4	UTILITY STRUCTURES: STD::PRINTLN AND STD::PRINT	35
9.5	UTILITY DATA TYPE: STD::DESERIALIZER	35
10	ADD NEW DATA TYPE TO LUBAN	36
10.1	CODE A LUBAN DATA TYPE IN C++	36
10.2	INFORM LUBAN ABOUT THE NEW TYPE	38
10.3	BASIC OPERATIONS	39
10.4	MORE OPERATIONS	39
10.5	STATIC CONSTRUCTOR AND CASTING	40
10.6	HELPER CLASSES	41
10.7	COMMON ASSUMPTIONS ABOUT LUBAN DATA TYPES	42
11	LUBAN INTERPRETER	43
12	SAMPLE APPLICATION: SIMPLE MESSAGING SYSTEM	44
13	TODOS	45



1	 What Is Luban

All night in my dreams,
everything was exactly the way it seems.
-	Highlands, Bob Dylan

Luban is a component oriented programming language. Luban is named to honor a 
legendary ancient Chinese civil engineer two thousand year ago whose constructions 
are still in use today.
Luban, in short speaking, is a scripting language with a robust component and 
composition model. Luban is easy to use. To start coding Luban requires almost zero 
understanding of any high level programming concepts. If you know what you want 
to do plus a minimum set of Luban's basic features, you can code your work with 
Luban. Luban's syntax is simple and clean. And Luban code requires no explicit 
compiling and linking steps to run. If you like the usability of scripting languages, 
you will like Luban at least as much.
Intuitiveness and usability are the design principles of Luban. And that is why Luban 
has the unique component composition feature. Component composition is a 
technology that has been used in engineering. Yet Luban is the first programming 
language that directly supports component composition in software construction. 
Luban component composition is analogous spreadsheet construction. User defines a 
new component by laying down sub-components and specifying dependencies among 
the sub-components. Composition fits a range of problems that could be awkward to 
code in traditional procedural way. More importantly, composition is simple and 
intuitive. Any one who can use a spreadsheet can immediately understand Luban 
component composition.
Besides simplicity and intuitiveness, Luban also fully supports component oriented 
programming paradigm. One regret people may get when using scripting languages is 
that it often becomes difficult to manage when code base grows. Luban has all the 
features to support code reuse and component management. The features include 
component interface definition and inheritance, component name space, built-in 
multi-threading, dynamic component loading and dynamic type checking. You can 
start using Luban only for scripting and later may find these component features 
handy when you try to collect your Luban scripts into one or more coherent systems.
In conclusion, Luban is an integration layer programming language that has both the 
usability of scripting languages and the scalability of formal languages. The goal of 
Luban is to present a simple component oriented programming tool to not only 
programmers but also a much wider audience that may never have been able to 
program before. The grand design is to empower people who have the field 
knowledge to directly code and share their knowledge in the form of software 
components, no matter if they are professional programmer or not.



2	Start Scripting Luban

This chapter introduces the basic procedural code constructions in Luban through code 
examples. This chapter is all you need to read for basic Luban scripting. The syntax of 
Luban's procedural constructions is very much like simplified C++ or Java. Basically a 
valid Luban script is a series of one or more Luban statements, separated by either 
semicolon or bracket. Change of line doesn't mean much for Luban. So you can put all 
your code in one big line and claim you finish a system in a single line of code.

2.1	Hello World
Nothing better illustrates a programming language than code examples. And all self-
respecting languages start with a "Hello, world" example. Luban is no exception.

	std::console().writeline("Hello, world!");

Type above line into an editor, save the file as for example "helloworld.lbn". Then you 
can run your first Luban program by type the following in your command prompt of your 
operating system:

	Mycomputer > luban helloworld.lbn
	Hello, world!

This simple "Hello, world" Luban example code does two things. One is to construct one 
object of type std::console. Second is to call the writeline member function of the 
std::console type to print "Hello, world!" message.

2.2	Procedural Statements
The basic procedural constructions of Luban consist of expressions and statements. If you 
know C++ or Java, you can skip most of this section except the foreach statement.

2.2.1	Expression and Assignment
The most basic Luban statement can be an expression or an assignment statement. Like 
always, examples are the best to show different kind of expressions, listed in the order of 
precedence.
Constants, variables, internal property reference and collections: 
	1; 3.14; true; false; "Hello"; 'a';  variablex; [1,2,3]; input.x;
Indexing, object construction, member function call, external property reference, type 
casting and component call:
idmap["xp"]; astring.split(); std::file("myfile", 'w'); x.prpty; string(objx); 
xcomponent(input1=1, input2=2);
Single operand operators, ++ -- and negation:
	i++; ++i; i--; --i; -x;
Common arithmetic operations:
1+2; 10.0*3.0; 50%3; 50/3; "Hello, "+"world";
Type checking operations:
	objx isa string;
	typeof(objx) == string;
Equality and order checking:
	x == y;  x != y; x > y; x < y; x >= y; x <= y;
Logical expressions:
	true or false; x and y; not true; not a and not b;
Conditional expression:
	x > y ? x: y;
Assignment statements:
x = 1; x += 1; x[index] = 2; x.property = 3;  x*=2;  x/=3;
The details of some of the expressions like property reference and component call can be 
found in later chapters.

2.2.2	Flow Control
Luban has a set of common flow control statements. The below is a brief list and 
examples of usage.

IF statement:
	if ( a>b ) result=a;
IF-ELSE statement:
	if ( a>b ) result = a; else result = b;
WHILE statement:
	while ( x < 100 ) x++;
FOR statement:
	for( i=0; i<100; i++) std::console().writeline(vec[i]);
	for(;;); // forever loop 
FOREACH statement:
	foreach( key, value in themap ) std::console().writeline(key, ' ', value);
BREAK statement, used to jump out of a loop:
	for( i=0; ; i++) if ( i>100 )  break;
CONTINUE statement, used to jump to the beginning of a loop:
	for( i=0; ; i++) if ( i<=100 )  continue; else break;
DONOTHING statement:
	;
FINISH statement, terminate the code execution in current component.
	finish; 

2.2.3	Compound Statement:
Using bracket {} to collect one or more statement together makes a compound statement. 
You can use compound statement anywhere you use a regular statement. For example:
	while ( x <100 or y < 200 )  { x++; y++; }

2.2.4	Component Property Batch Setting
You can set multiple properties of a component in one statement, as below:
	astruct.(prp1=1, prp2=2, prp3=3);

2.2.5	Comments
To put comments into Luban code is the same as C++. Anything from // to the end of line 
are comments. Anything between a /* to a */ are comments too. For example:
	; // This line does nothing
	; /* this line does nothing either */

2.3	Luban Built-In Data Types
Luban has a set of native data types to support most common operations. Below describes 
the native data types and their relations.

2.3.1	Double and Integer:
The key words for double (double precision floating point number) and integer types are 
double and int in Luban. Their relationship is similar to the double and int type in C. As 
below examples:
	10/3; 		// result is integer 3
	10.0/3.0; 	// result is double 3.333333
	10/3.0;		// result is double 3.3333 mix double and int, result in double
	0 == 0.0; 	// result is true, you can mix and compare double and int
	2 > 0.1; 	// result is true, you can mix and compare double and int

2.3.2	Boolean
The key word for Boolean type is bool. Boolean can only be true or false. And unlike C, 
There is no implicit casting to and from any other type. And the operators for Boolean 
type data are not, and, or. Applying arithmetic operation to Boolean type will result in 
error. The condition expression used in IF, WHILE and FOR statements must result in 
Boolean too, or the Luban code execution will stop.
 
2.3.3	Character
Character type key word is char. It contains a single character. Below code example 
shows some operations on character type.
	c='a';  while ( c <'z' ) c++; // iterate through alphabet

2.3.4	String
String type key word is string. The below example Luban code shows operations for 
string type.
	s = "Hello"; c = s[1]; // result is 'e'
	s = "Hello"; s[0] = 'h'; // s becomes "hello"
	s = "Hello"; foreach( c in s ) std::console().write( c );  // will print out Hello
	s = "Hello"*2;  // result is "HelloHello"
	s = -"Hello"; // result is "olleH"
	s = "Hello" + "World"; // result "HelloWorld"
	// below are member function examples
	s = "Hello World"; words = s.split( ); // words is a vector ["Hello", "World"]

2.3.5	Vector, Map and Set
Vector type key word is vector. 
	x = 1; y=2; z=3; v = [x,y,z,4]; // v = [ 1,2,3,4]
	v[0] = 10; // v = [10,2,3,4] 
	total = 0;  foreach( element in v ) total += element; // total = 
	v.sort(); // v become [2,3,4,10]
	v2 = v+  [11,12,13]; // v2 become [2,3,4,10,11,12,13]
	v2.remove(0); // v2 become [3,4,10,11,12,13]
	v2.removeobj(10);  // v2 become [3,4,11,12,13]
	v3 = [ v2,v2]; // v3 is two dimensional vector

Map type key word is map. Keys are unique in a map. Code examples:

	x=1; y=2; z = 3;  word2number = { "one" : x, "two" : y,  "three" : z };
	word2number["four"] = 4; // insert or replace
	word2nubmer.remove("one"); // remove key "one" and associated 1
	word2number.insert("two",2.0); // no impact because key already exist	
	union = word2number + { "five":5, "six":6};
	foreach(key,val in word2number ) std::console().writeline(key,val); // iterate
	emptymap = {:};

Set key word is set. Set is simply a collection of unique values. See examples:
	oneset = { 1,  "hello", 3.14 };
	another = { 1,2};
	union = oneset + another;  // union = { 1,2,"hello",3.14}
	minus = oneset  another ; // minus = { "hello", 3.14}, common values removed
	joint = oneset  minus; // joint = {1}, the common values of oneset and another
	foreach( val in oneset ) std::console().writeline(val);  // iterate
	emptyset = {};

Casting operations among vector, set and map:
	oneset = { 1,2,3}; onevec = vector(oneset);
	keyvec=['a','b']; valvec = ['A','B']; onemap = map(keyvec, valvec);

2.4	Null and Error
Null is a special value in Luban, its key word is null. Null can be used in expressions just 
like a normal constant. The null value is special in the following two ways. First the null 
value is the default setting for all variables and properties. Second the null value is of no 
type.
Error type is a special type in Luban, with key word error. Value of error type can be 
generated by Luban internal operations, or explicitly constructed by Luban code. For 
example:
	errval = 1/0;
	if ( not errval isa error ) 
std::console().writeline("Your Luban engine is on fire");
	expliciterr = error("Hey, I am a born error");

2.5	Parallel Computing: Threading and Synchronization
Parallel computing is a built-in part of Luban, as the below sample code shows.
	myjobs::dothis(arg=100)  & // dispatch the expression in a different thread
	myjobs::dothat(arg =200) & // dispatch thread
	{ c.doOne();  d.doTwo(); } & // dispatch a block
	wait; // wait for all three threads to finish

You can selectively wait for certain thread to finish, as far as the thread can be associated 
with a variable. For example:

	x = y.domagic() & a = b.dogood() & // dispatch two threads
	waitfor x;  // wait for first thread to finish

	{ x = y.domagic(); a = b.dogood(); } &
	{ c = d.doevil(); f = g.wastetime(); } &
	waitfor f; // wait for the second thread to finish, the thread is identifiable by the 
last assignment variable

 Luban engine guarantees the object integrity in the multi-threading environment. If more 
than one thread operating on the same object, the order of operation is not deterministic, 
though the integrity of each individual operation is guaranteed.

2.6	Everything Is Object
On handling variables and objects, the major difference between Luban and other major 
languages like C++ and Java, is that all objects and variables in Luban are passing by 
value. There is no reference or pointer type in Luban. When assigning one variable to 
another in Luban, the object is semantically copied instead of passing a reference like in 
Java. Actually Luban's value semantics is very similar to C, except Luban does not have 
the pointer type. For example:
	
	a = [1,2,3];
	b = a;
	b = b + [4,5]; // b = [1,2,3,4,5] and a = [1,2,3]

The reason behind the design of Luban's value semantics is simplicity. Value semantics 
is straightforward and intuitive, requiring almost zero learning to understand.




3	Introduction To Luban Component Structure

This chapter introduces the basics of Luban component model. The foundation stone of 
Luban component model is the Luban structure, which is indicated by a key word struct 
in Luban. The below will show how to define and use a Luban structure.

3.1	Define A Luban Structure
Suppose our hello-world program becomes so popular that we want to reuse it as a 
component. The way to do it is to define the hello-world code as a Luban structure, as 
below example shows:

	namespace demo;

	struct helloworld( )
	as process
	{
		std::console().writeline("Hello, world!");
	}

Now let's save the above code as file "hello.lbn". Then we can write the below script to 
call this component.

	demo::helloworld(=);

We then save this script as "callhello.lbn". And finally we can run this new 
componentized hello-world program by typing the following command in the command 
window of your operating system:

	Mycomputer > luban hello.lbn callhello.lbn
		Hello, world!

Let's take a look at this new hello-world program in details. In "hello.lbn" file, we define 
a Luban structure named "helloworld". Luban requires every component must reside in a 
name space. That is why we see the line "namespace demo;" at the top. So the full name 
of this component is "demo::helloworld". The key words "as process" indicate the body 
of the Luban structure is a process. The difference between a process structure and other 
structure will be discussed in later chapters. All we need to know now is that we can use 
all the constructions used for scripting in the body of a process structure.
In the next script "callhello.lbn". We make a call to the component by using its full name. 
The syntax "(=)" indicates a dynamic call to a Luban structure. The details of the 
dynamic call to a Luban structure can be found in later chapter and here we only need to 
know the call will invoke the execution of the code in the Luban structure 
"demo::helloworld".
One thing need to be mentioned here is that in the above example Luban source code, 
there is no referring to the actual source code file name, components are only referred by 
its full name. This is no incidental, it is purposely designed so to avoid hard coding 
source code media. Yet we don't care about this for now.

3.2	Hello World Structure With Input And Output
The previous example defines a Luban component structure without any input and output 
properties. In practice, a component as a processing unit may need input and output 
properties to pass information, as the below example shows:

	namespace demo;

		struct greeting
		(
			input:
				saywhat, towhom;
			output:
				greetingmsg;
		)
		as process
		{
			msg = input.saywhat + ", " + input.towhom + '!';
			std::console().writeline(msg);
			output.greetingmsg = msg;
		}

The above Luban code defines a Luban structure with two input properties, saywhat and 
towhom. The internal process of the structure combine the two input property values into 
a single greeting message and set it to output property named greetingmsg. The side 
effect of this structure is to print out the greeting message to the console. As we can see, 
inside the structure, "input.property" is the convention used to refer input and output 
properties.  
As you can see from the example, a Luban structure definition has two parts. First is the 
structure interface definition, which is defined by listing the input and output properties 
in between the parenthesis after the structure name. The second part is the internal 
implementation of the structure. In this the internal of the structure is defined as a process 
with code between the brackets.
Now let's save this Luban component code as "helloio.lbn". Then we need to write a 
script to use this new component, as below:

	demo::greeting(saywhat="Hello", towhom="world");

Save the above one line in a file named "callhelloio.lbn", then run the following 
command on your operating system like below:

	Mycomputer > luban helloio.lbn callhelloio.lbn
		Hello, world!

From the example, arguments are passed into structure to be called by using 
propertyname=value pairs in parenthesis. The syntax difference between a Luban 
structure call and regular function call in C is that instead of lining up the arguments by 
order, arguments are explicitly paired with input properties by name.

3.3	More On Use of Luban Structure
So far the previous examples show the use of Luban structure in a way just like calling 
functions. But there is a key difference between C function and Luban structure. Luban 
structure is object with state indicated by its property values, while C function is mostly 
stateless. Luban structure is more flexible and can be used in many different ways, as 
below example shows:

	greeter = demo::greeting(saywhat="", towhom=""); // construct
	greeter.saywhat = "Hello"; // print Hello,!
	greeter.towhom = "world"; // print Hello, world!
	greeter(saywhat="Nice to meet you"); // print Nice to meet you, world!
	greeter(=);  // print Hello, world!
	greeter.(saywhat = "How are you", towhom="Luban"); // print
	greeter(=); // print How are you,Luban!
	std::console().writeline(greeter.greetingmsg);// print How are you, Luban!

Save this file as "callhelloalt.lbn", then run the script as below:

	Mycomputer > luban helloio.lbn callhelloalt.lbn
		,!
		Hello,!
		Hello,world!
		Nice to meet you,world!
		Hello,world!
		How are you, Luban!
		How are you, Luban!
		How are you, Luban!


Here we explain some details of the script line by line. The first line construct a Luban 
structure, assign to a variable, while triggering the execution of the structure once in the 
process. That is why we see a ",!" output line above. The next line set the value "Hello" 
into the input property named "saywhat" of the structure in variable "greeter" and the 
setting of input trigger the execution of the structure. That's why we see the second 
output line "Hello,!".  Similar process happens for the third line of code, which sets the 
property "towhom" to value "world". The fourth line is a structure call to a structure 
variable instead of to a structure type name as we previously know. And this call 
overrides the property "saywhat" with value "Nice to meet you", making the fourth 
output line "Nice to meet you, world!". 
It is important to know that the call to a structure does NOT change the state of the 
structure at all. Even with the explicit overriding of property values in the call, the 
property values of the original structure remain the same during the call. Actually the 
structure call generates a temporarily new structure that can be assigned to a different 
variable. And that explains the fifth line of code calling the original structure without 
arguments ends up printing the same greeting as before.
As mentioned above, property setting will trigger the execution of the structure. 
Sometimes we may want to set multiple properties while we only want one code 
execution after we finish. That is why we have the sixth line, which setting multiple 
properties of the structure to different values, and executing the code once the settings of 
properties finish. And that is why we see the sixth output line "How are you, Luban!". 
Just to show the setting of multiple properties does change the state of the structure, the 
seventh line call the structure again without arguments and see the "How are you, Luban" 
output once again. The last line of the script read the output property "greetingmsg" of 
the structure and print it to console. That's the third "How are you, Luban!" from.

3.4	Pass By Value Semantics
It is necessary to once again iterate the pass by value semantics of Luban. The passing of 
arguments in Luban structure call is by value, plus it is a one way street. What happens 
inside the structure has no possible impact on the caller. For example, the following code 
will result in syntax error:

	namespace demo;

	struct swapobj
	(
		input:
			x,y;
	)
	as process
	{
		temp = input.x;
		input.x = input.y; // this line has syntax error
		input.y = temp;
	}

 The reason for the syntax error is that Luban does NOT allow assignment toward input 
property inside a structure. Input properties are read only inside the structure.

3.5	Name Space Basics And Program Entry Point
There are two kinds of Luban source code unit ( i.e file ) that Luban interpreter accepts. 
One is Luban script, which is a sequence of Luban process statements and expressions. 
Luban interpreter will simply execute the script upon request.
Another kind of source code unit is component structure definition module that defines 
Luban structures. The first line of a component definition module must be the definition 
of name space in which the following structures will reside. Luban name space uses a 
syntax similar to C++ name space. When Luban interpreter encounter a component 
definition module, it will scan the module and register the structure components into a 
global name space data structure so it can be used in later call. Luban script can be used 
as the entry point of an application or system, while Luban component definition module 
can be used like library.



4	Structure Interface and Inheritance

Component oriented programming can be compared with LEGO toys in many aspects. 
First you need to put the parts into the right boxes so you can easily find them out when 
you need them. That is what Luban name space does: put components into organized 
places. Second you need to recognize the parts by their shape and the way they make 
connections so you can use them in the right place. And that is what Luban structure 
interface and inheritance do: formalizing the contract with external world by defining 
interface, and categorizing the interfaces by inheritance. The goal of Luban name space, 
structure interface and inheritance is the same: to keep our component workshop nice and 
neat.

4.1	Structure Interface: Property Flow Type and External Access Permission
As shown by the examples in previous chapter, the interface of Luban structure consists 
of a list of different kind of properties. The previous examples have shown the basic 
usage of input and output properties. And below we describe all different kind of 
properties and their behavior in a little formal way.
There are four different kinds of flow types for properties in Luban: input, output, store 
and static. And the properties can have different read/write permission for external 
depending on their flow type. There are three kind of permissions: readwrite, readonly 
and hidden, and using these key words can only change the access permission for 
external caller. From within the structure the access permission for properties are 
predefined and unchangeable. The purpose of this design is to define a general 
framework of information flow for Luban components. The below table shows the 
details:

	input: 	For external, readwrite. For internal, read only. Both unchangeable.
		Change of value triggers evaluation of the structure.
	output:	For external, readonly. For internal, write only. Both unchangeable.
		Value can only be changed from internal by evaluation.
	store: 	For external, hidden by default, changeable to readwrite or readonly
		For internal, both read and write.
		Change of value does not trigger evaluation.
	static:	For external, readwrite by default, changeable to hidden or readonly
		For internal, both read and write.
		Change of value does not trigger evaluation.
		Accessible only through structure type name.

From the above table and previous examples, we can see that for a Luban structure data 
flows from input to output. And the flow can no way be reversed. This flow model is as 
fundamental for Luban as function semantics for C.
We have known input and output properties from examples. The below example shows 
the use of store and static properties:

	namespace demo;

	struct aggregator
	(
	input	incoming;
		output	total;
		store	sofar=0;
	)
	as process
	{
		store.sofar = store.sofar + input.incoming;
		output.total = store.sofar;
	}

	struct useagecounter
	(
		static readonly totaleval=0;
	)
	as process
	{
		static.totaleval++;
	}

Let's save above code into a file "storenstatic.lbn". Then we can test our new structures 
with the below script:

	// testing aggregator
	agg = demo::aggregator(); 
	for(i=1; i<=100;i++) agg.incoming = i;
	std::console().writeline(agg.total);
	
	// test static
	counter1 = demo::useagecounter();
	counter2 = demo::useagecounter();
	counter1(=); counter2(=);
	std::console().writeline(demo::useagecounter.totaleval);

Then we save the above script as file "testsns.lbn". Afterwards we run the test by typing 
the following in the command window:

Mycomputer > luban storenstatic.lbn testsns.lbn
	5050
	2

The structure "aggregator" adds all numbers setting to its "incoming" property together 
and output the total to "total" property. The store property "sofar" in aggregator is used 
for internal state keeping. Because Luban prohibits reading value back from output 
properties, store property is used when some state data need to be remembered among 
different evaluations. Store property is similar to private data of C++ class.
The structure "useagecounter" maintains a global static property "totaleval" to count the 
number of evaluations of the structure. The static property is actually associated with 
structure type instead of structure instance. From outside the structure, the static property 
can only be referred by <structure type name> .<static property name>. From within the 
structure, it can be accessed using internal property naming convention that is <flow 
type>.<property name>.

4.2	Structure Interface Inheritance
The interface is the service contract of structure with the external world. We have seen 
the property flow types and external access permission key words, which are basic terms 
that can be used to draft such a contract.
The structure interface declares what each individual structure type does. Though when 
the number of different structure type grows, a large collection of unrelated structure 
interfaces are still difficult to remember and manage. And that is where the Luban 
structure interface inheritance come to help.
Similar to the class inheritance concept in Object-Oriented programming, we want to take 
the advantage of commonalities among different components by categorizing them using 
inheritance. The idea is that it is easier to understand ten animal kind than to understand 
one hundred individual strange animals. The below example shows how to code 
inheritance in Luban:

	namespace demo;

	struct DualOp
	(
		input:
			op1,op2;
		output:
			result;
	)
	as process
	{
		output.result = error("No actually operation for general dual operand");
	}

	struct Adder implements ::DualOp
	(
	)
	as process
	{
		output.result = input.op1 + input.op2;
	}

The above Luban code defines two structures. Structure "DualOp" is a general interface 
for two operand operations. Structure "Adder" inherits its interface from "DualOp" and 
implements the internal to add two inputs together and set to output.
You may notice the syntax "::DualOp", which is a short name for "demo::DualOp". All 
Luban's structure type names are full name. The short name can be used if the name 
space of the referred Luban type is the same as the name space of the caller component.
From this example, we can see that "Adder" inherits all input and output properties from 
"DualOp" and does not define any new property of its own. And we need to mention here 
that ONLY input and output property can be inherited. The store and static property can 
NOT be inherited. The reason for this design is to make interface inheritance simple.

4.3	Luban Inheritance Is Only For Interface
Unlike the general Object-Oriented languages like Java and C++, Luban's inheritance 
mechanism is only for the interface. When one Luban structure inherits from another, 
only the interface of the parent structure is taken, and that excludes store and static 
properties. If you wish to use the internal implementation of the parent structure, you 
need to express you intention explicitly, as below example shows:

	// this example uses the Adder structure defined in previous example
	namespace demo;

	struct AdderWithUseCount implements ::Adder
	(
		static usecount=0;
	)
	as process
	{
		static.usecount++;
		output = ::Adder(input=::Adder.input).output;
	}

The above example defines a structure "AdderWithUseCount" that works the same as the 
structure "Adder", only with one more static usage counter property to count the number 
of evaluations.
The magic in this example is the last line of the structure process code. This line simply 
says: take the portion of input inherited from "Adder" structure, feed to a call to structure 
"Adder", then take the output of this call and set to the output of structure 
"AdderWithUseCount".
What actually happens in this example is very much like AdderWithUseCount inherits 
both interface and implementation from Adder. Though the taking of  "Adder" structure's 
implementation is explicitly stated in one line of code. The purpose of this design is to 
avoid the tricky ambiguity issue for inheritance by allowing programmer to state 
intention explicitly. Luban allows multiple inheritance of structure interfaces like C++.


5	The Dynamic Type System of Luban

All the objects inside Luban can be separated into two categories: data types and structure 
types. Structure types are the components coded in Luban. You can create as many kinds 
of Luban structure types as you wish just like you can code as many functions as you 
wish in C. 
Data types are those built-in and/or imported data types with predefined set of member 
functions and applicable operators. Map, set, vector, double, int, bool, char and string are 
the examples of built-in data types, while std::file, net::socket are examples of imported 
C++ data types. The fundamental difference between structure type and data type is that 
you can not code a new data type with Luban. One design philosophy of Luban is that the 
basic data types are low level software elements that should be accessible from Luban, 
but Luban should not be used to make low level elements. Just like bricks are used to 
build house, instead of bigger bricks. Luban's belief is there should be a fundamental 
programming paradigm shift from software element level to component level.
Though structure types and data types are naturally different. They still obey a more or 
less common set of rules. These rules are to be discussed in this chapter.

5.1	Name of Data Type and Structure Type
The naming rule of Luban data type and structure type are the same. They all must be a 
full name with name space. But Luban built-in types are keywords and do not need name 
space prefix. For example:

	string;  // built-in type
	std::file; // standard imported data type
	net::listener;  // imported data type
	net::socket; // imported data type
	std::print; // a structure type

The name space part in a type name can be omitted only when referred in a component 
that resides in the same name space, as below code shows:

	namespace std;

	struct print
	(
		input obj;
	)
	as process
	{
		::console().write(input.obj);
	}

The above code simply wraps the calling of member function of std::console type in a 
structure named std::print. We can see the referring to std::console in std::print structure 
does not use the name space part.

5.2	Construction of Data Type and Structure Type
The syntax of object construction in Luban is type name followed by parenthesis, as 
shown in the below example:

	// print hello world
	console = std::console();
	console.writeline("Hello, world!");

	// print hello world again
	printer = std::print();
	printer.obj = "Hello, world!\n";

Parameters can be used in the object construction. But the syntax of argument passing is 
different for data type and structure type. Look at the below example:

	// create file as data type
	file = std::file("helloworld", 'w');
	file.writeline("Hello, world!");

	// print hello world to console
	printer = std::print(obj = "Hello, world!\n");

To pass parameters into data type construction, you just need to line the parameter values 
up. To construct a structure with specified property values, you need to pair up the 
property names with its values. Another big difference for structure construction with 
specified property values is that if the specified properties include input property, the 
structure will be evaluated once after construction. Yet the structure construction without 
any specified property values does not trigger any evaluation.

5.3	Explicit Type Casting
Type casting in Luban is just an object construction with a single argument. Like below:

	int("100"); // result 100
	string(100); // result "100"
	double(100); // result 100.0
	int(3.1415); // result 3
	
Casting to string type is special because it is universally enabled for all Luban built-in 
and imported data types. Actually when std::console type is asked to print an object, it 
will cast the object to a string then print the string.

Type casting does not apply to structure type.

5.4	Dynamic Type Checking: isa and typeof Operators
You can dynamically check the type of any object in Luban with isa and typeof operators, 
as shown in below Luban script:
	d = 3.1416;
	s = std::file("pie", 'w');

	//  check type and decide what to do
	if ( d isa double and s isa std::file )
		s.writeline(d);
	else
		s.writeline("The end of world is coming");

	// do the same thing in a different way
	if ( typeof(d) == double and typeof(s) == std::file )
		s.writeline(d);
	else
		s.writeline("The end of world is coming");

The structure interface inheritance is taken into account for type checking. For example 
the variable "test" in below Luban code has value true because structure demo::Adder 
inherits interface from demo::DualOp ( Previous example):

	adder = demo::Adder();
	test = adder isa demo::DualOp; // test = true

5.5	Type Expression
One unique feature of Luban is type expression, which gives more power and flexibility 
to Luban's type system. Type expression is part of the Luban expression. The result of 
type expression can be assigned to variable and passed around just like normal object. 
The details of type expression can be shown in the following Luban code examples:

Type name alone can be a valid type expression.
	stype = string; // type name is type expression
if ( not "Hello"  isa dtype ) std::console().writeline("Insane");

Multi-type type expression is a collection of different type expressions. The isa operator 
returns true if the  type of object matches one of the types in a multi-type.

	streamtype = < std::file, net::socket >
	s1 = std::file("destfile",'w');
	s2 = net::socket("destserver",  6500);
	if ( s1 isa streamtype and s2 isa streamtype ) std::println(obj = "Good");

Enumerated type is a collection of constants. The isa operator returns true if the value of 
object equals any one of the collection. Look at the below example:

	littleprime = < 1,2,3,5,7 >;
	test = 5 isa littleprime; // test = true

The type name for type object is typeinfo. Below shows how it works:
	
	stringtype = string;
	test = stringtype isa typeinfo; // test = true


5.6	Gate Keeper: Typed Property and Variable
There are tools in Luban to enforce strong typing policy if necessary. The type of 
property can be explicitly declared with type expression in structure interface definition 
to make sure only the objects of specified type can pass through. And also local variable 
can be bound to certain type using type expression. The setting of object of wrong type to 
a typed variable will result in the abortion of structure evaluation or script execution.

We can see the use of typed variable from below Luban code:

	double dx;
	dx = "Hello"; // evaluation aborts here
	std::console().writeline("You should never see me, the world should have ended 
before me");

The above example assigns a string value to a variable "dx" that is a variable with 
predefined type double. The assignment results in the aborting of the evaluation of the 
script. So the last line of code should never be executed and the print should never appear 
on screen.

The below example shows the use of typed property in structure interface:

	namespace demo;

	struct powertoint
	(
		input:
			< double, int > base;
			int power;
		output:
			result;
	)
as process
	{
		result = 1;
		for( I = 0; I < input.power; I++)
			result *= base;
		output.result = result;
	}

We can save the above code to a file "powerint.lbn". Then we can write another script to 
call this new component, as below

	sqr = demo::powertoint( base = 4, power = 2 ).result; // pwr = 3.1416*3.1416
	std::println(obj=sqr);
	sqrt = demo::powertoint( base = 4, power = 0.5 ).result;
	if ( sqrt isa error ) std::println(obj="Good, to get square root failed as 
expected");
	
	pwrcalc = demo::powertoint();
	pwrcalc.power = 0.5; // evaluation stops here
	std::println(obj="Surprise! World should have ended before me");

We then save the above script as "testpowerint.lbn" and start the test like the following:

Mycomputer > luban powerint.lbn testpowerint.lbn
	16
	Good, to get square root failed as expected
	
We can see the first evaluation of demo::powertoint succeeded and gave result 16 to 
print. The second structure call having property "power" set to 0.5 that violates the int 
type of the property results in an error value, causing the printing of "square root failed" 
message. The line before the last line sets a double value into the property "power" of int 
type, causing the evaluation to stop. That's why we don't see the last line get executed.


6	Component Composition

So far we have learnt how to script Luban and write Luban structure component as 
process code. As we mentioned before, there is another way to define a Luban structure, 
which is composition. The way composition defines a Luban structure is to lay out the 
sub-components and specify the dependencies among them. The evaluation mechanism 
of composition cell is to propagate the data change The Luban structure defined as 
composition has the same interface as process structure and can be used the same way. In 
this chapter, we go through the component composition with a series of examples.

6.1	Composition 101
The basic format of Luban composition is simply  a list of sub-components. The sub-
component in a composition is called component cell. Each component cell has a name 
and a definition. The definition of the component cell specifies the content of the 
component cell and its dependencies with other component cells outside. The below 
example illustrate a basic composition:
 
	namespace demo;

	struct simplecomp ( output oneoone; )
	as composition
	{
		A1: 100;
		A2: A1+1;
		output.oneoone: A2;
	}

The above composition computes 100+1 in a way like spreadsheet. There are two 
component cells in above structure, A1 and A2. A1 contains a number 100. A2's content 
is an expression "A1+1". The last line links the result of A2 cell with output property 
"oneoone". Then we use the below Luban script to call this structure:

	result = demo::simplecomp(=).oneoone; // result = 101

To show the difference between composition and process, we change the structure 
"simplecomp" to below:

	namespace demo;

	struct simplecomp ( output oneoone; )
	as composition
	{
		output.oneoone: A2;
		A2: A1+1;
		A1: 100;
	}

The structure "simplecomp" behaves exactly the same as before. In Luban composition, 
the order of listing of the component cells does not matter, as far as all the cells and their 
dependencies remain the same, unlike the process structure for which the order of 
operations is essential.

6.2	Different Component Cells
There are two kinds of component cells that can be used in a Luban composition, ad hoc 
cell and typed cell. We discuss these two kinds of cells in this section.

6.2.1	Ad hoc Cell
Ad hoc cell contents are very much like what people normally put into spreadsheet cells. 
They can be constants, expressions. In Luban composition, the ad hoc cell can also 
contain Luban script code to do more sophisticated processing, as shown below:

	namespace demo;

	struct compadhoc
	(
		input	 in1, in2;
		output 	out;
	)
	as composition
	{
		A1: input.in1 + 1;
		A2: input.in2 + 1;
		A3: { std::console().writeline("run A3"); A3=A1*A2; }
		A4: { std::console().writeline("run A4"); A4=A2*A2; }
		output.out: A3+A4;
	}

The above composition uses only ad hoc cells. The cell A1 and A2 are simple 
expressions. Just as expected, Luban will evaluate the expression and save the result in 
the cell.
Cell A3 and A4 contains Luban script code. When data updating event reaches these two 
cells, Luban execute the script code just like normal script. The difference between an 
expression cell and a script cell is that script cell does not get any value returned from 
script by default unless the script in the cell explicitly set the value of the cell itself, like 
cell A3 and A4 do in above code.
The last line in above example links the result of expression "A3+A4" to the output 
property "out". The output property linking cell is one special kind of cell that can only 
contains single expression, no script code is allowed.

6.2.2	Typed Cell
Typed cell is to enable user to directly put pre-defined structure component into 
composition, like below example:

	namespace demo;
 	
	struct TwoAdder
	(
		input op1, op2;
		output result;
	)
	as process
	{
		output.result = input.op1+input.op2;
	}

	struct FourAdder
	(
		input op1,op2,op3,op4;
		output result;
	)
	as composition
	{ 
		adder1:  demo::TwoAdder(op1=input.op1, op2=input.op2);
		adder2: demo::TwoAdder(op1=input.op3, op2=input.op4);
		adder3: demo::TwoAdder(op1=adder1.result, op2=adder2.result);
		output.result: adder3.result;
	}

The above example illustrates how to compose a adder that can add up four numbers 
from adder that adds two. You can see inside the "FourAdder" composition there are 
three "TwoAdder" components inside, two of them linking to input properties while the 
third one adds the result of first two and send result to output property.
Actually the typed cell is not much different from expression cell, except that the typed 
cell can not be used by its own value like ad hoc cell. The other cells of the same 
composition can only use the output property of the typed cell.

6.3	Dependency Specification Rules
Luban composition gives user the freedom to put expression, script and typed structure 
into component cells, while Luban figures out the dependencies automatically for you. 
Yet there are still rules for dependency specification to make sure the composition is 
semantically clear and unambiguous.

6.3.1	Change Nothing But Yourself, But Do Read Your Surrounding
In a composition, a cell can not modify other cells, it can only read from them. These 
operations are considered as modification: directly assignment, member function call and  
property setting. So if there is such operation upon other cells in a cell definition, Luban 
will report error. This is to make sure the data flows one way as commonly expected.
A cell can change itself by directly assign value to itself. Though a cell can not read the 
previous value of itself back. So calling member function on itself is also prohibited 
because it involve reading previous value back. The purpose of this rule is simply to 
avoid confusion.

6.3.2	No Tail Chasing
Luban does not allow cyclic dependencies among synchronized cells in a composition. 
The details of synchronized cells can be found in later chapter. So far in all the sample 
compositions we have seen, all the cells are synchronized.

6.4	Inheritance and Composition
Composition can be used together with Luban interface inheritance to create new 
structure based on old one, like below example shows:

	namespace demo;

struct AdderPlus implements TwoAdder
(
	output diff;
)
as composition
{
	output: demo::TwoAdder(input=demo::TwoAdder.input);
	output.diff: input.op2  input.op1;
}

In above example, the structure "AdderPlus" takes the interface of "TwoAdder". It also 
put one instance of "TwoAdder" into its composition and wired the right portion of its 
input to the "TwoAdder" and wired the output of "TwoAdder" directly to its output. So 
"AdderPlus" basically get interface and implementation of "TwoAdder" in this way. It 
also adds one extra output of its own, which is the difference of its two input properties. 
The first line in the composition can only be used with structure inheriting interface from 
other structure. Luban will do type checking to make sure the wiring work with 
inheritance. There could be ambiguity in the case of multiple inheritance. The basic rule 
to handle ambiguity is to explicitly specify the wiring of the output property on which the 
ambiguity occurs.

6.5	Composition Vs. Process
Composition does its best when there are significant number of components in a system 
and the dataflow among the components are complicated. It is difficult to code multi-
directional dataflow with process that is basically one dimensional.
Process should be used when the system have sophisticated control logic, meaning if 
conditions and loops. In practice, it could be the case that small components more likely 
use process while large components could be more compositional.


7	Asynchronous Structure: Implicit Thread and Queue

So far the Luban structure we have seen can be called synchronous structure, meaning the 
property values of a structure reflect the state of the structure and you can expect the 
change of input properties will trigger the internal evaluation and likely the change of 
output properties to put the structure into a new consistent state. And the internal 
evaluation happens in an atomic fashion, meaning Luban guarantees that the structure is 
always in a consistent state in every access.
In this chapter we introduce a new kind of structure: asynchronous structure. 
Asynchronous structure can have all the input, output, store and static properties just like 
the synchronous structure. The major difference is the semantics of the set and get of 
input and output properties. For an asynchronous structure, the semantic of input and 
output is more loose. What is defined is that data flows into input and flows out of output, 
and there is no consistency pairing between input and output. And the data flows in and 
out a asynchronous structure will be queued, unlike the synchronous structure, the new 
property value will overwrite the previous one. The store and static property value of 
asynchronous structure will not be queued, queuing is only for input and output. 
Asynchronous structure behaves like pipe, while the synchronous structure is more 
functional.
The purpose of asynchronous structure is to model asynchronous components in system. 
The examples of asynchronous components include network messaging and interactive 
user interface. And usually large system more likely behaves in an asynchronous way.
In actual implementation of Luban, the asynchronous structure is implemented as an 
object with a live thread inside. The inside thread takes data from input queue and put the 
output to the output queue, while outside user can put new data onto input queue and take 
output from output queue. So asynchronous structure is multi-threading implicitly.

7.1	The First Asynchronous Structure Example

	namespace demo;

	asynch struct multiplexer
	(
		input flow1, flow2;
		output merged;
	)
	as process
	{
		output.merged = input.flow1 &
		output.merged = input.flow2 &
	}

The above example defines a asynchronous structure named "multiplexer". The structure 
merges data input from "flow1" and "flow2" into the output "merged" just like a telecom 
multiplexer. Inside the "multiplexer", there are two user coded threads, one to read 
"flow1", another to read "flow2", both put the reading into "merged". There are several 
details of asynchronous structure that make this structure work. 
First, every read of input property removes one value from the input queue. When the 
queue is empty, the read operations will block and wait until new value comes in. Input 
property can not be read from outside. Remember in the case of synchronous structure, 
repeated reading of the same input property read back the same value.
Second, every assignment to the output property adds one value to the output queue. For 
the same operation, synchronous structure will only take the last assignment to the output 
property. Reading of output property from outside will block if the output property queue 
is empty.
Understanding the above details, we can code a simple case of producer and consumer in 
which producer and consumer share the same queue for communication.

	namespace demo;

	struct simplequeue
	(
		input inq;
		output outq;
	)
	as process
	{
		outq = inq;
	}

The above component behaves like a simple multi-thread queue with one end to put in 
and another end to read out data, plus it will make reader wait when the queue is empty. 
Then we can use the above component in a sample script like below:

	// 

	q = demo::simplequeue();
	
	{ obj= myns::producer().produce(); q.inq=obj;  } &  // producer thread

	{  myns::consume( obj = q.outq ); } &  // consumer thread

	// 

Above script starts two threads, one to produce object and put it into the "inq" of the 
queue named "q", while another to read object out of "outq" of "q" and feed to 
"myns::consume" structure. When the "outq" is empty, the consumer thread will sleep.
Above examples show how to code asynchronous structure and use it in Luban script. 
The next section will show how to code and use asynchronous in composition.

7.2	Asynchronous Structure In Composition
Asynchronous structure and composition naturally work together. While in process script, 
user need to pay attention to the semantic difference of an asynchronous structure, in 
composition, user wire the asynchronous the same way as synchronous structure. Luban 
take care of the independent thread inside the asynchronous structure automatically.
In below example, we code one asynchronous structure to listen to network message. 
Then we use the structure in a composition.

	namespace demo;

	asynch struct messenger
	(
		output msg;
	)
	as process
	{
		socket = net::socket("msgserver", 6500);
		while ( true )
		{ 
obj = socket.readobj();
if ( obj == "good bye" ) break;
output.msg = obj;
		}
	}

	struct listenNprint
	()
	as composition
	{
		MSG:  ::messenger();
		PRINTER: std::println(obj = MSG.msg );
	}

Above code creates an asynchronous structure to listen to the port 6500 on server 
"msgserver", and set the output "msg" whenever object arrives from the server. The 
"messenger" structure will only stops when it hears "good bye" from the server. The next 
composition uses this structure as its component and wire it together with a structure that 
prints message on console. We can run the composition structure using the below script:

	demo::listenNprint(=);

When the composition "listenNprint" runs, it will listen to the message on network print 
what it hear on the console until the server says "good bye" to it.

7.3	Ad Hoc Asynchronous Cell In Composition
You can put ad hoc asynchronous cell into a composition by simple declare the ad hoc 
process cell as "asynch". The code inside the cell will follow the asynchronous structure 
semantics automatically. We can code the "listenNprint" structure using ad hoc 
asynchronous cell as below:

	namesapce demo;
	
	struct listenNprint
	()
	as composition
	{
		asynch MSG:  { socket = net::socket("msgserver", 6500);
				while ( true )
				    { 
obj = socket.readobj();
if ( obj == "good bye" ) break;
MSG = obj;
				    }
				}
		PRINTER: std::println(obj = MSG );
	}

You can notice that in the ad hoc cell, there is no output property to set except itself. And 
its fellow component cells can only refer the value of itself instead of the output property.

7.4	Asynchronous Component and Cycle In Composition
As mentioned in previous chapter, cycle consists of only synchronous cells in a 
composition is not allowed. In another word, if the cycle has one or more asynchronous 
component inside, it is OK for Luban. Let's look at the below example:

	namesapce demo;

	asynch struct player
	(
		input receive;
		output send;
	)
	{
output.send = 1; // send a ball
while ( true )
{
			ball = input.receive;
			std::println(obj=ball);
			if ( ball == 1000 ) break;
			ball++;
			output.send = ball;
		}
	}

	struct pingpong
	()
	as composition
	{
		P1:  ::player(receive = P2.send );
		P2: ::player(receive = P1.send );
	}

It is obvious that the composition structure "pingpong" has a cycle involving cell P1 and 
P2. Yet Luban is still going to happily take it and run through because P1 and P2 are 
asynchronous component, so it does not violate Luban's no-cycle rule.
If you run "pingping" structure, it will print out number 1 to 1000, and print each number 
twice in a row.


8	Error Handling of Luban

Luban use a special type: error type to handle errors. The value of error type is generated 
as error happens in Luban code evaluation. The basic principle of Luban error handling is 
very simple and can be described in below two points:

?	Propagate error value along the line of expression, assignment and control flow if 
sensible.
?	Abort the evaluation of Luban structure or script if the error can not be propagated 
in a sensible way.

8.1	So Long Try and Catch Madness
There are enough "catch what at where" confusion about exception in many different 
languages. Luban goes a different way, it does not have exception at all, neither try and 
catch statements. The basic idea is that to use error value to represent error is simpler and 
easier to understand. Error value also fits Luban's data flow model very well.

8.2	Error Value Generation and Propagation

	// below variables all contain error
	
	firsterr = 1/0;
	alsoerr1 = firsterr++;
	alsoerr2 = firsterr + alsoerr1;
	test = firsterr isa error and alsoerr1 isa error and alsoerr2 isa error; // test = 
true

In above script, first error is generated by operation to divide with zero. Then the error 
propagates through a series of expression and assignment statements. So the error 
happens and spread logically corresponding to the code structure. Responsible user can 
decide to check error and take action at any point.

8.3	Errors That Stop The Show
There are certain points that is error sensitive in Luban. When errors happen at those 
points, Luban can only stop the evaluation of the current structure or script and report 
error. These points are listed as following.

Failure of assignment is one of the error sensitive points. Failure of assignment can be 
caused by assign object of wrong type to typed variable or structure property, for 
example:

	int intvar;
	intvar = 3.1416; // world ends here, assign double to a int type variable
	std::println(obj="Devil shall never see the light"); // never reach this line

If the result of condition expression inside control flow statement is not of bool type, 
Luban will stop the evaluation because it can not determine the control flow.

	X = 0;
	if ( X )   // X is not bool type, evaluation stop 
  X++;

When the call to a process structure stops because of error, the call returns error value 
instead of a fully evaluated structure.

Except the above error sensitive points, when error happens Luban will happily continue 
and pass the error object around. It is totally up to the user to decide where they want to 
check the error or if they want to check the error at all.


9	Utility Data Types and Structures

There are a set of commonly used data types and structures packaged together with 
Luban programming language. Though they are not part of the Luban programming 
language, they are so useful that we need to use a chapter to describe them.

9.1	Console, File and Socket
These are the basic data types used to persist information or pass them around network. 
And they share a more or less common interface. Below listed are their Luban type 
names and the description of their member functions.

Luban type names.
Console:	std::console
File:		std::file
Socket:		net::socket

Member functions that apply to all above data types:
write(obj1,obj2):
Writes the object in human readable string format to the media.
Return null, or error in case of failure.
writeline(obj1,obj2):
Same as write, only adds one extra line break at the end of each object string.
Return null, or error in case of failure.
read( int n=1 ):
Reads specified number of characters, or read one character if n not specified.
Returns a string containing all characters read.
readline():
Reads the media to break of line.
Returns a string.
writeobj(obj1,obj2):
Writes the objects in platform independent binary format from which the object 
can be restored.
Returns null, or error for failure.
readobj():
	Restore object back from media, likely the object written by writeobj.
	Returns restored object.

What need to be mentioned is that writeobj and readobj are designed to be used in pair. 
Any object serialized and persisted with writeobj can be restored using readobj.

9.2	How To Create, Read and Write File
The below example script shows how to use file data type:

	fw = std::file("objfile", 'w'); // open a file for writing
	fw.writeobj([1,2,3]); // write a vector object
	fw.close(); // close the file
	fr = std::file("objfile", 'r'); // open file for reading
	vec = fr.readobj(); // read one object back
	std::println(obj=vec); // print out [1,2,3]

9.3	Socket Routine, Server and Client
The below scripts demonstrate how to use socket, including both client and server side. 
The server side uses a new data type net::listener that is basically a TCP port listener. It 
can be created given a port number. Its major member function is accept() that accepts 
one incoming connection and return a socket object that can talk to the client.

Server script:

	// this server just say hello to all clients
	listener = net::listener(6500); // take port 6500 and listen to it
	while( true ) // forever loop
	{
		socket = listener.accept();
		socket.writeobj("Hello, client");
	}

Client script:

	socket = net::socket("localhost", 6500); // connect to server
	msg = socket.readobj();
	std::console().writeline("The server says: ", msg);

9.4	Utility Structures: std::println and std::print
Just for convenience, std::println and std::print structures are coded as part of Luban 
package. The structure print object to console in a simple way. Below is their source 
code:

	namespace std;

 	struct println( input obj;)
	as process
	{   std::console().writeline(input.obj); }

 	struct print( input obj;)
	as process
	{   std::console().write(input.obj); }

9.5	Utility Structure std::des
Every Luban object can dump itself into a binary stream. In order to restore one object 
out of a binary string, the std::des structure is needed, as below sample code shows.
	xguts = x.serialize();
	xback = std::des(stream=xguts).obj;


10	Add New Data Type To Luban

This chapter demonstrates a way to code a C++ class and export it to Luban. This chapter 
is only for hard core professional who wishes to export C++ classes into Luban.
Basically the adding of new data type can be done in two steps. First is to code the class 
in a Luban compliant way, second is to let Luban know where to load the class.

10.1	Code a Luban Data Type In C++
Here the example is to code a new Luban data type demo::greeter. This data type does 
the simple job to print out "Hello, world" upon request. 
To code any Luban compliant data type in C++, the convention is to always use two 
source files, one header file and one source module. In our simple greeter case, we will 
code header file greeter.hpp and greeter.cpp.

Below is the source code in greeter.hpp:

	#include <lbtypes/lbobject.hpp>
	#include <lbtypes/LBDeclareMacro.hpp>

	class Greeter : public Luban::LBObject
{
 LBDECLARE( Greeter )

public:

string toString() const;   // for human readable printing
ostream& toStream(ostream& o) const;  // serialize guts
istream& fromStream(istream& i, int major=-1, int minor=-1); // restore
virtual bool equals(const LBObject& another) const;

// member function visible in Luban
LBObject *luban_greet(const LBVarArgs *args);
};
 
What the header file tells us:
?	All Luban data types are derived from Luban::LBObject data type.
?	A mysterious macro "LBDECLARE()" needs to be put in.
?	There are four functions must be implemented for all Luban data types. 
"toString()" is used to convert the data object to a human readable string, and this 
function makes all Luban types printable and castable to string type.
"toStream()" is used to serialize the internal content of the data object. This function 
makes Luban types universally serializeable.
"fromStream()" is used to restore content from a serialized data stream which is 
produced by the "toStream()" function in the same class. Please note that 
"toStream()" only needs to be responsible to "fromStream()" function, meaning that 
the stream from "toStream()" can be used by "fromStream()" to restore to the 
original state.
"equal" function offers the comparison among data objects in the same class or 
different classes.
The conclusion, a Luban data type is required to know minimum three things:
1.	Print itself
2.	Serialize/de-serialize itself
3.	Check equality against others
?	The last member function "luban_greet" bears a signature that is required for any 
luban class member function to be exported to Luban language.

Then next step is to define these in a CPP module. Below is the source code in 
greeter.cpp:

	 #include "greeter.hpp"
	#include <lbtypes/LBDefineMacro.hpp>

	  LBDEFINE_EXPORT(Greeter, "demo::greeter", 1, 0 )

 LBDEFAULT_STATIC_CONSTRUCTOR(Greeter);

  string Greeter::toString() const
  {
    return "Greeter";
  }
  ostream& Greeter::toStream(ostream& ost) const
  {
    return ost;
  }

  istream& Greeter::fromStream(istream& ist, int major, int minor)
  {
    return ist;
  }

  bool Greeter::equals(const LBObject& another) const
  {
return dynamic_cast<const Greeter*>(&another) ;
  }

LBEXPORT_MEMBER_FUNC(Greeter::luban_greet,"greet", "string greet()")
LBObject *Greeter::luban_greet(const LBVarArgs *args)
{
	if ( args == 0 || args->size() == 0 )
		return new LBString("Hello, World");
	return new LBError("demo::greeter() function takes no arguments");
}

For the greeter.cpp module, the first thing needs to be put in is the LBDEFINE_EXPORT 
macro. From its appearance it indicates the mapping from C++ class name to Luban data 
type name plus the version number, and the version number can be used by the 
fromSteam() member function to decide what to do when restoring a data object stream of 
different version.
The line after the LBDEFINE macro is another macro 
LBDEFAULT_STATIC_CONSTRUCTOR that defines a default form of static constructor 
that does nothing more than calling the default constructor. More details of static 
constructor can be found in next section.
greeter.cpp also defines the mandatory virtual functions. toString() function returns a 
simple string to indicate itself as a greeter object. ToStream, fromStream functions do 
virtually nothing because there are no internal data to be serialized or restored. Equals() 
function check if the object compared against is a Greeter type, and returns true if it is.
The most interesting function here is the luban_greet. Luban requires that the member 
functions to be exported to Luban to have the same signature, which luban_greet bears. 
Basically the function signature can pass any number of arguments of any type, though 
the member function itself has to check the number and type of arguments then either 
perform requested action or return error value.
To export a member function to Luban, the mapping from the C++ member function 
name to the Luban member function name needs to be indiciated. That is what the 
LBEXPORT_MEMBER_FUNC macro does. The first argument is the C++ member 
function name, then corresponding name in Luban. The last argument is the synopsis of 
the function.

After the coding, we can compile our new class into a shared library. In our case we 
named the library libgreeter.so. That finishes all we need to do for C++ coding of a new 
Luban data type.

10.2	Inform Luban About The New Type
Next thing we need to do is to tell Luban how to load this new data type. For this step all 
we need to do is to list the new data type's C++ class name, its Luban type name and the 
shared library name in a file, then tell Luban to read the file at starting. Luban has a 
dynamic data type loading mechanism that will load the shared library when the data type 
is needed at run time.
For our new demo::greeter type, we need to put the below line into a file.
	
	Greeter	libgreeter.so	demo::greeter

The format of the line is C++ class name, shared library name then Luban type name. 
Let's write the line into a file named "import_types".

Now everything is ready, we can test to use this new type in Luban, like below lines 
show:

Mycomputer > luban t import_types i
?	s
g = demo::greeter();
msg=g.greet();
^D
Hello, World
>quit
MyComputer>

In the above example, Luban interpreter is started with t flag that tells Luban to read a 
file of imported types. In our case there is only one data type demo::greeter in the file. At 
Luban interpreter command line, we use "s" command to start scripting. Then Luban runs 
the script and print out the result of the last evaluation that is the famous "Hello, World" 
message.

10.3	Basic Operations
For this new demo::greeter type, only a minimal basic operations can be performed. 
These operations include assignment, equality comparison, casting to string, serialize  to 
stream, restore from stream and member function call. The below sample code shows the 
basic operations.

	X = y;		// assignment
	X == y;	// equality check 
	x.y();		// member function call
	string(x);	// cast to string

There is a set of standard member functions available for all Luban data types:

	H = x.hash();  // hash key for the object, default value 0
	Sz = x.size();  // apply to container and string type, default value error
	x.contains(y); // apply to string and container type
	x.clear(); 	// apply to string and container
	guts = x.serialize(); // returns the binary guts stream in a string
	obj = std::des(stream=guts).obj;  // restore object from a string

10.4	More Operations
One obvious way to expand available operation is to add and export more member 
functions. There is also a set of virtual functions that can be implemented so more Luban 
expression operators can be applied on the data type. These functions are optional. If they 
are not implemented, the corresponding operation will result in error value. The 
following lists the virtual functions and their corresponding operation in Luban.

void plus(const LBObject& x)		+, +=
void minus(const LBObject& x)	-, -=
void mul(const LBObject& x)		*, *=
void div(const LBObject& x)		/, /=
void mod(const LBObject& x)	%, %=
void neg();				-x
void plusplus();			++
void minusminus();			--
bool before(const LBObject& x)	<,>,<=,>=

//container related functions
int hash()			//used as hash key when the object is used as key in a map
const  LBObject* index(const LBObject* idx)	//  a=b[c];
LBObject* index(const LBObject* idx)		// b[c] += 1;
bool replace(const LBObject* idx, const LBObject* value);		// a[b]=c; 
LBConstIterator *getIterator();	// foreach( x in vectory )
int size();				// number of elements

10.5	Static Constructor And Casting
As previously mentioned, Luban requires all data types to have a static constructor. 
Luban static constructor is simply the function Luban calls to construct the object upon 
request. Technically it is a relay between Luban and the real C++ constructors of the data 
type. There is a default implementation available in the format of a macro. But it does 
nothing more than calling the default constructor of the class.
You need to implement your own static constructor if you need to put arguments into 
object construction. A sample static constructor is like below:

	// sample static constructor for a fake LBComplex type
	LBObject *LBComplex::staticConstructor(const LBVarArgs *args)
	{
		int numarg = args? args->numArgs():0;
		switch ( numargs )
		{
			case 0:
				return new LBComplex();
			case 1:
	const LBDouble *dbl  = dynamic_cast<const LBDouble*>(args->getArg(0));
				if ( !dbl )
					throw LBException("Wrong type");
				return new LBComplex(double(*dbl));
			case 2:
	const LBDouble *dbl1  = dynamic_cast<const LBDouble*>(args->getArg(0));
	const LBDouble *dbl2  = dynamic_cast<const LBDouble*>(args->getArg(1));
			if ( !dbl1 || !dbl2 )
				throw LBException("Wrong type");
			return new LBComplex(double(*dbl1), double(*dbl2));
		}

		throw LBException("Wrong number of args");
	}

With above static constructor coded, user can construct complex type in Luban like 
below:

	C1 = math::complex(); // default
	C2 = math::complex(1.0); // complex with only real part
	C3 = math::complex(1.0, 2.0); // both real and imaginary

From above example, we can see static constructor also perform the task of type casting, 
in the case of single argument to the constructor. The variable C2 contains a complex cast 
from a simple real number.
If we wish to cast a complex to a double, using only static constructor, we have to change 
the static constructor of double type, which we may not be able to do because double is a 
built-in type and the code is out of the reach of us. Luban offers an alternative way to 
implement casting for the situation. That is to implement the below virtual function.

	void LBComplex::cast(LBObject *castto)
	{
		LBDouble * dbl = dynamic_cast<LBDouble *>(castto);
		if ( ! dbl )
			throw LBException("Wrong type to cast to");
		*dbl = LBDouble( _real );
	}

Above function is to cast the real part of the complex into the double number passed in. It 
will enable the below construction in Luban:

	C = math::complex(1., 2.);
	D = double( C );

There could be the case that both the static constructor and cast function can be applied to 
the same operation. And the rule is to choose static constructor over cast function.

10.6	Helper Classes
There are two helper classes in Luban C++ importing mechanism. One is class 
Luban::LBVarArgs that is used majorly to pass data into member functions. 
Luban::LBVarArgs is an abstract class.

class LBVarArgs
  {
  public:
    virtual int numArgs() const = 0;
    virtual const LBObject* getArg(int index) const = 0;
};

Another helper class Luban::LBConstIterator is also an abstract class. It is used by 
container data type to return iterator for Luban's foreach statement.

class LBConstIterator
  {
  public:
    virtual bool next()=0; // move forward
    virtual const LBVarArgs* getCurrentRow() = 0;
  };
Luban::LBConstIterator views each container as a number of rows and each row can 
contain one or more elements. It uses LBVarArgs interface to access elements in a row. 
The need to implement your own LBConstIterator derived class may arise when your 
implement your own specific container class and export to Luban.

10.7	Common Assumptions About Luban Data Types
Luban takes certain common assumptions about the data types imported from C++. The 
assumptions are actually in line with C++ common requirements for classes. They are 
listed as below.

?	A good copy constructor
This is mandatory. All types must have a working copy constructor.
?	An assignment operator
This operator will be called. Though you may implement one that does nothing more 
than throwing exception if necessary. Luban uses this operator to improve efficiency 
of variable assignment. But everything still works if the assignment operator fails.
?	A good default constructor
This is only necessary when you use the default static constructor, or your own static 
constructor calls the default constructor explicitly.
?	A good destructor
?	No worry about multi-threading
Though Luban is a multi-threading language, it has a mechanism to ensure that only 
one thread calls member function of an object at any time. So the coder of the class 
does not need to worry about thread safety.



11	Luban Interpreter

To run Luban code, we use a simple Luban interpreter plus name space explorer that is 
named "luban". This chapter explains the major features of Luban interpreter.

Below are the command line arguments that can be used to control the behavior of 
interpreter. 
?	-t <filename>
This flag is to specify the name of the file that lists all the data types imported 
from other languages like C++ in the form of shared library. If this argument is 
not specified, Luban uses a default imported type list file, which is either 
/usr/lib/luban/imports or environemtn variable $LUBAN_HOME/imports. More 
details of data type importing can be found in chapter 10.
?	-i
When this flag is set, Luban interpreter will open a interactive command line to 
allow interactive scripting and name space exploring, like the below example 
shows:
	
	Mycomputer > luban i
> list std
std::file 	std::file
std::console 	std::console
> script
std::console().writeline("Hello, world");
^D
Hello, world
		> quit
		Mycomputer >
		
The above example starts Luban interpreter with interactive command line. At the 
Luban command line, user then use "list" or "l" command to list the components 
with "std" name space, and "script" or "s" command to type in and run one line 
Luban code. At the end user uses the "quit" command to terminate the session and 
back to operating system.

?	-s <Luban code>
Use this flag you can put a short line of Luban code in the command line when 
starting Luban interpreter. And Luban interpreter will run the code, like below 
example:
	
	Mycomputer > luban s "std::console().writeline(100);"
	100
		Mycomputer >
	
?	All other arguments other than above flags will be taken as Luban source code file 
names. And all the non-component Luban script files will be run in the order of 
their command line position.



12	Sample Application: Simple Messaging System

Using Luban programming language and its socket and file utilities, it is very easy to 
write a simple messaging system. Client can subscribe and create message by topic. 
Server accepts to client subscription, receive topic message update and broadcast to 
subscribing clients.


13	Todos
To be written.

