This is librep.info, produced by makeinfo version 4.2 from librep.texi.

INFO-DIR-SECTION Programming Languages
START-INFO-DIR-ENTRY
* librep: (librep).		A flexible Lisp environment
END-INFO-DIR-ENTRY

   This is Edition 1.2, last updated 8 September 2000, of `The librep
Manual', for librep, Version 0.13.

   Copyright 1999-2000 John Harper.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.


File: librep.info,  Node: Sequencing Structures,  Next: Conditional Structures,  Up: Control Structures

Sequencing Structures
---------------------

   Each of the special forms in this section simply evaluates its
arguments in left-to-right order. The only difference is the result
returned.

   The most widely used sequencing special form is `progn': it
evaluates all its argument forms and returns the computed value of the
last one. Many other control structures are said to perform an
"implicit progn", this means that internally they call `progn' with a
list of forms.

   `progn' in Lisp is nearly analogous to a `begin...end' block in
Pascal; it is used in much the same places--to allow you to evaluate a
sequence of form where only one form was allowed (for example the
"true" clause of an `if' structure).

 - Special Form: progn forms...
     All of the FORMS are evaluated sequentially (from left-to-right),
     the result of the last evaluated FORM is the return value of the
     special form. If no arguments are given to `progn' it returns
     false.

          (progn 'one (+ 1 1) "three")
              => "three"
          
          (progn)
              => ()

 - Macro: prog1 first forms...
     This special form evaluates its FIRST form then performs an
     implicit progn on the rest of its arguments. The result of this
     structure is the computed value of the FIRST form.

          (prog1 'one (+ 1 1) "three")
              => one

 - Macro: prog2 first second forms...
     This is similar to `prog1' except that the evaluation of its
     SECOND form is returned.

     The FIRST form is evaluated, then its SECOND, then it performs an
     implicit progn on the remaining arguments.

          (prog2 'one (+ 1 1) "three")
              => 2


File: librep.info,  Node: Conditional Structures,  Next: Looping Structures,  Prev: Sequencing Structures,  Up: Control Structures

Conditional Structures
----------------------

   Lisp provides a number of conditional constructs, the most complex of
which (`cond') takes a list of conditions, the first of which evaluates
to true has its associated list of forms evaluated. Theoretically this
is the only conditional special form necessary--all others can be
implemented as macros.

 - Macro: if condition true-form else-forms...
     The `if' form is the nearest thing in Lisp to the "if-then-else"
     construct found in most programming languages.

     First the CONDITION form is evaluated, if it returns true the
     TRUE-FORM is evaluated and its result returned. Otherwise the
     result of an implicit progn on the ELSE-FORMS is returned. If
     there are no ELSE-FORMS false is returned.

     Note that one of the TRUE-FORM or the ELSE-FORMS is completely
     ignored--it is not evaluated.

          (if (special-form-p if)
              "`if' is a special form"
            "`if' is not a special form")
              => "`if' is not a special form"

 - Macro: when condition true-forms...
     CONDITION is evaluated, if it is true the result of an implicit
     progn on the TRUE-FORMS is returned, otherwise false is returned.

          (when t
            (message "Pointless")
            'foo)
              => foo

 - Macro: unless condition else-forms...
     This special form evaluates CONDITION, if its computed value is
     true, `()' is returned. Otherwise the ELSE-FORMS are evaluated
     sequentially, the value of the last is returned.

 - Special Form: cond clause...
     The `cond' special form is used to choose between an arbitrary
     number of conditions. Each CLAUSE is a list; the car of which is a
     CONDITION, the cdr is a list of forms to evaluate (in an implicit
     `progn') if the CONDITION evaluates to true.  This means that each
     CLAUSE looks something like:

          (CONDITION BODY-FORMS...)

     and a whole `cond' form looks like:

          (cond
           (CONDITION-1 BODY-FORMS-1...)
           (CONDITION-2 BODY-FORMS-2...)
           ...)

     The CONDITION in each CLAUSE is evaluated in sequence
     (CONDITION-1, then CONDITION-2, ...), the first one which
     evaluates to a true value has an implicit `progn' performed on its
     BODY-FORMS. The value of this `progn' is also the value of the
     `cond' statement.

     If the true CONDITION has no BODY-FORMS the value returned is the
     value of the CONDITION. If none of the clauses has a true
     CONDITION the value of the `cond' statement is false.

     Often you want a "default" clause which has its BODY-FORMS
     evaluated when none of the other clauses are true. The way to do
     this is to add a clause with a CONDITION of `t' and BODY-FORMS of
     whatever you want the default action to be.

          (cond
           ((stringp buffer-list))        ;Clause with no BODY-FORMS
           ((consp buffer-list)
            (setq x buffer-list)          ;Two BODY-FORMS
            t)
           (t                             ;Default clause
            (error "`buffer-list' is corrupted!")))
              => t

 - Macro: case key clauses...
     This special form is similar to `cond', but switches on the result
     of evaluating a single form KEY, checking for equality with a
     number of other values, defined by the CLAUSES. If any of these
     other values is the same as the result of evaluating KEY, then a
     sequence of forms associated with the value is evaluated.

     Each element of the CLAUSES list has the format:

          ((VALUE-1 VALUE-2 ... VALUE-N) FORMS...)

     Each of the values in the car of the clause is tested for equality
     with KEY, using the `eql' function. If any test positively, then
     the associated FORMS are evaluated and the resulting value becomes
     the result of the special form.

     Instead of supplying a list of possible values, it is also
     possible to just specify the symbol `t'. If such a clause is
     encountered, and no other clauses have matched the value of KEY,
     then this clause is assumed to match by default.

     If any of the values in the CLAUSES appear multiply, then the
     behaviour of the construct is undefined.

     Here is an example use of `case':

          (case foo
            ((bar baz)
              (print "It was either bar or baz"))
            ((quux)
              (print "It was quux"))
            (t
              (print "I've no idea what it was...")))

   There are also a number of special forms which combine conditions
together by the normal logical rules.

 - Macro: or forms...
     The first of the FORMS is evaluated, if it is true its value is
     the value of the `or' form and no more of `forms' are evaluated.
     Otherwise this step is repeated for the next member of FORMS.

     If all of the FORMS have been evaluated and none have a true value
     the `or' form evaluates to false.

          (or nil 1 nil (beep))           ;`(beep)' won't be evaluated
              => 1

 - Macro: and forms...
     The first of the FORMS is evaluated. If it is false no more of the
     FORMS are evaluated and false is the value of the `and' statement.
     Otherwise the next member of FORMS is evaluated and its value
     tested. If none of the FORMS are false the computed value of the
     last member of FORMS is returned from the `and' form.

          (and 1 2 nil (beep))            ;`(beep)' won't be evaluated
              => ()
          
          (and 1 2 3)                     ;All forms are evaluated
              => 3

 - Function: not object
     This function inverts the truth value of its argument. If OBJECT
     is true, false is returned, otherwise true is returned.

          (not nil)
              => t
          
          (not t)
              => ()
          
          (not (not 42))
              => t


File: librep.info,  Node: Looping Structures,  Next: Non-Local Exits,  Prev: Conditional Structures,  Up: Control Structures

Looping Structures
------------------

   The `librep' Lisp dialect only has one method of creating looping
control structures--recursion. Any looping construct found in an
imperative language can be represented as a recursive function. For
example the common `while' statement:

     (while CONDITION BODY...)
     ==
     (letrec ((loop (lambda ()
                      (when CONDITION
                        BODY
                        (loop)))))
       (loop))

Each successive iteration of the loop is simply another call to the
function. Also note that the recursive call to the `(loop)' function
occurs in the tail-position of the function. When combined with the
system's ability to eliminate tail-calls (*note Function Call Forms::)
the above example loop has bounded space requirements. This is
important when loops make a large number of iterations.

   Although tail-recursion is the only primitive method of looping, the
language offers a number of looping forms for convenience.

 - Macro: do vars (test expr...) body...
     `do' is an iteration construct; VARS specifies a set of variable
     bindings to be created, how they are initialized and how they are
     updated on each iteration. TEST specifies the termination
     condition of the loop, any EXPR... forms are evaluated immediately
     prior to exiting the `do' construct. The BODY...  forms specify
     the side effecting body of the loop.

     VARS is a list of variable clauses, each of which has the
     structure `(VARIABLE INIT STEP)' where VARIABLE is the name of a
     variable, INIT defines the initial value of its binding, and STEP
     defines how the next value of the binding is computed. An
     alternative form is `(VARIABLE INIT)', in this case the value of
     the binding does not change across loop iterations.

     Each iteration begins by evaluating TEST, if the result is false,
     then the BODY... expressions are evaluated, and the variables
     bound to new locations initialized to the results of evaluating
     the associated STEP forms.

     If the result of evaluating TEST is true then the EXPR... forms
     are evaluated, and the `do' construct returns the value of the
     last EXPR form evaluated.

          (do ((vec (make-vector 5))
               (i 0 (1+ i)))
              ((= i 5) vec)
            (aset vec i i))
          
              => [0 1 2 3 4]

   The "named-let" variant of the `let' form also provides a convenient
looping construct.

 - Macro: let variable bindings body...
     This is the same as the `(let BINDINGS BODY...)' form described in
     *Note Local Variables::, but within the BODY... forms, the symbol
     VARIABLE is bound to a function whose parameters are the bound
     variables defined by BINDINGS and whose body is the sequence of
     forms BODY...

     This means that the body of the `let' may be repeated by invoking
     the function VARIABLE with suitable parameters.

          (let loop ((rest '(1 2 3))
                     (total 0))
            (if (null rest)
                total
              (loop (cdr rest) (+ total (car rest)))))
          
              => 6

   Finally, the imperative `while' form shown at the start of the
section is also provided:

 - Macro: while condition body...
     The CONDITION form is evaluated. If it is true an implicit progn
     is performed on the BODY forms and the whole procedure is repeated.

     This continues until the CONDITION form evaluates to false.  The
     value of every `while' structure that terminates is false.


File: librep.info,  Node: Non-Local Exits,  Next: Continuations,  Prev: Looping Structures,  Up: Control Structures

Non-Local Exits
---------------

   A "non-local exit" is a transfer of control from the current point
of evaluation to a different point (somewhat similar to the
much-maligned `goto' statement in imperative languages).

   Non-local exits can either be used explicitly (`catch' and `throw')
or implicitly (errors).

* Menu:

* Catch and Throw::             Programmed non-local exits
* Function Exits::              Returning values from a function
* Cleanup Forms::               Forms which will always be evaluated
* Errors::                      Signalling that an error occurred


File: librep.info,  Node: Catch and Throw,  Next: Function Exits,  Up: Non-Local Exits

Catch and Throw
...............

   The `catch' and `throw' structures are used to perform explicit
transfers of control. First a `catch' form is used to setup a "tag";
this acts like a label for a `goto' statement.  To transfer control a
`throw' form is then used to transfer to the named tag. The tag is
destroyed and the `catch' form exits with the value provided by the
`throw'.

   In a program this looks like,

     (catch 'TAG
       ;; Forms which may `throw' back to TAG
       ...
       (throw 'TAG VALUE)
       ;; Control has now passed to the `catch',
       ;; no more forms in this progn will be evaluated.
       ...)
         => VALUE

where TAG is the tag to be used (this is normally a symbol) and VALUE
is the result of the `catch' form.

   When a throw actually happens all catches in scope are searched for
one with a tag which is `eq' to the tag in the throw. If more than one
exists the innermost is selected. Now that the catch has been located
the environment is `wound-back' to the catch's position (i.e. local
variables are unbound, cleanup forms executed, unused catches removed,
etc...) and all Lisp constructs between the current point of control
and the catch are immediately exited.

   For example,

     (let
         ((test 'outer))
       (cons (catch 'foo
               (let
                   ((test 'inner))
                 (throw 'foo test)
                 (setq test 'unreachable)))  ;Never reached
             test))
         => (inner . outer)

when the throw executes the second binding of `test' is unwound and the
first binding comes back into effect. For more details on variable
binding see *Note Local Variables::.

   Note that catch tags are _dynamically_ scoped, the thrower does not
have to be within the same lexical scope (this means that you can
`throw' through functions).

 - Macro: catch tag body-forms...
     This special form defines a catch tag which will be accessible
     while the BODY-FORMS are evaluated.

     TAG is evaluated and recorded as the tag for this catch. Next the
     BODY-FORMS are evaluated as an implicit `progn'. The value of the
     `catch' form is either the value of the `progn', or, if a `throw'
     happened, the value specified in the THROW form.

     Before exiting, the tag installed by this form is removed.

 - Function: throw tag #!optional catch-value
     This function transfers the point of control to the catch form
     with a tag which is `eq' to TAG. The value returned by this catch
     form is either CATCH-VALUE or false if CATCH-VALUE is undefined.

     If there is no catch with a tag of TAG an error is signalled and
     the interpreter returns to the top-level of evaluation.

   There are a number of pre-defined throw tags:

`quit'
     Terminate the `librep' interpreter, returning the value of the
     throw (if a number).

`exit'
     Exit the innermost event loop, unless currently in the outermost
     event loop, when control just passes back to the event loop.

`user-interrupt'
     As if a `SIGINT' or `C-c' signal has been received. Control passes
     back to the top-level event loop.

`term-interrupt'
     Triggered when a `SIGTERM' or `SIGHUP' signal is received.  Tries
     to clean up any existing state, then terminates the interpreter.

   Note that it is the event loop that catches these tags. If no event
loop is active (i.e. just in read-eval-print on the console mode), any
uncaught throws will result in termination.


File: librep.info,  Node: Function Exits,  Next: Cleanup Forms,  Prev: Catch and Throw,  Up: Non-Local Exits

Function Exits
..............

   `librep' has no explicit `return' statement, as found in most other
languages. Where a value has to returned from a function before the
function would normally exit, a `catch'/`throw' pair may be used.

   For example:

     (defun foo (x y)
       (catch 'return
          (when (= x 2)
            (throw 'return nil))
          ...


File: librep.info,  Node: Cleanup Forms,  Next: Errors,  Prev: Function Exits,  Up: Non-Local Exits

Cleanup Forms
.............

   It is sometimes necessary ensure that a certain form is _always_
evaluated, even when a non-local exit would normally bypass that form.
The `unwind-protect' special form is used in this case.

 - Macro: unwind-protect body-form cleanup-forms...
     The BODY-FORM is evaluated, if it exits normally the CLEANUP-FORMS
     are evaluated sequentially then the value which the BODY-FORM
     returned becomes the value of the `unwind-protect' form. If the
     BODY-FORM exits abnormally though (i.e. a non-local exit happened)
     the CLEANUP-FORMS are evaluated anyway and the non-local exit
     continues.

   One use of this is to ensure that an opened file is always closed,
for example,

     (catch 'foo
       (unwind-protect
           (let
               ((temporary-file (open-file (make-temp-name) 'write)))
             ;; Use `temporary-file'
             (write temporary-file "A test\n")
             ;; Now force a non-local exit
             (throw 'foo))
         ;; This is the CLEANUP-FORM it will _always_
         ;; be evaluated, despite the `throw'.
         (close temporary-file)))
         => ()


File: librep.info,  Node: Errors,  Prev: Cleanup Forms,  Up: Non-Local Exits

Errors
......

   Errors are a type of non-local exit; when a form can not be evaluated
for some reason an error is normally "signalled". If an error-handler
has been installed for that type of error, control is passed to the
handler for that error, and evaluation continues. If there is no
suitable handler, control is passed back to the innermost input loop
and a suitable error message is printed.

 - Function: signal error-symbol data
     Signals that an error has happened. ERROR-SYMBOL is a symbol
     classifying the type of error, it should have a property
     `error-message' (a string) which is the error message to be
     printed.

     DATA is a list of objects which are relevant to the error -- they
     will be made available to any error-handler or printed with the
     error message otherwise.

          (signal 'void-value '(some-symbol))
              error--> Value as variable is void: some-symbol

 - Variable: debug-on-error
     This variable is consulted by the function `signal'. If its value
     is either `t' or a list containing the ERROR-SYMBOL to `signal' as
     one of its elements, the Lisp debugger is entered.  When the
     debugger exits the error is signalled as normal.

 - Variable: backtrace-on-error
     Similar to `debug-on-error', but if an error is matched, the
     current backtrace is printed to the standard error stream, and
     control continues.

   When you expect an error to occur and need to be able to regain
control afterwards the `condition-case' special form may be used.

 - Macro: condition-case symbol body-form error-handlers...
     `condition-case' evaluates the BODY-FORM with the ERROR-HANDLERS
     in place. If an error occurs and one of the handles matches the
     error, then it is evaluated with the value of SYMBOL set to the
     error information.

     Each of the ERROR-HANDLERS is a list whose car is a symbol
     defining the type of error which this handler catches. The cdr of
     the list is a list of forms to be evaluated in a `progn' if the
     handler is invoked.

     While the forms of the error handler are being evaluated the
     variable SYMBOL is bound to the value `(ERROR-SYMBOL .  DATA)'
     (these were the arguments to the `signal' form which caused the
     error). If SYMBOL is the symbol `nil' (or the empty list `()'),
     then the error information is not available to the handler.

     The special value, the symbol `error', in the car of one of the
     ERROR-HANDLERS will catch _all_ types of errors.

          (condition-case data
              (signal 'file-error '("File not found" "/tmp/foo"))
            (file-error
             data)
            (error
             (setq x z)))         ;Default handler
              => (file-error "File not found" "/tmp/foo")


File: librep.info,  Node: Continuations,  Prev: Non-Local Exits,  Up: Control Structures

Continuations
=============

   Whenever a function is called, there is a control path waiting to
receive the result of the function, e.g. often the form following the
function invocation. This waiting control path is called the
"continuation" of the function, since control will continue down this
path when the called function exits.

   These continuations are usually not paid much thought, but in some
cases it may be useful to be able to directly manipulate the
continuation of a function. For this purpose rep provides the
`call-with-current-continuation' function (often shortened to
`call/cc') that is standard in the Scheme dialect of Lisp.

 - Function: call/cc function
     FUNCTION is a function with a single parameter; it will be
     immediately invoked with this parameter bound to an object
     representing the current continuation (i.e. the control path that
     would be taken after FUNCTION exits).

     The continuation object passed to FUNCTION is itself a function
     accepting a single argument, when called it transfers control to
     the continuation of FUNCTION, as if FUNCTION had returned the
     argument applied to the continuation object.

 - Function: call-with-current-continuation function
     This is an alias for `call/cc'.

   In its simplest form, `call/cc' can mimic the `catch' and `throw'
procedures (*note Catch and Throw::), for example:

     (defun foo (bar)
       (call/cc (lambda (esc)
                  (when (null bar)
                    ;; throws out of the call/cc
                    (esc nil))
                  ;; do something with bar
                  ...

this is roughly equivalent to:

     (defun foo (bar)
       (catch 'tag
         (when (null bar)
           (throw 'tag nil))
         ;; do something with bar
         ...

   This is only half the story--the most powerful feature of `call/cc'
is that since continuations have dynamic extent (that is, no object is
freed until no references to it exist) it is possible to return control
to scopes that have already exited.

   For example, consider the following fragment of a lisp interaction:

     (prog1 (call/cc (lambda (esc)
                       (setq cont esc)))
       (message "foo!"))
         -| foo!
         => #<closure>
     
     cont
         => #<closure>
     
     (cont 10)
         -| foo!
         => 10

The continuation of the `prog1' form is saved into the variable `cont'.
When subsequently called with a single argument, it has exactly the
same effect as the first time that the second form in the `prog1'
construct was evaluated.

Implementation Notes
--------------------

   `call/cc' works by making a copy of the process' entire call stack.
For this reason, it is likely to be less efficient than using the
control structures described in the previous parts of this section.  Of
course, it is much more powerful than the other constructs, so this
often outweighs the slight inefficiency.

   Also note that currently no attempt is made to save or restore the
dynamic state of the Lisp system, apart from variable bindings (both
lexical and special). This means that any `unwind-protect',
`condition-case' or `catch' forms that are active when invoking a
continuation are all ignored.

   Another restriction is that invoking a continuation may not cause
control to pass across a dynamic root (*note Threads::).


File: librep.info,  Node: Threads,  Next: Loading,  Prev: Control Structures,  Up: The language

Threads
=======

   `librep' supports a simple model of multi-threaded programming.
Multiple threads of execution may be created, with control preemptively
being switched between them.

   Unless otherwise noted, all definitions described in this section are
provided by the `rep.threads' module.

* Menu:

* Thread Contexts::
* Creating Threads::
* Deleting Threads::
* Manipulating Threads::
* Mutexes::
* Thread Implementation Notes::


File: librep.info,  Node: Thread Contexts,  Next: Creating Threads,  Up: Threads

Thread Contexts
---------------

   Every thread created by rep is a member of a "thread context", this
context is defined by the current position in the lisp call stack. At
any point in time, only threads which are members of the current
context may be executing.

 - Function: call-with-dynamic-root thunk
     Call the function of zero-parameters THUNK in a new thread
     context. The new context will contain a single thread, that
     executing THUNK.

     The call to `call-with-dynamic-root' will only return once all
     threads in the newly created context have been deleted, or a
     non-local exit causes control to leave forcibly.


File: librep.info,  Node: Creating Threads,  Next: Deleting Threads,  Prev: Thread Contexts,  Up: Threads

Creating Threads
----------------

   The `make-thread' function may be used to create threads that
execute within the current thread context (dynamic root). Each thread
is represented by a lisp object.

 - Function: threadp arg
     Return true if lisp object ARG represents a thread of execution in
     the lisp environment.

 - Function: make-thread thunk #!optional name
     Create and return a new thread of execution; it will initially
     invoke the zero-parameter function THUNK. If the call to THUNK
     returns the thread is automatically deleted.

     If NAME is defined, it is a string naming the current thread.

 - Function: make-suspended-thread #!optional name
     Similar to `make-thread', except that the newly created thread
     will be immediately suspended from running.

 - Function: current-thread
     Returns the currently executing thread. If no threads have been
     created yet in the current dynamic root (i.e. there is a single
     "implicit" thread) then false is returned.

 - Function: all-threads
     Returns a newly-created list containing all threads in the current
     dynamic root. If no threads have been created yet, returns a null
     list.


File: librep.info,  Node: Deleting Threads,  Next: Manipulating Threads,  Prev: Creating Threads,  Up: Threads

Deleting Threads
----------------

   A thread may be deleted by either returning from the function
specified when it was created, or by explicit deletion. Also, the
implicit thread created by the `call-with-dynamic-root' function may be
deleted by exiting from the function called in the new context.

 - Function: thread-delete #!optional thread
     Mark THREAD (or the current thread), as being deleted. It will not
     be switched to in the future. If the current thread is deleted,
     control will be passed to the next runnable thread. Deleting the
     last runnable thread results forces the containing dynamic root to
     be closed.

 - Function: thread-deleted-p thread
     Returns true if THREAD has been deleted.


File: librep.info,  Node: Manipulating Threads,  Next: Mutexes,  Prev: Deleting Threads,  Up: Threads

Manipulating Threads
--------------------

 - Function: thread-yield
     This function may be used to pass control away from the current
     thread if other threads are waiting to run. There is usually no
     need to call this function since running threads will be preempted
     after a period of time.

 - Function: thread-suspend #!optional thread milliseconds
     Mark THREAD (or the current thread) as being suspended. It will
     not be selected until either it has had this status removed, or
     MILLISECONDS milliseconds time has passed.

     Suspending the current thread will pass control to the next
     runnable thread in the same dynamic root. If there are no runnable
     threads, then the interpreter will sleep until the next thread
     becomes runnable.

 - Function: thread-join thread #!optional timeout default-value
     Suspends the current thread until either THREAD has exited, or
     TIMEOUT milliseconds have passed.

     If THREAD exits normally, then the value of the last form it
     evaluated is returned; otherwise DEFAULT-VALUE is returned.

     It is an error to call `thread-join' on a THREAD that is not a
     member of the current dynamic root.

 - Function: thread-wake thread
     Remove the suspended state from thread THREAD. It will then be
     scheduled for execution sometime subsequently, if its dynamic root
     is active.

 - Function: thread-suspended-p thread
     Returns true if THREAD is currently suspended.

   Thread preemption may be forbidden at times, to allow atomic
operations to take place. Each dynamic root has its own "forbid
counter". Only when this counter is zero may the current thread be
preempted.

 - Function: thread-forbid
     Increment the forbid count.

 - Function: thread-permit
     Decrement the forbid count.

 - Macro: without-interrupts #!rest forms
     Evaluate the list of forms FORMS with thread preemption
     temporarily disabled.


File: librep.info,  Node: Mutexes,  Next: Thread Implementation Notes,  Prev: Manipulating Threads,  Up: Threads

Mutual Exclusion Devices
------------------------

   "Mutexes" are lisp objects used to coordinate access to data shared
across multiple threads (where interleaved access would be bad). These
functions are exported by the `rep.threads.mutex' module (*note
Modules::).

 - Function: make-mutex
     Create and return a mutex object. No thread will own the new mutex.

 - Function: mutexp arg
     Return true if ARG is a mutex object.

 - Function: obtain-mutex mutex
     Obtain the mutex MUTEX for the current thread. Will suspend the
     current thread until the mutex is exclusively available.

 - Function: maybe-obtain-mutex mutex
     Attempt to obtain mutex MUTEX for the current thread without
     blocking. Returns true if able to obtain the mutex, false
     otherwise.

 - Function: release-mutex mutex
     Release the mutex object MUTEX (which must have previously been
     obtained by the current thread). Returns true if the mutex has no
     new owner.


File: librep.info,  Node: Thread Implementation Notes,  Prev: Mutexes,  Up: Threads

Thread Implementation Notes
---------------------------

   The threads used by `librep' are _software threads_. This means that
they are currently implemented by manually switching in and out thread
context (i.e. the call stack) as required. There are a number of
disadvantages to this method:

   * blocking I/O blocks _all_ threads, not just the thread doing the
     I/O,

   * only a single processor is used, thereby avoiding any true
     parallelism on multi-processor systems.

The main advantage is the ease of implementation, especially when
retrofitting threads into the previously single-threaded interpreter.


File: librep.info,  Node: Loading,  Next: Compiled Lisp,  Prev: Threads,  Up: The language

Loading
=======

   In Lisp, programs (also called "modules", or "libraries") are stored
in files. Each file is a sequence of Lisp forms (known as "top-level
forms"). Most of the top-level forms in a program will be definitions
(i.e. function, macro or variable definitions) since generally each
library is a system of related functions and variables.

   Before the program can be used it has to be "loaded" into the
editor's workspace; this involves reading and evaluating each top-level
form in the file, i.e. instantiating all function definitions, or
whatever.

* Menu:

* Load Function::               The function which loads programs
* Autoloading::                 Functions can be loaded on reference
* Features::                    Module management functions


File: librep.info,  Node: Load Function,  Next: Autoloading,  Up: Loading

Load Function
-------------

 - Function: load program #!optional no-error no-path no-suffix
     This function loads the file containing the program called PROGRAM;
     first the file is located then each top-level form contained by
     the file is read and evaluated in order.

     Each directory named by the variable `load-path' is searched until
     the file containing PROGRAM is found. In each directory three
     different file names are tried,

       1. PROGRAM with `.jlc' appended to it. Files with a `.jlc'
          suffix are usually compiled Lisp files. *Note Compiled Lisp::.

       2. PROGRAM with `.jl' appended, most uncompiled Lisp programs are
          stored in files with names like this.

       3. PROGRAM with no modifications.

     If none of these gives a result the next directory is searched in
     the same way, when all directories in `load-path' have been
     exhausted and the file still has not been found an error is
     signalled.

     Next the file is opened for reading and Lisp forms are read from it
     one at a time, each form is evaluated before the next form is
     read. When the end of the file is reached the file has been loaded
     and this function returns true.

     The optional arguments to this function are used to modify its
     behaviour,

    NO-ERROR
          When this argument is true no error is signalled if the file
          can not be located. Instead the function returns false.

    NO-PATH
          The variable `load-path' is not used, PROGRAM must point to
          the file from the current working directory.

    NO-SUFFIX
          When true no `.jlc' or `.jl' suffixes are applied to the
          PROGRAM argument when locating the file.

     If a version of the program whose name ends in `.jlc' is older than
     a `.jl' version of the same file (i.e. the source code is newer
     than the compiled version) a warning is displayed and the `.jl'
     version is used.

     If no Lisp file can be found matching PROGRAM, then each directory
     in the variable `dl-load-path' is searched for a `libtool' shared
     library called `PROGRAM.la' (*note Shared Libraries::).

 - Variable: load-filename
     Whilst loading a Lisp library, this variable is bound to the name
     of the file being loaded.

 - Variable: load-path
     A list of strings, each element is the name of a directory which is
     prefixed to the name of a program when Lisp program files are being
     searched for.

          load-path
              => ("/usr/local/lib/rep/1.0/lisp/"
                  "/usr/local/lib/rep/site-lisp/" "")

     The element `""' refers to the current directory, note that
     directory names should have an ending `/' (or whatever) so that
     when concatenated with the name of the file they make a meaningful
     filename.

 - Variable: dl-load-path
     A list of strings defining all directories to search for shared
     libraries.

 - Variable: lisp-lib-directory
     The name of the directory in which the standard Lisp files are
     stored.

          lisp-lib-dir
              => "/usr/local/lib/rep/1.0/lisp/"

 - Variable: after-load-alist
     An association list of elements of the format `(FILE FORMS ...)'.
     When the library FILE is loaded, all FORMS are executed. However,
     note that FILE must _exactly_ match the PROGRAM argument to the
     `load' function.

 - Function: eval-after-load library form
     Arrange for FORM to be evaluated immediately after the Lisp
     library of LIBRARY has been read by the `load' function.  Note
     that LIBRARY must exactly match the PROGRAM argument to `load'.


File: librep.info,  Node: Autoloading,  Next: Features,  Prev: Load Function,  Up: Loading

Autoloading
-----------

   Obviously, not all features of the `librep' environment are always
used. "Autoloading" allows libraries to only be loaded when they are
first required. This speeds up the initialisation process and may save
memory.

   Functions which may be autoloaded have a special form in their
symbol's function cell--an "autoload form". This is a special kind of
closure. When the function call dispatcher finds one of these forms it
loads the program file specified in the form then re-evaluates the
function call. The true function definition will then have been loaded
and therefore the call may proceed as normal.

   Autoload stubs may be created through the `autoload' function.

 - Function: autoload symbol file #!optional is-command
     Installs an autoload form into the symbol SYMBOL. It marks that
     when SYMBOL is called as a function the lisp library FILE should
     be loaded to provided the actual definition of SYMBOL.

   It is not necessary to call the `autoload' function manually.
Simply prefix the definitions of all the functions that may be
autoloaded (i.e. the entry points to your module; _not_ all the
internal functions.) with the magic comment `;;;###autoload'. Then load
the file into the Jade editor and invoke the `add-autoloads' command,
creating all the necessary calls to the autoload function in the
`autoloads.jl' Lisp file (this file which lives in the Lisp library
directory is loaded when the environment is initialised).

`Meta-x add-autoloads'
     Scans the current buffer for any autoload definitions. Functions
     with the comment `;;;###autoload' preceding them have autoload
     forms inserted into the `autoloads.jl' file. Simply save this
     file's buffer and the new autoloads will be used the next time
     Jade is initialised.

     It is also possible to mark arbitrary forms for inclusion in the
     `autoloads.jl' file: put them on a single line which starts with
     the comment `;;;###autoload' call the command.

     The unsaved `autoloads.jl' buffer will become the current buffer.

          ;;;###autoload
          (defun foo (bar)                ;`foo' is to be autoloaded
            ...
          
          ;;;###autoload (setq x y)       ;Form to eval on initialisation

`Meta-x remove-autoloads'
     Remove all autoload forms from the `autoloads.jl' file which are
     marked by the `;;;###autoload' comment in the current buffer.

     The unsaved `autoloads.jl' buffer will become the current buffer.

   XXX these editor commands don't really belong here, but they'll do
for now...


File: librep.info,  Node: Features,  Prev: Autoloading,  Up: Loading

Features
--------

   "Features" correspond to libraries of Lisp code. Each feature is
loaded separately. Each feature has a name, when a certain feature is
required its user asks for it to be present (with the `require'
function), the feature may then be used as normal.

   When a feature is loaded one of the top-level forms evaluated is a
call to the `provide' function. This names the feature and installs it
into the list of present features.

 - Variable: features
     A list of the features currently present (that is, loaded) in the
     current module. Each feature is represented by a symbol. Usually
     the print name of the symbol (the name of the feature) is the same
     as the name of the file it was loaded from, minus any `.jl' or
     `.jlc' suffix.

          features
              => (info isearch fill-mode texinfo-mode lisp-mode xc)

 - Function: featurep feature
     Returns true if the feature FEATURE has been loaded into the
     current module.

 - Function: provide feature
     Adds FEATURE (a symbol) to the list of loaded features. A call to
     this function is normally one of the top-level forms in a file.

          ;;;; maths.jl -- the `maths' library
          
          (provide 'maths)
          ...

 - Function: require feature #!optional file
     Show that the caller is planning to use the feature FEATURE (a
     symbol).  This function will check the `features' variable to see
     if FEATURE is already loaded, if so it will return immediately.

     If FEATURE is not present it will be loaded. If FILE is given it
     specifies the first argument to the `load' function, else the
     print name of the symbol FEATURE is used, with any `.' characters
     replaced by the operating system's directory separator (*note
     Module Loading::).

          ;;;; physics.jl -- the `physics' library
          
          (require 'maths)                ;Need the `maths' library
          (provide 'physics)
          ...

     When called interactively the symbol FEATURE is prompted for.

   Features may also be provided by modules, for more details *Note
Module Loading::.


File: librep.info,  Node: Compiled Lisp,  Next: Datums,  Prev: Loading,  Up: The language

Compiled Lisp
=============

   `librep' contains a Lisp compiler as well as an interpreter; this
takes a Lisp form or program and compiles it into a "byte-code" object.
This byte-code object is a string of characters representing virtual
machine instructions, a vector of constants and some other
meta-information. The system also contains a byte-code interpreter;
this takes the compiled byte-codes and executes them by simulating the
virtual machine. This simulation will have exactly the same effect as
interpreting the original form or program.

   One of the main reasons for compiling programs is to increase their
efficiency. Compiled functions are likely to be more efficient than
interpreted counterparts in all areas (space and time). For example:

     user> (define (fib n) (if (<= n 2) 1 (+ (fib (- n 1)) (fib (- n 2)))))
     user> ,time (fib 30)
     832040
     Elapsed: 17.05572 seconds
     user> ,compile
     user> ,time (fib 30)
     832040
     Elapsed: 1.479007 seconds

--the compiled function is over an order of magnitude faster than the
interpreted version.

* Menu:

* Compilation Functions::       How to compile Lisp programs
* Compiler Declarations::       Hinting to the compiler
* Compilation Tips::            Getting the most out of the compiler
* Disassembly::                 Examining compiled functions


File: librep.info,  Node: Compilation Functions,  Next: Compiler Declarations,  Up: Compiled Lisp

Compilation Functions
---------------------

 - Function: compile-form form
     This function compiles the Lisp form FORM into a byte-code form
     which is returned.

          (compile-form '(setq foo bar))
              => (run-byte-code "F!" [bar foo] 2)

 - Command: compile-function function
     This function replaces the uncompiled body of the function FUNCTION
     (a symbol) with a compiled version, then returns FUNCTION.

 - Command: compile-file file-name
     This function compiles the file called FILE-NAME into a file of
     compiled Lisp forms whose name is FILE-NAME with `c' appended to
     it (i.e. if FILE-NAME is `foo.jl' it will be compiled to
     `foo.jlc').

     If an error occurs while the file is being compiled any
     semi-written file will be deleted.

     When called interactively this function will ask for the value of
     FILE-NAME.

 - Command: compile-directory directory #!optional force exclude
     Compiles all the Lisp files in the directory called DIRECTORY which
     either haven't been compiled or whose compiled version is older
     than the source file (Lisp files are those ending in `.jl').

     If the optional argument FORCE is true _all_ Lisp files will be
     recompiled whatever the status of their compiled version.

     The EXCLUDE argument may be a list of filenames, these files will
     _not_ be compiled.

     When this function is called interactively it prompts for the
     directory.

 - Command: compile-module module-name
     Compiles all uncompiled function definitions in the module named
     MODULE-NAME (a symbol).

     When called interactively the module name will be prompted for.

 - Function: run-byte-code byte-codes constants stack
     Interprets the string of byte instructions BYTE-CODES with the
     vector of constants CONSTANTS.

     This function should _never_ be called by hand. The compiler will
     produce calls to this function when it compiles a form or a
     function.

   There is a second form that byte-code objects can take: a vector
whose read syntax includes a preceding `#' character is a "byte-code
subr". These objects represent compiled Lisp functions and macros.

 - Function: bytecodep arg
     Returns true if ARG is a byte-code subroutine.


File: librep.info,  Node: Compiler Declarations,  Next: Compilation Tips,  Prev: Compilation Functions,  Up: Compiled Lisp

Compiler Declarations
---------------------

   It is often useful to be able to give the compiler extra knowledge
about the program forms that it is compiling. The language includes
special declaration forms that have no effect when interpreted, but are
meaningful to the compiler as it traverses the program.

 - Macro: declare clause...
     Offer the information contained in the CLAUSE... forms to the
     compiler, which it may or may not use when compiling the program.

     Each CLAUSE is a list, the first element of each clause is a
     symbol defining the type of declaration, the interpretation of any
     other elements in the clause depends upon the declaration type.

     The following table lists the syntax of all currently supported
     declaration types:

    `(bound VARIABLES...)'
          This declaration tells the compiler that all symbols VARIABLES
          have lexical bindings for the extent of the current lexical
          scope. This is often useful to prevent spurious compiler
          warnings.

    `(special VARIABLES...)'
          This tells the compiler that all symbols VARIABLES have
          special (dynamic) bindings for the extent of the current
          lexical scope.

          (It is important that the compiler is able to distinguish
          special bindings from lexical bindings, since different
          instruction sequences must be generated to access the
          different types of binding.)

    `(unused VARIABLES...)'
          Directs the compiler not to warn about bindings for
          VARIABLES... being unreferenced.

    `(inline NAMES...)'
          Tells the compiler that it should consider inlining calls to
          the functions called NAMES.... Inlining will only occur if
          these functions are declared in the same module as, and
          after, the declaration itself.

    `(in-module MODULE-NAME)'
          This declaration should occur at the top-level of a program;
          it tells the compiler that the forms in the program will be
          evaluated within the context of the module called MODULE-NAME
          (a symbol).

    `(language MODULE)'
          Explicitly specifies the particular language dialect that the
          current module or file body is written for. Language dialects
          included with the librep distribution include `rep', `scheme'
          and `unscheme'. These are also the names of the modules that
          should be imported to use a particular dialect.

          By default, the `rep' dialect is assumed for code outside
          module definitions. For code inside a module definition the
          list of imported modules is scanned for a known language
          dialect (i.e. if the module imports `rep', then the rep
          language dialect is compiled for).

    `(unsafe-for-call/cc)'
          Tell the compiler that it may register-allocate variables,
          even if it can't prove that doing so wouldn't produce
          incorrect results if `call/cc' causes a function call to
          return more than once (*note Continuations::). This
          declaration applies to the entire file that it occurs in.

          Without this declaration, the compiler will only
          register-allocate bindings if the following conditions are
          met:

             * the binding is not accessed from any inner closures, and,

             * the binding is never modified after being initialized
               (actually, the binding may be modified between being
               intialized and the next function call)

          this declaration is often useful where `call/cc' isn't used,
          and there is a lot of side effecting of local variables.

     Declaration forms always evaluate to false.

   A second type of declaration is the `eval-when-compile' form, it
allows Lisp forms to be evaluated only at compile-time.

 - Macro: eval-when-compile form
     This form tells the system that FORM should only be evaluated when
     the containing code is being compiled.

     The compiler knows to recognize FORMs of the pattern
     `(eval-when-compile (require 'FEATURE))' as marking that FEATURE
     should be imported at compile-time. Any other FORMs are simply
     evaluated in an unspecified environment.

     When interpreted, `eval-when-compile' forms alway evaluate to
     false, when compiled they evaluate to the result of evaluating the
     FORM at compile-time.

