[Nickle] nickle: Branch 'master' - 5 commits

Keith Packard keithp at keithp.com
Sun Nov 4 21:47:28 PST 2012


 Makefile.am                              |    2 
 configure.ac                             |    6 +
 debian/control                           |    2 
 debian/docs                              |    1 
 doc/Makefile.am                          |    1 
 doc/tutorial/Makefile.am                 |   39 +++++++
 doc/tutorial/advanced/concurrency.sgml   |   18 +--
 doc/tutorial/advanced/continuations.sgml |   32 ++---
 doc/tutorial/advanced/exceptions.sgml    |   14 +-
 doc/tutorial/advanced/namespaces.sgml    |   22 ++--
 doc/tutorial/builtins/io.sgml            |   10 -
 doc/tutorial/builtins/math.sgml          |    2 
 doc/tutorial/intro/expressions.sgml      |   12 +-
 doc/tutorial/intro/functions.sgml        |   14 +-
 doc/tutorial/intro/statements.sgml       |  121 +++++++++++-----------
 doc/tutorial/intro/variables.sgml        |  170 +++++++++++++++----------------
 doc/tutorial/nickle-tutorial.sgml        |  115 ++++++++++++++++++++
 doc/tutorial/tour/tour.sgml              |    2 
 doc/tutorial/tutorial.sgml               |  115 --------------------
 19 files changed, 373 insertions(+), 325 deletions(-)

New commits:
commit b3e0c5b3893b8c67e4d8e42a013e1f16bae774c8
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 4 21:48:57 2012 -0800

    doc: Expand tabs to spaces in .sgml files
    
    Makes code examples readable.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/doc/tutorial/advanced/concurrency.sgml b/doc/tutorial/advanced/concurrency.sgml
index c393b8b..e60da32 100644
--- a/doc/tutorial/advanced/concurrency.sgml
+++ b/doc/tutorial/advanced/concurrency.sgml
@@ -90,11 +90,11 @@ Consider the following situation:
 import Thread;
 
 void function para() {
-	printf("My next statement will be false.\n");
+        printf("My next statement will be false.\n");
 }
 
 void function dox() {
-	printf("My previous statement was true.\n");
+        printf("My previous statement was true.\n");
 }
 
 thread t = fork para();
@@ -166,21 +166,21 @@ import Thread;
 mutex m = new();
 
 void function para() {
-	acquire(m);
-	printf("My next statement will be false.\n");
-	release(m);
+        acquire(m);
+        printf("My next statement will be false.\n");
+        release(m);
 }
 
 void function dox() {
-	acquire(m);
-	printf("My previous statement was true.\n");
-	release(m);
+        acquire(m);
+        printf("My previous statement was true.\n");
+        release(m);
 }
 
 thread t = fork para();
 thread s = fork dox();
 join(t);
-	join(s);
+        join(s);
 </screen></informalexample>
 </para>
 <para>
diff --git a/doc/tutorial/advanced/continuations.sgml b/doc/tutorial/advanced/continuations.sgml
index 479b43d..7c4b153 100644
--- a/doc/tutorial/advanced/continuations.sgml
+++ b/doc/tutorial/advanced/continuations.sgml
@@ -23,18 +23,18 @@ For example, the following is a simple binary tree search that uses continuation
 typedef tree;
 
 typedef struct {
-	int key;
-	poly data;
-	&poly left, right;
+        int key;
+        poly data;
+        &poly left, right;
 } tree;
 
 void function search ( tree t, int i, &continuation c ) {
-	if ( i < t.key && ! is_void ( t.left ) )
-		search ( t.left, i, &c );
-	else if ( i > t.key && ! is_void ( t.right ) )
-		search ( t.right, i, &c );
-	else if ( i == t.key )
-		longjmp ( c, t.data );
+        if ( i < t.key && ! is_void ( t.left ) )
+                search ( t.left, i, &c );
+        else if ( i > t.key && ! is_void ( t.right ) )
+                search ( t.right, i, &c );
+        else if ( i == t.key )
+                longjmp ( c, t.data );
 }
 
 tree t = { key = 2, data = "blah", left = reference ( <> ), right = reference ( <> ) };
@@ -42,14 +42,14 @@ tree t = { key = 2, data = "blah", left = reference ( <> ), right = reference (
 continuation c;
 int i = 0;
 {
-	poly p = setjmp ( &c, <> );
-	++i;
-	printf ( "I have been here %d times.\n", i );
+        poly p = setjmp ( &c, <> );
+        ++i;
+        printf ( "I have been here %d times.\n", i );
 
-	if ( is_void ( p ) )
-		search ( t, 2, &c );
-	else
-		printf ( "value = %g\n", p );
+        if ( is_void ( p ) )
+                search ( t, 2, &c );
+        else
+                printf ( "value = %g\n", p );
 }
 ]]></screen></informalexample>
 </para>
diff --git a/doc/tutorial/advanced/exceptions.sgml b/doc/tutorial/advanced/exceptions.sgml
index 6efbdc6..892f8a1 100644
--- a/doc/tutorial/advanced/exceptions.sgml
+++ b/doc/tutorial/advanced/exceptions.sgml
@@ -40,10 +40,10 @@ raise my_exception ( "message", 0, 1, 2 );
 Execution is broken and <literal>my_exception</literal> travels up the stack until it is caught by a try-catch block or it reaches the top level, where it prints an error message such as:
 <informalexample><screen>
 Unhandled exception "my_exception"
-	3
-	2
-	1
-	"message"
+        3
+        2
+        1
+        "message"
 </screen></informalexample>
 </para>
 </sect2>
@@ -65,7 +65,7 @@ exception my_exception(string msg,int a,int b,int c);
 
 try raise my_exception("blah",1,2,3);
 catch my_exception(string msg,int a,int b,int c) {
-	printf("%s: exception successfully caught (%d,%d,%d).\n",msg,a,b,c);
+        printf("%s: exception successfully caught (%d,%d,%d).\n",msg,a,b,c);
 }
 </screen></informalexample>
 </para>
@@ -86,8 +86,8 @@ For example,
 exception my_exception(string msg, int a, int b, int c);
 
 void foo(string msg, int a, int b, int c) {
-	twixt(printf("entering twixt..."); printf("leaving twixt.\n"))
-		raise my_exception(msg, a, b, c);
+        twixt(printf("entering twixt..."); printf("leaving twixt.\n"))
+                raise my_exception(msg, a, b, c);
 }
 
 try foo("blah", 1, 2, 3);
diff --git a/doc/tutorial/advanced/namespaces.sgml b/doc/tutorial/advanced/namespaces.sgml
index 190399e..1433583 100644
--- a/doc/tutorial/advanced/namespaces.sgml
+++ b/doc/tutorial/advanced/namespaces.sgml
@@ -16,16 +16,16 @@ An example namespace might be declared like this:
 <informalexample><screen>
 namespace Example {
 
-	int blah = 1;
-	public int a = 0;
+        int blah = 1;
+        public int a = 0;
 
-	int function bar(int a) {
-		...
-	}
-	
-	protected int function foo(int a) {
-		...
-	}
+        int function bar(int a) {
+                ...
+        }
+        
+        protected int function foo(int a) {
+                ...
+        }
 
 }
 </screen></informalexample>
@@ -37,7 +37,7 @@ The namespace itself may be preceeded by publication information, <emphasis>but
 If the example above had been declared
 <informalexample><screen>
 protected namespace Example {
-	...
+        ...
 }
 </screen></informalexample>
 Then the names within <literal>Example</literal> would have the same visibility as always, but <literal>Example</literal> itself would be protected in whatever namespace it belongs to.
@@ -54,7 +54,7 @@ The namespace <literal>name</literal> is reopened and the new <literal>statement
 For example,
 <informalexample><screen>
 extend namespace Example {
-	string[*] greeting = [2]{ "hello", "world" };
+        string[*] greeting = [2]{ "hello", "world" };
 }
 </screen></informalexample>
 </para>
diff --git a/doc/tutorial/builtins/io.sgml b/doc/tutorial/builtins/io.sgml
index 997187c..afb946a 100644
--- a/doc/tutorial/builtins/io.sgml
+++ b/doc/tutorial/builtins/io.sgml
@@ -188,27 +188,27 @@ It contains the following definitions:
 <informalexample><screen>
 public int scanf (string format, *poly args...)
 {
-	return File::vfscanf (stdin, format, args);
+        return File::vfscanf (stdin, format, args);
 }
 
 public int vscanf (string format, (*poly)[*] args)
 {
-	return File::vfscanf (stdin, format, args);
+        return File::vfscanf (stdin, format, args);
 }    
 
 public string gets ()
 {
-	return File::fgets (stdin);
+        return File::fgets (stdin);
 }
 
 public int getchar ()
 {
-	return File::getc (stdin);
+        return File::getc (stdin);
 }
 
 public void ungetchar (int ch)
 {
-	File::ungetc (ch, stdin);
+        File::ungetc (ch, stdin);
 }
 </screen></informalexample>
 Thus, <literal>scanf</literal>, <literal>vscanf</literal>, <literal>gets</literal>, <literal>getchar</literal>, and <literal>ungetchar</literal> call the appropriate functions in File and return their results.
diff --git a/doc/tutorial/builtins/math.sgml b/doc/tutorial/builtins/math.sgml
index d2e6c96..0d5249d 100644
--- a/doc/tutorial/builtins/math.sgml
+++ b/doc/tutorial/builtins/math.sgml
@@ -47,7 +47,7 @@ The logarithm of <literal>a</literal> in base e, ten, and two, respectively.
 $ nickle
 > log ( Math::e )
 1.000000000000000
-> log10 ( 16 ) / log10 ( 4 )	/* change of base formula, log_4 16 */
+> log10 ( 16 ) / log10 ( 4 )    /* change of base formula, log_4 16 */
 1.999999999999999
 > log2 ( 16 )
 3.999999999999999
diff --git a/doc/tutorial/intro/expressions.sgml b/doc/tutorial/intro/expressions.sgml
index 364ff90..addc366 100644
--- a/doc/tutorial/intro/expressions.sgml
+++ b/doc/tutorial/intro/expressions.sgml
@@ -19,7 +19,7 @@ If no initialization expressions are present, it is an error to use the value of
 <informalexample><screen><![CDATA[
 > val = (int i,j);
 Unhandled exception "uninitialized_value" at <stdin>:73
-	"Uninitialized value"
+        "Uninitialized value"
 ]]></screen></informalexample>
 </para>
 <para>
@@ -27,7 +27,7 @@ Because they are expressions, declarations can be used in contructs such as:
 <informalexample><screen>
 for (int i = 0; i < 10; i++)
 {
-	
+        
 }
 </screen></informalexample>
 </para>
@@ -171,10 +171,10 @@ See Storage classes in the section on Variables.
 Integer constants with a leading zero are interpreted in octal, with a leading 0x in hex-decimal and with a leading 0b in binary.
 Here are some examples:
 <informalexample><screen>
-12	/* 12, decimal */
-014	/* 12, octal */
-0xc	/* 12, hex */
-0b1100	/* 12, binary */
+12      /* 12, decimal */
+014     /* 12, octal */
+0xc     /* 12, hex */
+0b1100  /* 12, binary */
 </screen></informalexample>
 </para>
 </sect3>
diff --git a/doc/tutorial/intro/functions.sgml b/doc/tutorial/intro/functions.sgml
index a4c8617..b1c8d6c 100644
--- a/doc/tutorial/intro/functions.sgml
+++ b/doc/tutorial/intro/functions.sgml
@@ -3,11 +3,11 @@
 An example function might be declared like this:
 <informalexample><screen><![CDATA[
 int gcf ( int a, int b ) {
-	int f = 1;
-	for ( int i = 2; i <= abs ( a ) && i <= abs ( b ); ++i )
-		while ( ( a // f ) % i == 0 && ( b // f ) % i == 0 )
-			f *= i;
-	return f;
+        int f = 1;
+        for ( int i = 2; i <= abs ( a ) && i <= abs ( b ); ++i )
+                while ( ( a // f ) % i == 0 && ( b // f ) % i == 0 )
+                        f *= i;
+        return f;
 }
 ]]></screen></informalexample>
 </para>
@@ -25,7 +25,7 @@ The final argument may be succeeded by an ellipses (...) to indicate an arbitrar
 int sum (int a, int b ...)
 {
     for (int i = 0; i < dim (b); ++i)
-	a += b[i];
+        a += b[i];
     return a;
 }
 > sum(1,2)
@@ -54,7 +54,7 @@ See the section on Copy semantics for details on what functions may be assigned
 <para>
 Functions may also be declared and used anonymously:
 <informalexample><screen>
-(int func ( int a, int b ) { return a + b; })(2,3);	/* 5 */
+(int func ( int a, int b ) { return a + b; })(2,3);     /* 5 */
 </screen></informalexample>
 </para>
 <para>
diff --git a/doc/tutorial/intro/statements.sgml b/doc/tutorial/intro/statements.sgml
index a7c9ad4..9e2bbde 100644
--- a/doc/tutorial/intro/statements.sgml
+++ b/doc/tutorial/intro/statements.sgml
@@ -30,7 +30,7 @@ else <replaceable>statement</replaceable>
 For example:
 <informalexample><screen>
 if ( x == 0 )
-	printf ( "x is zero.\n" );
+        printf ( "x is zero.\n" );
 </screen></informalexample>
 </para>
 <para>
@@ -42,20 +42,20 @@ It executes its <replaceable>statement</replaceable> if the most recent <literal
 For example,
 <informalexample><screen>
 if ( x == 0 )
-	printf ( "x is zero.\n" );
+        printf ( "x is zero.\n" );
 else
-	printf ( "x is not zero.\n" );
+        printf ( "x is not zero.\n" );
 </screen></informalexample>
 </para>
 <para>
 More than one option may be presented by nesting further 'if's in 'else' statements like this:
 <informalexample><screen>
 if ( x == 0 )
-	printf ( "x is zero.\n" );
+        printf ( "x is zero.\n" );
 else if ( x < 0 )
-	printf ( "x is negative.\n" );
+        printf ( "x is negative.\n" );
 else
-	printf ( "x is positive.\n" );
+        printf ( "x is positive.\n" );
 </screen></informalexample>
 </para>
 </sect2>
@@ -99,21 +99,21 @@ If nothing is matched and there is no <literal>default</literal>, control skips
 This example prints out a number to the screen, replacing it by a letter as though it were a poker card:
 <informalexample><screen>
 switch ( x ) {
-	case 1:
-		printf ( "A\n" );	/* ace */
-		break;
-	case 11:
-		printf ( "J\n" );	/* jack */
-		break;
-	case 12:
-		printf ( "Q\n" );	/* queen */
-		break;
-	case 13:
-		printf ( "K\n" );	/* king */
-		break;
-	default:
-		printf ( "%d\n", x );	/* numeric */
-		break;
+        case 1:
+                printf ( "A\n" );       /* ace */
+                break;
+        case 11:
+                printf ( "J\n" );       /* jack */
+                break;
+        case 12:
+                printf ( "Q\n" );       /* queen */
+                break;
+        case 13:
+                printf ( "K\n" );       /* king */
+                break;
+        default:
+                printf ( "%d\n", x );   /* numeric */
+                break;
 }
 </screen></informalexample>
 </para>
@@ -125,12 +125,12 @@ Here is an example of this 'falling through':
 int x = 3;
 
 switch ( sign ( x ) ) {
-	case -1:
-		printf ( "x is negative.\n" );
-	case 1:
-		printf ( "x is positive.\n" );
-	default:
-		printf ( "x is zero.\n" );
+        case -1:
+                printf ( "x is negative.\n" );
+        case 1:
+                printf ( "x is positive.\n" );
+        default:
+                printf ( "x is zero.\n" );
 }
 </screen></informalexample>
 </para>
@@ -158,19 +158,19 @@ As always, <literal>default</literal> matches everything.
 The following example chooses the best way to print the union:
 <informalexample><screen>
 union {
-	int a;
-	string b;
+        int a;
+        string b;
 } u;
 
 u.b = "hello";
 
 union switch ( u ) {
-	case a:
-		printf ( "%d\n", u.a );
-		break;
-	case b:
-		printf ( "%s\n", u.b );
-		break;
+        case a:
+                printf ( "%d\n", u.a );
+                break;
+        case b:
+                printf ( "%s\n", u.b );
+                break;
 }
 </screen></informalexample>
 </para>
@@ -182,12 +182,12 @@ An additional name may follow that of a case; the union's value will be availabl
 The switch above could have been written:
 <informalexample><screen>
 union switch ( u ) {
-	case a num:
-		printf ( "%d\n", num );
-		break;
-	case b str:
-		printf ( "%s\n", str );
-		break;
+        case a num:
+                printf ( "%d\n", num );
+                break;
+        case b str:
+                printf ( "%s\n", str );
+                break;
 }
 </screen></informalexample>
 </para>
@@ -210,8 +210,8 @@ For example:
 <informalexample><screen>
 int x = 0;
 while ( x < 10 ) {
-	printf ( "%d\n", x );
-	++x;
+        printf ( "%d\n", x );
+        ++x;
 }
 </screen></informalexample>
 </para>
@@ -226,7 +226,7 @@ It is often used in input while testing for end-of-file:
 file f = File::open ( "test", "r" );
 
 do {
-	printf ( "%s\n", File::fgets ( f ) );
+        printf ( "%s\n", File::fgets ( f ) );
 } while ( ! end ( f ) );
 
 close ( f );
@@ -239,7 +239,7 @@ After each iteration, the third <replaceable>expr</replaceable> is evaluated, wh
 The <literal>while</literal> example above can also be written as the following <literal>for</literal> loop:
 <informalexample><screen>
 for ( int x = 0; x < 10; ++x )
-	printf ( "%d\n", x );
+        printf ( "%d\n", x );
 </screen></informalexample>
 </para>
 </sect2>
diff --git a/doc/tutorial/intro/variables.sgml b/doc/tutorial/intro/variables.sgml
index 7346f98..5274baf 100644
--- a/doc/tutorial/intro/variables.sgml
+++ b/doc/tutorial/intro/variables.sgml
@@ -72,7 +72,7 @@ string foo = "hello";
 string bar = "world";
 string msg = foo + ", " + bar;
 
-printf("%s\n", msg);		/* hello, world */
+printf("%s\n", msg);            /* hello, world */
 </screen></informalexample>
 </para>
 </sect3>
@@ -107,7 +107,7 @@ See the section on Concurrency and Continuations.
 <informalexample><screen>
 thread t = fork 5!;
 # do stuf...
-printf("5! = %d\n", join(t));	/* 5! = 120 */
+printf("5! = %d\n", join(t));   /* 5! = 120 */
 </screen></informalexample>
 </para>
 <para>
@@ -127,16 +127,16 @@ Nickle performs full run-time typechecking on poly datatypes to ensure that the
 > poly i=3, s="hello\n";
 > i+3
 6
-> s+3		/* can't add string and int */
+> s+3           /* can't add string and int */
 Unhandled exception "invalid_binop_values" at <stdin>:45
-	3
-	"hello\n"
-	"invalid operands"
-> printf(i)	/* printf expects a string */
+        3
+        "hello\n"
+        "invalid operands"
+> printf(i)     /* printf expects a string */
 Unhandled exception "invalid_argument" at <stdin>:47
-	3
-	0
-	"Incompatible argument"
+        3
+        0
+        "Incompatible argument"
 > printf(s)
 hello
 > 
@@ -175,17 +175,17 @@ One unusual feature is that a struct value is compatible with a struct type if t
 For example:
 <informalexample><screen>
 typedef struct {
-	int	i;
-	real	r;
+        int     i;
+        real    r;
 } i_and_r;
 
 typedef struct {
-	int	i;
+        int     i;
 } just_i;
 
-i_and_r	i_and_r_value = { i = 12, r = 37 };
+i_and_r i_and_r_value = { i = 12, r = 37 };
 
-just_i	i_value;
+just_i  i_value;
 
 i_value = i_and_r_value;
 </screen></informalexample>
@@ -206,8 +206,8 @@ Values can be converted to a union type by specifying a compatible union tag cas
 A control structure <literal>union switch</literal> exists to split out the different tags and perform different functions based on the current tag:  
 <informalexample><screen>
 typedef union {
-	int	i;
-	real	r;
+        int     i;
+        real    r;
 } i_and_r_union;
 
 i_and_r_union u_value;
@@ -216,15 +216,15 @@ u_value.i = 37;
 
 union switch (u_value) {
 case i:
-	printf ("i value %d\n", u_value.i);
-	break;
+        printf ("i value %d\n", u_value.i);
+        break;
 case r:
-	printf ("r value %d\n", u_value.r);
-	break;
+        printf ("r value %d\n", u_value.r);
+        break;
 }
 
 u_value = (i_and_r_union.r) 1.2;
-printf ("u_value %g\n", u_value);		/* u_value r = 1.2 */
+printf ("u_value %g\n", u_value);               /* u_value r = 1.2 */
 </screen></informalexample>
 </para>
 </sect3>
@@ -247,8 +247,8 @@ on its declaration but rather on its initialization.  See Initialization
 below.  Declaring multidimensional arrays in Nickle is different than in C;
 C provides only arrays of arrays while Nickle allows either:
 <informalexample><screen>
-int[3,3]	array_2d = {};
-int[3][3]	array_of_arrays = { (int[3]) {} ... };
+int[3,3]        array_2d = {};
+int[3][3]       array_of_arrays = { (int[3]) {} ... };
 
 array_2d[0,0] = 7;
 array_of_arrays[0][0] = 7;
@@ -283,8 +283,8 @@ performance characteristics of the underlying implementation clear.
 Hashes are declared a bit like arrays, but instead of a value in the
 brackets, a type is placed:
 <informalexample><screen>
-int[string]	string_to_int = { "hello" => 2, => 0 };
-float[float]	float_to_float = { 2.5 => 27 };
+int[string]     string_to_int = { "hello" => 2, => 0 };
+float[float]    float_to_float = { 2.5 => 27 };
 
 string_to_int["bar"] = 17;
 string_to_int["foo"] += 12;
@@ -303,18 +303,18 @@ separate key from value.  Eliding the key specifies the
 Pointers hold a reference to a separate object; multiple pointers may point at the same object and changes to the referenced object are reflected both in the underlying object as well as in any other references to the same object.
 While pointers can be used to point at existing storage locations, anonymous locations can be created with the reference built-in function; this allows for the creation of pointers to existing values without requiring that the value be stored in a named object.
 <informalexample><screen><![CDATA[
-*int	pointer;
-int	object;
+*int    pointer;
+int     object;
 
 pointer = &object;
 *pointer = 12;
 
-printf ("%g\n", object);		/* 12 */
+printf ("%g\n", object);                /* 12 */
 
 pointer = reference (37);
 (*pointer)++;
 
-printf ("%g\n", *pointer);		/* 38 */
+printf ("%g\n", *pointer);              /* 38 */
 ]]></screen></informalexample>
 </para>
 </sect3>
@@ -344,13 +344,13 @@ References, unlike pointers, need not be dereferenced; they are used exactly as
 Changing either the value it refers to or the reference itself changes both.
 </para>
 <informalexample><screen>
-printf("%g\n", i);	/* 3 */
-printf("%g\n", ref);	/* 3 */
+printf("%g\n", i);      /* 3 */
+printf("%g\n", ref);    /* 3 */
 
 ++ref;
 
-printf("%g\n", i);	/* 4 */
-printf("%g\n", ref);	/* 4 */
+printf("%g\n", i);      /* 4 */
+printf("%g\n", ref);    /* 4 */
 </screen></informalexample>
 </sect3>
 
@@ -362,13 +362,13 @@ Function types always have a return type and zero or more argument types.
 Functions may use the void return type.
 The final argument type may be followed by an elipsis (...), in which case the function can take any number of arguments at that point, each of the same type as the final argument type:
 <informalexample><screen>
-int(int, int)	a;
-void(int ...)	b;
+int(int, int)   a;
+void(int ...)   b;
 
 a(1,2);
 b(1);
 b(1,2);
-b(1,"hello");	/* illegal, "hello" is not compatible with int */
+b(1,"hello");   /* illegal, "hello" is not compatible with int */
 </screen></informalexample>
 </para>
 <para>
@@ -397,15 +397,15 @@ See Storage classes below.
 <listitem><para>
 Type is some type as described here, for instance
 <informalexample><screen><![CDATA[
-type			/* primitive type */
-*type			/* pointer to type */
-&type			/* reference to type */
-type[*] 		/* array of type */
-type[*,...]		/* multidimensional array of type */
-type(type,...)		/* function with type arguments and return value */
-struct { ... }		/* struct of types */
-union { ... }		/* union of types */
-type(type,...)[*]	/* array of functions */
+type                    /* primitive type */
+*type                   /* pointer to type */
+&type                   /* reference to type */
+type[*]                 /* array of type */
+type[*,...]             /* multidimensional array of type */
+type(type,...)          /* function with type arguments and return value */
+struct { ... }          /* struct of types */
+union { ... }           /* union of types */
+type(type,...)[*]       /* array of functions */
 /* etc. */
 ]]></screen></informalexample>
 </para>
@@ -421,23 +421,23 @@ In any case, type is always checked at runtime.
 Initializers in Nickle are expressions evaluated when the storage for a variable comes into scope.
 To initialize array and structure types, expressions which evaluate to a struct or array object are used:
 <informalexample><screen>
-int	k = 12;
-int	z = floor (pi * 27);
-int[3]	a = (int[3]) { 1, 2, 3 };
+int     k = 12;
+int     z = floor (pi * 27);
+int[3]  a = (int[3]) { 1, 2, 3 };
 
 typedef struct {
-	int 	i;
-	real	r;
+        int     i;
+        real    r;
 } i_and_r;
 
-i_and_r	s = (i_and_r) { i = 12, r = pi/2 };
+i_and_r s = (i_and_r) { i = 12, r = pi/2 };
 </screen></informalexample>
 </para>
 <para>
 As a special case, initializers for struct and array variables may elide the type leaving only the bracketed initializer:
 <informalexample><screen>
-int[3]	a = { 1, 2, 3 };
-i_and_r	s = { i = 12, r = pi/2 };
+int[3]  a = { 1, 2, 3 };
+i_and_r s = { i = 12, r = pi/2 };
 </screen></informalexample>
 </para>
 <para>
@@ -447,7 +447,7 @@ This avoids common mistakes when the structure type is redeclared.
 <para>
 An arrays initializer followed by an elipsis (...) is replicated to fill the remainder of the elements in that dimension:
 <informalexample><screen>
-int[4,4]	a = { { 1, 2 ... }, { 3, 4 ... } ... };
+int[4,4]        a = { { 1, 2 ... }, { 3, 4 ... } ... };
 </screen></informalexample>
 </para>
 <para>
@@ -466,9 +466,9 @@ Function declarations and statement blocks also create new lexical scopes.
 This limits the scope of variables in situations like:
 <informalexample><screen>
 if (int i = foo(x))
-	printf ("i in scope here %d\n", i);
+        printf ("i in scope here %d\n", i);
 else
-	printf ("i still in scope here %d\n", i);
+        printf ("i still in scope here %d\n", i);
 printf ("i not in scope here\n");
 </screen></informalexample>
 </para>
@@ -476,9 +476,9 @@ printf ("i not in scope here\n");
 Identifiers are lexically scoped even when functions are nested:
 <informalexample><screen>
 function foo (int x) {
-	int y = 1;
-	function bar (int z) { return z + y; }
-	return bar (x);
+        int y = 1;
+        function bar (int z) { return z + y; }
+        return bar (x);
 }
 </screen></informalexample>
 </para>
@@ -507,11 +507,11 @@ Storage captured and passed out of the function will remain accessible.
 <informalexample><screen><![CDATA[
 *int function foo (int x)
 {
-	return &x;
+        return &x;
 }
 
-*int	a1 = foo (1);
-*int	a2 = foo (2);
+*int    a1 = foo (1);
+*int    a2 = foo (2);
 ]]></screen></informalexample>
 </para>
 <para>
@@ -526,14 +526,14 @@ A function value includes both the executable code and the storage for any enclo
 <informalexample><screen>
 int() function incrementer ()
 {
-	return (func () { 
-		static int	x = 0;
-		return ++x;
-	});
+        return (func () { 
+                static int      x = 0;
+                return ++x;
+        });
 }
 
-int()	a = incrementer();
-int()	b = incrementer();
+int()   a = incrementer();
+int()   b = incrementer();
 </screen></informalexample>
 </para>
 <para>
@@ -545,13 +545,13 @@ Additionally, any auto variables declared within an initializer for a static var
 <informalexample><screen><![CDATA[
 function foo ()
 {
-	static function bar (*int z)
-	{
-		*z = (*z)!;
-	}
-	static x = ((int y = 7), bar (&y), y);
+        static function bar (*int z)
+        {
+                *z = (*z)!;
+        }
+        static x = ((int y = 7), bar (&y), y);
 
-	return x;
+        return x;
 }
 ]]></screen></informalexample>
 </para>
@@ -568,16 +568,16 @@ When declared within a function, storage is allocated when the function is parse
 <informalexample><screen>
 function foo ()
 {
-	function bar ()
-	{
-		global	g = 1;
-		static	s = 1;
-
-		g++;
-		s++;
-		return (int[2]) { g, s };
-	}
-	return bar ();
+        function bar ()
+        {
+                global  g = 1;
+                static  s = 1;
+
+                g++;
+                s++;
+                return (int[2]) { g, s };
+        }
+        return bar ();
 }
 </screen></informalexample>
 </para>
commit 48ab6b7bc8eccb9a0c79ae1a044e99381cd01111
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 4 21:27:30 2012 -0800

    Build tutorial when docbook2pdf is available
    
    And build it on debian
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Makefile.am b/Makefile.am
index f73522c..85a57a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,7 @@
 ## for licensing information.
 
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = bench test examples
+SUBDIRS = bench test examples doc
 
 BUILD_DATE := $(shell sh $(top_builddir)/date-sh)
 
diff --git a/configure.ac b/configure.ac
index eb85c8a..7b6e22f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,10 @@ AC_CHECK_FUNCS(unsetenv setenv putenv gettimeofday hstrerror select)
 AC_CHECK_FUNCS(sigaction sigrelse sigignore setrlimit getrlimit)
 AC_CHECK_FUNCS(dlopen dlsym dlerror dlclose)
 
+AC_PATH_PROGS([DOCBOOK2PDF],[docbook2pdf])
+
+AM_CONDITIONAL(HASDOCBOOK,test -n "$DOCBOOK2PDF")
+
 AC_FUNC_GETPGRP
 
 dnl The readline test is complicated enough to rate its own file
@@ -130,6 +134,8 @@ AC_CONFIG_FILES(
  examples/Makefile
  examples/smlng/Makefile
  examples/turtle/Makefile
+ doc/Makefile
+ doc/tutorial/Makefile
  date-sh)
 
 AC_OUTPUT
diff --git a/debian/control b/debian/control
index e68c664..8d27a70 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: nickle
 Section: interpreters
 Priority: optional
 Maintainer: Keith Packard <keithp at keithp.com>
-Build-Depends: debhelper (>= 7.0.50), libreadline-dev, autotools-dev
+Build-Depends: debhelper (>= 7.0.50), libreadline-dev, autotools-dev, docbook-utils
 Standards-Version: 3.9.2
 
 Package: nickle
diff --git a/debian/docs b/debian/docs
index 33024dd..76399c4 100644
--- a/debian/docs
+++ b/debian/docs
@@ -5,3 +5,4 @@ TODO
 examples
 test
 bench
+tutorial.pdf
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..8dd0b9f
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS=tutorial
\ No newline at end of file
diff --git a/doc/tutorial/Makefile.am b/doc/tutorial/Makefile.am
new file mode 100644
index 0000000..baf586b
--- /dev/null
+++ b/doc/tutorial/Makefile.am
@@ -0,0 +1,39 @@
+
+SGMLFILES=nickle-tutorial.sgml
+PDFFILES=$(SGMLFILES:.sgml=.pdf)
+
+.sgml.pdf:
+	docbook2pdf $<
+
+SGMLINC= \
+	tour/tour.sgml \
+	basics/invoke.sgml \
+	basics/command.sgml \
+	intro/variables.sgml \
+	intro/expressions.sgml \
+	intro/statements.sgml \
+	intro/functions.sgml \
+	builtins/io.sgml \
+	builtins/math.sgml \
+	builtins/strings.sgml \
+	advanced/copying.sgml \
+	advanced/namespaces.sgml \
+	advanced/exceptions.sgml \
+	advanced/concurrency.sgml \
+	advanced/continuations.sgml
+
+EXTRA_DIST=$(SGMLFILES) $(SGMLINC)
+
+if HASDOCBOOK
+
+all-local: $(PDFFILES)
+
+clean-local:
+	$(RM) -f $(PDFFILES)
+
+
+$(PDFFILES): $(SGMLINC)
+
+doc_DATA = $(PDFFILES)
+
+endif
\ No newline at end of file
commit 85e960e9091c34820ec08f68336a0614dffda634
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 4 21:26:40 2012 -0800

    tutorial: Use sgml entities instead of < and >
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/doc/tutorial/tour/tour.sgml b/doc/tutorial/tour/tour.sgml
index 7c5d00e..61c3309 100644
--- a/doc/tutorial/tour/tour.sgml
+++ b/doc/tutorial/tour/tour.sgml
@@ -82,7 +82,7 @@ Unhandled exception invalid_argument ("sqrt of negative number", 0, -1)
     sqrt (-1)
 /usr/share/nickle/math.5c:895:     result = sqrt (a);
     pow (-1, 0.5)
-<stdin>:1:     -1 ** (1 / 2);
+<stdin>:1:     -1 ** (1 / 2);
 - done
 > quit
 $
commit 8267429a2cc9f4a4f33a788dff6bca2ba7d38f1e
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 4 21:25:54 2012 -0800

    Tutorial: twixt doesn't have an optional 'else' block
    
    This was a proposed feature that was removed
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/doc/tutorial/intro/statements.sgml b/doc/tutorial/intro/statements.sgml
index 7bb062a..a7c9ad4 100644
--- a/doc/tutorial/intro/statements.sgml
+++ b/doc/tutorial/intro/statements.sgml
@@ -65,23 +65,24 @@ else
 twixt ( <replaceable>expr</replaceable>; <replaceable>expr</replaceable> ) <replaceable>statement</replaceable>
 </synopsis>
 <para>
-<literal>twixt</literal>, like <literal>if</literal>, executes <replaceable>statement</replaceable> only if the first <replaceable>expr</replaceable> is true.
-If <replaceable>statement</replaceable> is executed, the second <replaceable>expr</replaceable> is evaluated after it.
-<emphasis>That order is gauranteed</emphasis> - even if <replaceable>statement</replaceable> throws an exception or <literal>long_jmp</literal>s out of the <literal>twixt</literal>, the second <replaceable>expr</replaceable> will be evaluated.
-Thus, <literal>twixt</literal> is useful in locked operations where the statement should only be executed if a lock was successfully acquired and the lock must be released afterward:
+Ensures that the the first <replaceable>expr</replaceable> will always
+have been evaluated whenever control flow passes into any part
+of <replaceable>statement</replaceable> and ensures that the
+second <replaceable>expr</replaceable> will be evaluated anytime
+control flow passes out of <replaceable>statement</replaceable>.
+<emphasis>That order is gauranteed</emphasis>.
+If a <literal>long_jmp</literal> target is inside
+<replaceable>statement</replaceable>, the
+first <replaceable>expr</replaceable> will be executed before control
+passes to the target.
+If <replaceable>statement</replaceable> throws an exception
+or <literal>long_jmp</literal>s out of the <literal>twixt</literal>, the second <replaceable>expr</replaceable> will be evaluated.
+Thus, <literal>twixt</literal> is useful in locked operations where
+the statement should only be executed under a lock and that lock must
+be released afterwards.
 <informalexample><screen>
 twixt ( get_lock ( ); release_lock ( ) )
-	locked_operation ( );
-</screen></informalexample>
-</para>
-<para>
-'Else' statements may bind to 'twixt's as well as 'if's, providing choices
-such as:
-<informalexample><screen>
-twixt ( get_lock ( ); release_lock ( ) )
-	locked_operation ( );
-else
-	printf ( "failed to acquire lock.\n" );
+        locked_operation ( );
 </screen></informalexample>
 </para>
 </sect2>
commit 3a96936bea9ac3376f33d07628231c1ff176ab26
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Nov 4 21:24:45 2012 -0800

    Rename nickle tutorial to nickle-tutorial
    
    Makes any built files include 'nickle' by default
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/doc/tutorial/nickle-tutorial.sgml b/doc/tutorial/nickle-tutorial.sgml
new file mode 100644
index 0000000..6d5d708
--- /dev/null
+++ b/doc/tutorial/nickle-tutorial.sgml
@@ -0,0 +1,115 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+<!ENTITY tour SYSTEM "tour/tour.sgml">
+
+<!ENTITY invoke SYSTEM "basics/invoke.sgml">
+<!ENTITY command SYSTEM "basics/command.sgml">
+
+<!ENTITY variables SYSTEM "intro/variables.sgml">
+<!ENTITY expressions SYSTEM "intro/expressions.sgml">
+<!ENTITY statements SYSTEM "intro/statements.sgml">
+<!ENTITY functions SYSTEM "intro/functions.sgml">
+
+<!ENTITY io SYSTEM "builtins/io.sgml">
+<!ENTITY math SYSTEM "builtins/math.sgml">
+<!ENTITY strings SYSTEM "builtins/strings.sgml">
+
+<!ENTITY copying SYSTEM "advanced/copying.sgml">
+<!ENTITY namespaces SYSTEM "advanced/namespaces.sgml">
+<!ENTITY exceptions SYSTEM "advanced/exceptions.sgml">
+<!ENTITY concurrency SYSTEM "advanced/concurrency.sgml">
+<!ENTITY continuations SYSTEM "advanced/continuations.sgml">
+]>
+
+<book>
+
+<bookinfo>
+
+<title>Nickle Tutorial</title>
+
+<authorgroup>
+
+<author>
+<firstname>Robert</firstname>
+<surname>Burgess</surname>
+</author>
+
+<author>
+<firstname>Keith</firstname>
+<surname>Packard</surname>
+</author>
+
+</authorgroup>
+
+<abstract>
+<para>
+This is a user tutorial for Nickle, a powerful desktop
+calculator language. Nickle supports many features of
+advanced languages, as well as arbitrary precision numbers.
+This tutorial is intended to teach Nickle to someone who is already fairly familiar with programming, using descriptions with examples.
+Topics are covered progressively, beginning with invocation and commands, moving on to learning the language, and finally to more advanced topics.
+</para>
+</abstract>
+
+</bookinfo>
+
+<chapter><title>Nickle Tour</title>
+<abstract>
+<para>
+The following is an example Nickle session, interspersed with comments.
+</para>
+</abstract>
+&tour;
+</chapter>
+
+<chapter><title>Nickle Basics</title>
+<abstract>
+<para>
+Nickle is a powerful desktop calculator language with many features of advanced languages and support for arbitrary precision numbers.
+It can run interactively to fulfill its role as a calculator, evaluate single expressions, and execute Nickle scripts.
+It also has an array of useful top-level commands for interacting with the interpreter.
+</para>
+</abstract>
+&invoke;
+&command;
+</chapter>
+
+<chapter><title>Language introduction</title>
+<abstract>
+<para>
+In this chapter, the features of Nickle such as datatypes, expressions, control statements, and functions will be discussed.
+By the end, most of the basic language features will have been covered.
+</para>
+</abstract>
+&variables;
+&expressions;
+&statements;
+&functions;
+</chapter>
+
+<chapter><title>Builtins</title>
+<abstract>
+<para>
+This chapter will explain various important builtin functions of Nickle, such as those for input and output and math.
+It will also discuss the various operators and builtin functions that manipulate strings.
+</para>
+</abstract>
+&io;
+&math;
+&strings;
+</chapter>
+
+<chapter><title>Advanced topics</title>
+<abstract>
+<para>
+This chapter will discuss more advanced topics; these features make Nickle as powerful as it is.
+The semantics of copying and garbage collection, namespaces, exceptions, threading and mutual exclusion, and continuations will all be covered.
+</para>
+</abstract>
+©ing;
+&namespaces;
+&exceptions;
+&concurrency;
+&continuations;
+</chapter>
+
+</book>
diff --git a/doc/tutorial/tutorial.sgml b/doc/tutorial/tutorial.sgml
deleted file mode 100644
index 6d5d708..0000000
--- a/doc/tutorial/tutorial.sgml
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
-<!ENTITY tour SYSTEM "tour/tour.sgml">
-
-<!ENTITY invoke SYSTEM "basics/invoke.sgml">
-<!ENTITY command SYSTEM "basics/command.sgml">
-
-<!ENTITY variables SYSTEM "intro/variables.sgml">
-<!ENTITY expressions SYSTEM "intro/expressions.sgml">
-<!ENTITY statements SYSTEM "intro/statements.sgml">
-<!ENTITY functions SYSTEM "intro/functions.sgml">
-
-<!ENTITY io SYSTEM "builtins/io.sgml">
-<!ENTITY math SYSTEM "builtins/math.sgml">
-<!ENTITY strings SYSTEM "builtins/strings.sgml">
-
-<!ENTITY copying SYSTEM "advanced/copying.sgml">
-<!ENTITY namespaces SYSTEM "advanced/namespaces.sgml">
-<!ENTITY exceptions SYSTEM "advanced/exceptions.sgml">
-<!ENTITY concurrency SYSTEM "advanced/concurrency.sgml">
-<!ENTITY continuations SYSTEM "advanced/continuations.sgml">
-]>
-
-<book>
-
-<bookinfo>
-
-<title>Nickle Tutorial</title>
-
-<authorgroup>
-
-<author>
-<firstname>Robert</firstname>
-<surname>Burgess</surname>
-</author>
-
-<author>
-<firstname>Keith</firstname>
-<surname>Packard</surname>
-</author>
-
-</authorgroup>
-
-<abstract>
-<para>
-This is a user tutorial for Nickle, a powerful desktop
-calculator language. Nickle supports many features of
-advanced languages, as well as arbitrary precision numbers.
-This tutorial is intended to teach Nickle to someone who is already fairly familiar with programming, using descriptions with examples.
-Topics are covered progressively, beginning with invocation and commands, moving on to learning the language, and finally to more advanced topics.
-</para>
-</abstract>
-
-</bookinfo>
-
-<chapter><title>Nickle Tour</title>
-<abstract>
-<para>
-The following is an example Nickle session, interspersed with comments.
-</para>
-</abstract>
-&tour;
-</chapter>
-
-<chapter><title>Nickle Basics</title>
-<abstract>
-<para>
-Nickle is a powerful desktop calculator language with many features of advanced languages and support for arbitrary precision numbers.
-It can run interactively to fulfill its role as a calculator, evaluate single expressions, and execute Nickle scripts.
-It also has an array of useful top-level commands for interacting with the interpreter.
-</para>
-</abstract>
-&invoke;
-&command;
-</chapter>
-
-<chapter><title>Language introduction</title>
-<abstract>
-<para>
-In this chapter, the features of Nickle such as datatypes, expressions, control statements, and functions will be discussed.
-By the end, most of the basic language features will have been covered.
-</para>
-</abstract>
-&variables;
-&expressions;
-&statements;
-&functions;
-</chapter>
-
-<chapter><title>Builtins</title>
-<abstract>
-<para>
-This chapter will explain various important builtin functions of Nickle, such as those for input and output and math.
-It will also discuss the various operators and builtin functions that manipulate strings.
-</para>
-</abstract>
-&io;
-&math;
-&strings;
-</chapter>
-
-<chapter><title>Advanced topics</title>
-<abstract>
-<para>
-This chapter will discuss more advanced topics; these features make Nickle as powerful as it is.
-The semantics of copying and garbage collection, namespaces, exceptions, threading and mutual exclusion, and continuations will all be covered.
-</para>
-</abstract>
-©ing;
-&namespaces;
-&exceptions;
-&concurrency;
-&continuations;
-</chapter>
-
-</book>


More information about the Nickle mailing list