This is Info file icp.info, produced by Makeinfo-1.55 from the input
file prolog.texi.

This file documents the IC Prolog ][ system version 0.96, dated
28 September 1993.

Copyright (C) 1992,1993 Imperial College, London.  All rights reserved.


File: icp.info,  Node: MultiwayCommunication,  Prev: TwowayCommunication,  Up: MbxIntroduction

Multi-way Communication
-----------------------

A link may be established between two mailboxes.  When a message is
sent to the first mailbox, the message is automatically forwarded to
the second mailbox.  Note that the link is uni-directional only -
messages sent directly to the second mailbox will not by forwarded to
the first.  The second mailbox remains an ordinary mailbox while the
first becomes a `linked' mailbox.  Linked mailboxes do not store any
messages, only addresses of links.  A mailbox may be linked to many
mailboxes.  In this case, messages sent to the linked mailbox will
cause a copy of the message to be forwarded to each and every link.
This is how we can configure one-to-many communication.  Note that
there is a distinction between the case where multiple receivers each
receive copies of all messages, and the case where only one of the
multiple receivers receive each message.  In the former case, we can
use linked mailboxes but in the latter case, one mailbox is sufficient.

Many-to-one communication can also be configured by linking multiple
mailboxes to the same mailbox.  Indeed, any arbitrary communication
topology may be built up using links.

If a mailbox is linked to another mailboxes while some messages are
stored in it (waiting to be read), the messages will be kept until the
mailbox is unlinked or closed. If is unlinked, the messages will be
accessible again.


File: icp.info,  Node: MailboxServer,  Next: RestrictedAccess,  Prev: MbxIntroduction,  Up: Mailboxes

Mailbox Server
==============

All the above pre-supposes that a mailbox can be uniquely identified in
a network and can be accessed by all machines on the network.  This can
be guaranteed by ensuring that when a mailbox is created, the
identifier returned is a combination of the process number and the
number of the mailbox in that process.  The process number is allocated
by an external mailbox server program.  Note that the process number is
a generalisation of the machine number since a machine may run many
processes.

When a process requires the use of mailboxes, it first registers with
the mailbox server which allocates a process number to it.  The mailbox
server replies by sending the process numbers and physical network
addresses of all the other registered processes.  It also notifies
existing registered processes that there is a new process.  By keeping
all processes up-to-date with this information, processes may
communicate with each other directly without contacting the mailbox
server again.  The mailbox server does not become a bottleneck in the
system and in fact mailbox communication can continue even if the server
program is terminated.  Of course in this case, any further changes to
the registered process list will not be reflected.

Using a mailbox server, a set of processes can cooperate and
communicate with each other by registering with this server.  The set
of processes is called a MAILBOX GROUP.  A completely different mailbox
group can exist if there is another mailbox server program running.  In
general, there is no limit to the number of mailbox groups.  Each group
is a completely independent system.

* Menu:

* RegisteringMailboxNames::     Registering Mailbox Names


File: icp.info,  Node: RegisteringMailboxNames,  Up: MailboxServer

Registering Mailbox Names
-------------------------

In the model presented above, we can see how it would be possible to
communicate if we know the mailbox identifier.  However the
bootstrapping problem of finding out the relevant identifier still
remains.

If a process is willing to accept incoming communication, it should
create a mailbox and register a name along with the mailbox identifier.
This registration is done by sending a message to the mailbox server
program (the mailbox server has a pre-defined address).  Thereafter,
when another process wishes to talk to the named process, it can query
the mailbox server program for the mailbox identifier.  This is very
similar to telephone directories.  The correspondence between names and
telephone numbers is stored in a telephone directory.  If you do not
know the number, you look up the name.  The mailbox server program
provides this necessary directory lookup service.


File: icp.info,  Node: RestrictedAccess,  Next: StartingMailboxes,  Prev: MailboxServer,  Up: Mailboxes

Restricting Access
==================

Restricted access can be enabled for the mailbox server and individual
mailboxes.  This is implemented in two layers.

The first layer is a user level restriction. At mailbox creation time,
read and write permissions can be defined for the user, group and
others.  The possible values for permissions are `read_write', `read',
`write' and `none'.

The second layer is a process level restriction.  This filters the
processes that pass the first layer. At mailbox creation time, a read
password and/or a write password can be defined and every process
wishing to access the mailbox must supply the correct password.  The
passwords are actually integers.

These restrictions can be used for the mailbox server as well,
restricting the access to the services supplied.


File: icp.info,  Node: StartingMailboxes,  Next: MailboxPrimitives,  Prev: RestrictedAccess,  Up: Mailboxes

Starting Mailboxes
==================

The mailbox server is a standalone program written in C.  To use
mailboxes, there must first be a mailbox server running on the network.
A mailbox server with the mailbox group name of `mbx1' is started in
the background from the Unix command line like this :
             mbx_server mbx1 &
Note that this is run from Unix, not from within Prolog.  A
confirmation message should appear as follows :
             Server [mbx1] started on machine HOSTNAME
where HOSTNAME is the name of the machine on which the mailbox server
is running.  The program runs until it is explicitly killed using
CTRL-C.

The identifier `mbx1' is associated with a particular port number in
the file /etc/services.  If you get the message
             service: mbx1 not found
then /etc/services has not yet been modified.  Please read the
installation procedures on how to do this.  There are four pre-defined
mailbox group names in /etc/services, they are `mbx1', `mbx2', `mbx3'
and `icprolog'.  You may define more if you wish by adding lines to the
/etc/services file.

When starting the server, if you get the message
             error: server is already running or socket is in use
this means that the server is already running for that mailbox group.
If however, you do not wish to participate in an existing mailbox
group, then you should start another server using the identifiers
`mbx2' or `mbx3' instead.


File: icp.info,  Node: MailboxPrimitives,  Prev: StartingMailboxes,  Up: Mailboxes

Mailbox Primitives
==================

The Mailbox primitives described below are available to both Prolog and
Parlog components of the ICP system.

In the short forms of the primitives, the dafault values for the
arguments are user `read_write', group `write' and others `write'
permissions, `0' read password and `0' write password and they supply
`0' as password.

* Menu:

* MbxInit::                     Opening, Modifying and Closing Mailboxes
* MbxIO::                       Reading and Writing from Mailboxes
* MbxMisc::                     Miscellaneous Mailbox Predicates


File: icp.info,  Node: MbxInit,  Next: MbxIO,  Up: MailboxPrimitives

Opening, Modifying and Closing Mailboxes
----------------------------------------

`mbx_init(+ADDRESS, +MAILBOXGROUP)'
     Connects to server MAILBOXGROUP on machine ADDRESS.  This must be
     the first mailbox primitive to be called since this initialises
     the connection.  MAILBOXGROUP is normally one of `mbx1', `mbx2' or
     `mbx3', but it may be any string as long as it is defined in the
     /etc/services file.

`mbx_create(-MBX)'
`mbx_create(-MBX, +USER, +GROUP, +OTHERS, +RPASS, +WPASS)'
     This creates a mailbox, returning its global address as an
     identifier MBX.  For efficiency reasons, it is more natural
     (although not necessary) to create a mailbox on the machine that
     the processes which are going to receive from it are running.

`mbx_close(+MBX)'
`mbx_close(+MBX, +TIMEOUT, +RPASS)'
     This primitive closes the mailbox specified, breaking all the
     links from or to it.

`mbx_link(+MBXI, +MBXO)'
`mbx_link(+MBXI, +RPASS, +MBXO, +WPASS, +TIMEOUT)'
     This links one mailbox (MBXI) to another (MBXO), allowing one to
     one, many to one, one to many or many to many communication.
     Linking a mailbox to itself gives an error.

`mbx_unlink(+MBXI, +MBXO)'
`mbx_unlink(+MBXI, +RPASS, +MBXO, +WPASS, +TIMEOUT)'
     This breaks the link between MBXI  and MBXO.

`mbx_getlinks(+MBX, -LINKS)'
`mbx_getlinks(+MBX, +TIMEOUT, +RPASS , -LINKS)'
     Not implemented yet.  This returns the links of the specified
     mailbox. LINKS is a list with two elements, the first is a list
     with the addresses of mailboxes to which `Mbx' is linked to, and
     the second element is a list with the addresses of mailboxes
     linked to MBX.


File: icp.info,  Node: MbxIO,  Next: MbxMisc,  Prev: MbxInit,  Up: MailboxPrimitives

Reading and Writing from Mailboxes
----------------------------------

`mbx_send(+MBX, ?TERM)'
`mbx_send(+MBX, +FLAG, +TIMEOUT, ?TERM, +WPASS)'
     This sends a term to the mailbox specified by the global address
     MBX.  Sending is asynchronous (and therefore buffering is
     provided).

`mbx_recv(+MBX, -TERM)'
`mbx_recv(+MBX, +FLAG, +TIMEOUT, -TERM, +RPWD?)'
     This reads a term from the mailbox specified by the global address
     MBX.  FLAG specifies whether the message to be received is out of
     band data or normal data. TIMEOUT specifies whether call is in
     `block', `poll' or timeout (TIMEOUT is a number in seconds) mode.
     `block' means that the call will suspend until a message is
     available. `poll' means that if there is no message available, the
     call will fail with TIMEOUT error.  TIMEOUT means that the call
     will suspend for a message for at most the time specified and
     then, if there is no message available, it will fail.  RPWD is an
     integer password for reading the mailbox.

`mbx_look(+MBX, -TERM)'
`mbx_look(+MBX, +FLAG, +TIMEOUT, -TERM, +RPASS)'
     This reads a term from the mailbox MBX.  It is a blocking
     primitive.  A `mbx_look' call does not remove the message read.
     The mailbox is locked after such a call, so any other `mbx_read' or
     `mbx_look' calls suspend until the mailbox is unlocked. The reading
     process is supposed to test the message read and, depending on
     whether it is suitable or not, it should call `mbx_commit' or
     `mbx_discard', both of which unlock the mailbox.  `mbx_commit' or
     `mbx_discard' (whichever is chosen) should be run sequentially
     after `mbx_look', otherwise a SEQUENCE error will occur.

`mbx_commit(+MBX)'
`mbx_commit(+MBX, +FLAG, +TIMEOUT, +RPASS)'
     This unlocks the mailbox MBX removing the message read, so the next
     reader will read a different message.

`mbx_discard(+MBX)'
`mbx_discard(+MBX, +FLAG, +TIMEOUT, +RPASS)'
     This unlocks the mailbox MBX without removing the message read, so
     the next reader will read the same message.

`mbx_check(+MBX)'
`mbx_check(+MBX, +FLAG, +TIMEOUT, +RPASS)'
     This primitive checks whether there is a message available in the
     mailbox specified.  It is a non-blocking primitive.

`mbx_clear(+MBX)'
`mbx_clear(+MBX, +FLAG, +TIMEOUT, +PASS)'
     This removes all the normal data or out of band data kept in the
     specified mailbox.


File: icp.info,  Node: MbxMisc,  Prev: MbxIO,  Up: MailboxPrimitives

Miscellanious Mailbox Predicates
--------------------------------

`mbx_bind(+MBX, +ATOM)'
`mbx_bind(+MBX, +TIMEOUT, +ATOM, +RPASS)'
     This binds a global mailbox address to a global service in the
     mailbox server, making the address accessible to the whole system.
     There can be different services (ATOM) with the same address
     (MBX), but not one service with different addresses.

`mbx_getid(+ATOM, -MBX)'
`mbx_getid(+ATOM, +TIMEOUT, -MBX, +PASS)'
     This returns the global mailbox address associated with the global
     service specified. If the service is not recorded in the internal
     data base, the primitive fails.

`mbx_getname(+MBX, -ATOM)'
`mbx_getname(+MBX, +TIMEOUT, -ATOM, +PASS)'
     This returns the global service associated with the global mailbox
     address specified. If the address is not recorded in the internal
     data base, the primitive fails.

`mbx_initdb(-PTR)'
`mbx_initdb(-PTR, +TIMEOUT)'
     This initializes the internal data base reading pointer, allowing
     sequential access to it using the `mbx_getdb/4'  primitive.
     Returns an identifier for the initialize pointer.

`mbx_getdb(+PTR, -ATOM, -MBX)'
`mbx_getdb(+PTR, +TIMEOUT, -ATOM, -MBX, +RPASS)'
     This returns the global service and the global mailbox address
     associated with it, reading sequentially from the internal data
     base. The next call to this primitive will return the next data
     base entry. PTR is the identifier for the internal data base
     pointer.

`mbx_closedb(+PTR)'
`mbx_closedb(+PTR, +TIMEOUT)'
     It closes the internal data base reading pointer created by
     `mbx_initdb/1'.

The last two primitives always succeed, except when the arguments are
incorrect.


File: icp.info,  Node: Foreign Interface,  Next: Tracer,  Prev: Mailboxes,  Up: Top

Foreign Language Interface
**************************

ICP offers an interface to functions written in the programming language
`C' -- Brian W. Kerninghan and Dennis M. Ritchie, `The C Programming
Language', Prentice-Hall, inc. Currently the calling of `C' functions
from prolog is supported but `C' can not call prolog. In later versions
this support will be provided. Dynamic loading is achieved through the
unix `ld' command.

The arguments of predicates corresponding to `C' functions are
restricted to non complex terms - integers, floats or atoms. The type
of each argument must be specified together with whether it is an input
or output argument. Input arguments must be ground when called, while
output arguments may also be variables. The interface provides the
transformation to and from the internal Prolog representation of the
primitive types and the corresponding `C' representation.

* Menu:

* ForeignPredicates::           Foreign Language Predicates


File: icp.info,  Node: ForeignPredicates,  Up: Foreign Interface

Foreign Language Predicates
===========================

`load_foreign_files(+FILELIST)'
     This is used to load foreign functions into the running prolog
     system.  FILELIST is a list of object files (compiled `C' files).
     The ``tt .o'' extension may be ommited. A single atom (file name)
     is also allowed as a value of FILELIST. The files are searched for
     in the current search path.

`load_foreign_files(+FILELIST, +LINKERARGS)'
     Same as above with the additional parameter LINKERARGS specifying
     a list of arguments to be passed to the unix `ld' command.  This
     is typically used when additional system libraries are required.

     The user defined predicates `foreign_file/2' and `foreign/3' are
     used to specify the prolog predicates and corresponding `C'
     functions.

`foreign_file(-FILE, -FUNCTIONS)'
     FILE is an object (compiled `C') file while FUNCTIONS is a list of
     the `C' function names defined in this file which are to be
     interfaced.

`foreign(+CFUNCTION, +LANGUAGE, +PREDICATESPECIFICATION)'
     CFUNCTION is the name of a `C' function and LANGUAGE is the atom
     `c' (In future languages other than `C' may be supported).
     PREDICATESPECIFICATION describes the form of the prolog predicate
     to be used to access the foreign function. This is a term of the
     form
     PrologName(ARGSPEC1, ..., ARGSPECN)
     Each argument is of one of the following forms

        * +INTEGER The Prolog argument is an integer. The corresponding
          `C' argument type is `long int'.

        * -INTEGER The Prolog argument is an integer or a variable.
          The corresponding `C' argument type is `long int *'.

        * `[-INTEGER]' The Prolog argument is an integer or a variable.
          The corresponding `C' function type is `long int *'.

        * +FLOAT The Prolog argument is a floating point number.  The
          corresponding `C' argument type is `double'.

        * -FLOAT The Prolog argument is a floating point number or a
          variable.  The corresponding `C' argument type is `double *'.

        * `[-FLOAT]' The Prolog argument is a floating point number or
          a variable. The corresponding `C' function type is `long int
          *'.

        * +ATOM The Prolog argument is an atom. The corresponding `C'
          argument type is `char *'.

        * -ATOM The Prolog argument is an atom or a variable.  The
          corresponding `C' argument type is `char **'.

        * `[-ATOM]' The Prolog argument is an atom or a variable. The
          corresponding `C' function type is `char *'.

        * +STRING Synonym for +ATOM.

        * -STRING Synonym for -ATOM.

        * `[-STRING]' Synonym for `[-ATOM]'.

     The `C' function must include the file `ICprolog.h'.  There should
     be no more than one argument corresponding to a `C' function
     return type. If there is no such argument, the return type of the
     `C' function should be specified as `bool', and it should return
     one of the following values

    `FAIL'
          The prolog call will fail.

    `SUCCEED'
          The prolog call will succeed.

    `SUSPEND'
          If a primitive returns `SUSPEND', then that thread is taken
          out of the run queue.  This means that another thread will
          have to explicitly `resume' *Note Threads::, it before it can
          run again.

    `REQUEUE'
          `REQUEUE' means the primitive should be tried again later.
          This can result in a busy wait if nothing happens in between
          to change the status.

* Menu:

* ForeignComp::


File: icp.info,  Node: ForeignComp,  Up: ForeignPredicates

Compilation and Example
-----------------------

When compiling the `-I' option should be given to the `C' compiler to
specify the directory where the `ICprolog.h' file is located. For
example
     cc -w -O -I$ICP_INSTALLDIR/include -c myfuncs.c

With the following code for `myfuncs.c'
     #include "ICprolog.h"
     
     char *malloc();
     
     /* foreign(twice, c, ptwice(+float, [-float])). */
     double twice(a)
     double a;
     {
             return(2 * a);
     }
     
     /* foreign(concat, c, pconcat(+atom, +atom, -atom)). */
     bool concat(a, b, c)
     char *a, *b, **c;
     {
             int len;
             static int last_len = 0;
             static char *ret = NULL;
             char *pt;
     
             len = strlen(a) + strlen(b) + 1;
             if (!ret) {
                     last_len = len;
                     ret = malloc(len);
             } else if (len > last_len) {
                     free(ret);
                     ret = malloc(len);
                     last_len = len;
             }
             pt = ret;
             while (*pt = *a++)
                     pt++;
             while (*pt = *b++)
                     pt++;
             *c = ret;
             return(SUCCESS);
     }
     
     /* foreign(foo, c, pfoo(+integer,-integer,+atom,-atom,+float,-float)). */
     bool foo(int1, int2, atom1, atom2, float1, float2)
     int int1, *int2;
     char *atom1, **atom2;
     double float1, *float2;
     {
             *int2 = int1;
             *atom2 = atom1;
             *float2 = float1;
             return(SUCCESS);
     }

and the following prolog declarations

     foreign_file('test.o', [twice, concat, foo]).
     
     foreign(twice, c, ptwice(+float, [-float])).
     foreign(concat, c, pconcat(+atom, +atom, -atom)).
     foreign(foo, c, pfoo(+integer, -integer, +atom, -atom, +float, -float)).

will give the results:
     | ?- [test], listing([foreign_file, foreign]).
     foreign_file('test.o',[twice,concat,foo]).
     
     foreign(twice,c,ptwice(+ float,[- float])).
     foreign(concat,c,pconcat(+ atom,+ atom,- atom)).
     foreign(foo,c,pfoo(+ integer,- integer,+ atom,- atom,+ float,- float)).
     
     yes
     | ?- load_foreign_files('test.o').
     {loading foreign from ./test_interface.o ./test.o }
     
     yes
     | ?- ptwice(1.1, T).
     
     T = 2.2
     
     | ?- pconcat(ab, cd, E).
     
     E = abcd
     
     | ?- pfoo(4, I, hello, A, 1.3, F).
     
     I = 4
     A = hello
     F = 1.3


File: icp.info,  Node: Tracer,  Next: Operators,  Prev: Foreign Interface,  Up: Top

Prolog Tracer User Guide
************************

When programs do not work as expected, the next step is to use a Prolog
tracer to trace through the execution step by step. Our tracer uses an
extended set of the four port model described by Clocksin and Melish
`Programming in Prolog', Springer Verlag.

The tracer knows about the following eight ports: call, exit, redo,
fail, unify, try_match, succeed_match, and fail_match. On invoking the
tracer the first five of these are set on leash.  Leashed ports are
always echoed, and skipping and unleashing are allowed at call and redo
ports only. At leashed ports the `?' prompt awaits for the user to take
action by typing one of `RET s u n a e l p d !' The effect is as
follows:

`RET creeping takes place'
`s'
     the current goal is skipped

`u'
     the current goal is unleashed

`n'
     the trace continues by

`a'
     tracing is aborted

`e'
     the predicate set_leashes is called

`l'
     the predicate set_lechoes is called

`p'
     information is displayed indicating the ports that are currently
     leashed/echoed

`d'
     the ICP debugger is entered

`!'
     the user is allowed to solve a prolog query. On the user selecting
      this option the tracer types ! and awaits for a prolog query to
     be typed at   the terminal. Once the query has been solved,
     control returns to the tracer.

`trace'
     Turns the tracer on. All top level queries will be traced.

`notrace'
     Turns the tracer off.

`set_echoes'
     Gives the user the opportunity to turn echoes on or off on any of
     the tracer's ports.

     set_echoes types the message `...ports to be leashed?' and awaits
     for the user to type a term of the form `<Ports>':

    `<Ports>'
          ::=  all | none | <PortSeq>

    `<PortSeq>'
          ::= <Port> | -<Port> | <Port>,<Ports> | -<Port>,<Ports>

    `<Port>'
          ::= call | exit | redo | fail | try_match | succeed_match |
          fail_match

     If the term is `all' then the echo is set to be on all the
     tracer's ports.

     If the term is `none' then the echo and leash is set to be off on
     all tracer's ports.

     If the term has a subterm of the form <Port> then the echo is set
     to be on on the corresponding port.

     If the term has a subterm of the form -<Port> then the echo and
     leash are set to be off on the corresponding port.

     The port names call, exit, redo, fail, try_match, succeed_match,
     and fail_match can be respectively abbreviated to c, e, r, f, tm,
     sm, and fm.

`set_leashes'
     Gives the user the opportunity to turn leashes on or off on any of
     the tracer's ports.

     set_echoes types the message `...ports to be leashed?' and awaits
     for the user to type a term of the form <Ports> (see set_echoes).

     If the term is `all' then the echo and leash is set to be on all
     the tracer's ports.

     If the term is `none' then the leash is set to be off on all
     tracer's ports.

     If the term has a subterm of the form <Port> then the echo and
     leash are set to be on on the corresponding port.

     If the term has a subterm of the form -<Port> then the leash is
     set to be off on the corresponding port.

`?? +GOAL'
     GOAL is traced.  This operator can be used to trace a single goal
     when the tracer is off. Only dynamic code can be traced and if
     during a trace a query for a static predicate is encountered, the
     query is solved by a standard call to prolog.


File: icp.info,  Node: Operators,  Next: Error Codes,  Prev: Tracer,  Up: Top

Operators
*********

     Precedence  Type    Operators
     1200        yfy     (. )
     1200        yf      (. )
     1200        xfx     (-->) (:-)
     1200        fx      (:-) (?-)
     1150        fx      (multifile) (mode) (public) (meta_predicate) (dynamic)
     1100        xfy     (;)
     1050        xfy     (->)
     1000        xfy     (,)
     900         fy      (nospy) (\+) (not) (spy)
     900         fx      (??)
     700         xfx     (<) (=) (>) (=<) (==) (=:=) (@<) (@>) (@=<) (@>=)
                         (\=) (\==) (=..) (>=) (=\=) (is)
     600         xfy     (:)
     500         yfx     (\/) (++) (--) (/\) (-) (+)
     500         fx      (\) (-) (+)
     400         yfx     (<<) (**) (//) (*) (/) (>>)
     300         xfx     (mod)
     200         xfy     (^)
     100         fx      (ls) (cd) (vi)


File: icp.info,  Node: Error Codes,  Next: Low Level,  Prev: Operators,  Up: Top

Error Codes
***********

     	100	unbound variable in arithmetic expression
     	101	unbound variable in relational expression
     	102	unbound stream identifier
     	103	unbound filemode
     
     	200	non-integer in arithmetic expression
     	201	invalid clause
     	202	non-number in relational expression
     	203	non-atom filename
     	204	non-atom in operator declaration
     	205	non-variable stream identifier
     	206	invalid data for ram file
     	207	non-integer argument in throw/1
     	208	non-variable in 2nd argument
     	209	non-variable argument
     	210	invalid form of use
     	211	unterminated list
     	212	invalid list of ASCII codes
     	213	non-integer argument
     	214	attempt to assert/retract a static predicate
     	215	attempt to assert/retract a system predicate
     	216	invalid clause
     	217	invalid goal
     	218	non-number in arithmetic expression
     	219	invalid arithmetic expression
     
     	300	cannot open file
     	301	invalid stream
     	302	cannot close stream
     	303	incorrect or unknown file type
     	304	error occurred while reading object file
     	305	error occurred while writing object file
     	306	invalid ram file
     	307	invalid port
     	308	port has pending read
     	309	port has pending write
     	310	port is being read by another thread
     	311	port is being written to by another thread
     	312	port is owned by another thread
     
     	400	file mode must be read, write or append
     	401	operator priority must be in the range 0..1200
     	402	operator type must be fx, fy, xf, yf, xfx, xfy, yfx or yfy
     	403	predicate not defined
     	404	undefined property
     	405	undefined predicate
     	408	system deadlock
     	409	invalid return code from service function
     	410	parlog thread exists already
     	411	invalid thread ID
     	412	cannot switch to parlog from this thread
     
     	500	compiler error
     	501	invalid instruction found during code generation
     	502	multiply-defined label found during code generation
     	503	term nested too deep
     	504	out of stack space
     	505	out of heap space
     	506	invalid ICP instruction
     	507	invalid tag type found
     	508	too many variables in term
     	509	term too large in property
     	510	term too large for pipe
     
     	600	division by zero in arithmetic expression
     	601	cannot open any more file streams
     	602	cannot open any more memory streams
     	603	no space for RAM file
     	604	code segment too large
     	605	symbol space full during code generation
     	606	out of space during code generation
     	607	out of code space
     	608	out of space in dictionary maintenance
     	609	out of space for constants
     	610	no space for new thread
     	611	no space for property
     	612	out of space in term reader
     	613	out of system heap space
     	614	illegal instruction
     
     	700	Bad sequence of TCP instructions
     	701	Socket closed
     	702	Timeout (TCP)
     	703	Invalid socket descriptor
     	710	socket error (TCP)
     	711	setsockopt error (TCP)
     	712	bind error (TCP)
     	713	listen error (TCP)
     	714	accept error (TCP)
     	715	connect error (TCP)
     	716	ioctl error (TCP)
     	717	send error (TCP)
     	718	recv error (TCP)
     	719	sendto error (TCP)
     	720	recvfrom error (TCP)
     	721	close error (TCP)
     	722	getsockname error (TCP)
     	723	gethostname error (TCP)
     	724	gethostbyname error (TCP)
     	725	getpeername error (TCP)
     	726	gethostbyaddr error (TCP)
     	727	getservbyname error (TCP)
     	728	getservbyport error (TCP)
     	729	getsockopt error (TCP)
     	730	cannot open any more sockets
     	731	data too long for buffer
     
     	800	Maibox initialisation
     	801	Timeout (mailbox)
     	802	Incorrect mailbox identifier
     	803	Mailbox permission denied
     	804	Invalid operation on linked mailbox
     	805	The mailbox is locked
     	806	The mailbox is empty
     	807	Attempt to commit or discard an unlocked mailbox
     	808	The machine on which the mailbox is located is shut down
     	809	An error has happened in the low level communications
     	810	Attempt to bind a mailbox to a service which already exists
     	811	The specified service does not exist in the internal database
     	812	The specified mailbox does not exist in the internal database
     	813	Unspecified Mailbox error
     	814	Unification failure error (mailbox)


File: icp.info,  Node: Low Level,  Next: PredicateIndex,  Prev: Error Codes,  Up: Top

Low-level Primitives
********************

     noref                           % list undefined preds
     debugicp                        % debug emulator
     halt                            % exit emulator
     'add%f'(N,M,Sum)                % add two integers
     'sub%f'(N,M,Difference)         % subtract two integers
     'mul%f'(N,M,Product)            % multiply two integers
     'div%f'(N,M,Quotient)           % divide two integers
     'mod%f'(N,M,Remainder)          % modulus
     'cmp%f'(Order,term1,Term2)      % compare two terms
     'int%f'(Int)                    % integer test
     'atom%f'(Constant)              % atomic test
     'var%f'(Var)                    % var test
     'list%f'(List)                  % list test
     'tpl%f'(Tuple)                  % tuple test
     'arg%f'(N,Term,Element)         % extract from tuple
     'univ%f'(Tuple,List)            % univ
     'name%f'(Constant,List)         % print-names of terms
     'o_stream%f'(Filename,Mode,Id)  % initialise stream I/O
     'c_stream%f'(Id)                % finished with stream
     'o_mem%f'(Initialiser,Mode,Id)  % initialise memory file
     'c_mem%f'(Id)                   % finished with memory file
     'set_in%f'(Type,Id)             % set current input stream
     'set_out%f'(Type,Id)            % set current output stream
     'increment%f'(N,OneMore)        % increment by 1
     'put_q_atom%f'(Atom)            % write out a quoted atom
     'get0%f'(Char)                  % input a character
     'put%f'(Char)                   % output a character
     'unget%f'(Char)                 % put back a character
     'flush%f'(StreamId)             % flush output stream
     'addr%f'(Var,Address)           % numerical address of var
     'deepcut%f'(Cut)                % deep cut
     'back%f'(ChoicePt)              % pick up cut label
     'meta%f'(Goal)                  % meta-call
     'eq%f'(Number,Number)           % equality test
     'ne%f'(Number,Number)           % inequality test
     'lt%f'(Number,Number)           % less than test
     'le%f'(Number,Number)           % less than or equal test
     'gt%f'(Number,Number)           % greater than test
     'ge%f'(Number,Number)           % greater than or equal test
     'syntax_error%f'(Errorcode)     % Syntax Error Handler
     'assert%f'(Index,Mode)          % link clause of dynamic predicate
     'retract%f'(Name,Arity,Index)   % retract dynamic clause
     'dec%f'([N])                    % decrement N by 1 in [N]
     'inc%f'([N])                    % increment N by 1 in [N]
     'find_clause%f'(Name,Arity,ChainName,ChainArity,Index)
                                     % find specific clause in dynamic chain
     'time%f'(Time)                  % get CPU time
     'arity%f'(Term,Arity)           % get arity of tuple
     'funct%f'(Term,Functor)         % get functor of tuple
     'interm%f'(Term,Priority,Vars)  % read a term and produce var list
     'ntpl%f'(Length,Tuple)          % create a new tuple of unbounds
     'not%f'(N,Complement)           % binary complement
     'lshift%f'(N,Places,Result)     % left shift function
     'rshift%f'(N,Place,Result)      % right shift function
     'and%f'(N,M,Anded)              % and function
     'or%f'(N,M,Or)                  % or function
     'op_prefix%f'(OpPrior,Right,Name)     % define a new prefix operator
     'op_postfix%f'(Left,OpPrior,Name)     % define a new postfix operator
     'op_infix%f'(Left,OpPrior,Right,Name) % define a new infix operator
     'op_look%f'(Name,Pre,PreRight,InLeft,In,InRight,Post,PostLeft)
                                     % read specified operator details
     'op_get%f'(Name,IndexIn,Pre,PreRight,InLeft,In,InRight,
                Post,PostLeft,IndexOut).
                                     % read unspecified operator details
     'put_str%f'(List,Quote)         % write a quoted atom (list of ASCII)
     'put_atom%f'(Atom)              % write out an atom
     'put_number%f'(Number)          % write out a number
     'atom_type%f'(Constant,Type)    % is atom alphanumeric or symbols ?
     'defined%f'(Pred,Address)       % return address of predicate
     'read_catch%f'(ChoicePt)        % read CATCH register
     'set_catch%f'(ChoicePt)         % set CATCH register
     'read_error%f'(Error)           % read and reset ERROR register
     'catch%f'(B)                    % set CATCH to most recent chpt.
     'throw%f'(Error)                % throw an error
     'cg_init%f'(Type)               % initialise code generator
     'cg_fixup%f'(Public)            % fixup generated code
     'cg%f'(Instructions)            % generate code for one relation
     'undef%f'(Name,Arity)           % get name and arity of undfnd relation
     'c_ram%f'(Ramfile,Constant)     % create constant from memory file
     'load%f'                        % load code block from current input
     'varsin%f'(Term,Vars)           % Vars is list of variables in Term
     'fix_tables%f'                  % fixup externals and entries tables
     'save%f'(PredList,Saved,Unsaved)   % save code for pred to current output
     'pred_look%f'(Name,Arity,Seg,Type) % is specified predicate defined ?
     'pred_get%f'(Name,Arity,IndexIn,IndexOut,Seg,Type)
                                     % Get unspecified predicate details
     'abolish%f'(Name,Arity)         % Abolish predicate
     'validate%f'(DefindLst,ErrType) % Gets a list of preds being re-loaded
     'unload%f'                      % Free space for last loaded segment
     'kill%f'(Name,Arity)            % Kill predicate
     'write_term%f'(Term)            % write encoded term
     'read_term%f'(Term)             % read encoded term
     'tag%f'(Term,Tag)               % return tag as in integer
     'grnd_funct%f'(Functor)         % test for ground functor
     'tab%f'(Number)                 % print spaces
     'concat%f'(First,Second,Join)   % concat two symbols
     'prefix%f'(Longname,Prefix)     % symbol prefix test
     'suffix%f'(Longname,Suffix)     % symbol suffix test
     'to_ground%f'(Hllw,Grnd,Vr,VNm,Used) % create ground copy of term
     'to_hollow%f'(Grnd,Hllw,VNames,Vars) % creates hollow copy of a term
     'delete%f'(Name,Arity)          % free space for clauses of  Name/Arity
     'cg_out%f'                      % write out result of code generator
     'set_up_seg%f'                  % initialise segment from ram file
     'tty%f'(Name,InStream,OutStream) % create titled window with I/O streams
     'ram_pipe%f'(Out,In)            % create pseudo-pipe using ram files
     'close_port%f'(Port)            % close one end of a pipe
     'read_pipe%f'(Port,Term)        % read a term from a pipe
     'write_pipe%f'(Port,Term)       % write a term to a pipe
     'new_thread%f'(Thread)          % create a new thread
     'kill_thread%f'(Thread)         % kill a thread
     'fork%f'(Thread,InputStream)    % fork a thread
     'resume%f'(Thread)              % resume a thread
     'suspend%f'                     % suspend a thread
     'rpc%f'(Thread,InputStream,OutputStream) % remote procedure call
     'pipe%f'(In,Out)                % create a pipe using memory files
     'thread%f'(Thread)              % get address of current thread
     'set_prop%f'(Object, Property, Value) % setting a property
     'get_prop%f'(Object, Property, Value) % retrieving a property
     'del_prop%f'(Object, Property)  % deleting a property
     'get_props%f'(Object, List)     % get property names of an object
     'del_props%f'(Object)           % delete all properties of an object
     'get_cons%f'(Property, List)    % get objects which have property
     'del_cons%f'(Property)          % delete objects which have property
     'float%f'(Num)                  % floating-point number test
     'put_float%f'(Num)              % write out a floating-point
     'number%f'(Num)                 % integer/float test
     'fadd%f'(N,M,Sum)               % add two floating point numbers
     'fsub%f'(N,M,Difference)        % subtract two floating point numbers
     'fmul%f'(N,M,Product)           % multiply two floating point numbers
     'fdiv%f'(N,M,Quotient)          % divide two floating point numbers
     'int%f'(Float,Int)              % convert float to integer
     'sin%f'(N,Result)               % sine function
     'cos%f'(N,Result)               % cosine functions
     'tan%f'(N,Result)               % tangent function
     'asin%f'(N,Result)              % arcsin function
     'acos%f'(N,Result)              % arcosine function
     'atan%f'(N,Result)              % arctangent function
     'atan2%f'(N,M,Result)           % arctangent (N/M) function
     'sinh%f'(N,Result)              % hyperbolic sine function
     'cosh%f'(N,Result)              % hyperbolic cosine function
     'tanh%f'(N,Result)              % hyperbolic tangent function
     'exp%f'(N,Result)               % natural anti-logarithm function
     'log%f'(N,Result)               % natural logarithm function
     'log10%f'(N,Result)             % logarithm (base 10) function
     'sqrt%f'(N,Result)              % square root function
     'pow%f'(N,M,Result)             % N raised to the power M
     'abs%f'(N,Result)               % absolute value function
     'sign%f'(N,Result)              % sign of N
     'ceil%f'(N,Result)              % round up to next higher integer
     'floor%f'(N,Result)             % round down to next lower integer
     'pi%f'(Pi)                      % value of pi
     'rand%f'(N)                     % random integer in range 0-32767
     'deg2rad%f'(N,Result)           % degree to redian conversion
     'rad2deg%f'(N,Result)           % radian to degree conversion
     'interrupt%f'(Goal)             % retrieve interrupted goal
     'unix%f'(Command)               % execute unix command
     'out_of_date%f'(File)           % check if need to recompile
     'look_pipe%f'(Port,Term)        % read from pipe without removing
     'commit_read%f'(Port)           % commits the non-removing read
     'look_pipe%f'(Port,Term)        % unlock a pipe
     'init_parlog%f'(Th)             % start up a Parlog thread
     'tty_get0%f'(Char)              % read character from terminal
     'curr_input%f'(In)              % identify current input
     'curr_output%f'(Out)            % identify current output
     'release_port%f'(Port)          % relinquish ownership of port
     'empty_pipe%f'(Pipe)            % test if pipe is empty
     'is_iport%f'(Port)              % input port test
     'is_oport%f'(Port)              % output port test
     'runtime%f'(Flag, List)         % get CPU time (SICSTUS style)
     'decrement%f'(N,OneLess)        % decrement by 1
     'load_foreign%f'(File,List,Lib) % set up foreign C primitives
     'realtime%f'(Number)            % real time (seconds since 1/1/170)
     'errno%f'(Error,Msg)            % C errno
     'getenv%f'(Name, Value)         % get environment variable

