# Getting started

This chapter is a quick introduction to the Programming Language, simply called . The chapter provides a general description of the language in the form of a guided tour. The remaining of the book contains chapter that are dedicated to specific language features.

## First programs

The fundamental syntactic object is a form. A form is parsed and immediately executed by the engine. A form is generally constructed with a function name and a set of arguments. The process of executing a form is called the evaluation. As a simple program, the traditional `"hello world"` program is shown below.

## Hello world

The `"hello world"` program is de rigueur when introducing a new programming language. Here is the version of it.

afnix> println "hello world"

is an interpreted language. It is possible to invoke the interpreter and enter the above commands, or use a text editor and execute the file. By convention, an source file has the extension .als. A simple session to run the above program -- assuming the source file is called hello.als -- is shown below.

zsh> axi hello.als hello world

It is also possible to invoke the interpreter as to enter the commands interactively. The result will be the same. Simply typing `ctrl-d` will exit the session. Another way to operate is to call the compiler called axc, and then invoke the interpreter with the compiled file, even let the interpreter to figure this out. Note that the interpreter assume the .axc for compiled file.

zsh> axc hello.als zsh> axi hello.axc hello world zsh> axi hello hello world

The order of search is determined by a special system called the file resolver. Its behavior is described in a special chapter of this manual.

## Interpreter command

The interpreter can be invoked with several options, a file to execute and some program arguments. The `-h` option prints the various interpreter options.

zsh> axi -h usage: axi [options] [file] [arguments] [-h] print this help message [-v] print version information [-i] path add a path to the resolver [-f] assert enable assertion checking [-f] nopath do not set initial path

The `-v` option prints the interpreter version and operating system. The `-f` option turn on or off some additional options like assertion checking. The program arguments are illustrated later in this chapter. The `-i` option add a path to the interpreter file path resolver. Several `-i` options can be specified. The order of search is determined by the option order. The use of the resolver combined with the librarian is described in a specific chapter. If the initial file name to execute contains a directory path, such path is added automatically to the interpreter resolver path unless the `nopath` option is specified.

## Interactive line editing

Line editing capabilities are supported when the interpreter is used interactively. Error messages are displayed in red if the terminal supports colors. The following table is a resume of the default key bindings.

## Interactive line editing key bindings

Binding | Description
backspace | Erase the previous character
delete | Erase at the cursor position
insert | Toggle insert with in-place
left | Move the cursor to the left
right | Move the cursor to the right
up | Move up in the history list
down | Move down in the history list
ctrl-a | Move to the beginning of the line
ctrl-e | Move to the end of the line
ctrl-u | Clear the input line
ctrl-k | Clear from the cursor position
ctrl-l | Refresh the line editing

## Command line arguments

The command line arguments to the interpreter are stored in a vector called `argv` which is part of the `interp` class. A complete discussion about class data member is covered in the class object chapter. The example below which illustrates the use of the vector argument.

# argv.als # print the argument length and the first one println "argument length: " (interp:argv:length) println "first argument : " (interp:argv:get 0) zsh> axi argv.als hello world 2 hello

## Loading a source file

The interpreter class provides also the `load` method to load a source file. The argument must be a valid file path or an exception is raised. The `load` method returns `nil`. When the file is loaded, the interpreter input, output and error streams are used. The load operation read one form after another and executes them sequentially.

# load the source file fred.als afnix> interp:load "fred.als"

If the file has been compiled, the axc extension can be used instead. This force the interpreter to load the compiled version. If you are not sure, or do not care about which file is loaded, the extension can be omitted.

# load the compiled file fred.axc afnix> interp:load "fred.axc" # load whatever is found afnix> interp:load "fred"

Without extension, the compiled file is searched first. If it is not found the source file is searched and loaded.

## The compiler

The client `axc` is the cross compiler. It generates a binary file that can be run across platforms. The `-h` option prints the various compiler options.

usage: axc [options] [files] [-h] print this help message [-v] print version information [-i] path add a path to the resolver

One or several files can be specified on the command line. The source file can be searched by the resolver by using the `-i` option.

## builtin objects

provides several builtin objects, namely `Boolean`, `Integer`, `Real`, `Character` and `String`. A builtin object can be constructed literally for each of these types. The best way to build such object is to bind it to a symbol. The `const` and `trans` reserved keywords are used to declare a new symbol. A symbol is simply a binding between a name and an object. Almost any standard characters can be used to declare a symbol.

const boolean true const integer 1999 const real 2000.0 const string "afnix" const char 'a'

None of the symbols -- or names -- used in the program above are reserved keywords. In fact, the capitalize names are builtin objects such like Integer or String. The `const` reserved keyword creates a constant symbol and returns the last evaluated object. As a consequence, nested `const` constructs are possible like `trans b (const a 1)`. The `trans` reserved keyword declare a new non-constant symbol. That is, the symbol can be changed. Note that it is the symbol which is marked constant, not the object.

trans a-symbol "hello world" trans a-symbol 2000 println a-symbol

## Comments

Comments starts with the character `#`. All characters until the end of line are consumed. Comments can be placed anywhere in the source file. Comments entered during an interactive session are discarded.

## Forms

The previous program was an illustration of the simplest form declaration, referred as implicit form. An implicit form is a single line command. When a command is becoming complex, the use of the standard form notation is more readable. The standard form uses the `(` and `)` characters to start and close a form. The previous programs could have been written with the standard form notation instead of the implicit one. The use of standard form notation versus the implicit is one is a matter of style and readability.

A form causes an evaluation. When a form is evaluated, each symbol in the form are evaluated to their corresponding internal object. Then the interpreter treats the first object of the form as the object to execute and the rest is the argument list for the calling object. The use of form inside a form is the standard way to perform recursive evaluation for complex expression.

const three (+ 1 2)

The previous program defines a symbol which is initialized with the integer 3, that is the result of the computation `(+ 1 2)`. The program shows also that Polish notation is used for arithmetic. If fact, `+` is a builtin operator which causes the arguments to be summed (if possible). Evaluation can be nested as well as definition and assignation. When a form is evaluated, the result of the evaluation is made available to the calling form. If the result is obtained at the top level, that result is discarded.

const b (trans a (+ 1 2)) assert a 3 assert b 3 trans a 4 assert b 3

This program illustrates the mechanic of the evaluation process. The evaluation is done recursively. The `(+ 1 2)` form is evaluated as 3 and the result transmitted to the form `(trans a 3)`. This form not only creates the symbol `a` and binds to it the integer 3, but returns also 3 which is the result of the previous evaluation. Finally, the form `(const b 3)` is evaluated, that is, the symbol `b` is created and the result discarded. Internally, things are a little more complex, but the idea remains the same. This program illustrates also the usage of the `assert` keyword.

## Lambda expression

A lambda expression is a function in the terminology. The term come historically from Lisp to express the fact that a lambda expression is analog to the concept of expression found in the lambda calculus. There are various ways to create a lambda expression. A lambda expression is created with the `trans` reserved keywords. A lambda expression takes 0 or more arguments and return an object. A lambda expression is also an object by itself. When a lambda expression is called, the arguments are evaluated from left to right and placed on the interpreter eval stack. The function is then called and the object result is transmitted to the calling form. The use of `trans` vs `const` is explain later. As an example, we define the factorial of an integer in a recursive way.

# declare the factorial function trans fact (n) ( if (== n 1) 1 (* n (fact (- n 1)))) # compute factorial 5 println "factorial 5 = " (fact 5)

This program calls for several comments. First the `trans` keyword defines a new function object with one argument called `n`. The body of the function is defined with the `if` reserved keyword and can be easily understood. The function is called in the next form when the `println` reserved keyword is executed. Note that here, the call to `fact` produces an integer object, which is converted automatically by the `println` keyword.

## Block form

The notation used in the `fact` program is the standard form notation originating from Lisp and the Scheme dialect. offers another notation called the block form notation with the use of the `{` and `}` characters. A block form is a syntactic notation where each form in the block form is executed sequentially. The form can be either an implicit or a regular form. The `fact` procedure can be rewritten with the block notation as illustrated below.

# declare the factorial procedure trans fact (n) { if (== n 1) 1 (* n (fact (- n 1))) } # compute factorial 5 println "factorial 5 = " (fact 5)

Another way to create a lambda expression is via the reserved keyword `lambda`. Recall that a lambda expression is an object. So when such object is created, it can be bounded to a symbol. The factorial example could be rewritten with an explicit lambda call.

# declare the factorial procedure const fact (lambda (n) ( if (== n 1) 1 (* n (fact (- n 1)))) # compute factorial 5 println "factorial 5 = " (fact 5)

Note that here, the symbol `fact` is a constant symbol. The use of `const` is rather reserved for gamma expression.

## Gamma expression

A lambda expression can somehow becomes very slow during the execution, since the symbol evaluation is done within a set of nested call to resolve the symbols. In other words, each recursive call to a function creates a new symbol set which is linked with its parent. When the recursion is becoming deep, so is the path to traverse from the lower set to the top one. Afnix provides another mechanism called gamma expression which binds only the function symbol set to the top level one. The rest remains the same. Using a gamma expression can speedup significantly the execution.

# declare the factorial procedure const fact (n) ( if (== n 1) 1 (* n (fact (- n 1)))) # compute factorial 5 println "factorial 5 = " (fact 5)

We will come back later to the concept of gamma expression. The use of the reserved keyword `const` to declare a gamma expression makes now sense. Since most function definitions are constant with one level, it was a language choice to implement this syntactic sugar. Note that `gamma` is a reserved keyword and can be used to create a gamma expression object. On the other hand, note that the gamma expression mechanism does not work for instance method. We will illustrate this point later in this book.

## Lambda generation

A lambda expression can be used to generate another lambda expression. In other word, a function can generate a function, hence the term that is a functional programming language. Suppose one might want to write a function which take an argument and generate a function which add this argument to the generated function argument -- got that! --, then here is the implementation.

# a gamma which creates a lambda const gen (n)( lambda (x) (n) (+ x n)) # create a function which add 2 to its argument const add-2 (gen 2) # call add-2 with an argument and check println "result = " (add-2 3)

The interesting part in the previous program is the concept of closed variables. Looking at the lambda expression inside `gen`, notice that the argument to the gamma is `x` while `n` is marked in a form before the body of the gamma. This notation indicates that the gamma should retain the value of the argument `n` when the closure is created. In the literature, you might discover a similar mechanism referenced as a closure. A closure is simply a variable which is closed under a certain context. When a variable is reference in a context without any definition, such variable is called a free variable. We will see later more programs with closures. Note that in the terminology, it is the object created by the gamma call which is called a closure. Note also that the same mechanism apply with lambda. In short, a lambda expression is a function with or without closed variables, which works with nested symbol sets also called namesets. A gamma expression is a function with or without closed variable which is bounded to the top level nameset. The reserved keyword `trans` binds a lambda expression. The reserved keyword `const` binds a gamma expression. A gamma expression cannot be used as an instance method.

## Multiple arguments binding

A lambda or gamma expression can be defined to work with extra arguments using the special `args` binding. During a lambda or gamma expression execution, the special symbol `args` is defined with the extra arguments passed at the call. For example, a gamma expression with 0 formal argument and 2 actual arguments has `args` defined as a cons cell.

const proc-nilp (args) { trans result 0 for (i) (args) (result:+= i) eval result } assert 3 (proc-nilp 1 2) assert 7 (proc-nilp 1 2 4)

The symbol `args` can also be defined with formal arguments. In that case, `args` is defined as a cons cell with the remaining actual arguments.

# check with arguments const proc-args (a b args) { trans result (+ a b) for (i) (args) (result:+= i) eval result } assert 3 (proc-args 1 2) assert 7 (proc-args 1 2 4)

It is an error to specify formal arguments after `args`. Multiple `args` formal definition are not allowed. The symbol `args` can also be defined as a constant argument.

# check with arguments const proc-args (a b (const args)) { trans result (+ a b) for (i) (args) (result:+= i) eval result } assert 7 (proc-args 1 2 4)

## Nameset and bindings

A nameset is a container of bindings between a name and symbolic variable. We use the term symbolic variable to denote any binding between a name and an object. There are various ways to express such bindings. The common one in is called a symbol. Another type of binding is an argument. Despite the fact they are different, they share a set of common properties, like being settable. Another point to note is the nature of the nameset. As a matter of fact, has various type of namesets. The top level nameset is called a global set and is designed to handle a large number of symbols. In a lambda or gamma expression, the nameset is called a local set and is designed to be fast with a small number of symbols. The moral of this little story is to think always in terms of namesets, no matter how it is implemented. All namesets support the concept of parent binding. When a nameset is created (typically during the execution of a lambda expression), this nameset is linked with its parent one. This means that a symbol lookup is done by traversing all nameset from the bottom to the top and stopping when one is found. In term of notation, the current nameset is referenced with the special symbol `.`. The parent nameset is referenced with the special symbol `..`. The top level nameset is referenced with the symbol `...`.

## Symbol

A symbol is an object which defines a binding between a name and an object. When a symbol is evaluated, the evaluation process consists in returning the associated object. There are various ways to create or set a symbol, and the different reserved keywords account for the various nature of binding which has to be done depending on the current nameset state. One of the symbol property is to be `const` or not. When a symbol is marked as a constant, it cannot be modified. Note here that it is the symbol which is constant, not the object. A symbol can be created with the reserved keywords `const` or `trans`.

## Creating a nameset

A nameset is an object which can be constructed directly by using the object construction notation. Once the object is created, it can be bounded to a symbol. Here is a nameset called `example` in the top level nameset.

# create a new nameset called example const example (nameset .) # bind a symbol in this nameset const example:hello "hello" println example:hello

## Qualified name

In the previous example, a symbol is referenced in a given nameset by using a qualified name like `example:hello`. A qualified name define a path to access a symbol. The use of qualified name is a powerful notation to reference an object in reference to another object. For example, the qualified name `.:hello` refers to the symbol `hello` in the current nameset. The qualified name `...:hello` refers to the symbol `hello` in the top level nameset. There are other use for qualified names, like method call with an instance.

## Symbol binding

The `trans` reserved keyword has been shown in all previous example. The reserved keyword `trans` creates or set a symbol in the current nameset. For example, the form `trans a 1` is evaluated as follow. First, a symbol named `a` is searched in the current nameset. At this stage, two situations can occur. If the symbol is found, it is set with the corresponding value. If the symbol is not found, it is created in the current nameset and set. The use of qualified name is also permitted -- and encouraged -- with `trans`. The exact nature of the symbol binding with a qualified name depends on the partial evaluation of the qualified name. For example, `trans example:hello 1` will set or create a symbol binding in reference to the `example` object. If `example` refers to a nameset, the symbol is bound in this nameset. If `example` is a class, `hello` is bounded as a static symbol for that class. In theory, there is no restriction to use `trans` on any object. If the object does not have a symbol binding capability, an exception is raised. For example, if `n` is an integer object, the form `trans n:i 1` will fail. With 3 or 4 arguments, `trans` defines automatically a lambda expression. This notation is a syntactic sugar. The lambda expression is constructed from the argument list and bounded to the specified symbol. The rule used to set or define the symbol are the same as described above.

# create automatically a lambda expression trans min (x y) (if (< x y) x y)

## Constant binding

The `const` reserved keyword is similar to `trans`, except that it creates a constant symbol. Once the symbol is created, it cannot be changed. This constant property is hold by the symbol itself. When trying to set a constant symbol, an exception is raised. The reserved keyword `const` works also with qualified names. The rules described previously are the same. When a partial evaluation is done, the partial object is called to perform a constant binding. If such capability does not exist, an exception is raised. With 3 or 4 arguments, `const` defines automatically a gamma expression. Like `trans` the rule are the same except that the symbol is marked constant.

# create automatically a gamma expression const max (x y) (if (> x y) x y)

## Arguments

An expression argument is similar to a symbol, except that it is used only with function argument. The concept of binding between a name and an object is still the same, but with an argument, the object is not stored as part of the argument, but rather at another location which is the execution stack. An argument can also be constant. On the other hand, a single argument can have multiple bindings. Such situation is found during the same function call in two different threads. An argument list is part of the lambda or gamma expression declaration. If the argument is defined as a constant argument a sub form notation is used to defined this matter. For example, the `max` gamma expression is given below.

# create a gamma expression with const argument const max (gamma ((const x) (const y)) (if (> x y) x y))

A special symbols named `args` is defined during a lambda or gamma expression evaluation with the remaining arguments passed at the time the call is made. The symbol can be either `nil` or bound to a list of objects.

const proc-args (a b) { trans result (+ a b) for (i) (args) (result:+= i) eval result } assert 3 (proc-args 1 2) assert 7 (proc-args 1 2 4)

## Control flow

provides various reserved keywords which can be seen as standard imperative statements. Such statements are useful to write readable programs but are not necessary the best in terms of efficiency. In most cases, a statement returns the last evaluated object. Most of the statements are control flow statements.

## If statement

The `if` reserved keyword takes two or three arguments. The first argument is the boolean condition to check. If the condition evaluates to `true` the second argument is evaluated. The form return the result of such evaluation. If the condition evaluates to `false`, the third argument is evaluated or nil is returned if it does not exist. An interesting example which combines the `if` reserved keyword and a deep recursion is the computation of the Fibonacci sequence.

const fibo (gamma (n) ( if (< n 2) n (+ (fibo (- n 1)) (fibo (- n 2))))

## While statement

The `while` reserved keyword takes 2 or 3 arguments. With 2 arguments, the loop is constructed with a condition and a form. With 3 arguments, the first argument is an initial condition that is executed only once. When an argument acts as a loop condition, the condition evaluate to a boolean. The loop body is executed as long as the boolean condition is true. An interesting example related to integer arithmetic with a `while` loop is the computation of the greatest common divisor or gcd.

const gcd (u v) { while (!= v 0) { trans r (u:mod v) u:= v v:= r } eval u }

Note in this previous example the use of the symbol `=`. The qualified name `u:=` is in fact a method call. Here, the integer `u` is assigned with a value. In this case, the symbol is not changed. It is the object which is muted. In the presence of 3 arguments, the first argument is an initialization condition that is executed only once. In this mode, it is important to note that the loop introduce its own nameset. The loop condition can be used to initialize a local condition variable.

while (trans valid (is:valid-p)) (valid) { # do something # adjust condition valid:= (and (is:valid-p) (something-else)) }

## Do statement

The `do` reserved keyword is similar to the `while` reserved keyword, except that the loop condition is evaluated after the body execution. The syntax call is opposite to the `while`. The loop can accept either 2 or 3 arguments. With 2 arguments, the first argument is the loop body and the second argument is the exit loop condition. With 3 arguments, the first argument is the initial condition that is executed only once.

# count the number of digits in a string const number-of-digits (s) { const len (s:length) trans index 0 trans count 0 do { trans c (s:get index) if (c:digit-p) (count:++) } (< (index:++) len) eval count }

## Loop statement

The `loop` reserved keyword is another form of loop. It take four arguments. The first is the initialize form. The second is the exit condition. The third is the step form and the fourth is the form to execute at each loop step. Unlike the `while` and `do` loop, the `loop` statement creates its own nameset, since the initialize condition generally creates new symbol for the loop only.

# a simple loop from 0 to 10 loop (trans i 0) (< i 10) (i:++) (println i)

## Switch statement

The `switch` reserved keyword is a condition selector. The first argument is the switch selector. The second argument is a list of various value which can be matched by the switch value. A special symbol called `else` can be used to match any value.

# return the primary color in a rgb const get-primary-color (color value) ( switch color ( ("red" (return (value:substr 0 2)) ("green" (return (value:substr 2 4)) ("blue" (return (value:substr 4 6)) ) )

## Return statement

The `return` reserved keyword indicates an exceptional condition in the flow of execution within a lambda or gamma expression. When a return is executed, the associated argument is returned and the execution terminates. If `return` is used at the top level, the result is simply discarded.

# initialize a vector with a value const vector-init (length value) { # treat nil vector first if (<= length 0) return (Vector) trans result (Vector) do (result:add value) (> (length:--) 0) }

## Eval and protect

The `eval` reserved keyword forces the evaluation of the object argument. The reserved keyword `eval` is typically used in a function body to return a particular symbol value. It can also be used to force the evaluation of a protected object. In many cases, `eval` is more efficient than `return`. The `protect` reserved keyword constructs an object without evaluating it. Typically when used with a form, `protect` return the form itself. It can also be used to prevent a symbol evaluation. When used with a symbol, the symbol object itself is returned.

const add (protect (+ 1 2)) (eval add)

Note that in the preceding example that the evaluation will return a lambda expression which is evaluated immediately and which return the integer 3.

## Assert statement

The `assert` reserved keyword check for equality between the two arguments and abort the execution in case of failure. By default, the assertion checking is turn off, and can be activated with the command option `-f assert`. Needless to say that `assert` is used for debugging purpose.

assert true (> 2 0) assert 0 (- 2 2) assert "true" (String true)

## Block statement

The `block` reserved keyword executes a form in a new local set. The local set is destroyed at the completion of the execution. The `block` reserved keyword returns the value of the last evaluated form. Since a new local set is created, any new symbol created in this nameset is destroyed at the completion of the execution. In other word, the `block` reserved keyword allows the creation of a local scope.

trans a 1 block { assert a 1 trans a (+ 1 1) assert a 2 assert ..:a 1 } assert 1 a

## builtin objects

provides several builtin objects and builtin operators for arithmetic and logical operations. The `Integer` and `Real` classes are primarily used to manipulate numbers. The `Boolean` class is used to for boolean operations. Other builtin objects include `Character` and `String`. The exact usage of these classes is described in the next chapter.

## Arithmetic operations

provides various ways to perform arithmetic operations. Most of the operations are done with the `+`, `-`, `*` and `/` operators. Each of these operators works with both integer and real numbers.

(+ 1 2) (- 1) (* 3 5.0) (/ 4.0 2)

## Logical operations

The `Boolean` class is used to represent the boolean value `true` and `false`. These last two symbols are builtin in the interpreter as constant symbols. provides also some reserved keywords like `not`, `and` and `or`. Their usage is self understandable.

not true and true (== 1 0) or (< -1 0) (> 1 0)

## Predicates

A predicate is a function which returns a boolean object. provides several predicates to check for some builtin objects. By convention, a predicate terminates with the sequence -p. The `nil-p` predicate is a special predicate which returns true if the object is nil. provides a predicate for each builtin objects.

## builtin predicates

Predicate | Description
nil-p | check nil object
eval-p | check evaluation
real-p | check real object
regex-p | check regex object
string-p | check string object
number-p | check number object
boolean-p | check boolean object
integer-p | check integer object
character-p | check character object

For example, one can write a function which returns `true` if the argument is a number, that is, an integer or a real number.

# return true if the argument is a number const number-p (n) ( or (integer-p n) (real-p n))

Predicates for functional and symbolic programming are also builtin into the engine.

## Special predicates

Predicate | Description
class-p | check class object
thread-p | check thread object
promise-p | check promise object
lexical-p | check lexical object
literal-p | check literal object
closure-p | check closure object
nameset-p | check nameset object
instance-p | check instance object
qualified-p | check qualified object

Finally, for each object, a predicate is also associated. For example, `cons-p` is the predicate for the `Cons` object.

## Object predicates

Predicate | Description
cons-p | check a cons object
list-p | check for a list object
queue-p | check a queue object
bitset-p | check a bitset object
vector-p | check a vector object

Another issue related to evaluation, is to decide whether or not an object can be evaluated. The predicate `eval-p` which is a special form is designed to answer this question. Furthermore, the `eval-p` predicate is useful to decide whether or not a symbol is defined or if a qualified name can be evaluated.

assert true (eval-p .) assert false (eval-p an-unknown-symbol)

## Class and Instance

provides support for the object oriented programming paradigm. A class in the terminology is a nameset which can be bounded automatically when an instance of that class is created. Compared to other language, there is no need to declare the data member for a particular class. Data members are created during the instance construction. A class allows an instance to call function with the instance nameset visible for that function.

## Class and members

A class is declared with the reserved keyword `class`. The class acts like a nameset. Functions can be bounded to this class.

const Color (class) const Color:BLACK "#000000" const Color:WHITE "#FFFFFF"

Any object can be bounded as a data member, including lambda expressions.

const Color (class) const Color:get-primary-from-string (color value) { trans val "0x" val:+= (switch color ( ("red" (value:substr 1 3)) ("green" (value:substr 3 5)) ("blue" (value:substr 5 7)) ) Integer val }

## Instances

An instance of a class is created like any builtin object. If a method called `preset` is defined for that class, the method is used as an initializer of that instance.

const Color (class) trans Color:preset (red green blue) { const this:red (Integer red) const this:green (Integer green) const this:blue (Integer blue) } const red (Color 255 0 0) const green (Color 0 255 0) const blue (Color 0 0 255)

## Instance method

When a lambda expression is bound to the class or the instance, that lambda can be invoked as an instance method. When an instance method is invoked, the instance nameset is set as the parent nameset for that lambda. This is the main reason why a gamma expression cannot be used as an instance method. The instance nameset defines the instance data members and the special symbol `this`.

const int-max (x y) if (> x y) (Integer x) (Integer y)) const Color:RED-FACTOR 0.75 const Color:GREEN-FACTOR 0.75 const Color:BLUE-FACTOR 0.75 trans Color:get-darker nil { trans red (int-max (this:red:* Color:RED-FACTOR) 0) trans green (int-max (this:green:* Color:GREEN-FACTOR) 0) trans red (int-max (this:blue:* Color:BLUE-FACTOR) 0) Color red green blue } # get a darker color than red const dark-red (red:get-darker)

## Miscellaneous features

provides several facilities for control flow and exceptional operations. Most of these features are available via the use of reserved keywords.

## Iteration

An iteration facility is provided for some objects known as iterable objects. The `Cons`, `List` and `Vector` are typical iterable objects. There are two ways to iterate with these objects. The first method uses the `for` reserved keyword. The second method uses an explicit iterator which can be constructed by the object.

# compute the scalar product of two vectors const scalar-product (u v) { trans result 0 for (x y) (u v) (result:+= (* x y)) eval result }

The `for` reserved keyword iterate on both object `u` and `v`. For each iteration, the symbol `x` and `y` are set with their respective object value. In the example above, the result is obtained by summing all intermediate products.

# test the scalar product function const v1 (Vector 1 2 3) const v2 (Vector 2 4 6) (scalar-product v1 v2)

The iteration can be done explicitly by creating an iterator for each vectors and advancing steps by steps.

# scalar product with explicit iterators const scalar-product (u v) { trans result 0 trans u-it (u:get-iterator) trans v-it (v:get-iterator) while (u:valid-p) { trans x (u:get-object) trans y (v:get-object) result:+= (* x y) u:next v:next } eval result }

In the example above, two iterators are constructed for both vectors `u` and `v`. The iteration is done in a `while` loop by invoking the `valid-p` predicate. The `get-object` method returns the object value at the current iterator position.

## Exception

An exception is an unexpected change in the execution flow. The model for exception is based on a mechanism which throws the exception to be caught by a handler. The mechanism is also designed to be compatible with the native "C++" implementation. An exception is thrown with the reserved keyword `throw`. When an exception is thrown, the normal flow of execution is interrupted and an object used to carry the exception information is created. Such exception object is propagated backward in the call stack until an exception handler catch it. The reserved keyword `try` executes a form and catch an exception if one has been thrown. With one argument, the form is executed and the result is the result of the form execution unless an exception is caught. If an exception is caught, the result is the exception object. If the exception is a native one, the result is nil.

try (+ 1 2) try (throw) try (throw "hello") try (throw "hello" "world") try (throw "hello" "world" "folks")

The exception mechanism is also designed to install an exception handler and eventually retrieve some information from the exception object. The reserved symbol `what` can be used to retrieve some exception information.

# protected factorial const fact (n) { if (not (integer-p n)) (throw "number-error" "invalid argument") if (== n 0) 1 (* n (fact (- n 1))) } # exception handler const handler nil { errorln what:eid ',' what:reason } (try (fact 5) handler) (try (fact "hello") handler)

## Delayed evaluation

The interpreter provides a special mechanism to delay an evaluation. The reserved keyword `delay` creates a special object called a promise which records the form to be later evaluated. The reserved keyword `force` causes a promise to be evaluated. Subsequent call with `force` will produce the same result.

trans y 3 const l ((lambda (x) (+ x y)) 1) assert 4 (force l) trans y 0 assert 4 (force l)

## Regular Expressions

The interpreter provides a builtin mechanism for regular expression. A regex is an object which is used to match certain text patterns. Regular expressions are built implicitly by the reader wit the use of the `[` and `]` characters.

if (== (const re [($d$d):($d$d)]) "12:31") { trans hr (re:get 0) trans mn (re:get 1) }

In the previous example, a regular expression object is bound to the symbol `re`. The `regex` contains two groups. The call to the operator `==` returns `true` if the regex matches the argument string. The `get` method can be used to retrieve the group by index.

## Threads

The interpreter provides a powerful mechanism which allows the concurrent execution of forms and the synchronization of shared objects. There are two types of threads, namely normal thread and daemon thread. They differ only by the interpreter exit condition. The interpreter will wait until all normal threads are completed. On the other hand, the interpreter will not wait for daemon threads. They are automatically stopped when all normal threads are finished. Normal threads are created with the reserved keyword `launch`, and daemon threads are created with the reserved keyword `daemon`. When threads are used, the interpreter manages automatically the shared objects and protect them against concurrent access.

# shared variable access const var 0 const decr nil (while true (var:= (- var 1))) const incr nil (while true (var:= (+ var 1))) const prtv nil (while true (println "value = " var)) # start 3 threads launch (prtv) launch (decr) launch (incr)

## Form synchronization

Although, provides an automatic synchronization mechanism for reading or writing an object, it is sometimes necessary to control the execution flow. There are basically two techniques to do so. First, protect a form from being executed by several threads. Second, wait for one or several threads to complete their task before going to the next execution step. The reserved keyword `sync` can be used to synchronize a form. When a form, is synchronized, the engine guarantees that only one thread will execute this form.

const print-message (code mesg) ( sync { errorln "error : " code errorln "message: " mesg } )

The previous example create a gamma expression which make sure that both the error code and error message are printed in one group, when several threads call it.

## Thread completion

The other piece of synchronization is the thread completion indicator. The thread descriptor contains a method called `wait` which suspend the calling thread until the thread attached to the descriptor has been completed. If the thread is already completed, the method returns immediately.

# simple flag const flag false # simple shared tester const ftest (val) (flag) (assert val (flag:shared-p)) # no thread mean not shared ftest false # in a thread it is shared const thr (launch (ftest true)) thr:wait assert true (flag:shared-p)

This example is taken from the test suites. It checks that a closed variable becomes shared when started in a thread. Note the use of the `wait` method to make sure the thread has completed before checking for the shared flag. It is also worth to note that `wait` is one of the method which guarantees that a thread result is valid. Another use of the `wait` method can be made with a vector of thread descriptors when one wants to wait until all of them have completed.

# shared vector of threads descriptors const thr-group (Vector) # wait until all threads in the group are finished const wait-all nil (for (thr) (thr-group) (thr:wait))

## Condition variable

A condition variable is another mechanism to synchronize several threads. A condition variable is modeled with the `Condvar` object. At construction, the condition variable is initialized to `false`. A thread calling the `wait` method will block until the condition becomes `true`. The `mark` method can be used by a thread to change the state of a condition variable and eventually awake some threads which are blocked on it. The use of condition variable is particularly recommended when one need to make sure a particular thread has been doing a particular task.