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.
The Turtle programming language has these main characteristics:
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.
I don't know.
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.
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:
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.
The following command line options are available.
-h, --help
-v, --version
-m, --main=name
-p, --module-path=path
-d, --debug=MODIFIER
turtle --debug=ae
a
e
i
b
-z, --pragma=pragma
handcoded
compile-only
static
--main=name option is also given. This option may
require GCC.
turtledoc
deps
deps-stdout
deps, but instead of writing to a dependency
file, the dependencies are written to standard output.
-O, --optimize=FLAGS
C
c
J
j
G
g
0...6
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.
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
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.
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:
_implementation appended.
TTL_SAVE/RESTORE_REGISTERS pair and operate on global
registers
env->locals[X], where X ranges from 0 to the number of
parameters - 1.
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.
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).
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.
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.
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.
This section describes the grammar of the Turtle programming language.
The lexical and grammatical structure of Turtle is described using Extended Backus Naur Form (EBNF). This notation is summarized below.
Turtle programs are composed by tokens of the following token classes:
Reserved words
Identifiers
Ident ::= (Letter | Underscore) {Letter | Underscore | Digit} [?|!]
String constants
\",
backslashes as \\. Additionally, some non-printing characters
can be written as escape sequences as well:
\n
\r
\t
\b
StringConst ::= "{any except Special | \" | \\ | \n | \r | \t | \b}"
Special ::= " | \
Character constants
CharConst ::= '(any except Special | \" | \\ | \n | \r | \t | \b)'
Integer constant
long
values in the C implementation used to compile Turtle.
IntConst ::= Digit{Digit}
Real constant
double values in the
C implementation used to compile Turtle.
RealConst ::= Digit{Digit}.Digit{Digit}[(e|E)[-|+]Digit{Digit}]
Operators
Reserved Words Table:
module export import
module introduces a module, the others manage the import and
export of modules and identifiers.
fun
constraint
if then else
while do
end
return
var
type
array list string of
and not or
false true
require prefer retract
hd tl null
sizeof
Operator Table:
.
,
( )
{ }
[ ]
!
;
+ - * / %
= < <= > >= <>
:=
hd tl :
sizeof
The description of the Turtle grammar is divided in various sections, and each section is provided with some additional comments.
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} '>'
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'
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
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 ::= '=' | '<>' | '<' | '<=' | '>' | '>='
In the beforementioned syntax descriptions, the following non-terminals have been used:
QualIdent ::= Ident {'.' Ident}
This section documents informally the static and synamic semantics of Turtle programs.
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.
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.
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.
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.
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.
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.
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.
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.
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.
true and false.
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.
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.
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.
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.
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:
'\"'
'\"
'\\'
'\n'
'\r'
'\t'
'\b'
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.
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.
Turtle provides three data types which are made up of other data types: arrays, lists and function types.
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
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.
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.
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.
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:
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).
! (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);
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.
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.
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.
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;
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.
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.
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:
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);
This section documents general useful modules, which are not closely related to specific data structures or application fields like input/output or systems programming.
option data type.
This module provides mathematical constants and functions.
pi.
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.
ints.max.
This module exports one function, compose, which implements
function composition.
This module exports the function id, which is the identity
on values of the type given as the module parameter A.
map. For example,
l := listmap.map (identity.id, l)
can be used to copy a list.
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.
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.
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.
The function getopt, exported by this module, deconstructs a
command line into options, option parameters and other parameters.
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).
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:
-- will also be treated as
a parameter, even if it starts with a dash. Note that a
single dash is also a normal parameter.
main function, for example),
return a list of options, classified and deconstructed as flags,
options or parameters.
This module exports hash functions for the basic data types.
ints.max.
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.
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.
some(value) if the key was found, and none()
if not found in the table.
Functions for creating and inspecting binary trees of type
A, where A must be instantiated when importing
this module.
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.
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.
datatype tree<A, B> = tree(cmpfn: fun(A, A): int, root: trees.tree<(A, B)>)
Data type for binary search trees.
option.option type. If not found, the variant
option.none is returned.
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.
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.
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.
Support module for binary (byte-) arrays.
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.
binary_size returns the number of elements in the
binary array b.
chars.chr.
chars.ord.
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.
exceptions.handle, in the same way as the call would
return when thunk was returning without an exception.
That means that
exceptions.raise (exceptions.subscript_ex ())
has the same effect as
var s: string; s[-1] := 'a'
Library module for filename manipulation functions.
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.
This module provides basic input and output functions for some of the builtin data types. Also some functions for handling files are defined.
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.
The string reading functions returns null when the
end-of-file is reached.
null.
file object for reading from the opened file,
or return null if the file can't be opened.
file object for writing to the opened file,
or return null if the file can't be opened.
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.
This is a library module exporting integer data type related constants and functions.
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.
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.
ints.min...inits.max, the return value is
unspecified.
This is a library module which exports long data type related functions.
min is the smallest representable long value.
max is the largest representable long value.
This is a library module which exports real data type related functions.
Library module for utility functions for boolean values.
"true" or the string "false".
"true" and "false". Any other string will
cause an unspecified value to be returned.
Library module for character utilities.
EOF is the character which is returned by input functions
when the end of an input file is reached.
'\t'.
'\n'.
'\r'.
' '.
' '.
'\v'.
'\b'.
'\f'.
'\a'.
true, if c is a digit, a letter, an
uppercase letter or a lowercase letter, respectively.
Library module for string utilities.
substring(string, int, int), where the last
argument defaults to the length of the string.
strings.implode (lists.reverse (l));
but calling rimplode is more efficient.
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"]
rpad) or left
(for lpad) with character ch.
This module exports an union type for the builtin data types.
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.
Library module for string formatting.
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.
union.union values, which can hold different
data values. The supported formatting sequences are:
%s
%i, %d
%l
%r
%c
%b
Turtle comes with a set of list utility functions, for example for constructing, investigating, searching or sorting.
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.
listmap
(see section 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.
The module file `listfold' implements the functions
foldl and foldr for folding functions over lists.
fun sub(x: int, y: int): int return x - y; end; foldl (sub, [4, 3, 1]) => (4 - 3) - 1 => 0
fun sub(x: int, y: int): int return x - y; end; foldr (sub, [4, 3, 1]) => 4 - (3 - 1) => 2
The module file `listreduce' implements the functions
reducel and reducer for reducint functions over
lists.
fun sub (x: int, y: int): int return x - y; end; reducel (sub, 12, [2, 5, 3]) => 3 - (5 - (2 - 12)) => -12
fun sub (x: int, y: int): int return x - y; end; reducel (sub, 12, [2, 5, 3]) => 2 - (5 - (3 - 12)) => -12
Functions for combining two lists into one element-wise, and the reverse.
Some utility functions for lists which work on indices into the list.
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.
null if not found.
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.
Several modules for manipulating arrays are included in the standard library. They are structured similarly to the modules for list handling.
Utility functions for handling objects of type
array of A
where A must be instantiated when importing this 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.
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.
Note that if elem appear more than once in the array, the index of the first occurence is returned.
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.
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.
cmp as the comparison function.
The parameter a is modified for performing the sort.
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.
Utility functions for tuples of type
(A, B)
where A and B must be instantiated when importing this module.
datatype pair<A, B> = pair(first: A, second: B)
This datatype wraps a pair of values in an user-defined data type.
pair data type and 2-tuples.
Utility functions for tuples of type
(A, B, C)
where A, B and C must be instantiated when importing this module.
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.
triple data type and 3-tuples.
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.
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.
chars.EOF is returned.
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.
Module for handling files.
sys.errno.errno is set accordingly.
sys.errno.errno is set
accordingly.
On success, zero is returned. On error, -1 is returned and the
variable sys.errno.errno is set appropriately.
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.
datatype dir = adir
Directory handle for use with the directory functions below.
null if an
error occurs. The variable sys.errno.errno will be set
accordingly.
null if the end of the
stream is reached or an error occurs. sys.errno.errno
will be set accordingly.
sys.errno.errno accordingly.
Module for network programming.
Currently, only IPv4 is supported, and only the most basic operations are provided.
socket function. Note that currently only IPv4
(PF_INET) sockets are supported.
socket function. Only stream sockets
(SOCK_STREAM) have been tested yet.
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.
datatype sockaddr = inet(port: int, addr: internal.binary.binary)
Data type for specifying network addresses. Currently only IPv4 is supported.
accept.
accept, the
willingness to accept incoming connections and a queue limit
for incoming connections are specified with listen.
"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.
The return value is a byte array representing the internet
address or null, if the host name cannot be resolved.
==========================================================
Module for handling times.
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.
tm structure representing the current time in
Universal Coordinated Time (UTC).
tm structure representing the current time in
local time.
Module for accessing user information.
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.
datatype passwd = passwd(name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string)
datatype group = group(name: string, passwd: string, gid: int, members: array of string)
null is
returned.
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.
getpwent will return the first entry.
null is
returned.
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.
getgrent will return the first entry.
Module for accessing process information and dealing with processes.
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.
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.
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.
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.
waitpid.
The value of pid can be one of
wait exhibits.
The value of options is an OR of zero or more of the following constants:
WNOHANG
WUNTRACED
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.
true, if the status code indicates that the
process has exited normally.
WIFEXITED returned true for status.
true, if the status code indicates that the
process was terminated by a signal.
WIFSIGNALED returned true for
status.
true, if the status code indicates that the
process was stopped by a signal.
WIFSTOPPED returned true for
status.
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.
Module for accessing operating system errors.
strerror function
below.
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.
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.
Low-level module for version information.
Low-level module for random numbers.
ints.max.
Low-level module for interfacing to the runtime system statistics.
Low-level module for interfacing to the garbage collector.
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).
ex.handle, in the same way as the call would return when
thunk was returning without an exception.
That means that
internal.ex.raise (internal.ex.subscript_ex ())
has the same effect as
var s: string; s[-1] := 'a'
Module for installing a timeout function, that is a function which gets called repeatedly in some interval.
On a 800Mhz AMD Duron(tm) processor, the function is called about every 0.1 seconds.
set above.
Low-level module defining certain system limits.
There are no exports yet, but that may change in the future.
Jump to: a - b - c - d - e - f - g - h - i - k - l - m - n - o - p - r - s - t - u - v - w - z
This document was generated on 24 February 2003 using texi2html 1.56k.