Provided by: afnix_2.1.1-3_i386 bug

NAME

       vol-1 - 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 until the  end  of
       line  are consumed. 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,  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 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:get-iterator)
         trans v-it   (v:get-iterator)
         while (u:valid-p) {
           trans x (u:get-object)
           trans y (v:get-object)
           result:+= (* x y)
           u:next
           v:next
         }
         eval result
       }

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

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

       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 and  real  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

       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 get-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  get-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:get-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 resize itself if needed.

       # create a queue with objects
       const q (Queue "hello" "world")
       q:empty-p # false
       q:length  # 2
       # dequeue some object
       q:dequeue # hello
       q:dequeue # 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 symbols and methods bound to the
       interpreter.

       Symbol                   Description
       argv                     Command arguments vector
       os-name                  Operating system name
       os-type                  Operating system type
       version                  Full version
       program-name             Interpreter program name
       major-version            Major version number
       minor-version            Minor version number

       patch-version            Patch version number
       afnix-uri                Official uri name
       load                     Load a file and execute it
       launch                   Launch a normal thread
       library                  Load and initialize a library
       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

       File loading
       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.

       Library loading
       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)

       Interpreter duplication
       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)"

       Interpreter loop
       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

       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.

       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.

       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.