Provided by: afnix_3.8.0-1_amd64 bug

NAME

       std-us-guide - afnix programmer's guide

GETTING STARTED

       AFNIX   is  a  multi-threaded  functional  engine  with  dynamic symbol bindings that supports the object
       oriented paradigm. The system features a state of the art runtime engine that runs on both 32 and 64 bits
       platforms. The system specification offers a rich syntax that makes the functional programming a pleasant
       activity. When the interpreter is used interactively, text is entered on the command  line  and  executed
       when  a  complete  and  valid  syntactic  object has been constructed. Alternatively, the interpreter can
       execute a source file or operates with an input stream.  AFNIX  is a  comprehensive  set  of  application
       clients,  modules  and  services. The original distribution contains the core interpreter with additional
       clients like the compiler, the librarian and the debugger. The distribution contains also a rich  set  of
       modules  that  are  dedicated  to a particular domain. The basic modules are the standard i/o module, the
       system module and the networking module. Above modules are services. A service is  another  extension  of
       the  engine  that provides extra functionalities with help of several modules. This hierarchy is strictly
       enforced in the system design and provides a clear functional separation between application domain. When
       looking for a particular feature, it is always a good  idea  to  think  in  term  of  module  or  service
       functionality.   AFNIX   operates  with a set of keywords and predicates. The engine has a native Unicode
       database. The set of standard objects provides support for integers, real  numbers,  strings,  characters
       and  boolean.  Various containers like list, vector, hash table, bitset, and graphs are also available in
       the core distribution. The syntax incorporates the concept of lambda expression  with  explicit  closure.
       Symbol  scope  limitation  within  a  lambda  expression  is a feature called gamma expression. Form like
       notation with an easy block declaration is also another extension  with  respect  to  other  system.  The
       object  model  provides  a  single inheritance mechanism with dynamic symbol resolution. Special features
       include instance parenting, class binding instance inference and deference. Native class  derivation  and
       method  override  is  also  part  of  the  object  model  with  fixed class objects and forms. The engine
       incorporates an original regular expression engine with  group  matching,  exact  or  partial  match  and
       substitution.  An  advanced  exception engine is also provided with native run-time compatibility.  AFNIX
       implements a true multi-threaded engine with an automatic object protection mechanism against  concurrent
       access.  A  read and write locking system which operates with the thread engine is also built in the core
       system. The object memory management is automatic inside the core interpreter.  Finally,  the  engine  is
       written  in  C++  and  provides runtime compatibility with it. Such compatibility includes the ability to
       instantiate C++ classes, use virtual methods and raise or catch exceptions. A  comprehensive  programming
       interface has been designed to ease the integration of foreign libraries.

       First contact
       The fundamental syntactic object is a form. A form is parsed and immediately executed by the interpreter.
       A  form  is generally constructed with a function name and a set of arguments. The process of executing a
       form is called the evaluation. The next example illustrates one of the simplest form which  is  supported
       by the engine. This form simply displays the message hello world.

       Hello world
       At  the interpreter prompt, a form is constructed with the special object println. The unique argument is
       a string which is placed between double quotes.

       (axi) println "Hello World"
       Hello World

       The interpreter can be invoked to enter one or several forms interactively. The form can also  be  placed
       in  a  text  file  and the interpreted called to execute it. The als is the referred extension for a text
       file, but it can be anything. A simple session which executes the above file  --  assuming  the  original
       file is called hello.als -- is shown below.

       zsh> axi hello.als
       Hello World

       In  interactive  mode,  the  interpreter waits for a form. When a form is successfully constructed, it is
       then immediately executed by the engine. Upon completion, the interpreter prompt  is  displayed  and  the
       interpreter  is  ready to accept a new form. A session is terminated by typing ctrl-d. Another way to use
       the engine is to call the compiler client called axc, and then invoke the interpreter with  the  compiled
       file.  The  interpreter  assumes  the  .axc extension for compiled file and will automatically figure out
       which file to execute when a file name is given without an extension.

       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 system version
       [m]           enable the start module
       [i   path]    add a resolver path
       [e   mode]    force the encoding mode
       [f assert]    enable assertion checks
       [f nopath]    do not set initial path
       [f noseed]    do not seed random engine
       [f   seed]    seed random engine

       The  v  option  prints  the  interpreter  version and operating system. The f option turns on or off some
       additional options like the assertion checking. The use of program arguments is illustrated later in this
       chapter. The i option adds a path to the interpreter resolver. Several i options can  be  specified.  The
       order of search is determined by the option order. As mentioned earlier, 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  is  provided  when the interpreter is used interactively. Error messages are
       displayed in red if the terminal supports colors. Various accelerators  are  bound  to  the  terminal  as
       indicated in the table below.
       Binding     Description
       backspace   Erase the previous character
       delete      Erase at the cursor position
       insert      Toggle insert with in-place
       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

       The arrow are also bound to their usual functions. Note that when using the history, a multi-line command
       editing access is provided by the interpreter.
       Binding   Description
       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

       Command line arguments
       The  interpreter  command  line  arguments are stored in a vector called argv which is part of the interp
       object. A complete discussion about object and class is covered in the  class  object  chapter.  At  this
       time,  it  is  just necessary to note that a method is invoked by a name separated from the object symbol
       name with a semicolon. The example below 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 object provides also the load method to load a 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 reads one form after  another  and  executes
       them sequentially.

       # load the source file demo.als
       (axi) interp:load "demo.als"
       # load the compiled file demo.axc
       (axi) interp:load "demo.axc"
       # load whatever is found
       (axi) interp:load "demo"

       The  load method operates with the help of the interpreter resolver. By default the source file extension
       is 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. 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 several
       platforms. The h option prints the compiler options.

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

       One or several files can be specified on the command line. The source file is searched with the  help  of
       the resolver. The resolver i option can be used to add a path to the resolver.

       Writing structure
       The  structure  of  file is a succession of valid syntactic objects separated by blank lines or comments.
       During the compilation or the execution process, each syntactic object is processed one after another  in
       a  single pass. Reserved keywords are an integral part of the writing systems. The association of symbols
       and literal constitutes a form. A form is the basic execution block in the writing system. When the  form
       uses reserved keyword, it is customary to refer to it as a special form.

       Character set and comments
       The  writing  system operates with the standard Unicode character set. Comments starts with the character
       #. All characters are consumed until the end of line. Comments can be placed anywhere in the source file.
       Comments entered during an interactive session are discarded.

       Native objects
       The writing system operates mostly with objects. An object is created upon request  or  automatically  by
       the engine when a native representation is required. To perform this task, several native objects, namely
       Boolean  for  boolean  objects,  Integer  ,  Relatif for integer numbers, Real for floating-point number,
       Complex> for complex number, Byte, Character and String for character or string  manipulation  are  built
       inside the engine. Most of the time, a native object is built implicitly from its lexical representation,
       but an explicit representation can also be used.

       const boolean  true
       const integer  1999
       const relatif  1234567890R
       const complex  1.0+1.0i
       const real     2000.0
       const string   "afnix"
       const char     'a'
       trans symbol   "hello world"
       trans symbol   2000

       The  const  and  trans  reserve  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.  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
       transient  symbol. When a symbol is marked transient, the object bound to the symbol can be changed while
       this is not possible with a constant symbol. Eventually, a symbol can be destroyed with the special  form
       unref.  It  is  worth to note that it is the symbol which is destroyed and not the object associated with
       it.

       Stop and resume parsing
       The parsing process is stopped in the presence of the ◀ character (Unicode U+25C0). The parsing operation
       is resumed with the ▶ character (Unicode U+25B6). Such mechanism is useful when dealing with  multi  line
       statements. This mechanism is also a good example of Unicode based control characters.

       Forms
       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.
       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 with complex expressions.

       const three (+ 1 2)

       This example defines a symbol which is initialized with  the  integer  3,  that  is  the  result  of  the
       computation  (+ 1 2). The example shows also that a Polish notation is used for arithmetic. If fact, + is
       a built-in 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, the result is discarded.

       const  b (trans a (+ 1 2))
       assert a 3
       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 another name for a function. The term comes 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
       keyword. A lambda expression takes 0 or more arguments and returns 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.
       The function is then called and the object result is transmitted to the calling form. The use of trans vs
       const is explain later. To illustrate the use of a lambda  expression,  the  computation  of  an  integer
       factorial is described in the next example.

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

       This  example  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  special  form  and  can  be  easily
       understood.  The function is called in the next form when the println special form 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. There is also 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 lambda special form. 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 reserved for  the  creation  of
       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. There  is  also  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 design 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,  an  that  capability  is  an  essential  ingredient of the functional programming
       paradigm. The interesting part with lambda expression is the concept of closed  variables.  In  the  next
       example,  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 it is the object created by the lambda
       or the gamma call which is called a closure.

       # 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)

       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  most  common  one 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, there is 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
       look-up  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 such like
       example:hello. A qualified name defines a path to access a symbol. The use  of  a  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 class symbol. 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)

       Symbol unreferencing
       The  unref reserved keyword removes a symbol reference in a given context. When the context is a nameset,
       the object associated with the symbol is detached from the symbol, eventually destroyed with  the  symbol
       removed from the nameset.

       # create a symbol number
       const x 1
       # unreference it
       unref x

       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)

       Special forms
       Special forms provides are reserved keywords which are most of the time imperative statement, as part  of
       the  writing  system. Special forms are an integral part of the writing system and interact directly with
       the interpreter. In most cases, a special forms returns the last evaluated object. Most  of  the  special
       forms are control flow statements.

       If special form
       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 special form
       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 special form
       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 special form
       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 special form 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)

       A loop can also be designed with a Counter object. In this case, a counter is created with an initial and
       final count values. The counter step-p method can then be used to run the loop

       # a counter from 0 to 10
       trans cntr (Counter 10)
       # a simple loop from 1 to 10
       loop (cntr:step-p) (println cntr)

       In  this  example,  the counter prints from 1 to 10 since the counter is designed to operate from 0 to 9,
       and the println function is called after the step-p predicate.

       Switch special form
       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 special form
       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 special form
       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 special form
       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

       Built-in objects
       Several built-in objects and built-in operators for arithmetic and logical operations are also integrated
       in the writing system. The Integer and Real classes are primarily used to manipulate numbers. The Boolean
       class  is  used to for boolean operations. Other built-in objects include Character and String. The exact
       usage of these objects is described in the next chapter.

       Arithmetic operations
       Support for the arithmetic operations is provided with the standard operator  notation.  Normally,  these
       operators  will  tolerate various object type mixing and the returned value will generally be bound to an
       object that provides the minimum loss of information. Most of the operations are done with the  +,  -,  *
       and / operators.

       (+ 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
       built-in in the interpreter as constant symbols. There are also special forms 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. There is always a built-in predicate associated
       with a built-in object. 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. The object-p predicate is the negation of
       the nil-p predicate.
       Predicate     Description
       nil-p         check nil object
       eval-p        check evaluation
       real-p        check real object
       regex-p       check regex object
       object-p      check for non nil object
       string-p      check string object
       number-p      check number object
       method-p      check method 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))

       Special predicates for functional and symbolic programming are also built-in in the engine.
       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 and vector-p is the predicate for the 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
       Classes  and instances are the fundamental objects that provide support for the object oriented paradigm.
       A class is a nameset which can be bounded automatically when an instance of that class  is  created.  The
       class  model  is  sloppy.  Compared  to other systems, there is no need to declare the data members for a
       particular class. Data members are created during the instance construction.  An  instance  can  also  be
       created  without  any reference to a class. Methods can be bound to the class or the instance or both. An
       instance can also be muted during the execution process.

       Class and members
       A class is declared with the reserved keyword class. The resulting object acts like a nameset and  it  is
       possible to bind symbol to it.

       # create a class object
       const Circle (class)
       const Circle:PI 3.1415926535
       # access by qualified name
       println Circle:PI

       In  the  previous  example,  the symbol Circle is created as a class object. With the help of a qualified
       name, the symbol PI is created inside the class nameset. In this case, the symbol PI  is  invariant  with
       respect  to the instance object. A form can also be bound to the class nameset. In both cases, the symbol
       or the form is accessed with the help of a qualified name.

       Instances
       An instance of a class is created like any built-in object. If a method called preset is defined for that
       class, the method is used to initialize the instance.

       # create a class
       const Circle (class)
       trans Circle:preset (r) {
         const this:radius (r:clone)
       }
       # create a radius 1 circle
       const c (Circle 1)

       This example calls for several comments. First the preset lambda expression is bound to the class.  Since
       preset  is  a  reserved  name  for  the  class object, the form is automatically executed at the instance
       construction. Second, note that the instance data member radius is created by the lambda  expression  and
       another  reserved  keyword  called  this is used to reference the instance object as it is customary with
       other programming systems.

       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. Therefore,
       the use of the reserved keyword this is not recommended in a gamma expression, although it  is  perfectly
       acceptable to create a symbol with such name.

       # create a perimeter method
       trans Circle:perimeter nil (
         * (* 2.0 Circle:PI) this:radius)
       # call the method with our circle
       trans p (c:perimeter)

       It  must  be  clear  that  the  perimeter  symbol  defines  a  method at the class level. It is perfectly
       acceptable to define a methods at the instance level. Such method is called a specialized method.

       Miscellaneous features

       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:iterator)
         trans v-it   (v: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 exception model 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 implementation.  An exception is thrown with the special form 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  special form 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)

       The special symbol what stores the necessary information about the place that  generated  the  exception.
       Most  of  the  time,  the  qualified  name  what:reason or what:about is used.The only difference is that
       what:about contains the file name  and  line  number  associated  with  the  reason  that  generated  the
       exception.

       Regular Expressions
       A  regular  expression  or  regex  is  an  object  which  is used to match certain text patterns. Regular
       expressions are built implicitly by the parser with the use of the [ and ] characters. Special  class  of
       characters are defined with the help of the $ character. For example, $d is the class of character digits
       as defined by the Unicode consortium. Different regular expression can be grouped by region to be matched
       as indicated in the example below.

       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.

       Delayed evaluation
       The special form delay creates a special object called a promise which  records  the  form  to  be  later
       evaluated.  The  special  form  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)

       Threads
       The interpreter provides a powerful mechanism which allows the concurrent  execution  of  forms  and  the
       synchronization  of  shared objects. The engine provides supports the creation and the synchronization of
       threads with a native object locking mechanism. During the execution,  the  interpreter  wait  until  all
       threads  are completed. A threads is created with the reserved keyword launch. In the presence of several
       threads, 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, the engine 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 (bval) (flag:= bval)
       # run the thread and wait
       const thr (launch (ftest true))
       thr:wait
       assert true flag

       This  example  is  taken from the test suites. It checks that a boolean variable is set in a thread. Note
       the use of the wait method to make sure the thread has completed before checking for the flag  value.  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.

       Asynchronous evaluation
       The special form future creates a special object called a future which is  used  to  evaluate  an  object
       asynchronously.  The  evalution starts with the help of the force special form. The sync special form can
       be used to synchronise with the future.

       trans f (future 1)
       force f

       The interpreter object
       The interpreter can also be seen as an object. As such, it provides several special  symbols  and  forms.
       For  example,  the  symbol  argv is the argument vector. The symbol library is an interpreter method that
       loads a library. A complete description of the interpreter object is made in a special  chapter  of  this
       book.

LITERALS

       This  chapters  covers  in  detail the literals objects used to manipulate numbers and strings. First the
       integer, relatif, real and complex numbers are described. There is a broad range  of  methods  for  these
       three  objects  that  support  numerical  computation. As a second step, string and character objects are
       described. Many examples show the various operations which can be used as  automatic  conversion  between
       one  type  and  another.  Finally, the boolean object is described. These objects belongs to the class of
       literal objects, which are objects that have a string representation. A special literal object  known  as
       regular expression or regex is also described at the end of this chapter.

       Integer number
       The  fundamental  number  representation  is  the Integer. The integer is a 64 bits signed 2's complement
       number. Even when running with a 32 bits machine, the  64  bits  representation  is  used.  If  a  larger
       representation  is  needed, the Relatif object might be more appropriate. The Integer object is a literal
       object that belongs to the number class.

       Integer format
       The default literal format for an integer is  the  decimal  notation.  The  minus  sign  (without  blank)
       indicates a negative number. Hexadecimal and binary notations can also be used with prefix 0x and 0b. The
       underscore character can be used to make the notation more readable.

       const a  123
       trans b -255
       const h  0xff
       const b  0b1111_1111

       Integer  number  are  constructed from the literal notation or by using an explicit integer instance. The
       Integer class offers standard constructors.  The  default  constructor  creates  an  integer  object  and
       initialize  it  to  0.  The  other  constructors  take either an integer, a real number, a character or a
       string.

       const a (Integer)
       const b (Integer 2000)
       const c (Integer "23")

       When the hexadecimal or binary notation is used, care should be taken to avoid a  negative  integer.  For
       example,  0x_8000_0000_0000_0000  is  the smallest negative number. This number exhibits also the strange
       property to be equal to its negation since with 2's complement, there is no positive representation.

       Integer arithmetic
       Standard arithmetic operators are available as built-in operators. The usual addition +, multiplication *
       and division / operate with two arguments. The subtraction - operates with one or two arguments.

       + 3 4
       - 3 4
       - 3
       * 3 4
       / 4 2

       As a built-in object, the Integer object offers various methods for built-in  arithmetic  which  directly
       operates on the object. The following example illustrates these methods.

       trans i 0
       i:++
       i:--
       i:+ 4
       i:= 4
       i:- 1
       i:* 2
       i:/ 2
       i:+= 1
       i:-= 1
       i:*= 2
       i:/= 2

       As  a  side  effect, these methods allows a const symbol to be modified. Since the methods operates on an
       object, they do not modify the state of the symbol. Such methods are called mutable methods.

       const i 0
       i:= 1

       Integer comparison
       The comparison operators works the same. The only difference is that they always return a Boolean result.
       The comparison operators are namely equal ==, not equal !=, less than <, less equal  <=,  greater  >  and
       greater equal >=. These operators take two arguments.

       == 0 1
       != 0 1

       Like  the  arithmetic  methods,  the  comparison operators are supported as object methods. These methods
       return a Boolean object.

       i:=  1
       i:== 1
       i:!= 0

       Integer calculus
       Armed with all these functions, it is possible to develop a battery of functions operating with  numbers.
       As  another  example, we revisit the Fibonacci sequence as demonstrated in the introduction chapter. Such
       example was terribly slow, because of the double recursion. Another  method  suggested  by  Springer  and
       Friedman uses two functions to perform the same job.

       const fib-it (gamma (n acc1 acc2) (
           if (== n 1) acc2 (fib-it (- n 1) acc2 (+ acc1 acc2))))
       const fiboi (gamma (n) (
           if (== n 0) 0 (fib-it n 0 1)))

       This  later  example  is  by  far  much  faster, since it uses only one recursion. Although, it is no the
       fastest way to write it, it is still an elegant way to write complex functions.

       Other Integer methods
       The Integer class offers other convenient methods. The odd-p and even-p are predicates. The mod take  one
       argument and returns the modulo between the calling integer and the argument. The abs methods returns the
       absolute value of the calling integer.

       i:even-p
       i:odd-p
       i:mod 2
       i:= -1
       i:abs
       i:to-string

       The  Integer  object  is a literal object and a number object. As a literal object, the to-string and to-
       literal methods are provided to obtain a string representation for the integer object. Although  the  to-
       string  method  returns  a  string representation of the calling integer, the to-literal method returns a
       parsable string. Strictly speaking for an integer, there is no difference between a string representation
       and a literal representation. However, this is not true for other objects.

       (axi) const i 0x123
       (axi) println (i:to-string)
       291
       (axi) println (i:to-literal)
       291

       As a number object, the integer number can also be represented in hexadecimal format. The to-hexa and to-
       hexa-strign methods are designed to obtained such representation. In the first form, the  to-hexa  method
       return  a literal hexadecimal string representation with the appropriate prefix while the second one does
       not.

       (axi) const i 0x123
       (axi) println (i:to-hexa)
       0x123
       (axi) println (i:to-hexa-string)
       123

       Relatif number
       A relatif or big number is an integer with infinite precision.  The  Relatif  class  is  similar  to  the
       Integer class except that it works with infinitely long number. The relatif notation uses a r or R suffix
       to express a relatif number versus an integer one. The Relatif object is a literal object that belongs to
       the number class. The predicate associated with the Relatif object is relatif-p.

       const a  123R
       trans b -255R
       const c  0xffR
       const d  0b1111_1111R
       const e (Relatif)
       const f (Relatif 2000)
       const g (Relatif "23")

       Relatif operations
       Most  of  the  Integer  class operations are supported by the Relatif object. The only difference is that
       there is no limitation on the number size. This naturally comes with a computational  price.  An  amazing
       example  is  to compute the biggest know prime Mersenne number. The world record exponent is 6972593. The
       number is therefore:

       const i 1R
       const m (- (i:shl 6972593) 1)

       This number has 2098960 digits. You can use the println method if you wish, but you have been warned...

       Real number
       The real class implements the representation for floating point number. The  internal  representation  is
       machine  dependent, and generally follows the double representation with 64 bits as specified by the IEEE
       754-1985 standard for binary floating point arithmetic. All integer operations  are  supported  for  real
       numbers. The Real object is a literal object that belongs to the number class.

       Real format
       The  parser supports two types of literal representation for real number. The first representation is the
       dotted decimal notation. The second notation is the scientific notation.

       const a  123.0 # a positive real
       const b -255.5 # a negative real
       const c  2.0e3 # year 2000.0

       Real number are constructed from the literal notation or by using an explicit  real  instance.  The  Real
       class  offers  standard constructors. The default constructor creates a real number object and initialize
       it to 0.0. The other constructors takes either an integer, a real number, a character or a string.

       Real arithmetic
       The real arithmetic is similar to the integer one. When an integer is added to a real number, that number
       is automatically converted to a real. Ultimately, a pure integer operation might generate a real result.

       + 1999.0 1   # 2000.0
       + 1999.0 1.0 # 2000.0
       - 2000.0 1   # 1999.0
       - 2000.0 1.0 # 1999.0
       * 1000 2.0   # 2000.0
       * 1000.0 2.0 # 2000.0
       / 2000.0 2   # 1000.0
       / 2000.0 2.0 # 1000.0

       Like the Integer object, the Real object has arithmetic built-in methods.

       trans  r 0.0 # 0.0
       r:++       # 1.0
       r:--       # 0.0
       r:+ 4.0    # 4.0
       r:= 4.0    # 4.0
       r:- 1.0    # 3.0
       r:* 2.0    # 8.0
       r:/ 2.0    # 2.0
       r:+= 1.0   # 5.0
       r:-= 1.0   # 4.0
       r:*= 2.0   # 8.0
       r:/= 2.0   # 4.0

       Real comparison
       The comparison operators works as the integer one. As for the other  operators,  an  implicit  conversion
       between an integer to a real is done automatically.

       == 2000 2000   # true
       != 2000 1999   # true

       Comparison methods are also available for the Real object. These methods take either an integer or a real
       as argument.

       r:=  1.0 # 1.0
       r:== 1.0 # true
       r:!= 0.0 # true

       Complex number
       A  complex  number  is  another type of number used to solve compex operations that are not possible with
       rela number. A complex number is made of a real part and  an  imaginary  part.  When  the  rela  part  is
       ommitted,  one  has a pure imginary number. The standard notation is to write the imaginary part with the
       letter i giving a litteral notation that ressembles an arithmetic operation.

       trans z 1.0+1.0i
       trans z (Complex 1.0 1.0)
       trans z "1.0i"

       Complex operations
       Most of the real class operations are supported by the Complex object  including  addition,  substraction
       and multiplication. A special case arises with the square root of negative number.

       A complex example
       One  of  the most interesting point with functional programming language is the ability to create complex
       function. For example let's assume we wish to compute the value at a point x of the  Legendre  polynomial
       of order n. One of the solution is to encode the function given its order. Another solution is to compute
       the function and then compute the value.

       # legendre polynomial order 0 and 1
       const lp-0 (gamma (x) 1)
       const lp-1 (gamma (x) x)
       # legendre polynomial of order n
       const lp-n (gamma (n) (
           if (> n 1) {
             const lp-n-1 (lp-n (- n 1))
             const lp-n-2 (lp-n (- n 2))
             gamma (x) (n lp-n-1 lp-n-2)
             (/ (- (* (* (- (* 2 n) 1) x)
                   (lp-n-1 x))
                 (* (- n 1) (lp-n-2 x))) n)
           } (if (== n 1) lp-1 lp-0)
         ))
       # generate order 2 polynomial
       const lp-2 (lp-n 2)
       # print lp-2 (2)
       println "lp2 (2) = " (lp-2 2)

       Note  that  the computation can be done either with integer or real numbers. With integers, you might get
       some strange results anyway, but it will work. Note also how the closed variable mechanism is  used.  The
       recursion  capture  each  level  of the polynomial until it is constructed. Note also that we have here a
       double recursion.

       Other real methods
       The real numbers are delivered with a battery of functions. These include  the  trigonometric  functions,
       the  logarithm  and couple others. Hyperbolic functions like sinh, cosh, tanh, asinh, acosh and atanh are
       also supported. The square root sqrt method return the square root of the calling  real.  The  floor  and
       ceiling returns respectively the floor and the ceiling of the calling real.

       const r0 0.0       # 0.0
       const r1 1.0       # 1.0
       const r2 2.0       # 2.0
       const rn -2.0      # -2.0
       const rq (r2:sqrt) # 1.414213
       const pi 3.1415926 # 3.141592
       rq:floor           # 1.0
       rq:ceiling         # 2.0
       rn:abs             # 2.0
       r1:log             # 0.0
       r0:exp             # 1.0
       r0:sin             # 0.0
       r0:cos             # 1.0
       r0:tan             # 0.0
       r0:asin            # 0.0
       pi:floor           # 3.0
       pi:ceiling         # 4.0

       Accuracy and formatting
       Real  numbers  are not necessarily accurate, nor precise. The accuracy and precision are highly dependent
       on the hardware as well as the nature of the operation being performed. In any case, never assume that  a
       real  value  is an exact one. Most of the time, a real comparison will fail, even if the numbers are very
       close together. When comparing real numbers, it is preferable to  use  the  ?=  operator.  Such  operator
       result  is  bounded by the internal precision representation and will generally return the desired value.
       The real precision is an interpreter value which is set with the set-absolute-precision method while  the
       get-absolute-precision returns the interpreter precision. There is also a set-relative-precision and get-
       relative-precision  methods  used  for  the  definition  of  relative precision. By default, the absolute
       precision is set to 0.00001 and the relative precision is set to 1.0E-8.

       interp:set-absolute-precision 0.0001
       const r 2.0
       const s (r:sqrt) # 1.4142135
       (s:?= 1.4142)    # true

       Real number formatting is another story. The format method takes a precision argument which indicates the
       number of digits to print for the decimal part. Note that the format command might round  the  result  as
       indicated in the example below.

       const pi 3.1415926535
       pi:format 3  # 3.142

       If additional formatting is needed, the Stringfill-left and fill-right methods can be used.

       const pi  3.1415926535        # 3.1415926535
       const val (pi:format 4)       # 3.1416
       println (val:fill-left '0' 9) # 0003.1416

       Number object
       The  Integer,  Relatif and Real objects are all derived from the Number object which is a Literal object.
       As such, the predicate number-p is the right mechanism to test an object for a  number.  The  class  also
       provides  the  basic mechanism to format the number as a string. For integer and relatif, the hexadecimal
       representation can be obtained by the to-hexa and to-hexa-string methods. For integer and  real  numbers,
       the format method adjusts the final representation with the precision argument as indicated before. It is
       worth to note that a formatted integer gets automatically converted into a real representation.

       Character
       The Character object is another built-in object. A character is internally represented by a quad by using
       a 31 bit representation as specified by the Unicode standard and ISO 10646.

       Character format
       The  standard  quote  notation  is  used  to  represent  a  character.  In  that respect, there is hare a
       substantial difference with other functional language where the quote protect a form.

       const LA01 'a' # the character a
       const ND10 '0' # the digit 0

       All characters from the Unicode  codeset  are  supported  by  the   AFNIX   engine.  The  characters  are
       constructed  from  the  literal  notation or by using an explicit character instance. The Character class
       offers standard constructors. The default constructor creates a null character.  The  other  constructors
       take  either  an  integer, a character or a string. The string can be either a single quoted character or
       the literal notation based on the U+ notation in hexadecimal. For example, U+40 is the @ character  while
       U+3A3 is the sigma capital letter Σ.

       const nilc (Character)        # null character
       const a    (Character 'a')    # a
       const 0    (Character 48)     # 0
       const mul  (Character "*")    # *
       const div  (Character "U+40") # @

       Character arithmetic
       A  character  is  like  an  integer,  except that it operates in the range 0 to 0x7FFFFFFF. The character
       arithmetic is simpler compared to the integer one and no overflow or underflow  checking  is  done.  Note
       that the arithmetic operations take an integer as an argument.

       + 'a' 1 # 'b'
       - '9' 1 # '8'

       Several  Character  object  methods  are  also provided for arithmetic operations in a way similar to the
       Integer class.

       trans  c 'a' # 'a'
       c:++         # 'b'
       trans  c '9' # '9'
       c:--         # '8'
       c:+ 1        # '9'
       c:- 9        # '0'

       Character comparison
       Comparison operators are also working with the Character object. The standard operators are namely  equal
       ==,  not  equal  !=, less than <, less equal <=, greater > and greater equal >=. These operators take two
       arguments.

       == 'a' 'b' # false
       != '0' '1' # true

       Other character methods
       The Character object comes with additional methods. These are mostly conversion methods  and  predicates.
       The  to-string  method  returns  a  string representation of the calling character. The to-integer method
       returns an integer representation the calling character. The predicates are  alpha-p,  digit-p,  blank-p,
       eol-p, eos-p and nil-p.

       const LA01 'a'  # 'a'
       const ND10 '0'  # '0'
       LA01:to-string  # "a"
       LA01:to-integer # 97
       LA01:alpha-p    # true
       ND10:digit-p    # true

       String
       The  String  object  is  one  of  the most important built-in object in the  AFNIX  engine. Internally, a
       string is a vector of Unicode characters. Because a string operates with Unicode characters, care  should
       be taken when using composing characters.

       String format
       The standard double quote notation is used to represent literally a string. Standard escape sequences are
       also accepted to construct a string.

       const hello "hello"

       Any literal object can be used to construct a string. This means that integer, real, boolean or character
       objects  are  all  valid  to construct strings. The default constructor creates a null string. The string
       constructor can also takes a string.

       const nils (String)      # ""
       const one  (String 1)    # "1"
       const a    (String 'a')  # "a"
       const b    (String true) # "true"

       String operations
       The String object provides numerous methods and operators. The most common ones are  illustrated  in  the
       example  below.  The  length  methods  returns the total number of characters in the string object. It is
       worth to note that this number is not necessarily the number of printed characters since some  characters
       might  be combining characters used, for example, as diacritics. The non-combining-length method might be
       more adapted to get the number of printable characters.

       const h "hello"
       h:length       # 5
       h:get 0        # 'h'
       h:== "world"   # false
       h:!= "world"   # true
       h:+= " world"  # "hello world"

       The sub-left and sub-right methods return a sub-string, given the position index. For sub-left, the index
       is the terminating index, while sub-right is the starting index, counting from 0.

       # example of sub-left method
       const msg "hello world"
       msg:sub-left  5 # "hello"
       msg:sub-right 6 # "world"

       The strip, strip-left and strip-right are methods used  to  strip  blanks  and  tabs.  The  strip  method
       combines both strip-left and strip-right.

       # example of strip method
       const str " hello world "
       println (str:strip) # "hello world"

       The  split  method  returns a vector of strings by splitting the string according to a break sequence. By
       default, the break sequence is the blank, tab and newline characters. The break sequence can  be  one  or
       more characters passed as one single argument to the method.

       # example of split method
       const str "hello:world"
       const vec (str:split ":" # "hello" "world")
       println (vec:length) # 2

       The  fill-left  and  fill-right  methods  can  be  used to fill a string with a character up to a certain
       length. If the string is longer than the length, nothing happens.

       # example of fill-left method
       const pi  3.1415926535  # 3.1415926535
       const val (pi:format 4) # 3.1416
       val:fill-left '0' 9     # 0003.1416

       Conversion methods
       The case conversion methods are the standard to-upper and to-lower methods. The method operates with  the
       internal  Unicode  database. As a result, the conversion might change the string length. Other conversion
       methods related to the Unicode representation are also available. These are rather technical, but can  be
       used  to  put  the string in a normal form which might be suitable for comparison. Such conversion always
       uses the Unicode database normal form representation.

       # example of case conversion
       const str "hello world"
       println (str:to-upper) # HELLO WORLD

       String hash value
       The hashid method is a method that computes the hash value of a string. The value depends on  the  target
       machine and will change between a 32 bits and a 64 bits machine. Example example 0203.als illustrates the
       computation of a hash value for our favorite test string.

       # test our favorite string
       const hello "hello world"
       hello:hashid # 1054055120

       The algorithm used by the engine is shown as an example below. As a side note, it is recommended to print
       the  shift  amount  in  the  program.  One may notice, that the value remains bounded by 24. Since we are
       xoring the final value, it does illustrate that the algorithm is design for a 32 bits machine. With a  64
       bits  machine  the algorithm is slightly modified to use the extra space. This also means that the hashid
       value is not portable across platforms.

       # compute string hashid
       const hashid (s) {
         const len (s:length)
         trans cnt 0
         trans val 0
         trans sht 17
         do {
           # compute the hash value
           trans i (Integer (s:get cnt))
           val:= (val:xor (i:shl sht))
           # adjust shift index
           if (< (sht:-= 7) 0) (sht:+= 24)
         } (< (cnt:++) len)
         eval val
       }

       Regular expression
       A regular expression or regex is a special literal object designed to describe a character  string  in  a
       compact  form  with  regular  patterns. A regular expression provides a convenient way to perform pattern
       matching and filed extraction within a character string.

       Regex syntax
       A regular expression is defined with a special Regex object. A regular expression can be built implicitly
       or explicitly with the use of the Regex object. The regex syntax uses the [ and  ]  characters  as  block
       delimiters.  When used in a source file, the parser automatically recognizes a regex and built the object
       accordingly. The following example shows two equivalent methods for the same regex expression.

       # syntax built-in regex
       (== [$d+] 2000)         # true
       # explicit built-in regex
       (== (Regex "$d+") 2000) # true

       In its first form, the  [  and  ]  characters  are  used  as  syntax  delimiters.  The  lexical  analyzer
       automatically  recognizes this token as a regex and built the equivalent Regex object. The second form is
       the explicit construction of the Regex object. Note also that the [ and ] characters  are  also  used  as
       regex block delimiters.

       Regex characters and meta-characters
       Any  character,  except  the  one  used as operators can be used in a regex. The $ character is used as a
       meta-character -- or control character -- to represent a  particular  set  of  characters.  For  example,
       [hello  world]  is a regex which match only the "hello world" string. The [$d+] regex matches one or more
       digits. The following meta characters are built-in in the regex engine.
       Character   Description
       $a          matches any letter or digit
       $b          matches any blank characters
       $c          matches any combining alphanumeric
       $d          matches any digit
       $e          matches eol, cr and eos
       $l          matches any lower case letter
       $n          matches eol or cr
       $s          matches any letter
       $u          matches any upper case letter
       $v          matches any valid afnix constituent
       $w          matches any word constituent
       $x          matches any hexadecimal characters

       The uppercase version is the complement of the corresponding lowercase character set.  A character  which
       follows  a  $ character and that is not a meta character is treated as a normal character. For example $[
       is the [ character. A quoted string can be used to define character matching  which  could  otherwise  be
       interpreted as control characters or operator. A quoted string also interprets standard escaped sequences
       but not meta characters.

       (== [$d+]   2000) # true
       (== ["$d+"] 2000) # false

       Combining  alphanumerical  characters  can  generate  surprising  result  when  used with Unicode string.
       Combining alphanumeric characters are alphanumeric characters and non spacing combining mark  as  defined
       by  the Unicode consortium. In practice, the combining marks are the diacritics used with regular letter,
       such like the accents found in the western  languages.  Because  the  writing  system  uses  a  canonical
       decomposition  for  representing  the  Unicode  string, it turns out that the printed string is generally
       represented with more bytes, making the string length longer than it appears.

       Regex character set
       A character set is defined with the < and > characters. Any enclosed character defines a  character  set.
       Note that meta characters are also interpreted inside a character set. For example, <$d+-> represents any
       digit  or  a plus or minus. If the first character is the ^ character in the character set, the character
       set is complemented with regards to its definition.

       Regex blocks and operators
       The [ and ] characters are the regex sub-expressions delimiters. When used at the top level  of  a  regex
       definition, they can identify an implicit object. Their use at the top level for explicit construction is
       optional. The following example is strictly equivalent.

       # simple real number check
       const real-1 (Regex "$d*.$d+")
       # another way with [] characters
       const real-2 (Regex "[$d*.$d+]")

       Sub-expressions  can  be nested -- that's their role -- and combined with operators. There is no limit in
       the nesting level.

       # pair of digit testing
       (== [$d$d[$d$d]+] 2000)  # true
       (== [$d$d[$d$d]+] 20000) # false

       The following unary operators can be used with single character, control characters and sub-expressions.
       Operator   Description
       *          match 0 or more times
       +          match 1 or more times
       ?          match 0 or 1 time
       |          alternation

       Alternation is an operator which work with a secondary expression. Care should be taken when writing  the
       right  sub-expression. For example the following regex [$d|hello] is equivalent to [[$d|h]ello]. In other
       word, the minimal first sub-expression is used when compiling the regex.

       Grouping
       Groups of sub-expressions are created with the ( and ) characters. When a group is matched, the resulting
       sub-string is placed on a stack and can be used later. In this respect, the regex engine can be  used  to
       extract  sub-strings.  The  following  example  extracts  the  month, day and year from a particular date
       format: [($d$d):($d$d):($d$d$d$d)]. This regex assumes a date in the form mm:dd:yyyy.

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

       Grouping is the mechanism to retrieve sub-strings when a match is successful. If the regex is bound to  a
       symbol, the get method can be used to get the sub-string by index.

       Regex object
       Although  a  regex  can  be built implicitly, the Regex object can also be used to build a new regex. The
       argument is a string which is compiled during the object  construction.  A  Regex  object  is  a  literal
       object.  This  means  that  the to-string method is available and that a call to the println special form
       will work directly.

       const   re (Regex "$d+")
       println re           # $d+
       println re:to-string # [$d+]

       Regex operators
       The == and != operators are the primary operators to perform a regex match. The == operator returns  true
       if  the  regex matches the string argument from the beginning to the end of string. Such operator implies
       the begin and end of string anchoring. The < operator returns true if the regex matches the string  or  a
       sub-string or the string argument.

       Regex methods
       The  primary  regex  method is the get method which returns by index the sub-string when a group has been
       matched. The length method returns the number of group match.

       if (== (const re [($d$d):($d$d)]) "12:31") {
         re:length # 2
         re:get 0  # 12
         re:get 1  # 31
       }

       The match method returns the first string which is matched by the regex.

       const regex [$d+]
       regex:match "Happy new year 2000" # 2000

       The replace method any occurrence of the matching string with the string argument.

       const regex [$d+]
       regex:replace "Hello year 2000" "3000" # hello year 3000

       Argument conversion
       The use of the Regex operators implies that the arguments are  evaluated  as  literal  object.  For  this
       reason, an implicit string conversion is made during such operator call. For example, passing the integer
       12  or  the  string "12" is strictly equivalent. Care should be taken when using this implicit conversion
       with real numbers.

CONTAINER OBJECTS

       This chapter covers the standard container objects and more  specifically,  iterable  objects  such  like
       Cons,  List  and  Vector.  Special  objects  like  Fifo,  Queue and Bitset are treated at the end of this
       chapter. Although the name container is sufficient enough to describe the  object  functionality,  it  is
       clear  that  a container is more than a simple object reservoir. In particular, the choice of a container
       object is often associated to the underlying algorithm used to store the object. For example, a vector is
       appropriate when storing by index is important. If the order of storage must be preserved,  then  a  fifo
       object  might  be  more  appropriate.  In  any  case,  the  choice of a container is always a question of
       compromise, so is the implementation.

       Cons object
       Originally, a Cons object or cons cell have been the fundamental object of the Lisp  or  Scheme  machine.
       The  cons  cell  is  the building block for list and is similar in some respect to the cons cell found in
       traditional functional programming language. A Cons object is a simple element used to build linked list.
       The cons cell holds an object and a pointer to the next cons cell. The cons cell object is called car and
       the next cons cell is called the cdr. This original Lisp notation is maintained  here  for  the  sake  of
       tradition.  Although  a  cons cell is the building block for single linked list, the cell itself is not a
       list object. When a list object is needed, the List double linked list object might be more appropriate.

       Cons cell constructors
       The default constructor creates a cons cell those car is initialized to the nil object.  The  constructor
       can also take one or several objects.

       const nil-cons (Cons)
       const lst-cons (Cons 1 'a' "hello")

       The  constructor  can  take  any kind of objects. When all objects have the same type, the result list is
       said to be homogeneous. If all objects do not have  the  same  type,  the  result  list  is  said  to  be
       heterogeneous.  List  can  also be constructed directly by the parser. Since all internal forms are built
       with cons cell, the construction can be achieved by simply protecting the form from being interpreted.

       const blist (protect ((1) ((2) ((3)))))

       Cons cell methods
       A Cons object provides several methods to access the car and the cdr of a cons cell. Other methods allows
       access to a list by index.

       const c (Cons "hello" "world")
       c:length   # 2
       c:get-car  # "hello"
       c:get-cadr # "world"
       c:get 0    # "hello"
       c:get 1    # "world"

       The set-car method set the car of the cons cell. The add method adds a new cons cell at the  end  of  the
       cons list and set the car with the specified object.

       List object
       The  List  object  provides  the  facility  of  a double-link list. The List object is another example of
       iterable object. The List object provides support for forward and backward iteration.

       List construction
       A list is constructed like a cons cell with zero or more arguments. Unlike the cons cell,  the  List  can
       have a null size.

       const nil-list (List)
       const dbl-list (List 1 'a' "hello")

       List methods
       The  List  object  methods  are  similar the Cons object. The add method adds an object at the end of the
       list. The insert method inserts an object at the beginning of the list.

       const list (List "hello" "world")
       list:length      # 2
       list:get 0       # "hello"
       list:get 1       # "world"
       list:add "folks" # "hello" "world" "folks"

       Vector object
       The Vector object provides the facility of an index array  of  objects.  The  Vector  object  is  another
       example of iterable object. The Vector object provides support for forward and backward iteration.

       Vector construction
       A  vector  is  constructed  like  a  cons cell or a list. The default constructor creates a vector with 0
       objects.

       const nil-vector (Vector)
       const obj-vector (Vector 1 'a' "hello")

       Vector methods
       The Vector object methods are similar to the List object. The add method appends an object at the end  of
       the vector. The set method set a vector position by index.

       const vec (Vector "hello" "world")
       vec:length          # 2
       vec:get 0           # "hello"
       vec:get 1           # "world"
       vec:add "folks"     # "hello" "world" "folks"
       vec:set 0 "bonjour" # "bonjour" "world" "folks"

       Set object
       The  Set  object  provides  the  facility  of  an  object container. The Set object is another example of
       iterable object. The Set object provides support for forward iteration. One of the property of a  set  is
       that  there  is  only  one object representation per set. Adding two times the same object results in one
       object only.

       Set construction
       A set is constructed like a vector. The default constructor creates a set with 0 objects.

       const nil-set (Set)
       const obj-set (Set 1 'a' "hello")

       Set methods
       The Set object methods are similar to the Vector object. The add method adds an object in the set. If the
       object is already in the set, the object is not added. The length method returns the number  of  elements
       in the set.

       const set       (Set "hello" "world")
       set:get-size    # 2
       set:add "folks" # "hello" "world" "folks"

       Iteration
       When an object is iterable, it can be used with the reserved keyword for. The for keyword iterates on one
       or  several  objects and binds associated symbols during each step of the iteration process. All iterable
       objects provides also the method iterator which returns an iterator  for  a  given  object.  The  use  of
       iterator is justified during backward iteration, since for only perform forward iteration.

       Function mapping
       Given a function func, it is relatively easy to apply this function to all objects of an iterable object.
       The  result  is  a list of successive calls with the function. Such function is called a mapping function
       and is generally called map.

       const map (obj func) {
         trans result (Cons)
         for (car) (obj) (result:link (func car))
         eval result
       }

       The link method differs from the add method in the sense that the object to append is  set  to  the  cons
       cell car if the car and cdr is nil.

       Multiple iteration
       Multiple  iteration can be done with one call to for. The computation of a scalar product is a simple but
       illustrative example.

       # 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
       }

       Note that the function scalar-product does not make any assumption about the object to iterate. One could
       compute the scalar product between a vector a list for example.

       const u (Vector 1 2 3)
       const v (List   2 3 4)
       scalar-product u v

       Conversion of iterable objects
       The use of an iterator is suitable for direct conversion between one object and another.  The  conversion
       to a vector can be simply defined as indicted below.

       # convert an iterable object to a vector
       const to-vector (obj) {
         trans result (Vector)
         for (i) (obj) (result:add i)
         eval result
       }

       Explicit iterator
       An  explicit  iterator is constructed with the iterator method. At construction, the iterator is reset to
       the beginning position. The get-object method returns the object at the current  iterator  position.  The
       next  advances the iterator to its next position. The valid-p method returns true if the iterator is in a
       valid position. When the iterator supports backward operations, the prev method move the iterator to  the
       previous  position.  Note that Cons objects do not support backward iteration. The begin method reset the
       iterator to the beginning. The end method moves the iterator the last position. This method is  available
       only with backward iterator.

       # reverse a list
       const reverse-list (obj) {
         trans result (List)
         trans itlist (obj:iterator)
         itlist:end
         while (itlist:valid-p) {
           result:add (itlist:get-object))
         itlist:prev
       }
       eval result
       }

       Special Objects
       The  engine  incorporates  other  container objects. To name a few, such objects are the Queue, Bitset or
       Fifo objects.

       Queue object
       A queue is a special object which acts as container with a fifo policy. When an object is placed  in  the
       queue,  it remains there until it has been dequeued. The Fifo and Queue objects are somehow similar, with
       the fundamental difference that the queue is a blocking.

       # create a queue with objects
       const q (Queue 2)
       q:push "hello"
       q:push "world"
       q:empty-p # false
       q:length  # 2
       # dequeue some object
       q:pop # hello
       q:pop # world
       q:empty-p # true

       Bitset object
       A bit set is a special container for bit. A bit set can be constructed with a specific size. When the bit
       set is constructed, each bit can be marked and tested by index. Initially, the bitset size is null.

       # create a bit set by size
       const bs (Bitset 8)
       bitset-p bs # true
       # check, mark and clear
       assert false (bs:marked-p 0)
       bs:mark 0
       assert true  (bs:marked-p 0)
       bs:clear 0
       assert false (bs:marked-p 0)

CLASSES

       This chapter covers the class model and its associated operations. The class model is slightly  different
       compared  to  traditional  one  because  dynamic symbol bindings do not enforce to declare the class data
       members. A class is an object which can be manipulated by itself. Such class is  said  to  belongs  to  a
       group  of  meta  class  as described later in this chapter. Once the class concept has been detailed, the
       chapter moves to the concept of instance of that class and shows how instance data members and  functions
       can be used. The chapter terminates with a description of dynamic class programming.

       Class object
       A  class  object  is  simply  a  nameset which can be replicated via a construction mechanism. A class is
       created with the special form class. The result is an object of type Class which supports various  symbol
       binding operations.

       Class declaration and bindings
       A  new  class  is an object created with the reserved keyword class. Such class is an object which can be
       bound to a symbol.

       const Color (class)

       Because a class acts like a nameset, it is possible to bind directly  symbols  with  the  qualified  name
       notation.

       const Color (class)
       const Color:RED-FACTOR   0.75
       const Color:BLUE-FACTOR  0.75
       const Color:GREEN-FACTOR 0.75

       When  a  data  is  defined in the class nameset, it is common to refer it as a class data member. A class
       data member is invariant over the instance of that class. When the data member is declared with the const
       reserved keyword, the symbol binding is in the class nameset.

       Class closure binding
       A lambda or gamma expression can be define for a class. If the class do not reference an instance of that
       class, the resulting closure is called a class method of that class. Class methods  are  invariant  among
       the class instances. The standard declaration syntax for a lambda or gamma expression is still valid with
       a class.

       const Color:get-primary-by-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
       }

       The invocation of a class method is done with the standard qualified name notation.

       Color:get-primary-by-string "red"   "#23c4e5"
       Color:get-primary-by-string "green" "#23c4e5"
       Color:get-primary-by-string "blue"  "#23c4e5"

       Class symbol access
       A  class acts as a nameset and therefore provides the mechanism to evaluate any symbol with the qualified
       name notation.

       const Color:RED-VALUE "#ff0000"
       const Color:print-primary-colors (color) {
         println "red   color " (
           Color:get-primary-color "red"   color)
         println "green color " (
           Color:get-primary-color "green" color)
         println "blue  color " (
           Color:get-primary-color "blue"  color)
       }
       # print the color components for the red color
       Color:print-primary-colors Color:RED-VALUE

       Instance
       An instance of a class is an object which is constructed by a special class method called a  constructor.
       If  an  instance  constructor  does  not  exist,  the instance is said to have a default construction. An
       instance acts also as a nameset. The only difference with a class, is that a symbol  resolution  is  done
       first  in  the instance nameset and then in the instance class. As a consequence, creating an instance is
       equivalent to define a default nameset hierarchy.

       Instance construction
       By default, a instance of the class is an object which defines an instance nameset. The simplest  way  to
       define an anonymous instance is to create it directly.

       const i     ((class))
       const Color (class)
       const red   (Color)

       The  example above define an instance of an anonymous class. If a class object is bound to a symbol, such
       symbol can be used to create an instance of that class. When an instance is created, the  special  symbol
       named  this  is defined in the instance nameset. This symbol is bounded to the instance object and can be
       used to reference in an anonymous way the instance itself.

       Instance initialization
       When an instance is created, the engine looks for a special lambda expression called preset. This  lambda
       expression,  if  it  exists,  is  executed  after  the default instance has been constructed. Such lambda
       expression is a method since it can refer to  the  this  symbol  and  bind  some  instance  symbols.  The
       arguments which are passed during the instance construction are passed to the preset method.

       const Color (class)
       trans Color:preset (red green blue) {
         const this:red   (Integer red)
         const this:green (Integer green)
         const this:blue  (Integer blue)
       }
       # create some default colors
       const Color:RED   (Color 255   0   0)
       const Color:GREEN (Color   0 255   0)
       const Color:BLUE  (Color   0   0 255)
       const Color:BLACK (Color   0   0   0)
       const Color:WHITE (Color 255 255 255)

       In  the example above, each time a color is created, a new instance object is created. The constructor is
       invoked with the this symbol bound to the newly created instance. Note that the qualified  name  this:red
       defines  a  new  symbol  in  the  instance nameset. Such symbol is sometimes referred as an instance data
       member. Note as well that there is no ambiguity in resolving the symbol red. Once the symbol is  created,
       it shadows the one defined as a constructor argument.

       Instance symbol access
       An  instance  acts as a nameset. It is therefore possible to bind locally to an instance a symbol. When a
       symbol needs to be evaluated, the instance nameset is searched first. If the symbol  is  not  found,  the
       class  nameset  is  searched. When an instance symbol and a class symbol have the same name, the instance
       symbol is said to shadow the class symbol. The simple example below illustrates this property.

       const c   (class)
       const c:a 1
       const i   (c)
       const j   (c)
       const i:a 2
       # class symbol access
       println   c:a
       # shadow symbol access
       println   i:a
       # non shadow access
       println   j:a

       When the instance is created, the special symbol meta is bound in the instance nameset with the  instance
       class object. This symbol can therefore be used to access a shadow symbol.

       const c   (class)
       const i   (c)
       const c:a 1
       const i:a 2
       println   i:a
       println   i:meta:a

       The  symbol  meta  must  be  used carefully, especially inside an initialization since it might create an
       infinite recursion as shown below.

       const c (class)
       trans c:preset nil (const i (this:meta))
       const i (c)

       Instance method
       When lambda expression is defined within the class or the instance nameset,  that  lambda  expression  is
       callable  from  the instance itself. If the lambda expression uses the this symbol, that lambda is called
       an instance method since the symbol this is defined in the instance nameset. If the  instance  method  is
       defined in the class nameset, the instance method is said to be global, that is, callable by any instance
       of  that  class. If the method is defined in the instance nameset, that method is said to be local and is
       callable by the instance only. Due to the nature of the nameset parent binding,  only  lambda  expression
       can  be used. Gamma expressions will not work since the gamma nameset has always the top level nameset as
       its parent one.

       const Color (class)
       # class constructor
       trans Color:preset (red green blue) {
         const this:red   (Integer red)
         const this:green (Integer green)
         const this:blue  (Integer blue)
       }
       const Color:RF 0.75
       const Color:GF 0.75
       const Color:BF 0.75
       # this method returns a darker color
       trans Color:darker nil {
         trans lr (Integer (max (this:red:*   Color:RF) 0))
         trans lg (Integer (max (this:green:* Color:GF) 0))
         trans lb (Integer (max (this:blue:*  Color:BF) 0))
         Color lr lg lb
       }
       # get a darker color than yellow
       const yellow      (Color 255 255 0)
       const dark-yellow (yellow:darker)

       Instance operators
       Any operator can be defined at the class or the  instance  level.  Operators  like  ==  or  !=  generally
       requires  the  ability to assert if the argument is of the same type of the instance. The global operator
       == will return true if two classes are the same. With the use of the  meta  symbol,  it  is  possible  to
       assert such equality.

       # this method checks that two colors are equals
       trans Color:== (color) {
         if (== Color color:meta) {
           if (!= this:red   color:red)   (return false)
           if (!= this:green color:green) (return false)
           if (!= this:blue  color:blue)  (return false)
           eval true
         } false
       }
       # create a new yellow color
       const  yellow (Color 255 255 0)
       (yellow:== (Color 255 255 0)) # true

       The  global  operator  == returns true if both arguments are the same, even for classes. Method operators
       are left open to the user.

       Complex number example
       As a final example, a class simulating  the  behavior  of  a  complex  number  is  given  hereafter.  The
       interesting  point  to  note  is  the  use of the operators. As illustrated before, the class uses uses a
       default method method to initialize the data members.

       # class declaration
       const Complex (class)
       # constructor
       trans Complex:preset (re im) {
         trans this:re (Real re)
         trans this:im (Real im)
       }

       The constructor creates a complex object with the help of the real  part  and  the  imaginary  part.  Any
       object type which can be bound to a Real object is acceptable.

       # class mutators
       trans Complex:set-re (x) (trans this:re (Real re))
       trans Complex:set-im (x) (trans this:im (Real im))
       # class accessors
       trans Complex:get-re nil (Real this:re)
       trans Complex:get-im nil (Real this:im)

       The accessors and the mutators simply provides the interface to the complex number components and perform
       a cloning of the calling or returned objects.

       # complex number module
       trans Complex:module nil {
         trans result (Real (+ (* this:re this:re)
             (* this:im this:im)))
         result:sqrt
       }
       # complex number formatting
       trans Complex:format nil {
         trans result (String this:re)
         result:+= "+i"
         result:+= (String this:im)
       }

       The module and format are simple methods. Note the the complex number formatting is arbitrary here.

       # complex predicate
       const complex-p (c) (
         if (instance-p c) (== Complex c:meta) false)

       The  complex-p  predicate is the perfect illustration of the use of the meta reserved symbol. However, it
       shall be noted that the meta-comparison is done if and only if the calling argument is an instance.

       # operators
       trans Complex:== (c) (
         if (complex-p c) (and (this:re:== c:re)
           (this:im:== c:im)) (
           if (number-p c)  (and (this:re:== c)
             (this:im:zero-p)) false))
       trans Complex:= (c) {
         if (complex-p c) {
           this:re:= (Real c:re)
           this:im:= (Real c:im)
           return this
         }
         this:re:= (Real c)
         this:im:= 0.0
         return this
       }
       trans Complex:+ (c) {
         trans result (Complex this:re this:im)
         if (complex-p c) {
           result:re:+= c:re
           result:im:+= c:im
           return result
         }
         result:re:+= (Real c)
         eval result
       }

       The operators are a little tedious to write. The comparison can be done with a complex number or a built-
       in number object. The assignation operator creates a copy for both  the  real  and  imaginary  part.  The
       summation operator is given here for illustration purpose.

       Inheritance
       Inheritance is the mechanism by which a class or an instance inherits methods and data member access from
       a  parent object. The class model is based on a single inheritance model. When an instance object defines
       a parent object, such object is called a super instance. The instance  which  has  a  super  instance  is
       called  a  derived instance. The main utilization of inheritance is the ability to reuse methods for that
       super instance.

       Derivation construction
       A derived object is generally defined within the preset method of that instance by setting the super data
       member. The super reserved keyword is set to nil at the instance construction. The good news is that  any
       object can be defined as a super instance, including built-in object.

       const c (class)
       const c:preset nil {
         trans this:super 0
       }

       In  the  example  above,  an  instance  of  class c is constructed. The super instance is with an integer
       object. As a consequence, the instance is derived from the Integer instance. Another consequence of  this
       scheme is that derived instance do not have to be built from the same base class.

       Derived symbol access
       When  an  instance  is  derived  from  another one, any symbol which belongs to the super instance can be
       access with the use of the super data member. If the super class can evaluate a symbol,  that  symbol  is
       resolved automatically by the derived instance.

       const c       (class)
       const i       (c)
       trans i:a     1
       const j       (c)
       trans j:super i
       println j:a

       When  a symbol is evaluated, a set of search rules is applied. The engine gives the priority to the class
       nameset vs the super instance. As a consequence, a class data member might shadow a super  instance  data
       member. The rule associated with a symbol evaluation can be summarized as follow.
              Look in the instance nameset.
              Look in the class nameset.
              Look in the super instance if it exists.
              Look in the base object.

       Instance re-parenting
       The  ability  to  set dynamically the parent instance make the object model an ideal candidate to support
       instance re-parenting. In this model, a change in the parent instance is automatically reflected  at  the
       instance method call.

       const c (class)
       const i (c)
       trans i:super 0
       println (i:to-string) # 0
       trans i:super "hello world"
       println (i:to-string) # hello world

       In this example, the instance is originally set with an Integer instance parent. Then the instance is re-
       parented with a String instance parent. The call to the to-string method illustrates this behavior.

       Instance re-binding
       The ability to set dynamically the instance class is another powerful feature of the class model. In this
       approach,  the  instance  meta  class can be changed dynamically with the mute method. Furthermore, it is
       also possible to create initially an instance without any class binding, which is later muted.

       # create a point class
       const  point (class)
       # point class
       trans point:preset (x y) {
         trans this:x x
         trans this:y y
       }
       # create an empty instance
       const p (Instance)
       # bind the point class
       p:mute point 1 2

       In this example, when the instance is muted, the preset method is called  automatically  with  the  extra
       arguments.

       Instance inference
       The  ability to instantiate dynamically inferred instance is offered by the instance model. An instance b
       is said to be inferred by the instance a when the instance a is the super instance of the instance b. The
       instance inference is obtained by binding the infer symbol to a class. When an instance of that class  is
       created, the inferred instance is also created.

       # base class A
       const A  (class)
       # inferred class B
       const B  (class)
       const A:infer B
       # create an instance from A
       const  x (A)
       assert B (x:meta)
       assert A (x:super:meta)

       In  this example, when the instance is created, the inferred instance is also created and returned by the
       instantiation process. The preset method is only called for the inferred instance if possible or the base
       instance if there  is  no  inferring  class.  Because  the  base  preset  preset  method  is  not  called
       automatically, the inferred method is responsible to do such call.

       trans B:preset (x y) {
         trans this:xb x
         trans this:yb y
         if (== A this:super:meta) (this:super:preset x y)
       }

       Because  the  class can mute from one call to another and also the inferred class, the preset method call
       must be used after a discrimination of the meta class has been made as indicated by the above example.

       Instance deference
       In the process of creating instances, one might have a generic class  with  a  method  that  attempts  to
       access  a data member which is bound to another class. The concept of class deference is exactly designed
       for this purpose. With the help of reserved keyword defer, a class with virtual data member accessors can
       be bound to a base class as indicated in the example below.

       # create the base and defer class
       const bc (class)
       const dc (class)
       # bind the base preset method
       trans bc:preset nil (const this:y 2)
       # bind the defer accessor to the base data member
       trans dc:get-y nil (eval this:y)
       # bind the defer class in the base class
       const bc:defer dc
       # create an instance from the base class
       const i (bc)
       # access to the base member with the defer method
       assert 2 (i:get-y)

       It is worth to note that the class deference is made at the class level. When an  instance  of  the  base
       class  is  created,  all methods associated with the deferent class are visible from the base class, thus
       making the deferent class a virtual interface to the base class.

ADVANCED CONCEPTS

       This chapter covers advanced concepts of the writing system. The first subject is  the  exception  model.
       The  second  subject covers some properties of the namesets in the context of the interpreter object. The
       thread sub-system is then described along with the synchronization mechanism. Finally, some notes related
       to the functional system are given at the end of this chapter.

       Exception
       An exception is an unexpected change in the execution flow. The exception model 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.

       Throwing an exception
       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.

       if (not (number-p n))
       (throw "type-error" "invalid object found" n)

       The  example above is the general form to throw an exception. The first argument is the the exception id.
       The second argument is the exception reason. The third argument is the exception object. The exception id
       and reason are always a string. The exception object can be any object which is carried by the exception.
       The reserved keyword throw accepts 0 or more arguments.

       throw
       throw "type-error"
       throw "type-error" "invalid argument"

       With 0 argument, the exception is thrown  with  the  exception  id  set  to  "user-exception".  With  one
       argument, the argument is the exception id. With 2 arguments, the exception id and reason are set. Within
       a  try  block,  an  exception can be thrown again by using the exception object represented with the what
       symbol.

       try {
         ...
       } {
         println "exception caught and re-thrown"
         throw what
       }

       Exception handler
       The special form 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")

       In its second form, the try reserved keyword can accept a second form which is executed when an exception
       is caught. When an exception is caught, a new nameset is created and the special symbol what  is  bounded
       with the exception object. In such environment, the exception can be evaluated.
       Symbol   Description
       eid      Exception id
       name     Exception file name
       line     Exception line number
       about    Exception extended reason
       reason   Exception reason
       object   Exception object

       try (throw "hello")
       (eval what:eid)
       try (throw "hello" "world")
       (eval what:reason)
       try (throw "hello" "world" 2000)
       (eval what:object)

       Exceptions  are useful to notify abruptly that something went wrong. With an untyped language, it is also
       a convenient mechanism to abort an expression call if some arguments do not match the expected types.

       # protected factorial
       const fact (n) {
         if (not (integer-p n))
         (throw "number-error" "invalid argument in fact")
         if (== n 0) 1 (* n (fact (- n 1)))
       }
       try (fact 5) 0
       try (fact "hello") 0

       Nameset
       A nameset is created with the reserved keyword nameset. Without argument, the  nameset  reserved  keyword
       creates  a nameset without setting its parent. With one argument, a nameset is created and the parent set
       with the argument.

       const nset (nameset)
       const nset (nameset ...)

       Default namesets
       When a nameset is created, the symbol . is automatically created and bound to the newly created  nameset.
       If  a  parent nameset exists, the symbol .. is also automatically created. The use of the current nameset
       is a useful notation to resolve a particular name given a hierarchy of namesets.

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

       Nameset and inheritance
       When a nameset is set as the super object of an instance, some interesting results are obtained.  Because
       symbols are resolved in the nameset hierarchy, there is no limitation to use a nameset to simulate a kind
       of multiple inheritance. The following example illustrates this point.

       const   cls (class)
       const   ins (cls)
       const   ins:super (nameset)
       const   ins:super:value 2000
       const   ins:super:hello "hello world "
       println ins:hello ins:value # hello world 2000

       Delayed Evaluation
       The  engine provides a mechanism called delayed evaluation. Such mechanism permits the encapsulation of a
       form to be evaluated inside an object called a promise.

       Creating a promise
       The reserved keyword delay creates a promise. When the promise is created, the associated object  is  not
       evaluated. This means that the promise evaluates to itself.

       const a (delay (+ 1 2))
       promise-p a # true

       The  previous  example creates a promise and store the argument form. The form is not yet evaluated. As a
       consequence, the symbol a evaluates to the promise object.

       Forcing a promise
       The reserved keyword force the evaluation of a promise. Once the promise has  been  forced,  any  further
       call  will produce the same result. Note also that, at this stage, the promise evaluates to the evaluated
       form.

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

       Enumeration
       Enumeration, that is, named constant bound to an object, can be declared with the reserved keyword  enum.
       The enumeration is built with a list of literal and evaluated as is.

       const  e    (enum E1 E2 E3)
       assert true (enum-p e)

       The  complete  enumeration evaluates to an Enum object. Once built, enumeration item evaluates by literal
       and returns an Item object.

       assert true   (item-p e:E1)
       assert "Item" (e:E1:repr)

       Items are comparable objects. Only items can be compared. For a given item, the source enumeration can be
       obtained with the get-enum method.

       # check for item equality
       const i1 e:E1
       const i2 e:E2
       assert true  (i1:== i1)
       assert false (== i1 i2)
       # get back the enumeration
       assert true (enum-p (i1:get-enum))

       Logger
       The Logger class is a message logger that stores messages in a buffer with a level. The default level  is
       the  level  0.  A  negative  level  generally  indicates a warning or an error message but this is just a
       convention which is not enforced by the class. A high level generally indicates a less important message.
       The messages are stored in a circular buffer. When the logger is full, a new message replace  the  oldest
       one. By default, the logger is initialized with a 256 messages capacity that can be re-sized.

       const log    (Logger)
       assert true  (logger-p log)

       When  a  message  is  added,  the message is stored with a time-stamp and a level. The time-stamp is used
       later to format a message. The length method returns the  number  of  logged  messages.  The  get-message
       method  returns  a  message by index. Because the system operates with a circular buffer, the get-message
       method manages the indexes in such way that the old messages are accessible with the  oldest  index.  For
       example,  even after a buffer circulation, the index 0 will point to the oldest message. The get-message-
       level returns the message level and the get-message-time returns the message posted time.

       const mesg (log:get-message 0)

       In term of usage, the logger facility can be conveniently used with other derived classes.  The  standard
       i/o module provides several classes that permits to manage logging operations in a convenient way.

       Interpreter
       The interpreter is by itself a special object with specialized methods which do not have equivalent using
       the  standard  notation. The interpreter is always referred with the special symbol interp. The following
       table is a summary of the symbol bound to the interpreter.
       Symbol          Description
       argv            Command arguments vector
       os-name         Operating system name
       os-type         Operating system type
       version         Full version
       loader          The interpreter loader
       resolver        The interpreter resolver
       afnix-uri       Official uri name
       program-name    Interpreter program name
       big-endian-p    Machine big endian predicate
       64-bits-p-p     Machine size predicate
       major-version   Major version number
       minor-version   Minor version number
       patch-version   Patch version number
       machine-size    The interpreter machine size

       The interpreter provides also special methods which can be used to access internal features that  do  not
       operate  like  standard methods or functions. Some methods are also designed to modify the internal state
       of the interpreter. Note that some methods provide a mechanism to interact at the process level.
       Symbol                   Description
       dup                      duplicate the interpreter
       roll                     run the interpreter loop
       wait                     Wait for normal threads
       load                     Load a file and execute it
       launch                   Launch a normal thread
       daemon                   Launch a daemon thread
       library                  Load and initialize a library
       deserialize              Deserialize an object
       read-line                Get an input stream line
       read-credential          Get an input credential
       get-input-stream         Get interpreter input stream
       get-output-stream        Get interpreter output stream
       get-error-stream         Get interpreter output stream
       wait-kill-signal         Wait for a process signal
       get-primary-prompt       Get primary prompt
       get-secondary-prompt     Get secondary prompt
       set-absolute-precision   Set absolute precision
       set-relative-precision   Set relative precision
       get-absolute-precision   Get absolute precision
       get-relative-precision   Get relative precision

       Arguments vector
       The interp:argv qualified name evaluates to a vector of strings. Each argument is stored  in  the  vector
       during the interpreter initialization.

       zsh> axi hello world
       (axi) println (interp:argv:length) # 2
       (axi) println (interp:argv:get 0)  # hello

       Interpreter version
       Several  symbols  can be used to track the interpreter version and the operating system. The full version
       is bound to the interp:version qualified name. The full version is composed of the major, minor and patch
       number. The operating system name is bound to the qualified name  interp:os-name.  The  operating  system
       type is bound to the interp:os-type.

       println "major number   : " interp:major-version
       println "minor number   : " interp:minor-version
       println "patch number   : " interp:patch-version
       println "version number : " interp:version
       println "system name    : " interp:os-name
       println "system type    : " interp:os-type
       println "official uri   : " interp:afnix-uri

       Method load
       The interp:load method loads and execute a file. The interpreter interactive command session is suspended
       during  the  execution  of the file. In case of error or if an exception is raised, the file execution is
       terminated. The process used to load a file is governed  by  the  file  resolver.  Without  extension,  a
       compiled  file  is  searched  first and if not found a source file is searched. The module is loaded only
       once unless the force flag is used.

       interp:load "module"
       interp:load "module" true
       interp:load "module" "tag" true

       In the first form the module is loaded by name only once. In the second form, the module is loaded with a
       force flag set to true. In the third form, the module is given a tag which is used to detect  whether  or
       not the module has been loaded. If no tag is given, the module name is used instead.

       Method library
       The  interp:library  method  loads  and initializes a library. The interpreter maintains a list of opened
       library. Multiple execution of this method for the same library does  nothing.  The  method  returns  the
       library object.

       interp:library "afnix-sys"
       println "random number: " (afnix:sys:get-random)

       Method dup
       The  interpreter  can  be  duplicated  with  the help of the dup method. Without argument, a clone of the
       current interpreter is made and a terminal object is attached to it. When used in  conjunction  with  the
       roll  method,  this  approach permits to create an interactive interpreter. The dup method also accepts a
       terminal object.

       # duplicate the interpreter
       const si (interp:dup)
       # change the primary prompt
       si:set-primary-prompt "(si)"

       Method roll
       The interpreter loop can be run with the roll. The loop operates by reading the interpreter input stream.
       If the interpreter has been cloned with the help of the dup method, this method provides a convenient way
       to operate in interactive mode. The method is not called loop  because  it  is  a  reserved  keyword  and
       starting a loop is like having the ball rolling.

       # duplicate the interpreter
       const si (interp:dup)
       # loop with this interpreter
       si:roll

       Method wait
       The  interpreter  can wait for all normal threads to complete. When invoked, the interpreter monitors all
       normal threads and wait unil the terminate normally. This is  a  standard  synchronization  method  in  a
       multithreaded environment.

       # create a thread
       launch f
       # wait for completion
       interp:wait

       Librarian object
       A  librarian  file  is  a  special  file that acts as a containers for various files. A librarian file is
       created with the axl -- cross librarian --utility. Once a librarian file is created, it can be  added  to
       the  interpreter  resolver.  The  file  access is later performed automatically by name with the standard
       interpreter load method.

       Creating a librarian
       The axl utility is the preferred way to create a librarian. Given a set of files, axl combines them  into
       a single one.

       zsh: axl -h
       usage: axl [options] [files]
       [h]      print this help message
       [v]      print version information
       [c]      create a new librarian
       [x]      extract from the librarian
       [s]      get file names from the librarian
       [t]      report librarian contents
       [f] lib  set the librarian file name

       The c option creates a new librarian. The librarian file name is specified with the f option.

       zsh: axl -c -f librarian.axl file-1.als file-2.als

       The  previous  command  combines file-1.als and file-2.als into a single file called librarian.axl . Note
       that any file can be included in a librarian.

       Using the librarian
       Once a librarian is created, the interpreter -i option can be used to specify it. The -i  option  accepts
       either  a  directory  name  or a librarian file. Once the librarian has been opened, the interpreter load
       method can be used as usual.

       zsh> axi -i librarian.axl
       (axi) interp:load "file-1.als"
       (axi) interp:load "file-2.als"

       The librarian acts like a file archive. The interpreter file resolver takes care to extract the file from
       the librarian when the load method is invoked.

       Librarian contents
       The axl utility provides the -t and -s options to look at the librarian contents. The -s  option  returns
       all  file  name  in  the  librarian.  The  -t  option returns a one line description for each file in the
       librarian.

       zsh: axl -t -f librarian.axl
       --------       1234 file-1.als
       --------       5678 file-2.als

       The one line report contains the file flags, the file size and the file name. The file flags are not used
       at this time. One possible use in the future is for example, an auto-load bit or any other useful things.

       Librarian extraction
       The -x option permits to extract file from the librarian.  Without  any  file  argument,  all  files  are
       extracted. With some file arguments, only those specified files are extracted.

       zsh: axl -x -f librarian.axl
       zsh: axl -x -f librarian.axl file-1.als

       Librarian object
       The  Librarian  object can be used as a convenient way to create a collection of files or to extract some
       of them.

       Output librarian
       The Librarian object is a standard object. Its predicate is librarian-p. Without argument, a librarian is
       created in output mode. With a string argument, the librarian is opened in input mode, with the file name
       argument. The output mode is used to create a new librarian by adding file into it.  The  input  mode  is
       created to read file from the librarian.

       # create a new librarian
       const lbr (Librarian)
       # add a file into it
       lbr:add "file-1.als"
       # write it
       lbr:write "librarian.axl"

       The  add  method adds a new file into the librarian. The write method the full librarian as a single file
       those name is write method argument.

       Input librarian
       With an argument, the librarian object is created in input mode.  Once  created,  file  can  be  read  or
       extracted.  The  length method -- which also work with an output librarian -- returns the number of files
       in the librarian. The exists-p predicate returns true if the file name argument exists in the  librarian.
       The  get-names  method  returns  a  vector of file names in this librarian. The extract method returns an
       input stream object for the specific file name.

       # open a librarian for reading
       const lbr (Librarian "librarian.axl")
       # get the number of files
       println (lbr:length)
       # extract the first file
       const is (lbr:extract "file-1.als")
       # is is an input stream - dump each line
       while (is:valid-p) (println (is:readln))

       Most of the time, the librarian object is used to extract file dynamically. Because a librarian is mapped
       into the memory at the right offset, there is no worry to use big librarian, even for a small file.  Note
       that any type of file can be used, text or binaries.

       File resolver
       The  file  resolver  is a special object used by the interpreter to resolve file path based on the search
       path. The resolver uses a mixed list of directories and librarian files in its search path. When  a  file
       path  needs  to  be  resolved, the search path is scanned until a matched is found. Because the librarian
       resolution is integrated inside the resolver, there is no need  to  worry  about  file  extraction.  That
       process is done automatically. The resolver can also be used to perform any kind of file path resolution.

       Resolver object
       The resolver object is created without argument. The add method adds a directory path or a librarian file
       to  the resolver. The valid method checks for the existence of a file. The lookup method returns an input
       stream object associated with the object.

       # create a new resolver
       const rslv (Resolver)
       assert true (resolver-p rslv)
       # add the local directory on the search path
       rslv:add "."
       # check if file test.als exists
       # if this is ok - print its  contents
       if (rslv:valid-p "test.als") {
         const is (rslv:lookup "test.als")
         while (is:valid-p) (println (is:readln))
       }

       Thread operations
       The interpreter is a multi-threaded engine with a native implementation of objects locking. A  thread  is
       started  with  the  reserved keyword launch. The execution is completed when all threads have terminated.
       This means that the master thread (i.e the first thread)  is  suspended  until  all  other  threads  have
       completed their execution.

       Starting a thread
       A  thread  is  started with the reserved keyword launch. The form to execute in a thread is the argument.
       The simplest thread to execute is the nil thread.

       launch (nil)

       There exists an alternate mechanism to start a thread with the  reserved  keyword  launch  and  a  thread
       object.  Such  mechanism  is used when using deferred thread object creation or a thread generator object
       known as a thread set.

       Thread object and result
       When a thread terminate, the thread object holds the result of the last executed form. The thread  object
       is  returned  by  the  launch  command.  The  thread-p  predicates returns true if the object is a thread
       descriptor.

       const thr (launch (nil))
       println   (thread-p thr) # true

       The thread result can be obtained with the help of the result method. Although the result can be accessed
       at any time, the returned value will be nil until the thread as completed its execution.

       const thr (launch (nil))
       println   (thr:result)   # nilp

       Although the engine will ensure that the result is nil until the thread has completed its  execution,  it
       does  not  mean  that  it is a reliable approach to test until the result is not nil. The engine provides
       various mechanisms to synchronize a thread and eventually wait for its completion.

       Future object
       The future special form provides a simple mechanism to perform asynchronous  evaluation.  When  a  future
       object  is  created,  the  evaluation  is  pending  a  call to the force special form. When the future is
       complete, the evalution result is available.

       # create a future
       const f (future 1)
       # do not necessarily evaluates to 1
       println (force f)

       Shared objects
       The whole purpose of using a multi-threaded environment is to provide a concurrent  execution  with  some
       shared  variables.  Although,  several  threads  can  execute concurrently without sharing data, the most
       common situation is that one or more global variable are accessed -- and even changed -- by one  or  more
       threads.  Various  scenarios  are  possible.  For example, a variable is changed by one thread, the other
       thread just read its value. Another scenario is one read,  multiple  write,  or  even  more  complicated,
       multiple  read  and  multiple write. In any case, the interpreter subsystem must ensure that each objects
       are in a good state when such operation do  occur.  The  engine  provides  an  automatic  synchronization
       mechanism for global objects, where only one thread can modify an object, but several thread can read it.
       This  mechanism  known  as  read-write  locking  guarantees that there is only one writer, but eventually
       multiple reader. When a thread starts to modify an object, no other thread are allowed to read  or  write
       this  object  until  the  transaction has been completed. On the opposite, no thread is allowed to change
       (i.e. write) an object, until all thread which access (i.e. read) the object  value  have  completed  the
       transaction.  Because a context switch can occur at any time, the object read-write locking will ensure a
       safe protection during each concurrent access.

       Shared protection access
       We illustrate the previous discussion with an interesting example and some variations  around  it.  Let's
       consider a form which increase an integer object and another form which decrease the same integer object.
       If the integer is initialized to 0, and the two forms run in two separate threads, we might expect to see
       the  value  bounded  by  the time allocated for each thread. In other word, this simple example is a very
       good illustration of your machine scheduler.

       # shared variable access
       const var 0
       # increase method
       const incr nil {
         while true (println "increase: " (var:= (+ var 1)))
       }
       # decrease method
       const decr nil {
         while true (println "decrease: " (var:= (- var 1)))
       }
       # start both threads
       launch (decr)
       launch (incr)

       In the previous example, var is initialized to 0. The incr thread increments var while  the  decr  thread
       decrements  var.  Depending on the operating system, the result stays bounded within a certain range. The
       previous example can be changed by using the main thread or a third thread to print the  variable  value.
       The end result is the same, except that there is more threads competing for the shared variable.

       # shared variable access
       const var 0
       # incrementer, decrementer and printer
       const incr nil (while true (var:= (+ var 1)))
       const decr nil (while true (var:= (- var 1)))
       const prtv nil (while true (println "value = " var))
       # start all threads
       launch (decr)
       launch (incr)
       launch (prtv)

       Synchronization
       Although,  there  is  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.

       Form synchronization
       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. In the special case of the form beeing a future,
       the interpreter will block until the future is complete.

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

       The previous example creates 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 tester
       const ftest (bval) (flag:= bval)
       # run the thread and wait
       const thr (launch (ftest true))
       thr:wait
       assert true flag

       This  example  is  taken from the test suites. It checks that a boolean variable is set when started in a
       thread. Note the use of the wait method to make sure the thread has completed  before  checking  for  the
       flag value. 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))

       Complete example
       We illustrate the previous discussion  with  a  complete  example.  The  idea  is  to  perform  a  matrix
       multiplication. A thread is launched when when multiplying one line with one column. The result is stored
       in the thread descriptor. A vector of thread descriptor is used to store the result.

       # initialize the shared library
       interp:library "afnix-sys"
       # shared vector of threads descriptors
       const thr-group (Vector)
       # waits until all threads in the group are finished
       const wait-all nil (for (thr) (thr-group) (thr:wait))

       The group of threads is represented as a vector. Based on the the previous discussion, a simple loop that
       blocks until all threads are completed is designed as a simple gamma expression.

       # initializes a matrix with random numbers
       const init-matrix (n) {
         trans i (Integer 0)
         const m (Vector)
         do {
           trans v (m:add (Vector))
           trans j (Integer)
           do {
             v:add (afnix:sys:get-random)
           } (< (j:++) n)
         } (< (i:++) n)
         eval m
       }

       The  matrix initialization is quite straightforward. The matrix is represented as a vector of lines. Each
       line is also a vector of random integer number. It is here worth to note that the  standard  math  module
       provides a native implementation of real matrix.

       # this procedure multiply one line with one column
       const mult-line-column (u v) {
         assert (u:length) (v:length)
         trans result 0
         for (x y) (u v) (result:+= (* x y))
         eval result
       }
       # this procedure multiply two vectors assuming one
       # is a line and one is a column from the matrix
       const mult-matrix (mx my) {
         for (lv) (mx) {
           assert true (vector-p lv)
           for (cv) (my) {
             assert true (vector-p cv)
             thr-group:add (launch (mult-line-column lv cv))
           }
         }
       }

       The  matrix  vector  multiplication  is  at  the heart of the example. Each line-column multiplication is
       started into a thread and the thread object is placed into the thread group vector.

       # check for some arguments
       # note the use of errorln method
       if (== 0 (interp:argv:length)) {
         errorln "usage: axi 0607.als size"
         afnix:sys:exit 1
       }
       # get the integer and multiply
       const n (Integer (interp:argv:get 0))
       mult-matrix (init-matrix n) (init-matrix n)
       # wait for all threads to complete
       wait-all
       # make sure we have the right number
       assert (* n n) (thr-group:length)

       The main execution is started with the matrix size as the first argument. Two random  matrices  are  then
       created  and  the multi-threaded multiplication is launched. The main thread is blocked until all threads
       in the thread group are completed.

       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 following example shows how the main  thread  blocks  until  another  change  the  state  of  the
       condition.

       # create a condition variable
       const cv (Condvar)
       # this function runs in a thread - does some
       # computation and mark the condition variable
       const do-something nil {
         # do some computation
         ....
         # mark the condition
         cv:mark
       }
       # start some computation in a thread
       launch (do-something)
       # block until the condition is changed
       cv:wait-unlock
       # continue here

       In  this  example, the condition variable is created at the beginning. The thread is started and the main
       thread blocks until the thread change the state of the condition variable. It is important  to  note  the
       use  of the wait-unlock method. When the main thread is re-started (after the condition variable has been
       marked), the main thread owns the lock associated with the condition  variable.  The  wait-unlock  method
       unlocks  that  lock  when  the  main thread is restarted. Note also that the wait-unlock method reset the
       condition variable. if the wait method was used instead of wait-unlock the lock would still be  owned  by
       the  main  thread. Any attempt by other thread to call the mark method would result in the calling thread
       to block until the lock is released. The Condvar class has several methods which can be used  to  control
       the  behavior of the condition variable. Most of them are related to lock control. The reset method reset
       the condition variable. The lock and unlock control the condition variable locking. The  mark,  wait  and
       wait-unlock method controls the synchronization among several threads.

       Function expression
       A  lambda  expression  or  a gamma expression can be seen like a function object with no name. During the
       evaluation process, the expression object is evaluated as well as the arguments -- from left to right  --
       and  a  result is produced by applying those arguments to the function object. An expression can be built
       dynamically as part of the evaluation process.

       (axi) println ((lambda (n) (+n 1)) 1)
       2

       The difference between a lambda expression and a gamma expression is only in the nameset  binding  during
       the  evaluation  process.  The  lambda expression nameset is linked with the calling one, while the gamma
       expression nameset is linked with the top level nameset. The use  of  gamma  expression  is  particularly
       interesting  with  recursive  functions  as it can generate a significant execution speedup. The previous
       example will behaves the same with a gamma expression.

       (axi) println ((gamma (n) (+n 1)) 1)
       2

       Self reference
       When combining a function expression with recursion, the need for the function to call itself is becoming
       a problem since that function expression does not have a  name.  For  this  reason,  the  writing  system
       provides  the  reserved  keyword  self that is a reference to the function expression. We illustrate this
       capability with the well-known factorial expression written in pure functional style.

       (axi) println ((gamma (n)
           (if (<= n 1) 1 (* n (self (- n 1))))) 5)
       120

       The use of a gamma expression versus a lambda expression is a matter of speed. Since the gamma expression
       does not have free variables, the symbol resolution is not a concern here.

       Closed variables
       One of the writing system characteristic is the treatment of free variables. A variable  is  said  to  be
       free  if  it  is  not  bound  in  the  expression  environment  or its children at the time of the symbol
       resolution. For example, the expression ((lambda (n) (+ n x)) 1) computes the sum of the argument n  with
       the  free  variable  x.  The  evaluation  will succeeds if x is defined in one of the parent environment.
       Actually this example can also illustrates the  difference  between  a  lambda  expression  and  a  gamma
       expression. Let's consider the following forms.

       trans x 1
       const do-print nil {
         trans x 2
         println ((lambda (n) (+ n x)) 1)
       }

       The  gamma  expression  do-print  will  produce  3 since it sums the argument n bound to 1, with the free
       variable x which is defined in the calling environment as 2. Now if we rewrite the previous example  with
       a  gamma expression the result will be one, since the expression parent will be the top level environment
       that defines x as 1.

       trans x 1
       const do-print nil {
         trans x 2
         println ((gamma (n) (+ n x)) 1)
       }

       With this example, it is easy to see that there is a need to be able to  determine  a  particular  symbol
       value  during the expression construction. Doing so is called closing a variable. Closing a variable is a
       mechanism that binds into the expression a particular symbol with a value and such  symbol  is  called  a
       closed  variable,  since  its  value is closed under the current environment evaluation. For example, the
       previous example can be rewritten to close the symbol x.

       trans x 1
       const do-print nil {
         trans x 2
         println ((gamma (n) (x) (+ n x)) 1)
       }

       Note that the list of closed variable immediately follow the argument list. In this particular case,  the
       function  do-print  will print 3 since x has been closed with the value 2 has defined in the function do-
       print.

       Dynamic binding
       Because there is a dynamic binding symbol resolution, it is possible to have under some  circumstances  a
       free  or  closed  variable. This kind of situation can happen when a particular symbol is defined under a
       condition.

       lambda (n) {
         if (<= n 1) (trans x 1)
         println (+ n x)
       }

       With this example, the symbol x is a free variable if the argument  n  is  greater  than  1.  While  this
       mechanism can be powerful, extreme caution should be made when using such feature.

       Lexical and qualified names
       The basic forms elements are the lexical and qualified names. Lexical and qualified names are constructed
       by  the  parser.  Although the evaluation process make that lexical object transparent, it is possible to
       manipulate them directly.

       (axi) const sym (protect lex)
       (axi) println   (sym:repr)
       Lexical

       In this example, the protect reserved keyword is used to avoid the evaluation of the lexical object named
       lex. Therefore the symbol sym refers to a lexical object. Since a lexical -- and a qualified -- object is
       a also a literal object, the println reserved function will work and print the object name.  In  fact,  a
       literal object provides the to-string method that returns the string representation of a literal object.

       (axi) const sym (protect lex)
       (axi) println   (sym:to-string)
       lex

       Symbol and argument access
       Each  nameset  maintains  a  table  of  symbols.  A  symbol  is  a  binding between a name and an object.
       Eventually, the symbol carries the const flag. During the lexical evaluation process, the lexical  object
       tries  to  find  an  object  in the nameset hierarchy. Such object can be either a symbol or an argument.
       Again, this process is transparent, but can be controlled manually.  Both  lexical  and  qualified  named
       object have the map method that returns the first object associated in the nameset hierarchy.

       (axi) const obj 0
       (axi) const lex (protect obj)
       (axi) const sym (lex:map)
       (axi) println   (sym:repr)
       Symbol

       A  symbol  is also a literal object, so the to-string and to-literal methods will return the symbol name.
       Symbol methods are provided to access or modify the symbol values. It is  also  possible  to  change  the
       const symbol flag with the set-const method.

       (axi) println (sym:get-const)
       true
       (axi) println (sym:get-object)
       0
       (axi) sym:set-object true
       (axi) println (sym:get-object)
       true

       A  symbol  name  cannot be modified, since the name must be synchronized with the nameset association. On
       the other hand, a symbol can be explicitly constructed. As any object, the =  operator  can  be  used  to
       assign a symbol value. The operator will behaves like the set-object method.

       (axi) const sym (Symbol "symbol")
       (axi) println sym
       symbol
       (axi) sym:= 0
       (axi) println (eval sym)
       0

       Closure
       As  an  object,  the  Closure  can be manipulated outside the traditional declarative way. A closure is a
       special object that holds an argument list, a set of closed variables and a form to execute. The mechanic
       of a closure evaluation has been described earlier. What  we  are  interested  here  is  the  ability  to
       manipulate a closure as an object and eventually modify it. Note that by default a closure is constructed
       as  a  lambda  expression. With a boolean argument set to true the same result is obtained. With false, a
       gamma expression is created.

       (axi) const f (Closure)
       (axi) println (closure-p f)
       true

       This example creates an empty closure. The default closure is equivalent to the trans f nil nil. The same
       can be obtained with const f (Closure true). For a gamma expression, the following forms are  equivalent,
       const  f  (Closure  false)  and  const  f nil nil. Remember that it is trans and const that differentiate
       between a lambda and a gamma expression. Once the closure object is defined, the set-form method  can  be
       used to bind a form.

       # the simple way
       trans f nil (println "hello world")
       # the complex way
       const f    (Closure)
       f:set-form (protect (println "hello world"))

       There  are  numerous  situations  where  it  is  desirable  to mute dynamically a closure expression. The
       simplest one is the closure that mute itself based on some context. With the use of self, a new form  can
       be  set  to  the one that is executed. Another use is a mechanism call advice, where some new computation
       are inserted prior the closure execution. Note that appending to a  closure  can  lead  to  some  strange
       results  if  the  existing closure expression uses return special forms. In a multi-threaded environment,
       the ability to change a closure expression is particularly handy. For example a special thread  could  be
       used  to  monitor  some  context.  When  a particular situation develops, that threads might trigger some
       closure expression changes. Note that changing a closure expression does  not  affect  the  one  that  is
       executed. If such change occurs during a recursive call, that change is seen only at the next call.

AFNIX Users Manual                                    AFNIX                                      STD-US-GUIDE(7)