Turtle

Reference Manual

Version 1.0.0

Martin Grabmueller


Table of Contents


1. Introduction

Turtle is both a programming language and the name of a compiler for this language.

The language Turtle is a programming language which supports constraint imperative programming, that means that standard imperative programming constructs can be combined with the declarative style of constraint programming.

The chapter after this introduction describes the Turtle compiler from the user's point of view, you will learn how to run the compiler and how to develop programs using it.

After that, in the third chapter, the Turtle programming language is presented in detail, including formal descriptions like EBNF grammars, and an informal description of the semantics of Turtle.

The fourth chapter contains the reference documentation for the standard library modules which come with the Turtle system.

The manual is closed by a a glossary and an index of all functions and variables of the standard library.

1.1 About Turtle

The Turtle programming language has these main characteristics:

Imperative
Turtle has the basic imperative constructs like variables, side-effects, loops, procedures, procedure calls, statements, and statement sequencing. Thus the semantics of a Turtle program relies on state and time.
Constraints
Turtle supports constraint programming. That means that constraints can be asserted on program variables, so that these constraints can be checked and values for the variables can be deduced.
Higher-order programming
Functions and procedures are first-class values, they can be returned from functions and even be stored in data structures. Additionally to the imperative and constraint programming styles, this makes functional programming possible.
Garbage collection
Memory is managed automatically in Turtle programs. Garbage collection is now standard in new programming languages, since it frees the programmer from many possible bug sources, such as dangling pointers (because references to freed memory regions are used) or memory leaks (because unneeded references are kept).
Module system
Turtle comes with a module system for structuring programs in smaller, encapsulated subsystems. This is a key feature for software engineering, because it makes the interfaces between subsystems clean and makes life easier if several programmers are working on different parts of a larger program. Additionally, modules can be parametrisized over data types. The programmer can thus write generic modules which implement abstract data types which can be used with arbitrary objects of arbitrary types.
Rich set of data types
Turtle comes with builtin basic data types (integers, reals, booleans, strings, characters) as well as aggregate types such as arrays, lists and tuples.
Efficiency
Turtle programs run reasonably fast, mainly because they are not interpreted but compiled to machine code (via generating C code and running a C compiler).

1.2 Turtle History

Turtle is the product of my master's thesis, written at the Technical University of Berlin.

The language definition was sketched in February 2002, and after the thesis was officially started, development towards turning it into a usable constraint imperative language began.

1.3 Turtle Future

I don't know.

2. Using Turtle

This chapter describes how to use the Turtle compiler. You will learn how to invoke the compiler in order to produce an executable program, what command line options the compiler understands and how the compiler can be used to access the underlying system an how to produce documentation from source code comments.

2.1 Compiling source programs

The Turtle compiler is run by executing the command `turtle', giving the names of the source files to be compiled on the command line:

turtle ex1.t

Turtle source code files are named with the file name extension `.t' by convention.

The compiler will generate a bunch of files from earch Turtle source file:

`ex1.ifc'
This is the interface file in which the exported identifiers, imported modules and some other data is stored. Interface files are read when modules are imported.
`ex1.c'
This is the C source code generated for the input file. It is compiled by the C compiler to produce the file `ex1.o' mentioned below.
`ex1.h'
This is the header file (for the C compiler) which contains declarations for all exported variables and functions and for the initialization files.
`ex1.o'
This is the object code for the input file, it contains the machine code.

If you don't want to compile a library module, but a complete program, you have to give the --main=name option to the compiler. section 2.2 Command line options for details.

2.2 Command line options

The following command line options are available.

-h, --help
This option will force the compiler to show a short usage message and to exit successfully.
-v, --version
The compiler will print its version number and exit successfully.
-m, --main=name
This option must be given when compiling the main module of a program. It tells the compiler to link the module with all imported modules and to produce an executable program called name. With this option, only one source file may be given, which must be the main module.
-p, --module-path=path
Tells the compiler to look in all directories in path (which must be a colon-separated list of directory names) when searching for imported modules.
-d, --debug=MODIFIER
This options switches on one or more debugging options. Each debugging option is denoted by a different letter; they must be given one after the other without intervening spaces, as in the following example:
turtle --debug=ae
a
This option causes the compiler to print out the abstract syntax tree of each parsed source file after reading it.
e
With this option, the compiler prints the top-level environment of each source file after parsing and analyzing it.
i
The highlevel intermediate language (HIL) representation of the source program will be printed to standard out just after type checking.
b
The lowlevel intermediate language (LIL) representation of the source module will be printed to standard out just after code generation.
-z, --pragma=pragma
This option is used to pass additional information about the source file or the compilation process. The following pragmas can be given:
handcoded
Handcoded modules (that is, modules which contain functions implemented in C) must be compiled with this option, otherwise the compiler will refuse to compile the source file. This is a safety feature, because declarations for handcoded functions can be easily written by error and would otherwise lead to hard understandable error messages.
compile-only
With this option, the C compiler will not be run on the generated C code. This option is mainly useful for debugging the compiler.
static
Causes the linker to statically link the program. Only has an effect if the --main=name option is also given. This option may require GCC.
turtledoc
Instead of compiling the source files on the command line, the compiler will extract documentation comments and create Texinfo documentation for the modules. For each module to be compiled, a Texinfo node will be written to standard output with documentation for all data types, variables and functions defined in the module.
deps
In addition to normal compilation, a the dependencies of the source file will be written to a file with the same basename as the input file, but with the extension `.P'. The dependencies are formatted to be usable with `make'.
deps-stdout
Like the pragma deps, but instead of writing to a dependency file, the dependencies are written to standard output.
-O, --optimize=FLAGS
Set some flags for the Turtle optimizer and the C compiler. By default all Turtle optimizations are on and the C optimizations are off. One or more of the following flags can be given:
C
Optimize module-local calls.
c
Do not optimize module-local calls.
J
Convert module-local calls to jumps.
j
Do not convert module-local calls to jumps.
G
Merge all GC checks which appear in a basic block into one at the start of the block.
g
Do not merge all GC checks in one basic block.
0...6
Set the optimization level for the C compiler to the given value. This option may require GCC.

2.3 Handcoding

A lot of low-level functions cannot be implemented in Turtle, because there is currently no way to access operating system features or the C library directly. Therefore, `handcoded' modules have been added to the Turtle compiler.

Handcoded modules can contain normal Turtle definitions for functions, variables and data types, but additionally they can contain functions whose body has been omitted, and whose implementation is written in C in another place. This other place is a C source code file which must be named like the module to be compiled, but with the added extension `.i'. That means that the implementation of handcoded functions in the module file `core.t' must reside in the file called `core.t.i'.

Currently, there are two kinds of handcoded functions. The first is to simply omit the function body and give the implementation as a C macro which will be placed into the generated C code by the cmopiler. This has the advantage that there is no runtime penalty for using a handcoded function, and that the macro can directly access all virtual registers without the need to flush them to their memory locations. The disadvantage is that it is quite easy to mess up the virtual machine's state. Handcoded functions written as macros are called "implementation macros".

The second method is to write down the function header, followed by an equal sign and a string which names a C function. This function will then be called from the generated code. The parameters to the declared Turtle function are passed as normal C parameters to the named function, so that there is no way to mess with the Turtle stack or registers. This method is recommended and should be used unless their is an urgent need for efficiency or access to the virtual machine from inside the handcoded function. Functions of this kind are called "mapped functions", because their functionality is mapped directly to a C function.

2.3.1 Compiling handcoded modules

Because it is easy to break your programs with handcoded modules, the compiler will only accept such modules when explicitly instructed with the pragma option handcoded. For example:

turtle --pragma=handcoded math.t

2.3.2 Implementation include file

An implementation include file must list all needed implementation macros and mapped function implementations. If the macros or functions need any declaration from the C library, file inclusion statements can also appear in the file, and C variables and typedefs can also be written here.

2.3.3 Implementation macros

These macro definitions must be written in a file called like the Turtle source file, but with a `.i' added to the file name. This file is included into the compiled C file. The implementation macros are expected to be named like the mangled function names, appended with the string _implementation, and they must not have parameters. The easiest way to get at the mangled name is to implement the function in the Turtle module, compile it with the --pragma=handcoded option, ignore the errors from the linker and take the mangled name from the C output file. Additionally, you may want to add the function's signature to the implementation macro, for documentation purposes.

Function entry and exit code are compiled like for normal Turtle functions, so that the parameters to the Turtle function can be found in the first elements of the array env->locals.

This is an example for an implementation macro as used in the library module core. The following is code from the module file `core.t':

fun version (): string;

And this is the corresponding implementation macro from the file `core.t.i':

#define core_version_F_0__To_S_implementation                   \
{                                                               \
  TTL_SAVE_REGISTERS;                                           \
  {                                                             \
    ttl_global_acc = ttl_string_to_value (ttl_version_string (),\
                                          -1);                  \
  }                                                             \
  TTL_RESTORE_REGISTERS;                                        \
}

There are some important rules to keep in mind when writing handcoded functions, but note that there may be other problems as well, which have just not yet come to the surface:

2.3.4 Mapped functions

Mapped functions are much easier to write than implementation macros, because you don't have to take care of heap overflows causing garbage collection, for extracting the parameters from the correct environment locations or for finding the mangled name of functions from the generated C code. As an example for a mapped functions, we'll examine the getlogin function from the unix module.

This is the function declaration as it appears in the Turtle file:

fun getlogin (): string = "ttl_getlogin";

The function is declared as a mapped function, which should be mapped to the C function ttl_getlogin. This function is an additional layer between the code generated for the Turtle function and the C library function. Its responsibility is to unbox the parameters (if any), call the C library function and to box the result and return it to the caller. Here is how this looks like for the getlogin example:

ttl_value
ttl_getlogin (void)
{
  char * val = getlogin ();
  if (val)
    return ttl_string_to_value (val, -1);
  else
    return ttl_string_to_value ("", 0);
}

Compared to the implementation macros described above, this is really easy. But note that the same restrictions apply as for the implementation macros described in the previous subsection.

In the future the Turtle compiler could be equipped with the additional functionality to generate such glue code itself, so that all boxing/unboxing etc. would be done by compiler-generated code, on the basis of some data type declrations.

2.4 Documenting Turtle Modules

Documentation is a very important part in software creation. It is not only important for programmers using third-party modules, but also to make sure that one's own modules will be reusable and can be still understood in the future.

The Turtle compiler has support for simple inline documentation of Turtle modules, called turtledoc. It is similar in spirit to the well-known `JavaDoc' program which extracts documentation comments from Java source files and creates fully indexed and linked HTML documentation for Java packages. Though turtledoc is much simpler, it is nevertheless quite useful and has been used to create the documentation for the Turtle standard library in this manual (see section 5. Standard library).

2.4.1 Preparing Turtle Modules for turtledoc

The basic concept of turtledoc are so-called "documentation strings". Each function, variable or data type of a module can have a documentation string attached, and even the module itself can have one. The first step in using turtledoc is to attach documentation strings to these entities, and the second step is to use the Turtle compiler to extract these strings from the module and have them printed together with the name, type and kind of the entity they document.

This subsection documents the first step, the second step is described in the next subsection.

For illustration, we will prepare an example module with documentation strings. This is the example:

module docex;

fun do_nothing ()
end;

fun do_nothing2 ()
end;

fun ignored ()
end;

fun do_nothing_too ()
  var i: int := 10000;
  while i > 0 do
    i := i - 1;
  end;
end;

We could already run the compiler on this and instruct it to extract documentation, but the result would be a bit disappointing:

@node docex module
@subsection docex module
@cpindex docex (Module)

@deftypefn {Library function} {} do_nothing ()
@end deftypefn

@deftypefn {Library function} {} do_nothing2 ()
@end deftypefn

@deftypefn {Library function} {} ignored ()
@end deftypefn

@deftypefn {Library function} {} do_nothing_too ()
@end deftypefn

Turtledoc comments are written like normal comments, but with an asterisk directly after the comment starting characters:

//* Like this...
/** ... or this.  */

The documentation strings must preceed the entity they document. A module's documentation string will be written out preceeding the documentation of the variables, functions etc., Variable and function documentation will be placed between their Texinfo documentation constructs. Datatype documentation is additionally equipped with the definition of the data type, which is normally very instructive for the reader who wishes to use the data type.

A function can be ommitted from the output by providing it with a documentation string starting with a - (minus sign).

Often it is useful to group several functions together with the same documentation, for example when they do similar things and only differ in the types of their arguments. This can be accomplished by writing the documentation string down with the first of the functions to be grouped, and by placing the other functions of the group directly behind that, where each of the functions has a documentation string starting with " (doublequote).

This is the example, now equipped with documentation strings:

//* Example module for turtledoc.
module docex;

//* This function does nothing.
fun do_nothing ()
end;

//* ""
fun do_nothing2 ()
end;

//* -
fun ignored ()
end;

//* This function does nothing too, but expensively.
fun do_nothing_too ()
  var i: int := 10000;
  while i > 0 do
    i := i - 1;
  end;
end;

And this is the output produced from the annotated source code:

@node docex module
@subsection docex module
@cpindex docex (Module)

Example module for turtledoc.

@deftypefn {Library function} {} do_nothing ()
@deftypefnx {Library function} {} do_nothing2 ()
This function does nothing.
@end deftypefn

@deftypefn {Library function} {} do_nothing_too ()
This function does nothing too, but expensively.
@end deftypefn

We can see that the module's documentation comes directly after the node header. The do_nothing and do_nothing2 functions are grouped together and the ignore function is not documented at all. The last function, do_nothing_too, is documented seperately.

The documentation strings can contain arbitrary Texinfo markup, such as for tables or node references. The strings are not interpreted or modified in any way.

2.4.2 Extracting the Documentation

After having equipped the source code with properly marked documentation strings, you have to run the compiler on the source file and instruct it to create the turtledoc documentation. This is done by simply giving the pragma option turtledoc to the compiler, like for the example module from the previous subsection:

turtle --pragma=turtledoc docex.t

The documentation is then written to standard output and can be included into the Texinfo documentation for your project.

3. Language Reference

This chapter describes the Turtle programming language. First, the syntax and semantics of the language are presented, then the runtime environment and the standard library are documented.

3.1 Turtle Grammar

This section describes the grammar of the Turtle programming language.

3.1.1 Notation

The lexical and grammatical structure of Turtle is described using Extended Backus Naur Form (EBNF). This notation is summarized below.

A ::= E
The non-terminal A produces the form E.
E | F
Alternative; either E or F is produced.
{ E }
The form E is repeated, possibly zero times.
[ E ]
The form E is optional, it may be omitted completely.
( E )
For grouping, denotes E itself.
<empty>
Denotes the empty string.

3.1.2 Lexical Structure

Turtle programs are composed by tokens of the following token classes:

Reserved words
Reserved words look like identifiers (see below), but they have special meanings in the source program. They are summarized in the Reserved Words Table below. Identifiers denoting reserved words cannot be used for other purposes (variable names, function names, etc.).
Identifiers
An identifier is used for naming semantic entities in the program text: variables, functions, constraints, modules, etc. Like in most other imperative languages descending from Algol, identifiers start with an alphabetic letter or an underscore, followed by a number of alphabetic letters, underscores or digits. Additionally, identifiers may be terminated with a question mark. There is no length restriction on identifiers.
Ident ::= (Letter | Underscore) {Letter | Underscore | Digit} [?|!]
String constants
Strings of characters are enclosed in double quotes. Inside of the string, double quotes are denoted as the escape sequence \", backslashes as \\. Additionally, some non-printing characters can be written as escape sequences as well:
\n
The newline character (ASCII 10).
\r
The carriage return character (ASCII 13).
\t
The tabulator character (ASCII 8).
\b
The backspace character (ASCII 9).
StringConst ::= "{any except Special | \" | \\ | \n | \r | \t | \b}"
Special     ::= " | \
Character constants
Characters are enclosed in single quotes. As in string constants, escape characters can be used in character constants. Only one character (resp. escape sequence) can be in a character constant.
CharConst  ::= '(any except Special | \" | \\ | \n | \r | \t | \b)'
Integer constant
Integer constants are currently limited to the range of long values in the C implementation used to compile Turtle.
IntConst   ::= Digit{Digit}
Real constant
Real constants denote floating point approximations of real numbers. They are currently limited to the range of double values in the C implementation used to compile Turtle.
RealConst  ::= Digit{Digit}.Digit{Digit}[(e|E)[-|+]Digit{Digit}]
Operators
The operators are summarized in the Operator Table below.

Reserved Words Table:

module export import
module introduces a module, the others manage the import and export of modules and identifiers.
fun
Used for declaring functions, function expressions and function types.
constraint
Used for declaring constraints and constraint expressions.
if then else
Used in if-then-else statements.
while do
Used in while-do statements.
end
Ends functions, constraints and compound statements.
return
Returns values from functions.
var
Variable declarations.
type
Type declarations.
array list string of
Used in type expressions, and in array, list and string constructors.
and not or
Logical operators.
false true
Truth constants.
require prefer retract
Used for managing the constraint store.
hd tl null
List operators and the empty list constant.
sizeof
Generic size operator.

Operator Table:

.
Dot. Used to separate the components of qualified identifiers.
,
Comma. Separating items in parameter lists, variable declarations, lists, arrays tuples etc.
( )
Parenthesis are used to group elements of value and type expressions, parameter lists etc.
{ }
Curly braces enclose array expressions.
[ ]
Square brackets are used as indexing operators for using in indexed (array) expressions and enclose list expressions.
!
Annotates constrained types.
;
The semicolon terminates declarations and statements.
+ - * / %
Arithmetic operators.
= < <= > >= <>
Comparison operators.
:=
Assignment operator.
hd tl :
List operators.
sizeof
Generic size operator.

3.1.3 Turtle Syntax

The description of the Turtle grammar is divided in various sections, and each section is provided with some additional comments.

3.1.3.1 Module Syntax

Turtle programs are organized in compilation units. These compilation units are called "Modules". The head of a module consists of a module header which states the name of the module, and then the (possibly empty) import and export statements, followed by a sequence of declarations. The import statements states which modules will be used in the module, and the export statement lists the bindings which are public. These bindings can be variable, function and constraint definitions as well as type declarations.

CompUnit     ::= Module
Module       ::= 'module' QualIdent [ModuleParams] ';' 
                 ModDecls Declarations
ModuleParams ::= '<' ModuleParam {',' ModuleParam} '>'
ModuleParam  ::= Ident
ModDecls     ::= Imports Exports
Imports      ::= <empty>
              |  'import' ImportIdent {, ImportIdent} ';'
Exports      ::= <empty>
              |  'export' QualIdent {, QualIdent} ';'
ImportIdent  ::= QualIdent [ImportAnnotation]
ImportAnnotation ::= '<' Type {',' Type} '>'

3.1.3.2 Declaration Syntax

Declarations in Turtle can be type, variable, function and constraint declarations. Their syntax is given below. In a program, more than one declarations can have the same name, provided that they can be distinguished by declaration kind (type declarations vs. the other kinds) or by type.

Definitions     ::= { Definition ';' }
Definition      ::= TypeDef | DatatypeDef | VarDef | FunDef | ConstraintDef
TypeDef         ::= 'type' Ident = Type
DatatypeDef     ::= 'datatype' Ident '=' 
                    DatatypeVariant {'or' DatatypeVariant}
DatatypeVariant ::= Ident ['(' VariableList ')']

FieldList       ::= Field {',' Field}
Field           ::= Ident ':' Type

VarDef          ::= 'var' VariableList

VariableList    ::= Variable {',' Variable}
Variable        ::= Ident ':' Type [':=' ConsExpression]

FunDef          ::= 'fun' Ident ParameterList [':' Type] SubrBody
ConstraintDef   ::= 'constraint' Ident ParameterList SubrBody

ParameterList   ::= '(' [Parameter {',' Parameter}] ')' 
Parameter       ::= ['out'] Ident ':' Type 

Type            ::= QualIdent
                 |  '!' Type
                 |  '(' ')'
                 |  '(' Type {',' Type} ')'
                 |  'array' 'of' Type
                 |  'list' 'of' Type
                 |  'string'
                 |  'fun' '(' [Type {',' Type}] ')' [':' Type]

SubrBody        ::= StmtList 'end'

3.1.3.3 Statement Syntax

Statements are the basic entities of which imperative programs are based. Statements in a statement list are executed in top-down direction, and statements can have side effects. In Turtle, there are three statements uncommon in other languages, the constraint statements require, prefer and retract. They are used for maintaining the constraint store.

StmtList        ::= { Statement ';' }
Statement       ::= VarDef | FunDef | ConstraintDef
                 |  IfStatement | WhileStatement |  ReturnStatement
                 |  RequireStatement | PreferStatement |  RetractStatement 
                 |  ExpressionStatement 
IfStatement     ::= 'if' CompareExpression 'then' {Statement} 'end'
                 |  'if' CompareExpression 'then' {Statement} 'else'
                    {Statement} 'end'
WhileStatement  ::= 'while' CompareExpression 'do' {Statement} 'end'
ReturnStatement ::= 'return' [TupleExpression]
RequireStatement::= 'require' CompareExpression
PreferStatement ::= 'prefer' CompareExpression
RetractStatement::= 'retract' CompareExpression
ExpressionStatement ::= Expression

3.1.3.4 Expression Syntax

Expressions consist of assignment expressions, comparing and boolean expressions and arithmetic expressions. Additionally, functions and constraints can result from evaluating expressions, such as in functional programming languages.

Expression           ::= AssignExpression
AssignExpression     ::= TupleExpression [':=' TupleExpression]

TupleExpression      ::= ConsExpression {',' ConsExpression} 

ConsExpression       ::= CompareExpression ['::' ConsExpression]

CompareExpression    ::= AddExpression [CompareOp AddExpression]
AddExpression        ::= MulExpression {AddOp MulExpression}
MulExpression        ::= Factor {MulOp Factor}
Factor               ::= SimpleExpression
                      |  '-' Factor
                      |  'not' Factor
                      |  'hd' Factor
                      |  'tl' Factor
                      |  'sizeof' Factor

SimpleExpression     ::= AtomicExpression {ActualParameters | Index}
ActualParameters     ::= '(' [ConsExpression {',' ConsExpression}] ')'
Index                ::= '[' AddExpression ']'

AtomicExpression     ::= QualIdent
                      |  IntConst | RealConst | StringConst | CharConst
                      |  BoolConst | ArrayExpr | ListExpr
                      |  FunExpression | ConstraintExpression
                      |  'array' AddExpression 'of' TupleExpression
                      |  'list' AddExpression 'of' TupleExpression
                      |  'string' AddExpression 'of' SimpleExpression
                      |  '(' TupleExpression ')'
                      |  'null'
BoolConst           ::= 'false' | 'true'

FunExpression        ::= 'fun' ParameterList [':' TypeExpr] SubrBody
ConstraintExpression ::= 'constraint' ParameterList SubrBody
ArrayExpr            ::= '{' [{ConsExpression}
                              {',' ConsExpression}] '}'
ListExpr             ::= '[' [{ConsExpression}
                              {',' ConsExpression}] ']'

MulOp                ::= '*' | '/' | 'and'
AddOp                ::= '+' | '-' | 'or'
CompareOp            ::= '=' | '<>' | '<' | '<=' | '>' | '>='

3.1.3.5 Basic syntax items

In the beforementioned syntax descriptions, the following non-terminals have been used:

QualIdent      ::= Ident {'.' Ident}

3.2 Turtle semantics

This section documents informally the static and synamic semantics of Turtle programs.

3.2.1 Expression Types

Arithmetic operators (AddOp and MulOp in the grammar, and unary -) may only be applied to operands of numeric type, and the type for both operands of the binary operators must be the same. The result type is the same type as the types of the operands.

The comparison operators may only be applied to operands of comparable types, which are integers, reals, characters and booleans. Both operands must be of the same type. They yield a result of type boolean.

The operators and, or and not may only be applied to operands of boolean types. The result type is boolean, too. The evaluation of and and or expressions is short-circuited, that means that if in an and expression the first operand evaluates to false, the second operand is not evaluated, because the result of the overall expression is known. Similarly, if the first operand to or evaluates to true, there is no need to evaluate the second operand.

3.2.2 List operators

The operators hd and tl return the head or tail of a list value, respectively. If the list operand is null (the empty list), an exception is raised.

The : (pronounced "cons") operator takes an expression and a list expression and creates a new list cell with the expression as the list head and the list expression as the list tail.

In addition to the cons operation, lists can be created as documented in section 3.2.4 List and array expressions.

The empty list can be detected by comparing a list expression against null: all lists are terminated by this constant.

3.2.3 Array operators

Arrays are aggregations of homogenous objects. Arrays can have varying lengths, but the length must be specified when creating the array value. Arrays can be constructed by the means documented in section 3.2.4 List and array expressions.

Array elements are addressed by their index, which must be in the range 0...N-1, where N is the length of the array. An array index expression looks like this:

A[2]

This expressions references the array element with index 2 (the third element, because of zero-based indexing). If written on the lefthand side of an assignment operator (:=), an array element can be overwritten with the expression on the right hand side.

This indexing can be used for string in the same way.

The length of an array expression (or string) can be determined with the sizeof operator.

3.2.4 List and array expressions

All elements of list and array expressions must have the same type. The type of a list or array expression is list of element type or array of element type, respectively. The empty list expression [] is equivalent to the constant null and is compatible with all list types. The empty array expression {} is compatible with all array types.

The special constant null is compatible to all list types.

The array constructor array expr of expr has the type array of element type, where element type is the type of the second expression of the constructor. The first expression must be of type int. The constructor returns an array of the length given as the first expression, where each list element is initialized to the second expression.

The list constructor list expr of expr has the type list of element type, where element type is the type of the second expression of the constructor. The first expression must be of type int. The constructor returns a list of the length given as the first expression, where each list element is initialized to the second expression.

The string constructor string expr [of expr] has the type string. The first expression must be of type int, the second expression, if given, must be of type char. If omitted, the contents of the newly created string value is unspecified.

3.2.5 Return statements

Return statements are not followed by an expression if they are contained in a function of return type void. Otherwise, the expression must have a type compatible with the return type of the enclosing function. A function with non-void return type must have a return expression in tail position.

3.2.6 Overloading

A Turtle module may declare more than one type, variable, function or constraint with the same name, as long as they are distinguishable by identifier kind (type vs. variable, function or constraint), or by type. Consider the following Turtle fragment:

var a: int, a: real;
a := 1;
a := 1.1;

This code is legal, because the compiler can determine unambiguously which variable is used in the second and third line. The second line refers to the int variable, because an int value is assigned, and the third line modifies the real variable.

Turtle's overloading is more powerful that in C++ or Java, because not only the parameter types of functions can be overloaded but also the return type and variables which don't have function types. Because of these restrictions in C++/Java, the above code would not work there. Turtle is similar to Ada in that respect.

When type-checking programs, the Turtle compiler considers every possible interpretation of a given expression, and then tries to find a unique type-consistent interpretation. If this is not possible, an error message is issued, either stating that no possible typing was found or that the expression is ambiguous, that means, there is more than one legal interpretation. Consider this example:

var a: int, a: real;
var b: array of int, b: array of real;
b := {a, a};

Here, both the assignment of a two-element array of integers and reals to an integer or real array variable is legal. The compile will signal an error for this example.

3.2.7 Generic Modules

Turtle supports so-called generic modules. They provide a restricted form of polymorphism. Modules can be declared to have module parameters, which are types. In the module, these parameters can be used for defining functions and data types. When a generic module is then imported, it must be instantiated, that is, actual types must be provided for the module parameters. The exported functions of the module are then available with the actual type substituted for the module parameter.

A module can be imported more than once into the same scope, provided that the combination of module parameters differ.

Module parameters can be used to form the actual types in module import statements, too.

3.3 Data Types

Turtle provides a variety of builtin data types, such as integers, reals, strings etc., and support for arrays and lists is also built into the language. Additionally, Turtle provides a powerful mechanism for defining new data types for specific purposes. This functionality is used in the standard library, which provides a set of abstract data types such as binary trees, hash tables and so on.

This subsection documents the basic data types, compound data types and user-defined data types.

3.3.1 Basic data types

Basic data types provide the most basic functionality for computing. For the numeric data types (integers and reals), arithmetic operations are defined, strings can be decomposed to characters and so on.

3.3.1.1 Integers

Integer numbers are numbers without a fraction part.

Integer numbers are written as a non-empty sequence of the digits 0 to 9. The name of the data type is int, which is not a reserved word but defined in the standard outermost compilation environment.

1
10
1000
424242
23

Turtle defines the arithmetic operators + (addition), - (subtraction), * (multiplication), / (division) and % (modulo). Integers can be compared with the operators =, <>, <, >, <= and >=.

The module ints (see section 5.3.1 ints module) provides some useful constants and functions for integer values.

3.3.1.2 Longs

While there is an integer data type called int, there is an additional integer data type supported, called long. The difference between int and long is that integer values are restricted to the range ints.min...ints.max, which is not necessarily the complete 32-bit value space. long values, on the other side, are guaranteed to have at least 32 bits, on 64 bit platforms, it can be even 64 bits.

Long integer constants are written like integer constants, but must be appended with an uppercase L, as in the following examples:

42L
23L
0L
2147483647L

Note especially the last example, which is too large to fit into an int value on 32 bit systems.

The same arithmetic operations as supported for int values are supported, that is, + (addition), - (subtraction), * (multiplication), / (division) and % (modulo). Long integers can be compared with the operators =, <>, <, >, <= and >=.

The module longs (see section 5.3.2 longs module) provides some useful constants and functions for integer values.

3.3.1.3 Reals

In contrast to integers, reals can have a fraction part. The fraction part is separated from the leading sequence of digits by a period, and can be followed by an optional exponent part, like in C or Java. The name of the data type is real, which is not a reserved word but defined in the standard outermost compilation environment.

1.0
3.14159
1.0e12
20E-12

Turtle defines the arithmetic operators + (addition), - (subtraction), * (multiplication) and / (division). Reals can be compared with the operators =, <>, <, >, <= and >=.

The module reals (see section 5.3.3 reals module) provides some useful constants and functions for real values.

3.3.1.4 Booleans

The booleans represent the two truth values true and false. They are denoted by the reserved words true and false. The name of the data type is bool, which is not a reserved word but defined in the standard outermost compilation environment.

Boolean values can be compared with = and <>. The operations and for conjunction, or for disjunction and not for negation can be used with expression of type bool. The and and or are evaluated with short-circuiting, that is if the first operand of and evaluates to false, the second operand is not evaluated, and if the first operand of or is true, the evaluation of the second is skipped.

3.3.1.5 Characters

Characters are used for storing character data. Character constants are denoted by enclosing a character in single quotes, as in C/C++/Java. For denoting some special characters, the following escape sequences are defined:

'\"'
Denotes a double quote.
'\"
Denotes a single quote.
'\\'
Denotes a backslash character.
'\n'
Denotes a newline character.
'\r'
Denotes a carriage return character.
'\t'
Denotes a tab character.
'\b'
Denotes a backspace character.

The name of the data type is char, which is not a reserved word but defined in the standard outermost compilation environment.

The module chars (see section 5.3.5 chars module) provides some useful constants and functions for character values.

3.3.1.6 Strings

Strings are sequences of characters. They have a fixed length, which is specified when creating a new string value, or when writing down a string literal. String literals consist of zero or more characters, enclosed in double quotes. They may contain the same escape sequences as character literals section 3.3.1.5 Characters, but they may not span a line boundary, that is they may not contain a character with the character code of '\n'.

Strings are different than the former documented basic data types, because they contain zero or more values of another data type, character. The reason for building this data type into Turtle is that it is so common, that using (for example) array of char or list of char is considered too inconvenient.

The name of the data type is string, which is, unlike the other type names so far, a reserved word.

Elements of a string can be extracted by applying the subscript operator, [], to a string expression:

var s: string := "Hallo";
io.put (s[1]);    // Writes 'a' to stdout.

The same operator, when applied to the lefthand side of an assignment, will change an element of the string.

var s: string := "Hallo";
io.put (s[1]);    // Writes 'a' to stdout.
s[1] := 'u';
io.put (s);       // Writes "Hullo" to stdout.

Strings are either created by writing down string literals, like this:

""       // Empty string.
"Hello"
"a"

or with a string constructor expression, which creates a string of a given length and initializes all elements to a given character:

var s: string := string 12 of '!';

The length of a string can be determined with the sizeof operator.

The module strings (see section 5.3.6 strings module) provides some useful constants and functions for string values.

3.3.2 Compound data types

Turtle provides three data types which are made up of other data types: arrays, lists and function types.

3.3.2.1 Array data type

An array data type is written as array of basetype.

The length of an array is fixed when the array value is created and can be determined later with the sizeof operator.

Elements of an array can be fetched from the array value or stored into it using the subscript operator [].

Arrays can be created with array constructor expressions or by writing down array expressions.

Array constructor expressions create arrays of a specified length, where each element of the array is initialized to the same value. It is important to note that the array elements are really initialized to the same value, so that if this value is of an array, list, string or user-defined data type, the same value is shared by all array elements and by modifying one element, all other array elements are affected as well.

var a: array of int := array 20 of 23;
var l: array of string := array 12 of "Hello";

Array expressions are used to create array values with pre-defined contents. They are written as comma-separated lists of array elements, enclosed in curly braces.

var a: array of int := {1, 3, 12, 4};
var a: array of string := {"O", "sole", "mio"};

The library module arrays (see section 5.5.1 arrays module) provides some useful and functions for array values. The library also contains the module arraysort (see section 5.5.4 arraysort module) for sorting arrays of arbitrary contents and the module arraysearch (see section 5.5.3 arraysearch module) for searching arrays linearly or by bisection. The library module arraymap (see section 5.5.2 arraymap module) exports a function for applying functions to all elements of an array in turn, returning an array of the function results

3.3.2.2 List data type

A list data type is written as list of basetype.

The length of a list is variable, a list can be extended by prepending values to the front of the list.

The first element of a list (the head) is fetched from a list with the prefix operator hd, the list of the remaining elements (the tail) is fetched with the operator tl. An element is added to the front with the so-called cons operator, written as ::.

Lists can be created with list constructor expressions or by writing down list expressions.

List constructor expressions create lists of a specified length, where each element of the list is initialized to the same value. It is important to note that the list elements are really initialized to the same value, so that if this value is of an array, list, string or user-defined data type, the same value is shared by all list elements and by modifying one element, all other list elements are affected as well.

var l: list of int := list 20 of 23;
var l: list of string := list 12 of "Hello";

List expressions are used to create lists with pre-defined contents. They are written as comma-separated lists of list elements, enclosed in square brackets.

var l: list of int := [1, 3, 12, 4];
var l: list of string := ["O", "sole", "mio"];

The library module lists (see section 5.4.1 lists module) provides some useful functions for lists. The library also contains the module listsort (see section 5.4.8 listsort module) for sorting lists of arbitrary contents and the module listsearch (see section 5.4.7 listsearch module) for searching lists. The library module listmap (see section 5.4.2 listmap module) exports a function for applying a function to all elements of a list, producing a list of the function's results.

3.3.2.3 Function data type

A function data type is written as fun(paramtypes...): returntype

Functions can be created with function expressions or by function declarations..

The standard module compose (see section 5.1.3 compose module) provides a function for composing functions.

3.3.2.4 Tuple data type

Values can be composed to form tuples. Tuples are ordered sequences of fixed length, where the data types of the elements can be different.

A tuple type is written by enclosing more than one type expression in parentheses, seperated by commas, for example:

(int, string, array of string)

Tuple values are created by writing down comma-separated list of more than one expression.

Tuple values are decomposed by assigning to a tuple of variables, such as in:

var a: int, b: int, c: (int, int);
c := 1, 2;
a, b := c;

For programming convenience, the standard library contains two modules which export functions for dealing with two very common tuple types. The modules pairs (see section 5.6.1 pairs module) and triples (see section 5.6.2 triples module) export selector functions for tuple components.

3.3.3 User-defined data types

User-defined data types are defined using the datatype declaration. As an example, we will define a data type representing a binary tree. The name of the new type will be tree, and there are two variants for objects of this type: First, there will be a variant for interior node, which consist of a left and a right subtree, and second there must be a variant for the leafs of the tree. This is how such a datatype declration looks like in Turtle:

datatype tree = node (left: tree, right: tree) or
                leaf (value: int);

There are several things to note here. The variants of the data type are listed on the right hand side of the declaration, separated by the reserved word or. User-defined data types can be recursive, that means that the left hand side of the declaration may appear on the right hand side as well.

Each variant has a number of data fields. This field list can be empty, and if it is empty, the parenthesis can be omitted. Fields in different variants can have the same name and must not have the same types if they have the same name, but the fields of one variant must be distinct either in name or in type.

A datatype declaration causes the compiler to create several functions automatically:

Constructor functions
For each variant a constructor function is created which can be called to create objects of this variant. Constructor functions are called like the variant and expect the fields' data types as arguments.
Discriminator functions
For each variant a discriminator function is created which expects an object of the data type and returns true if the object is of the correct variant, and false otherwise. The name of the discriminator function is the name of the variant with an appended ? (question mark).
Selector functions
For each name/type combination of the fields a selector function is created which extract the field from an object of the data type. If the object is of a variant which does not have a field with the name/type combination, an exception is raised. The name of the selector functions is simply the name of the fields.
Setter functions
For each name/type combination of the fields a selector function is created which sets the field to an object of type of the field. If the object is of a variant which does not have a field with the name/type combination, an exception is raised. The name of the setter functions is derived from the field names by appending a ! (exclamation point).

For our example above, the following functions are automatically created:

// Constructors
fun node (tree, tree): tree;
fun leaf (int): tree;

// Discriminators
fun node? (tree): bool
fun leaf? (tree): bool

// Selectors
fun left (tree): tree;
fun right (tree): tree;
fun value (tree): int

// Setters
fun left! (tree, tree);
fun right! (tree, tree);
fun value! (tree, int);

3.4 Runtime environment

The Turtle runtime environment consists of a standard virtual machine like the ones used for other imperative programming languages, enriched with a constraint solver interface, a constraint store and several constraint solvers for solving primitive constraints. User-defined constraints are either translated by the compiler or dynamically by the runtime library to primitive constraints, which are then solved using the primitive solvers.

4. Constraint Programming

Turtle is a constraint-imperative language. That means that the normal imperative language constructs found in today's imperative programming languages are present in Turtle as well as more declarative language elements. This chapter gives an introduction to constraint programming in Turtle, will describe the principles of constraint programming and the interaction between imperative and constraint features, and will give some hints about what can be accomplished with constraints in Turtle.

4.1 Constraints and the Constraint Store

Before we jump into constraint programming, we have to give a brief introduction to constraints and the mechanisms necessary to manage and solve constraint systems.

One basic notion is the constraint. A constraint is a formula, in Turtle it is defined to be either an expression of type boolean, or the application of a user-defined constraint. All constraints which are to be solved in a program are added to the so-called constraint store, which is simply a set of constraints.

In Turtle, constraints are added to or removed from the store by using constraint statements (see section 4.3 Constraint Statements). Whenever a constraint is added to or removed from the store, the constraint solver tries to enforce as many constraints as possible.

Since Turtle supports constraint hierarchies, that is, constraints of different strength, each constraint in the constraint store is labelled with its associated strength. Strengths are given to constraints when adding them to the store. One special strength is called required, and constraints of this strength must hold during program execution, or otherwise an exception will be raised.

4.2 Constrainable Variables

In Turtle, variables are either normal variables or constrainable variables. Constrainable variables have the special property that they can not be set by assignment statements, but only by constraints. The following example will demonstrate the difference:

var x: int;
x := 2;

`x' is a normal variable, and is set to the value 2 by assignment. In the next example, the variable `y' is declared as a constrainable variable (note the ! (exclamation point) in the type declaration of the variable), and can thus be used in a constraint to set its value.

var x: !int;
require y = 2;

4.3 Constraint Statements

The language Turtle knows about three statement kinds normally not found in imperative languages: require, prefer and retract statements. These commands are used to maintain the constraint store (see section 4.1 Constraints and the Constraint Store).

This example adds a constraint to the store:

require x > 3;

Executing this constraint statements will cause the Turtle runtime to add the constraint `x > 3' to the store, and to try to satisfy it. If the current value of the variable `x' is greater than 3, nothing will happen. If not, an exception will be raised saying that a required constraint was not satisfued. The statement prefer, on the other hand, will only try to satisfy a constraint if possible. For the constraint example above, this would not make sense, but if instead a constrainable variable was involve in the constraint, the solver would try to satisfy it as well as possible by adjusting the variable's value:

var x: !int := 2;
prefer x > 3;

The constraint will set the variable to 4, because this will cause the constraint to be satisfied.

4.4 Constraints as Assertions

For the start, constraints can simply be used to code checks for program invariants. If a utility function you write expects that an integer parameter be always greater than zero, you can add the constraint statement

require x > 0;

at the beginning of the function. This is similar to the use of the assert() macro in C source code. Since no constrainable variables appear in the constraint, the constraint does not get added to the constraint store, but only tested. If the test fails, an exception is raised. In this way, preconditions can be tested by adding constraint statements at the beginning of functions, and postconditions by adding such statements at the end, just before any return statements.

Of course this is not real constraint programming, but it shows that sometimes new features can be adapted to old needs.

5. Standard library

The Turtle standard library comes with a couple of modules for commonly needed programming tasks, such as input/output, string handling, list manipulation etc.

The functions in the standard library are documented like shown below:

Library function: bla (foo: bar): baz
Description of function...

This means that a library function called bla is documented. The function expects one parameter, called foo which is of type bar. The type of the return value is called baz. The function header is then followed by a description of what the function does, and which preconditions must be fulfilled when calling the function.

Remember that in Turtle all references to functions and variables in other modules must be fully qualified, so if you want to call the function map of module listmap from your main program, you have to write:

l := listmap.map (proc, l);

5.1 General modules

This section documents general useful modules, which are not closely related to specific data structures or application fields like input/output or systems programming.

5.1.1 math module

This module provides mathematical constants and functions.

Constant: pi : real
This is the constant pi.

Function: sin (x: real): real
Function: asin (x: real): real
Function: cos (x: real): real
Function: acos (x: real): real
Function: tan (x: real): real
Function: atan (x: real): real
Function: atan (x: real, y: real): real
These are the common trigonometric functions. They are mapped directly to the functions in the C library.

5.1.2 random module

The exported functions rand delivers a random number in the range 0..ints.max. The current implementation uses the C library function rand() for obtaining the random numbers and the C library function srand() for seeding the generator.

Function: seed (seed: int)
Seed the random number generator with the given seed value seed.

Function: rand (): int
Return a random number in the range 0..ints.max.

5.1.3 compose module

This module exports one function, compose, which implements function composition.

Function: compose (f: fun(inter): res, g: fun(arg): inter): fun(arg): res
Return a function of one argument, which first applies g to its argument and then f to the result of this function application.

5.1.4 identity module

This module exports the function id, which is the identity on values of the type given as the module parameter A.

Function: id (data: A): A
Return the argument data unchanged. This function is especially useful for higher-order functions which expect a function to apply to all members of a collection, such as map. For example,
l := listmap.map (identity.id, l)

can be used to copy a list.

5.1.5 compare module

The module compare exports several comparison functions, where each of the functions compares two values of a basic data type. These functions are especially useful as parameters for the higher-order functions, such as the sorting functions in the listsort or arraysort modules.

Function: cmp (x: bool, y: bool): int
Function: cmp (x: int, y: int): int
Function: cmp (x: long, y: long): int
Function: cmp (x: real, y: real): int
Function: cmp (x: char, y: char): int
Function: cmp (x: string, y: string): int
Compare the values x and y, and return -1 if the first argument is to be considered smaller, 0 if they are equal, and 1 if the first argument is greater than the second.

5.1.6 option module

This module exports one data type, option, and the corresponding constructor, accessor and discriminator functions.

The option type is intended to be the result of partial functions, which can either succeed and return a useful value, or fail. The former result will be of variant some with the useful packaged in the data field, whereas the latter will yield a value of variant none.

This is (of course) inspired by the option type in ML.

Data type: option
Defined as:
datatype option<A> =
  none or
  some(data: A)

The option data type. It either represents nothing (variant none), or a value of the data type A, which is a parameter to this module.

5.1.7 cmdline module

The function getopt, exported by this module, deconstructs a command line into options, option parameters and other parameters.

Data type: optspec
Defined as:
datatype optspec =
  flag(flag_char: char, flag_string: string) or
  option(option_char: char, option_string: string)

Values of type optspec define the possibilities of command line flags (parameterless options) and options (which have parameters).

Data type: option
Defined as:
datatype option =
  flag(flag_char: char) or
  option(option_char: char, argument: string) or
  parameter(param: string)

Calls to the getopt function return lists of this type. Each element of the list stands for one of three different argument types:

Flag
A flag is a parameterless option, which acts as a switch.
Option
An option has an associated argument, which gives the program additional information about the option.
Parameter
Everything not beginning with one or two dashes is considered a normal parameter, such as a filename to act on. Everything following the special option -- will also be treated as a parameter, even if it starts with a dash. Note that a single dash is also a normal parameter.

Function: getopt (specs: list of optspec, args: list of string): list of option
Given a list of option specifications and a list of command line arguments (as passed to the main function, for example), return a list of options, classified and deconstructed as flags, options or parameters.

5.1.8 hash module

This module exports hash functions for the basic data types.

Function: hash (i: int): int
Function: hash (l: long): int
Function: hash (r: real): int
Function: hash (b: bool): int
Function: hash (c: char): int
Function: hash (s: string): int
Calculate a hash value for the given argument. The returned value is in the range 0...ints.max.

5.1.9 hashtab module

This is a generic implementation for hash table. The range and domain types for the partial mapping implemented by the hash table are supplied as module parameters and the hash function for mapping the keys to integers must be given when constructing a hash table.

The module expects two module parameters, range and domain, where range is the type of the keys in the hash table and domain is the type of the associated values.

Data type: hashtable
Defined as:
datatype hashtable =
  tab(size: int, data: array of bucket, hashfn: fun(range): int, cmpfn: fun(range, range): bool)

This is the hastable data type. It stores the hashing and comparison functions to be used with the keys, so that these functions must not be passed to the insertion/search functions each time they are invoked.

Function: make (hashfn: fun(range): int, cmpfn: fun(range, range): bool): hashtable
Create a new hash table which maps keys of type range to values of type domain. hashfn is a function which determines the hash value of a key and cmdfn is a function which determines whether two keys are actually the same.

Function: insert (tab: hashtable, key: range, val: domain)
Insert the key/value pair into the hash table tab. If key is already in the table, its value is overwritten.

Function: delete (tab: hashtable, key: range)
Remove the entry with key key from the hash table tab. Do nothing, if the key is not present in the table.

Function: lookup (tab: hashtable, key: range): option.option
Search the hash table tab for an entry with key key and return some(value) if the key was found, and none() if not found in the table.

5.1.10 trees module

Functions for creating and inspecting binary trees of type A, where A must be instantiated when importing this module.

Data type: tree
Defined as:
datatype tree<A> =
  nil or
  node(data: A, left: tree, right: tree)

Data type for binary trees. The empty tree is created with a call to the constructor nil, and a non-empty tree with the constructor node.

Function: node (d: A): tree
Utility function for creating a singleton tree.

Function: preorder (t: tree, f: fun(A))
Function: inorder (t: tree, f: fun(A))
Function: postorder (t: tree, f: fun(A))
Iterate over the tree t in preorder, inorder or postorder, respectively and call function f at every node, with the data element of the node as argument.

Function: copy (t: tree): tree
Create a deep copy of the tree t.

5.1.11 bstrees module

Functions for creating and inspecting binary search trees with a key of type A, and a data object of type B, where A and B must be instantiated when importing this module.

Data type: tree
Defined as:
datatype tree<A, B> =
  tree(cmpfn: fun(A, A): int, root: trees.tree<(A, B)>)

Data type for binary search trees.

Function: tree (cmpfn: fun(A, A): int): bstrees.tree<A, B>

Function: insert (t: bstrees.tree<A, B>, key: A, val: B): bstrees.tree<A, B>
Insert the pair (key, val) into the binary search tree t and return the updated tree. The old copy of the search tree remains usable; the binary search tree implemented by this module is persistent.

Function: search (t: bstrees.tree<A, B>, key: A): option.option<B>
Search the binary search tree t for the key key and return the associated value, if found, packaged in an option.option type. If not found, the variant option.none is returned.

5.1.12 bintree module

Simple, but working binary tree implementation for building search trees. A binary tree is parametrized by two types, one for the key and one for the associated value. Both the insertion and the search function require a comparison function to be passed, so that an order on the keys can be established.

The module expects two module parameters, A and B, where A is the type of the keys in the search tree and B is the type of the associated values.

Data type: tree
Defined as:
datatype tree<A, B> =
  empty or
  leaf(element: A, data: B) or
  node(left: tree, right: tree, key: A)

The binary search trees are made up of this data type.

Function: insert (t: bintree.tree<A, B>, key: A, data: B, cmp: fun(A, A): int): bintree.tree<A, B>
Return a new search tree in which all key/value pairs from the input tree t are stored and additionally a pair of the parameters key and data is stored. cmp is a comparison function used to determine the order in the tree. cmp is expected to return a value less than 0 if the first argument is smaller than the second, a value greater than 0 if the first argument is greater and 0 if they are equal.

Function: find (t: bintree.tree<A, B>, key: A, cmp: fun(A, A): int): option.option<B>
Search the binary search tree t for an entry with key key. Return option.some (data) with the data value associated with key if key was found, otherwise return option.none (). Note that it is not specified which data value will be returned if the key key appears more than once in the tree.

5.1.13 binary module

Support module for binary (byte-) arrays.

Data type: binary
Defined as:
type binary = internal.binary.binary

The binary data type is an alias for the type of the same name from the module internal.binary, where the real type and function definitions reside.

Constant: make_binary : fun(int): binary
Constant: binary_get : fun(binary, int): int
Constant: binary_set : fun(binary, int, int)
Constant: binary_size : fun(binary): int
These functions create binary arrays of a given size, extract an element from these arrays or stores an integer into a specified location. binary_size returns the number of elements in the binary array b.

Function: to_string (b: internal.binary.binary): string
Convert the binary array b to a string by simply converting the integer values in b to characters using the function chars.chr.

Function: from_string (s: string): internal.binary.binary
Convert the string s to a binary array by converting the characters in the string to their code values using the function chars.ord.

5.1.14 exceptions module

This module exports some functions for raising and handling exceptions.

Exceptions are raised by calling the function exceptions.raise, which has the same effect as performing some illegal operation such as taking the head of the empty list. The argument to raise is the name of the exception.

Exception handling is done by calling the function exceptions.handle. The first argument is a functions which might possibly raise an exception, while the second is a function which will be called when an exception occurs. If no exception is raised, handle returns without calling the handler function.

Function: raise (s: string)
Raise an exception with name s.

Function: handle (thunk: fun(): (), handler: fun(string))
Call the function thunk. If any exception is raised while thunk is running, the function handler will be called with the exception name as the only argument. When handler returns, it will return to the caller of exceptions.handle, in the same way as the call would return when thunk was returning without an exception.

Function: null_pointer_ex (): string
Function: out_of_range_ex (): string
Function: subscript_ex (): string
Function: wrong_variant_ex (): string
Function: require_ex (): string
The return value of these functions is the corresponding exception name, which is the same that would be used if the illegal operation would be performed.

That means that

exceptions.raise (exceptions.subscript_ex ())

has the same effect as

var s: string;
s[-1] := 'a'

5.1.15 filenames module

Library module for filename manipulation functions.

Variable: path_seperator : char
The path name element seperator used by the module.

Function: basename (s: string): string
Function: basename (s: string, ext: string): string
Return the filename s without any directory component. If the parameter ext is specified and matches the file name extension of s, this is removed also.

Function: dirname (s: string): string
Return the directory component of the filename s, without any trailing path seperator.

5.2 Input and output modules

This section collects all input/output related modules of the standard library. The most basic module in this group is io, which provides basic input and output operations for basic data types.

5.2.1 io module

This module provides basic input and output functions for some of the builtin data types. Also some functions for handling files are defined.

Data type: file
Defined as:
datatype file =
  file(fd: int, buf: string, pos: int, fill: int, writable: bool)

The file data type represents input and output streams. Values of this type are either found in one of the pre-defined variables input, output or error, or are obtained by calling functions like open.

Variable: input : file
Standard input file.

Variable: output : file
Standard output file.

Variable: error : file
Standard output file for error messages.

Function: put (f: file, s: string)
Function: put (s: string)
Function: put (f: file, i: int)
Function: put (i: int)
Function: put (f: file, l: long)
Function: put (l: long)
Function: put (f: file, r: real)
Function: put (r: real)
Function: put (f: file, b: bool)
Function: put (b: bool)
Function: put (f: file, c: char)
Function: put (c: char)
Write the string representation of the argument to the file f or the standard output file, respectively.

Function: put (f: file, ls: list of string)
Function: put (ls: list of string)
Write all strings in the argument list to the given file, or standard output, respectively. The strings are separated by newline characters in the output.

Function: nl (f: file)
Function: nl ()
Terminate the current output line by writing a newline character to the given file or standard output, respectively.

Function: putln (s: string)
Function: putln (f: file, s: string)
Function: putln (c: char)
Function: putln (f: file, c: char)
Function: putln (i: int)
Function: putln (f: file, i: int)
Function: putln (l: long)
Function: putln (f: file, l: long)
Function: putln (r: real)
Function: putln (f: file, r: real)
Function: putln (b: bool)
Function: putln (f: file, b: bool)
Write the textual representation of the argument to standard output or the given file, respectively. Then terminate the output with a newline character.

Function: get (f: file): string
Function: get (): string
Function: get (f: file): int
Function: get (): int
Function: get (f: file): bool
Function: get (): bool
Function: get (f: file): char
Function: get (): char
Function: get (f: file): real
Function: get (): real
Read the string representation of a value matching the return type, convert it, and return that value. If the string cannot be converted, return an unspecified value.

The string reading functions returns null when the end-of-file is reached.

Function: get (f: file): list of string
Function: get (): list of string
Read all lines from the file f and return them as a list of strings. For an empty file, return null.

Function: unget (f: file, c: char)
Function: unget (c: char)
Put the character c back into the input file f or standard input, respectively.

Function: open (name: string): file
Open the file called name for reading. Return a file object for reading from the opened file, or return null if the file can't be opened.

Function: create (name: string): file
Create a new file called name and open if for writing. Return a file object for writing to the opened file, or return null if the file can't be opened.

Function: close (f: file)
Close the file object f. After calling this function, f may not be used for file operations anymore.

Function: flush (f: file)
Flush all buffered output to the underlying operating system file descriptor.

5.3 Data type related modules

This section documents the modules for handling values of the various basic data types. The modules for the numeric data types export some important constants and utility functions, for example for determining the minimum or maximum of two values. The character handling module exports conversion functions, and the string module functions for deconstructing, composing and examining strings, etc.

5.3.1 ints module

This is a library module exporting integer data type related constants and functions.

Constant: min : int
min is the smallest representable integer value. This value may (and most probably will) differ from the minimum integer value representable on the underlying hardware.

Constant: max : int
max is the largest representable integer value. This value may (and most probably will) differ from the maximum integer value representable on the underlying hardware.

Function: min (x: int, y: int): int
Return the minimum of two integer values.

Function: max (x: int, y: int): int
Return the maximum of two integer values.

Function: from_string (s: string): int
Convert the string value s to the integer number it represents. If s does not represent any integer number, or if the resulting integer is not in the range ints.min...inits.max, the return value is unspecified.

Function: to_string (i: int): string
Convert the integer value i to its string representation.

Function: to_real (i: int): real
Convert the integer value i to a real value.

Function: from_real (r: real): int
Convert the real value r to an integer value. Decimal places are stripped.

Function: even? (i: int): bool
Function: odd? (i: int): bool
Function: zero? (i: int): bool
Function: positive? (i: int): bool
Function: negative? (i: int): bool
Return true iff i is even, odd, equal to zero, positive or negative, respectively.

Function: abs (i: int): int
Return the absolute value of i, that is, remove i's sign.

Function: signum (i: int): int
Return 1 if i is greater than zero, 0 if i is equal to zero and -1 if i is less than zero.

Function: pred (i: int): int
Function: succ (i: int): int
Return the predecessor or successor of i, respectively.

Function: pow (b: int, e: int): int
Return b raised to the power of e.

5.3.2 longs module

This is a library module which exports long data type related functions.

Constant: min : long
min is the smallest representable long value.

Constant: max : long
max is the largest representable long value.

Function: min (x: long, y: long): long
Return the minimum of two long values.

Function: max (x: long, y: long): long
Return the maximum of two long values.

Function: from_string (s: string): long
Convert the string value s to the long number it represents. If s does not represent any long integer number, the return value is unspecified.

Function: to_string (l: long): string
Convert the long number l to its string representation.

Function: from_int (i: int): long
Convert the integer value i to a long value.

Function: to_int (l: long): int
Convert the long value l to an integer value.

Function: from_real (r: real): long
Conver the real number r to a long value, stripping off any decimal places.

Function: to_real (l: long): real
Conver the long value l to a real value.

Function: even? (l: long): bool
Function: odd? (l: long): bool
Function: zero? (l: long): bool
Function: positive? (l: long): bool
Function: negative? (l: long): bool
Return true iff l is even, odd, equal to zero, positive or negative, respectively.

Function: abs (l: long): long
Return the absolute value of l, that is, remove l's sign.

Function: signum (l: long): long
Return 1L if l is greater than zero, 0L if l is equal to zero and -1L if l is less than zero.

Function: pred (l: long): long
Function: succ (l: long): long
Return the predecessor or successor of i, respectively.

Function: pow (b: long, e: int): long
Return b raised to the power of e.

5.3.3 reals module

This is a library module which exports real data type related functions.

Function: min (x: real, y: real): real
Return the minimum of two real values.

Function: max (x: real, y: real): real
Return the maximum of two real values.

Function: from_string (s: string): real
Convert the string value s to the real number it represents. If s does not represent any integer number, the return value is unspecified.

Function: to_string (r: real): string
Convert the real number r to its string representation.

Function: from_int (i: int): real
Convert the integer value i to a real value.

Function: to_int (r: real): int
Convert the real value r to an integer value. Decimal places are stripped.

Function: zero? (r: real): bool
Function: positive? (r: real): bool
Function: negative? (r: real): bool
Return true iff i is equal to zero, positive or negative, respectively.

Function: abs (r: real): real
Return the absolute value of r, that is, remove r's sign.

Function: signum (r: real): real
Return 1.0 if r is greater than zero, 0.0 if r is equal to zero and -1.0 if r is less than zero.

Function: pow (a: real, b: int): real
Return a raised to the power of b.

5.3.4 bools module

Library module for utility functions for boolean values.

Function: to_string (b: bool): string
Convert the boolean value b to a string. The result will be either the string "true" or the string "false".

Function: from_string (s: string): bool
Convert a string to a boolean value. The two recognized strings are "true" and "false". Any other string will cause an unspecified value to be returned.

5.3.5 chars module

Library module for character utilities.

Constant: min : char

Constant: max : char

Constant: EOF : char
EOF is the character which is returned by input functions when the end of an input file is reached.

Constant: tab : char
Convenience variable containing the character '\t'.

Constant: newline : char
Convenience variable containing the character '\n'.

Constant: carriage_return : char
Convenience variable containing the character '\r'.

Constant: blank : char
Convenience variable containing the character ' '.

Constant: space : char
Convenience variable containing the character ' '.

Constant: vtab : char
Convenience variable containing the character '\v'.

Constant: backspace : char
Convenience variable containing the character '\b'.

Constant: formfeed : char
Convenience variable containing the character '\f'.

Constant: bell : char
Convenience variable containing the character '\a'.

Function: ord (c: char): int
Return the character code of character c.

Function: chr (i: int): char
Return the character which has character code i.

Function: to_string (c: char): string
Convert the character c to a string of length one which only contains c.

Function: from_string (s: string): char
Convert a string to a character value by simply extracting the first character. An exception will be raised if the string is empty.

Function: digit? (c: char): bool
Function: letter? (c: char): bool
Function: uppercase? (c: char): bool
Function: lowercase? (c: char): bool
Function: control? (c: char): bool
Function: punctuation? (c: char): bool
Function: letgit? (c: char): bool
Function: space? (c: char): bool
Function: whitespace? (c: char): bool
Function: printable? (c: char): bool
Return true, if c is a digit, a letter, an uppercase letter or a lowercase letter, respectively.

Function: upcase (c: char): char
If c is a lowercase letter, return its uppercase equivalent, otherwise, return c.

Function: downcase (c: char): char
If c is an uppercase letter, return its lowercase equivalent, otherwise, return c.

Function: pred (c: char): char
Function: succ (c: char): char
Return the predecessor or successor of c, respectively.

5.3.6 strings module

Library module for string utilities.

Function: length (s: string): int
Return the number of characters in s.

Function: copy (s: string): string
Return a freshly allocated string with the same length and contents as the given string s.

Function: substring (s: string, from: int, to: int): string
Return a string containing the characters from s starting at index from (inclusive), up to to (exclusive).

Function: substring (s: string, from: int): string
Similar to substring(string, int, int), where the last argument defaults to the length of the string.

Function: append (s1: string, s2: string): string
Function: append (s1: string, s2: string, s3: string): string
Return a string which is the concatenation of the argument strings.

Function: to_string (b: bool): string
Function: to_string (i: int): string
Function: to_string (l: long): string
Function: to_string (r: real): string
Function: to_string (c: char): string
Return the string representation of the argument.

Function: index (s: string, c: char): int
Return the smallest index of any appearence of character c in the string s. Return -1 if not found.

Function: rindex (s: string, c: char): int
Return the largest index of any appearence of character c in the string s. Return -1 if not found.

Function: indices (s: string, c: char): list of int
Return a list containing all indices of the appearences of character c in the string s. An empty list is returned if c does not appear in s.

Function: eq (s1: string, s2: string): bool
Return true if the two strings have the same length and contents, false otherwise.

Function: explode (s: string): list of char
Return a list of characters containing the characters of string s, in the same order.

Function: rexplode (s: string): list of char
Return a list of characters containing the characters of string s, in reversed order. This function is often convenient when constructing strings from character lists.

Function: implode (l: list of char): string
Return a string with the same length as the list l, and with the elements of l as string contents, in the same order.

Function: rimplode (l: list of char): string
Return a string with the same length as the list l and with the elements of l as string contents, but in reverse order. The same result would be obtained by calling
strings.implode (lists.reverse (l));

but calling rimplode is more efficient.

Function: split (s: string, c: char): list of string
Split up the string s at all occurences of the character c and return a list of the strings between these occurences. Note that occurences of c without any characters between will result in empty strings in the resulting list.
strings.split ("root:x:0:0:root:/root:/bin/bash", ':')
=>
["root", "x", "0", "0", "root", "/root", "/bin/bash"]

strings.split (":x:0:0:root::/bin/bash", ':')
=>
["", "x", "0", "0", "root", "", "/bin/bash"]

Function: replicate (elem: char, len: int): string
Return a string of length len, consisting of the character elem.

Function: rpad (s: string, places: int, ch: char): string
Function: lpad (s: string, places: int, ch: char): string
Return a string of at least places characters which contains s, padded on the right (for rpad) or left (for lpad) with character ch.

Function: upcase (s: string): string
Function: downcase (s: string): string
Return a newly allocated string containing the characters from s converted to upper case or lower case, respectively.

5.3.7 union module

This module exports an union type for the builtin data types.

Data type: union
Defined as:
datatype union =
  i(i: int) or
  l(l: long) or
  r(r: real) or
  b(b: bool) or
  c(c: char) or
  s(s: string)

This data type is intended to be used for functions which should be able to deal with all or some of the builtin data types.

5.3.8 strformat module

Library module for string formatting.

Function: fmt (fmt: string, args: list of string): string
String formatting function. This is similar to the sprintf() function in C, but much more limited. fmt is expected to be a string with embedded formatting instruction. A formatting instruction is a % character followed by an s character. In the result string, each occurence of a formatting instruction is replaced by the corresponding element in the argument list.

Function: fmt (fmt: string, s: string): string
Function: fmt (fmt: string, s1: string, s2: string): string
Convenience versions of the function above, to be used for one or two argument strings.

Function: fmt (fmt: string, args: list of union.union): string
Generalized version of the formatting function. This accepts a list of union.union values, which can hold different data values. The supported formatting sequences are:
%s
Format a string.
%i, %d
Format an integer value.
%l
Format a long value.
%r
Format a real value.
%c
Format a character.
%b
Format a boolean value.

5.4 List utility modules

Turtle comes with a set of list utility functions, for example for constructing, investigating, searching or sorting.

5.4.1 lists module

The module file `lists' exports list manipulation functions. It is a generic module with one module parameter, which is the type of the list elements. The name of this parameter is A.

Function: empty? (l: list of A): bool
Return true if l is the empty list, false otherwise.

Function: cons (a: A, b: list of A): list of A
Cons the element a onto the head of list b.

Function: head (l: list of A): A
Return the head of list l. An exception is raised if l is empty.

Function: tail (l: list of A): list of A
Return the tail of list l. An exception is raised if l is empty.

Function: last (l: list of A): A
Return the last element of list l. An exception is raised if l is empty.

Function: init (l: list of A): list of A
Return the initial sequence of list l, excluding the last element. An exception is raised if l is empty.

Function: append (a: list of A, b: list of A): list of A
Append the lists a and b.

Function: concat (lists: list of list of A): list of A
Return a list which is the concatenation of the lists in lists.

Function: length (a: list of A): int
Return the length of list a.

Function: reverse (l: list of A): list of A
Return a list with the elements of l in reserved order.

Function: foreach (p: fun(A), l: list of A)
Apply the procedure p to each element of the list l, in order. For a function which returns a list of the results of the function application, see module listmap (see section 5.4.2 listmap module).

Function: iota (count: int): list of int
Return an integer list of count elements, with the number 0 to count-1 as the list elements.

Function: filter (p: fun(A): bool, l: list of A): list of A
Return a list with all elements from l which satisfy predicate p, in the same order as in l.

Function: insert (s: A, l: list of A, cmp: fun(A, A): int): list of A
Insert the element s into the list l, maintaining the order as defined by the comparison function cmp which takes two elements of type A and returns a value less then 0 if the first is smaller than the second, 0 if they are to be considered equal and a value greater than 0 if the second is greater.

Function: index (elem: A, l: list of A, cmp: fun(A, A): int): int
Return the index of element elem in list l, according to the comparison function cmp. Return -1 if elem does not appear in l.

Function: indices (elem: A, l: list of A, cmp: fun(A, A): int): list of int
Return a list of the indices of all appearences of elem in l, according to the comparison function cmp. Return the empty list of elem does not appear in l.

Function: replicate (elem: A, len: int): list of A
Create a list of length l, where all list elemens are initialized to elem.

Function: copy (l: list of A): list of A
Create a copy of the list l. Note that only the spine of the list is copied, not the elements.

Function: take (l: list of A, n: int): list of A
Take the first n elements from the list l, dropping the following elements.

Function: drop (l: list of A, n: int): list of A
Drop the first n elements from list l and return the remaining list.

5.4.2 listmap module

The module file `listmap' exports higher-order functions for iterating over lists. It is a generic module with two module parameters, which are the types of the list elements. The name of the first parameter is A and denotes the element type of the input lists, the name of the second is B and stands for the element type of the output lists of map.

Function: map (f: fun(A): B, l: list of A): list of B
Apply the function f to every element of l, return a list containing the results of the function applications. The order in which f is applied to the list elements is not specified.

5.4.3 listfold module

The module file `listfold' implements the functions foldl and foldr for folding functions over lists.

Function: foldl (f: fun(A, A): A, l: list of A): A
Fold the function f from left to right over the list l and return the result.
fun sub(x: int, y: int): int
return x - y;
end;
foldl (sub, [4, 3, 1])
=>
(4 - 3) - 1
=>
0

Function: foldr (f: fun(A, A): A, l: list of A): A
Fold the function f from to left right over the list l and return the result.
fun sub(x: int, y: int): int
return x - y;
end;
foldr (sub, [4, 3, 1])
=>
4 - (3 - 1)
=>
2

5.4.4 listreduce module

The module file `listreduce' implements the functions reducel and reducer for reducint functions over lists.

Function: reducel (f: fun(from, to): to, init: to, l: list of from): to
Reduce the list l with function f, bracketing on the left.
fun sub (x: int, y: int): int
return x - y;
end;
reducel (sub, 12, [2, 5, 3])
=>
3 - (5 - (2 - 12))
=>
-12

Function: reducer (f: fun(from, to): to, init: to, l: list of from): to
Reduce the list l with function f, bracketing on the right.
fun sub (x: int, y: int): int
return x - y;
end;
reducel (sub, 12, [2, 5, 3])
=>
2 - (5 - (3 - 12))
=>
-12

5.4.5 listzip module

Functions for combining two lists into one element-wise, and the reverse.

Function: zip (f: fun(from1, from2): to, l1: list of from1, l2: list of from2): list of to
Zip two lists of equal length together by applying the function f to the corresponding elements of the lists and forming the result lists from the function result(s).

Function: unzip (f: fun(to): (from1, from2), l: list of to): (list of from1, list of from2)
Decompose the list l by applying the function f to the successive list elements and returning the two lists of the function results.

5.4.6 listindex module

Some utility functions for lists which work on indices into the list.

Function: nth (l: list of A, idx: int): A
Return the element at index idx in list l.

Function: pos (p: fun(A): bool, l: list of A): int
Return the index of the first element in list l which satisfies predicate p. Return -1 if no element satisfies p.

Function: slice (l: list of A, start: int, ende: int): list of A
Return the sublist of l which starts at index start (inclusive) and ends at index ende (exclusive).

5.4.7 listsearch module

Function for searching in lists of type

list of A

where A must be instantiated when importing this module.

The comparison function cmp is used for comparing elements of the input arrays. cmp is expected to return a value less than 0 if the first argument is to be considered smaller than the second, a value greater than 0 if it is greater, and exactly 0 if the two arguments are equivalent.

Function: lsearch (l: list of A, elem: A, cmp: fun(A, A): int): list of A
Search linearly through the list l, until an element equal to elem is found. Use cmp for comparing the elements of the list to elem. Return the first list cell whose head is equal to elem, or null if not found.

5.4.8 listsort module

Function for sorting lists of type

list of A

where A must be instantiated when importing this module.

The comparison function cmp is used for comparing elements of the input arrays. cmp is expected to return a value less than 0 if the first argument is to be considered smaller than the second, a value greater than 0 if it is greater, and exactly 0 if the two arguments are equivalent.

Function: sort (a: list of A, cmp: fun(A, A): int): list of A
Sort the list a, using cmp as the comparison function. The parameter a is not modified for performing the sort, instead a freshly allocated list is returned.

5.5 Array utility modules

Several modules for manipulating arrays are included in the standard library. They are structured similarly to the modules for list handling.

5.5.1 arrays module

Utility functions for handling objects of type

array of A

where A must be instantiated when importing this module.

Function: length (a: array of A): int
Return the number of elements of array `a'.

Function: foreach (p: fun(A), a: array of A)
Apply the procedure p to each element of the array a, in order.

Function: copy (a: array of A): array of A
Create a copy of array a. Note that only the array holding the elements is copied, not the elements themselves. The result is the same as a if a is empty.

Function: reverse (a: array of A): array of A
Return a new array which contains the elements of a, but in reverse order. The result is the same as a if a is empty.

Function: replicate (elem: A, len: int): array of A
Create an array of len elements, where each element is initialized to elem.

5.5.2 arraymap module

Utility function for applying functions to arrays of type

array of A.

Map returns values of type

array of B.

A and B are type variables which must be instantiated when importing this module.

Function: map (f: fun(A): B, l: array of A): array of B
Apply the function f to every element of the array a, return an array containing the results of the function applications. The order in which f is applied to the array elements is not specified.

5.5.3 arraysearch module

This module exports a functions for sorting objects of type

array of A

where A must be instantiated when importing this module.

The comparison function cmp is used for comparing elements of the input arrays. cmp is expected to return a value less than 0 if the first argument is to be considered smaller than the second, a value greater than 0 if it is greater, and exactly 0 if the two arguments are equivalent.

Function: lsearch (a: array of A, elem: A, cmp: fun(A, A): int): int
Search linearly through the array a, until an element equal to elem is found. Use cmp for comparing the elements of the array to elem. Return the index of the first occurence if found; return -1 otherwise.

Note that if elem appear more than once in the array, the index of the first occurence is returned.

Function: bsearch (a: array of A, elem: A, cmp: fun(A, A): int): int
Binary search. Search in the array a for an element equal to elem, using cmp as the comparison function. Return the index of the element if found, return -1 otherwise.

The array a must be sorted according to the comparison function cmp, otherwise the search will most probably fail, even if elem does appear in a.

Note that if elem appear more than once in the array, it is not specified the index of which will be returned.

5.5.4 arraysort module

This module exports a functions for sorting objects of type

array of A

where A must be instantiated when importing this module.

The comparison function cmp is used for comparing elements of the input arrays. cmp is expected to return a value less than 0 if the first argument is to be considered smaller than the second, a value greater than 0 if it is greater, and exactly 0 if the two arguments are equivalent.

Function: sort (a: array of A, cmp: fun(A, A): int)
Sort the array a, using cmp as the comparison function. The parameter a is modified for performing the sort.

5.6 Tuple utility modules

Two modules for handling common tuple types are also in the distribution, one for handling pairs of two data types, and one for handling triples of three data types.

5.6.1 pairs module

Utility functions for tuples of type

(A, B)

where A and B must be instantiated when importing this module.

Data type: pair
Defined as:
datatype pair<A, B> =
  pair(first: A, second: B)

This datatype wraps a pair of values in an user-defined data type.

Function: unpair (p: pair): (A, B)
Function: pair (p: (A, B)): pair
These are conversion functions between the user-defined pair data type and 2-tuples.

Function: first (p: (A, B)): A
Function: second (p: (A, B)): B
Return the first or second component of the argument tuple, respectively.

5.6.2 triples module

Utility functions for tuples of type

(A, B, C)

where A, B and C must be instantiated when importing this module.

Data type: triple
Defined as:
datatype triple<A, B> =
  triple(first: A, second: B, third: C)

This datatype wraps a 3-tuples of values in an user-defined data type.

Function: untriple (t: triple): (A, B, C)
Function: triple (t: (A, B, C)): triple
These are conversion functions between the user-defined triple data type and 3-tuples.

Function: first (p: (A, B, C)): A
Function: second (p: (A, B, C)): B
Function: third (p: (A, B, C)): C
Return the first, second or third component of the argument tuple, respectively.

5.7 Low level modules

Some of the modules in the standard library are very low-level. These modules are either not convenient to use, or are machine or system dependent, so it is a good idea to avoid using them as far as possible, and rather use the functionality implemented by the higher-level modules in the previous sections.

A lot of functions in the higher-level modules are implemented in terms of the low-level ones, and sometimes access to low-level features is useful. That is the reason why these modules are documented here even though their use is discouraged.

5.7.1 core module

This file defines some useful low-level functions, but does not implement all of them. For some of the functions only the declaration is given, and the implementation is written in C in the file core.t.i.

The module core is a very basic library module. Very low-level functions for input and output are provided. The user should not use these functions directly, but use one of the higher-level modules like io instead.

Function: write_char (fd: int, c: char)
Write the character c to the file descriptor fd.

Function: read_char (fd: int): char
Read a character from file descriptor fd. On end-of-file, the constant chars.EOF is returned.

Function: real_to_string (r: real): string
Convert the real number r to its string representation.

Function: string_to_real (s: string): real
Convert the string value s to a real value. If s is not a valid real number representation, the returned value is undefined.

Function: chr (i: int): char
Return the character with character code i.

Function: ord (c: char): int
Return the character code of the character c.

Function: int_to_real (i: int): real
Convert the integer value i to a real value.

Function: real_to_int (r: real): int
Convert the real value r to an integer value, stripping off any decimal places.

5.8 Subsystem sys

The subsystem sys contains some system-dependant modules which access operating system specific functions.

All functions and variables in these modules are close to the underlying operating system calls and C library functions of the same name, and the semantics are the same as far as possible. Only some minor changes to the semantics have been made in order to map the different data types in Turtle and C onto each other.

5.8.1 sys.files module

Module for handling files.

Constant: stdin : int
Constant: stdout : int
Constant: stderr : int
File descriptors for standard input, output and error..

Function: open (fname: string): int
Open the existing file named fname for reading and return a file descriptor; or return -1 on error.

Function: create (fname: string): int
Create a new file named fname and open it for writing and return a file descriptor; or return -1 on error. An existing file named fname will be overwritten, so use with caution.

Function: close (fd: int): int
Close the file associated with file descriptor fd, and return 0 on success or -1 on error.

Function: close (fd: int)
Close the file associated with file descriptor fd. Ignore any errors.

Function: write (fd: int, b: internal.binary.binary, len: int): int
Write len bytes from the byte array b to the file descriptor fd, starting at offset 0 of the byte array. Return the number of bytes actually written, or -1 if an error occurs. The variable sys.errno.errno is set accordingly.

Function: read (fd: int, b: internal.binary.binary, len: int): int
Read len bytes from the file descriptor fd into the byte array b. Return the number of bytes read, or -1 if an error occurs. The variable sys.errno.errno is set accordingly.

Function: unlink (filename: string): int
Delete a name from the filesystem. If that name was the alst linkt to a file and no processes have the file open the file is deleted and the space it was using is made available for reuse.

On success, zero is returned. On error, -1 is returned and the variable sys.errno.errno is set appropriately.

5.8.2 sys.dirs module

Module for handling directories. The exported data type dirs serves as a handle for directories and must be obtained by calling the function opendir. Calling readdir repeatedly on a valid dir value will return all entries of a directory, and the directory stream can then be closed with closedir or reset to the beginning with rewinddir.

Data type: dir
Defined as:
datatype dir =
  adir

Directory handle for use with the directory functions below.

Function: opendir (name: string): dir
Open a directory stream corresponding with the directory called name, and return a handle for that stream. The stream is positioned at the first entry in the directory. Return a handle for the opened stream on success, or null if an error occurs. The variable sys.errno.errno will be set accordingly.

Function: readdir (d: dir): string
Return a string representing the next directory entry in the directory stream d. Return null if the end of the stream is reached or an error occurs. sys.errno.errno will be set accordingly.

Function: closedir (d: dir): int
Close the directory stream associated with the handle d. The stream descriptor d cannot be used anymore after this call. Return 0 on success or -1 on failure, and set sys.errno.errno accordingly.

Function: rewinddir (d: dir)
Reset the position of the directory stream d to the beginning of the directory.

5.8.3 sys.net module

Module for network programming.

Currently, only IPv4 is supported, and only the most basic operations are provided.

Constant: PF_UNSPEC : int
Constant: PF_UNIX : int
Constant: PF_LOCAL : int
Constant: PF_INET : int
These constants are to be used as the domain parameter to the socket function. Note that currently only IPv4 (PF_INET) sockets are supported.

Constant: SOCK_STREAM : int
Constant: SOCK_DGRAM : int
Constant: SOCK_RAW : int
These are the socket type constants for calls to the socket function. Only stream sockets (SOCK_STREAM) have been tested yet.

Function: socket (domain: int, typ: int, protocol: int): int
Create an endpoint for communication and return a descriptor.

The domain parameter specifies a communication domain; this selects the protocol family which will be used for communication. These families are defined as the PF_* constants.

The socket has the indicated type typ, which specifies the communication semantics. The currently defined types are the SOCK_* constants.

-1 is returned if an error occurs and sys.errno.errno is set accordingly, othersie the return value is a descriptor referencing the socket.

Data type: sockaddr
Defined as:
datatype sockaddr =
  inet(port: int, addr: internal.binary.binary)

Data type for specifying network addresses. Currently only IPv4 is supported.

Function: sockaddr_addr (addr: sockaddr): internal.binary.binary
Function: sockaddr_port (addr: sockaddr): int
Return the IP number or the port of the socket address addr, respectively.

Function: bind (sockfd: int, addr: sockaddr): int
Give the socket sockfd the local address addr. This is necessary for a stream socket may receive connections with accept.

Function: connect (sockfd: int, serv_addr: sockaddr): int
Establish a connection for socket descriptor sockfd to the server specified by serv_addr. The return value is -1 if an error occurs and zero on success.

Function: listen (sockfd: int, backlog: int): int
Before accepting connections with accept, the willingness to accept incoming connections and a queue limit for incoming connections are specified with listen.

Function: accept (sockfd: int): (int, sockaddr)
Accept a client connection on the given socket sockfd. Return a pair of a socket descriptor for the connection to the client, and the address of the client.

Function: inetaddr (port: int, b0: int, b1: int, b2: int, b3: int): sockaddr
Function: inetaddr (port: int): sockaddr
Function: inetaddr (port: int, b: internal.binary.binary): sockaddr
Create an internet address structure with a given port and the given bytes of the internet address. The bytes are to be passed highest-order byte first, for example:
"127.0.0.1"
=>
127, 0, 0, 1

The second version of the function will set the address to zero and can be used when binding an address for a server socket where the address should be the default.

Function: gethostbyname (name: string): internal.binary.binary
Return the IPv4 address of host name. name must be either a valid host name or an internet address in dotted decimal notation.

The return value is a byte array representing the internet address or null, if the host name cannot be resolved.

==========================================================

5.8.4 sys.times module

Module for handling times.

Data type: tm
Defined as:
datatype tm =
  tm(sec: int, min: int, hour: int, mday: int, mon: int, year: int, wday: int, yday: int, isdst: int)

This data type represents date and time information.

Function: gmtime (t: long): tm
Return a tm structure representing the current time in Universal Coordinated Time (UTC).

Function: localtime (t: long): tm
Return a tm structure representing the current time in local time.

Function: time (): long
Return the current time in seconds since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds.

Function: asctime (tm: tm): string
Return a string representation of the time tm or t, respectively.

Function: ctime (t: long): string

5.8.5 sys.users module

Module for accessing user information.

Function: getuid (): int
Function: geteuid (): int
getuid returns the real user ID of the calling process.

geteuid returns the effective user ID of the current process. The effective ID corresponds to the set ID bit on the file being executed.

Data type: passwd
Defined as:
datatype passwd =
  passwd(name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string)

Data type: group
Defined as:
datatype group =
  group(name: string, passwd: string, gid: int, members: array of string)

Function: getpwnam (name: string): passwd
Function: getpwuid (uid: int): passwd
Return the password file structure for the user with the given user name or user id, respectively. If the user name or id is not valid on the system the program runs on, null is returned.

Function: getpwent (): passwd
Return the next entry from the password file, as a value of the data type sys.users.passwd. If called for the first time, the first entry will be returned, then successive entries until the end of the user data base is reached. The end of the file is indicated by returning null.

Function: setpwent ()
Reset the read pointer for the user data base so that the next call to getpwent will return the first entry.

Function: endpwent ()
Close the password file. Use this function when you are ready with the user data base.

Function: getgrnam (name: string): group
Function: getgrgid (uid: int): group
Return the group file structure for the group with the given group name or group id, respectively. If the group name or id is not valid on the system the program runs on, null is returned.

Function: getgrent (): group
Return the next entry from the group file, as a value of the data type sys.users.group. If called for the first time, the first entry will be returned, then successive entries until the end of the group data base is reached. The end of the file is indicated by returning null.

Function: setgrent ()
Reset the read pointer for the group data base so that the next call to getgrent will return the first entry.

Function: endgrent ()
Close the group file. Use this function when you are ready with the group data base.

Function: getlogin (): string
Return a string containing the name of the user logged in on the controlling terminal of the process, or an empty string if this information cannot be determined.

5.8.6 sys.procs module

Module for accessing process information and dealing with processes.

Function: getpid (): int
Return the process identifier of the current process.

Function: getppid (): int
Return the process identifier of the parent of the current process.

Function: sleep (sec: int): int
Function: sleep (sec: int)
Make the current process sleep until sec seconds have elapsed or a signal arrives which is not ignored.

The first version returns zero if the requested time has elapsed, or the number of seconds left to sleep. The second version does not return anything.

Function: exit (status: int)
Terminate the current process normally and return the value of status to the parent.

Function: kill (pid: int, sig: int): int
Function: kill (pid: int, sig: int)
kill can be used to send any signal to any process group or process.

If pid is positive, then signal sig is sent to pid. If pid equals 0, then sig is sent to every process in the process group of the current process. If pid equals -1, then sig is sent to every process except for the first one, from higher numbers in the process table to lower. If pid is less than -1, then sig is sent to every process in the process group -pid.

If sig is 0, then no signal is sent, but error checking is still performed.

On sucess, zero is returned, On error, -1 is returned and errno is set appropriately. The second version of the kill function does not return anything and ignores any errors.

Function: fork (): int
Create a child process that differs from the parent process only in its PID and PPID, and in the fact that resource utilizations are set to 0. File locks and pending signals are not inherited.

On success, the process identifier of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of execution. On failure, -1 will be returned in the parent's context, no child process will be created, and the variable errno.errno will be set appropriately.

Function: wait (): (int, int)
Suspend execution of the current process until a child has exited, or until a signal is delivered whose action is to terminate the current process or to call a signal handling function. If a child has already exited by the time of the call (a so-called "zombie" process), the function returns immediately. Any system resources used by the child are freed.

The return value is a pair of the process ID of the exited child (or -1 on error) and the status of the exited child.

Constant: WNOHANG : int
Constant: WUNTRACED : int
Constants to be used as the options argument to waitpid.

Function: waitpid (pid: int, options: int): int
Suspend execution of the current process until a child as specified by the pid argument, or until a signal is delivered whose action is to terminate the current process or to call a signal handling function. If a child as requested by pid has already exited by the time of the call (a so-called "zombie" process", the function returns immediately. Any system resources used by the child are freed.

The value of pid can be one of

< -1
which means to wait for any child process whose process group ID is equal to the absolute value of pid.
-1
which means to wait for any child process; this is the same behaviour which wait exhibits.
0
which means to wait for any child process whose process group ID is equal to that of the calling process.
> 0
which means to wait for the child whose process ID is equal to the value of pid.

The value of options is an OR of zero or more of the following constants:

WNOHANG
which means to return immediately if no child has exited.
WUNTRACED
which means to also return for children which are stopped, and whose status has not been reported.

The return value is a pair of the process ID of the exited child (or -1 on error) and the status of the exited child.

If WNOHANG was given as an option, and no child has exited, 0 is returned as the process ID.

Function: WIFEXITED (status: int): bool
Return true, if the status code indicates that the process has exited normally.

Function: WEXITSTATUS (status: int): int
Return the exit status of the exited process. This may only be called if WIFEXITED returned true for status.

Function: WIFSIGNALED (status: int): bool
Return true, if the status code indicates that the process was terminated by a signal.

Function: WTERMSIG (status: int): int
Return the number of the signal which terminated the process. This may only be called if WIFSIGNALED returned true for status.

Function: WIFSTOPPED (status: int): bool
Return true, if the status code indicates that the process was stopped by a signal.

Function: WSTOPSIG (status: int): int
Return the number of the signal which stopped the process. This may only be called if WIFSTOPPED returned true for status.

Function: execve (filename: string, argv: array of string, envp: array of string): int
Function: execve (filename: string, argv: array of string, envp: array of string)
Function: execve (filename: string, argv: list of string, envp: list of string): int
Function: execve (filename: string, argv: list of string, envp: list of string)
Function: execve (filename: string, argv: array of string): int
Function: execve (filename: string, argv: array of string)
Function: execve (filename: string, argv: list of string): int
Function: execve (filename: string, argv: list of string)
Execute the program called filename. argv is an array or list of argument strings passed to the new program. envp is an array of string, conventionally of the form key=value, which are passed as environment to the new program.

Normally these functions do not return, on error, the value -1 is returned and the appropriate error code is placed in the variable sys.errno.errno.

Function: getenv (varname: string): string
Return the value of the environment variable called varname

5.8.7 sys.errno module

Module for accessing operating system errors.

Variable: errno : int
The variable errno contains the result code set by the last operating system call. A value of 0 means success, all other values indicate failure. The value can be translated to a readable error message using the strerror function below.

Function: strerror (errnum: int): string
Return a string describing the error code passed in the argument errnum.

5.8.8 sys.signal module

Module for installing a signal function, that is a function which gets called whenever the process receives an operating system signal.

In Turtle, signals are handled synchroneously, that means that a Turtle process repeatedly checks whether a signal has arrived and then calls the signal handler function.

Variable: SIGHUP : int
Variable: SIGINT : int
Variable: SIGQUIT : int
Variable: SIGILL : int
Variable: SIGABRT : int
Variable: SIGFPE : int
Variable: SIGKILL : int
Variable: SIGSEGV : int
Variable: SIGPIPE : int
Variable: SIGALRM : int
Variable: SIGTERM : int
Variable: SIGUSR1 : int
Variable: SIGUSR2 : int
Variable: SIGCHLD : int
Variable: SIGCONT : int
Variable: SIGSTOP : int
Variable: SIGTSTP : int
Variable: SIGTTIN : int
Variable: SIGTTOU : int
These are the signals defined in POSIX.1.

Function: signal (no: int, handler: fun(int))
Install a signal handler for signal number no. Whenever a signal is received, the process will stop at the next safe point and call the handler function. with the signal number as the argument.

5.9 Subsystem internal

Some of the modules in the standard library are very low-level. These modules are either not convenient to use, or are machine or system dependent, so it is a good idea to avoid using them as far as possible, and rather use the functionality implemented by the higher-level modules in the previous sections.

A lot of functions in the higher-level modules are implemented in terms of the low-level ones, and sometimes access to low-level features is useful. That is the reason why these modules are documented here even though their use is discouraged.

5.9.1 internal.version module

Low-level module for version information.

Function: version (): string
Return the version number of the running Turtle runtime in string form, e.g "0.1.1".

5.9.2 internal.random module

Low-level module for random numbers.

Function: srand (seed: int)
Set the seed of the random number generator to seed.

Function: rand (): int
Return a random number in the range 0 to ints.max.

5.9.3 internal.stats module

Low-level module for interfacing to the runtime system statistics.

Function: dispatch_call_count (): int
Function: direct_call_count (): int
Function: local_call_count (): int
Function: closure_call_count (): int
Function: gc_checks (): int
Function: gc_calls (): int
Function: allocations (): int
Function: alloced_words (): int
Function: forwarded_words (): int
Function: save_cont_count (): int
Function: restore_cont_count (): int
Function: total_gc_time (): int
Function: min_gc_time (): int
Function: max_gc_time (): int
These functions deliver some statistics gathered by the runtime system.

5.9.4 internal.gc module

Low-level module for interfacing to the garbage collector.

Function: gc_calls (): int
Return the number of heap garbage collections since the program started.

Function: gc_checks (): int
Return the number of heap overflow checks since the program started.

Function: garbage_collect ()
Force a garbage collection.

5.9.5 internal.ex module

Low-level module for raising and handling exceptions. Do not use this module directly, rather use the standard library module exception (see section 5.1.14 exceptions module).

Function: raise (s: string)
Raise an exception with name s.

Function: handle (thunk: fun(): (), handler: fun(string))
Call the function thunk. If any exception is raised while thunk is running, the function handler will be called with the exception name as the only argument. When handler returns, it will return to the caller of ex.handle, in the same way as the call would return when thunk was returning without an exception.

Function: null_pointer_exception (): string
Function: out_of_range_exception (): string
Function: subscript_exception (): string
Function: wrong_variant_exception (): string
Function: require_exception (): string
The return value of these functions is the corresponding exception name, which is the same that would be used if the illegal operation would be performed.

That means that

internal.ex.raise (internal.ex.subscript_ex ())

has the same effect as

var s: string;
s[-1] := 'a'

5.9.6 internal.timeout module

Module for installing a timeout function, that is a function which gets called repeatedly in some interval.

Function: set (handler: fun())
Register handler as the timeout function for the Turtle runtime. The timeout function gets called repeatedly, but there is no guarantee on how often it will be called.

On a 800Mhz AMD Duron(tm) processor, the function is called about every 0.1 seconds.

Function: clear ()
Remove the current timeout function, so that no function will be called until another handler is registered with the function set above.

5.9.7 internal.limits module

Low-level module defining certain system limits.

There are no exports yet, but that may change in the future.

Glossary

basic constraint
A basic constraint is a linear equation, which may contain constrainable and unconstrainable variables.
constrainable variable
A constrainable variable is a variable whose value can be determined by a constraint. Unconstrainable variables can only be changed by assignment.
constraint
A constraint is a condition which specifies the properties of the values a solution to a certain problem must have.
declarative
With declarative programming, we name the programming style where the computer is told which properties a problem's solutions must have, but not how to compute the solution. The compiler and runtime system of the language implementation is responsible for determining an efficient way to compute the solution.
imperative
Imperative programming means the programming style where the computer is explicitly told which steps to perform when and in which order, to find the solution to a problem. Imperative programs are rather low-level, compared to declarative programs.
module
A module is a collection of functions, variables, constraints and type declarations, which can be compiled independently of other modules. A collection of modules forms a program.
variable
A variable is a storage location. The contents of variables can be fetched and new values can be stored into variables, using assignment. In Turtle, the values of variables can also be determined by using constraints on constrainable variables.

Index

Jump to: a - b - c - d - e - f - g - h - i - k - l - m - n - o - p - r - s - t - u - v - w - z

a

  • abs, abs, abs
  • accept
  • acos
  • allocations
  • alloced_words
  • append, append, append
  • asctime
  • asin
  • atan, atan
  • b

  • backspace
  • basename, basename
  • bell
  • binary_get
  • binary_set
  • binary_size
  • bind
  • bla
  • blank
  • bsearch
  • c

  • carriage_return
  • chr, chr
  • clear
  • close, close, close
  • closedir
  • closure_call_count
  • cmp, cmp, cmp, cmp, cmp, cmp
  • compose
  • concat
  • connect
  • cons
  • control?
  • copy, copy, copy, copy
  • cos
  • create, create
  • ctime
  • d

  • delete
  • digit?
  • direct_call_count
  • dirname
  • dispatch_call_count
  • downcase, downcase
  • drop
  • e

  • empty?
  • endgrent
  • endpwent
  • EOF
  • eq
  • errno
  • error
  • even?, even?
  • execve, execve, execve, execve, execve, execve, execve, execve
  • exit
  • explode
  • f

  • filter
  • find
  • first, first
  • flush
  • fmt, fmt, fmt, fmt
  • foldl
  • foldr
  • foreach, foreach
  • fork
  • formfeed
  • forwarded_words
  • from_int, from_int
  • from_real, from_real
  • from_string, from_string, from_string, from_string, from_string, from_string
  • g

  • garbage_collect
  • gc_calls, gc_calls
  • gc_checks, gc_checks
  • get, get, get, get, get, get, get, get, get, get, get, get
  • getenv
  • geteuid
  • getgrent
  • getgrgid
  • getgrnam
  • gethostbyname
  • getlogin
  • getopt
  • getpid
  • getppid
  • getpwent
  • getpwnam
  • getpwuid
  • getuid
  • gmtime
  • h

  • handle, handle
  • hash, hash, hash, hash, hash, hash
  • head
  • i

  • id
  • implode
  • index, index
  • indices, indices
  • inetaddr, inetaddr, inetaddr
  • init
  • inorder
  • input
  • insert, insert, insert, insert
  • int_to_real
  • iota
  • k

  • kill, kill
  • l

  • last
  • length, length, length
  • letgit?
  • letter?
  • listen
  • local_call_count
  • localtime
  • lookup
  • lowercase?
  • lpad
  • lsearch, lsearch
  • m

  • make
  • make_binary
  • map, map
  • max, max, max, max, max, max
  • max_gc_time
  • min, min, min, min, min, min
  • min_gc_time
  • n

  • negative?, negative?, negative?
  • newline
  • nl, nl
  • node
  • nth
  • null_pointer_ex
  • null_pointer_exception
  • o

  • odd?, odd?
  • open, open
  • opendir
  • ord, ord
  • out_of_range_ex
  • out_of_range_exception
  • output
  • p

  • pair
  • path_seperator
  • PF_INET
  • PF_LOCAL
  • PF_UNIX
  • PF_UNSPEC
  • pi
  • pos
  • positive?, positive?, positive?
  • postorder
  • pow, pow, pow
  • pred, pred, pred
  • preorder
  • printable?
  • punctuation?
  • put, put, put, put, put, put, put, put, put, put, put, put, put, put
  • putln, putln, putln, putln, putln, putln, putln, putln, putln, putln, putln, putln
  • r

  • raise, raise
  • rand, rand
  • read
  • read_char
  • readdir
  • real_to_int
  • real_to_string
  • reducel
  • reducer
  • replicate, replicate, replicate
  • require_ex
  • require_exception
  • restore_cont_count
  • reverse, reverse
  • rewinddir
  • rexplode
  • rimplode
  • rindex
  • rpad
  • s

  • save_cont_count
  • search
  • second, second
  • seed
  • set
  • setgrent
  • setpwent
  • SIGABRT
  • SIGALRM
  • SIGCHLD
  • SIGCONT
  • SIGFPE
  • SIGHUP
  • SIGILL
  • SIGINT
  • SIGKILL
  • signal
  • signum, signum, signum
  • SIGPIPE
  • SIGQUIT
  • SIGSEGV
  • SIGSTOP
  • SIGTERM
  • SIGTSTP
  • SIGTTIN
  • SIGTTOU
  • SIGUSR1
  • SIGUSR2
  • sin
  • sleep, sleep
  • slice
  • SOCK_DGRAM
  • SOCK_RAW
  • SOCK_STREAM
  • sockaddr_addr
  • sockaddr_port
  • socket
  • sort, sort
  • space
  • space?
  • split
  • srand
  • stderr
  • stdin
  • stdout
  • strerror
  • string_to_real
  • subscript_ex
  • subscript_exception
  • substring, substring
  • succ, succ, succ
  • t

  • tab
  • tail
  • take
  • tan
  • third
  • time
  • to_int, to_int
  • to_real, to_real
  • to_string, to_string, to_string, to_string, to_string, to_string, to_string, to_string, to_string, to_string, to_string
  • total_gc_time
  • tree
  • triple
  • u

  • unget, unget
  • unlink
  • unpair
  • untriple
  • unzip
  • upcase, upcase
  • uppercase?
  • v

  • version
  • vtab
  • w

  • wait
  • waitpid
  • WEXITSTATUS
  • whitespace?
  • WIFEXITED
  • WIFSIGNALED
  • WIFSTOPPED
  • WNOHANG
  • write
  • write_char
  • wrong_variant_ex
  • wrong_variant_exception
  • WSTOPSIG
  • WTERMSIG
  • WUNTRACED
  • z

  • zero?, zero?, zero?
  • zip

  • This document was generated on 24 February 2003 using texi2html 1.56k.