@c -*-texinfo-*-
@node ReferenceManual, IC-PrologII, UserManual, Top
@comment  node-name,  next,  previous,  up
@chapter Reference Manual

@menu
* Syntax::                      Syntax
* EscapeSequences::             Escape Sequences
* Semantics::                   Semantics
* CommandLine::                 Command Line Options
* Environment::                 Environment Variables
* StartupFile::                 Startup File Processing
* FilenamesAndPaths::           Filenames and Paths
* SystemOperatorDeclarations::  System Operator Declarations
* SystemPredicates::            System Predicates
* ForeignRoutines::             Foreign Routines
* AlternativeTracer::           An Alternative Tracer
* ParlogShell::                 Parlog Shell
* SPMCompatibility::            SPM Compatibility
* MacParlogCompatibility::      MacParlog Compatibility
* OldChanges::                  Changes Between V1.0 and V1.4
* Changes::                     Changes Between V1.4 and V1.5
* BugsFeatures::                Bugs/Features
@end menu

@node Syntax, EscapeSequences,  , ReferenceManual
@comment  node-name,  next,  previous,  up
@section Syntax

A Parlog program consists of a finite set of @dfn{guarded clauses} and
@dfn{mode declarations}.  A guarded clause has the form:
@example
H <- G1, ..., Gm : B1, ..., Bn  (m,n >= 0)
@end example

where @code{H} is called the @dfn{clause head}, @code{G1}, ...,
@code{Gm} is its @dfn{guard} and @code{B1}, ..., @code{Bn} its
@dfn{body}.  The @code{:} is a @dfn{commit operator}.  If the guard is
empty (i.e.  @code{m} = 0) then the commit operator can be omitted.

The clause head @code{H} and each of the @code{G1}, ..., @code{G}
and @code{B1}, ..., @code{Bn}
are @dfn{goals}.
A goal has the form:
@example
R(T1, ..., Tk)      (k >= 0)
@end example

where @code{R} is the @dfn{relation name} and @code{T1}, ..., @code{Tk}
are its @dfn{argument terms}.  The number of arguments, @code{k} is
called the goal's @dfn{arity}.  If the goal has no arguments (i.e.
@code{k} = 0) then the brackets are omitted.  A @dfn{relation} or
@dfn{procedure} @code{R/k} comprises all clauses with the relation name
@code{R} and arity @code{k}.

A @dfn{mode declaration}
is associated with a Parlog procedure. For a relation @code{R/k}
this has the form:
@example
mode R(m1, .., mk).
@end example

where each @code{m} is either @code{?} or @code{^}.  A @code{?}
denotes an @dfn{input} mode and a @code{^} denotes an @dfn{output} mode.
If a mode declaration is omitted for a relation @code{R} then all of its
argument terms are assumed to have an input mode.  A mode @code{m} can
be prefixed with argument names; these are comments of no semantic
significance.

A @dfn{term} can be a variable, constant or structured term. A
@dfn{variable} is denoted by an identifier beginning with a capital
letter or the underscore character @code{_}. Examples are @code{X} and
@code{Tree}.  The underscore character may also be used on its own to
denote a unique @dfn{anonymous} or @dfn{singleton} variable.  A
@dfn{constant} is either a number or an @dfn{atom} (a name denoted
by a character
string), which must be enclosed in single quotes when it can be confused
with other types of term; examples are @code{jim}, @code{'Hello World'}
and @code{'$primitive'}.  Non-printable character may be included in
quoted atoms by using @dfn{escape characters} (@pxref{EscapeSequences}).

Numbers may be integers or floating-point numbers.  Numbers may also
be represented using radix notation where the radix is given by a
single digit, followed by the quote character (@code{'}) and the number
in that base.  Some examples will help to clarify this.
@example
	4'100 (base 4) = 16 (base 10)
	8'123 (base 8) = 83 (base 10)
@end example
Radix 0 has a special meaning.  It performs character to ASCII code
conversion. e.g.
@example
	0'A = 65 (decimal)	'A' is ASCII 65
	0'( = 40 (decimal)	'(' is ASCII 40
@end example

A @dfn{structured term} is denoted by:
@example
F(T1, ..., Tn)      (n >= 1)
@end example

where @code{F} is the @dfn{functor name} and the @dfn{arguments}
@code{T1}, ..., @code{Tn} are terms.  An example of a structured term
is @code{point(X,Y,Z)}, whose functor name is @code{point} of arity 3,
with arguments @code{X}, @code{Y} and @code{Z}.  Infix notation may be
used for certain structured terms where the functor is defined as an
operator; thus the term @code{=(X,Y)} can be written as @code{X=Y}.

A special syntax is used for the type of structured term known as
@dfn{lists}.  The notation @code{[H|T]} is used to denote the list with
the head @code{H} and tail @code{T}.  A nested list term
@code{[X|[Y|Z]]} may be abbreviated as @code{[X,Y|Z]} and if @code{Z} is
the empty list or @code{nil} term (denoted by constant @code{[]}) then
this can be abbreviated to @code{[X,Y]}.

A shorthand for representing a list of ASCII codes is to write the
ASCII characters within double-quotes (@code{"}).  Thus the string
@example
	"ABC"
@end example
is the same as the list [65,66,67].

A Parlog program is invoked by executing a @dfn{query}.  A query is a
conjunction of goals:
@example
?- Q1, ..., Qn      (n >= 1)
@end example

Goals in a clause or query may be separated by the @dfn{parallel
conjunction} operator, @code{`,'}, or the @dfn{sequential conjunction}
operator, @code{`&'}. Similarly, clauses in a relation may be separated by
Parlog's @dfn{parallel} and @dfn{sequential clause search} operators,
denoted as @code{`.'} and @code{`;'} respectively.  In addition, the last
clause of a relation is always terminated by @code{`.'}.

Programs may include comments, which are defined as any text following a
@code{%} character up to the next newline character.


@node EscapeSequences, Semantics, Syntax, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Escape Sequences

In quoted atoms, double-quote delimited lists or base 0 notation, escape
sequences can be used to denote characters.  This is used to avoid
ambiguity and to enter unusual characters.  The following escape
sequences are defined :

@table @code
@item \a
alarm/bell (ASCII 7)
@item \b
backspace (ASCII 8)
@item \t
tab (ASCII 9)
@item \n
newline (ASCII 10)
@item \v
vertical tab (ASCII 11)
@item \f
formfeed (ASCII 12)
@item \r
carriage return (ASCII 13)
@item \e
escape (ASCII 27)
@item \s
space (ASCII 32)
@item \d
delete (ASCII 127)
@item \<octal string>
the character with ASCII code @kbd{<octal string>}
base 8.  e.g. @code{\007} is the
bell character and @code{\040} is the space character (ASCII 32).
@item \^<control char>
the character whose ASCII code is the @kbd{<control char>} mod 32.
e.g. @code{\^P} is @kbd{@key{CTL}-P}.
@item \<CR>
no character.  This is most useful when
splitting atoms over two
lines where the ignored newline character is preceded by a backslash.
@item \c
no character, also all characters up to, but not including,
the next
non-layout character are ignored.  Layout characters are characters
with ASCII code =< 32 or >= 127.
@item \<other>
the character @kbd{<other>}, where @code{<other>} is
any character not defined above.
@end table

@node Semantics, CommandLine, EscapeSequences, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Semantics

Parlog differs from Prolog in three important respects : concurrent
evaluation, don't-care non-determinism, and its (optional) use of mode
declarations to specify communication constraints on shared variables.

During the evaluation of a call @samp{r(a1,...,ak)}, all of the
clauses for the predicate @code{r} can be searched in parallel for a
candidate clause. The clause :
@example
r(t1, . . ., tk)  <-  < guard >  :  < body >
@end example

is a candidate clause if the head @samp{r(t1,...,tk)} matches the call
@samp{r(a1,..., ak)} and the guard succeeds.  It is a non-candidate if
the match or the guard fails. If all clauses are non-candidates the call
fails, otherwise one of the candidate clauses is selected and the call
is reduced to the substitution instance of the body of that clause.

There is no backtracking on the choice of candidate clause since we
``don't care'' which candidate clause is selected. In practice, the
language implementation dictates that the first one (chronologically) to
be found is chosen.  The absence of backtracking in Parlog is
compensated for by guard tests which can be used to guarantee that the
correct clause is chosen. This idea has been more formally stated in
Gregory's @dfn{sufficient guards law} [Gregory 1987], which identifies
the situations under which a Parlog computation returns a solution to a
query, if a solution exists. It states that Parlog predicates should be
written so that guards in each clause guarantee that if a clause is
selected to reduce a goal then either a solution to the call can be
computed using this clause, or no solution can be found using any other
clause.

The search for a candidate clause can be controlled by using either the
parallel clause search operator @code{`.'} or the sequential clause search
operator @code{`;'} between clauses. For instance, if a predicate is
defined by the clauses :
@example
Clause1  .
Clause2  ;
Clause3.
@end example

Then Clause3 will not be tried for candidacy until both Clause1 and
Clause2 have been found to be non-candidate clauses.

Non-variable terms that appear in input argument positions in the head
of a clause can only be used for input matching. If an argument of the
call is not sufficiently instantiated for an input match to succeed, the
attempt to use the clause suspends until some other process further
instantiates the input argument of the call.  If all clauses for a call
are suspended, the call suspends but a candidate clause can be selected
even if there are other suspended clauses.

Parlog utilises unification for output bindings which means that
bindings to output variables will be unified with any values in those
argument positions in the goal.

@node CommandLine, Environment, Semantics, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Command Line Options

@table @code
@item -n x
Specifies the number of processors to execute. The default value is @file{-n1}.
@item -m x
[BBN Butterfly and Encore Multimax only] Specifies the number of
memory segments (i.e. 64Kbyte blocks) to
allocate on startup. The default value is 7 + 5n, where @file{n}
is the number of processors.
@item -C x
[BBN Butterfly only] Specifies the number of memory segments (i.e.
64Kbyte blocks) to allocate for the private code area.  The default
value is 6.
@end table

On machines that allow shared memory to be expanded during execution
there should be no reason to use the @file{-m} option as the system can
allocate extra memory if needed automatically. Currently the Alliant,
Sequent Balance and Symmetry and the uniprocessor versions of the system
support this memory expansion feature.  On the BBN Butterfly and the
Encore Multimax, you may need to re-run your program using the @file{-m}
option when you get the error message
@example
	can't extend shared memory, use -m option to get more
@end example


@node Environment, StartupFile, CommandLine, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Environment Variables

The Parallel Parlog system uses three environment variables -
@kbd{PARLOGDIR}, @kbd{PARLOG_PATH} and @kbd{PARLOG_INIT}.

@kbd{PARLOGDIR} is the top level directory of the Parlog run-time
system.  This is normally set automatically by the script which
starts the Parallel Parlog system.  You will only need to set this
variable explicitly if you wish to use an alternative run-time system
located in another directory.

@kbd{PARLOG_PATH} is a colon-separated list of directories in the style
of the @kbd{PATH} environment variable.  This is used to give a default
list of directories to search for when looking for files.  Normally,
this environment variable is not set, and only files in the current
directory will be found.  To access files in other directories, a
relative or full pathname must be given.  If you set @kbd{PARLOG_PATH},
then you will be able to access files in those directories by specifying
the filename only (@pxref{FilenamesAndPaths}).

@kbd{PARLOG_INIT} is the name of a file containing commands to be executed
at startup time (@pxref{StartupFile}).


@node StartupFile, FilenamesAndPaths, Environment, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Startup File Processing

When Parallel Parlog is started, commands in a startup file are executed.
The commands should be of the form :
@example
	<- ConjunctionOfGoals.
@end example
For example, the following startup file will display a welcome message
and load a customised library file.  Note that
lines not beginning with a @code{`<-'} are ignored.
@example
	<- nl &
	   write('Welcome to Parlog') & nl.

	<- load(mylib).

	load(otherlibs).	% this line is not executed.
@end example
The default startup file is @file{~/.parlog} but this may be altered
by setting the environment variable @kbd{PARLOG_INIT}.  If the file
specified by @kbd{PARLOG_INIT} does not exist, the system behaves as
if the file was empty.


@node FilenamesAndPaths, SystemOperatorDeclarations, StartupFile, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Filenames and Paths

There are a few primitives which take a filename as an argument.  The most
commonly used are @code{open/3}, @code{load/1}
and @code{compile/1} for opening a file, loading compiled code and compiling
Parlog source respectively.  Filenames are atoms, so they are usually quoted
since they commonly contain non-alphanumeric characters such as @code{`/'},
@code{`.'} and @code{`~'}.  In accordance with Unix conventions, if the filename
begins with a @code{`~'} character, the @code{`~'} is substituted by the home
directory of the current user.  If the filename begins with @code{`~<user>'}
then the home directory of @code{<user>} is substituted instead.  @code{`.'}
signifies the current directory and @code{`..'} denotes the parent directory
of the path name so far.

By default, filenames are searched for in the current directory only.  This
may become tedious since files not in the current directory will need to
be specified by giving the full path name.  By setting the environment
variable @kbd{PARLOG_PATH} (@pxref{Environment}), a list of directories may
be supplied for
filename searching.  This list is a colon-separated list of path names. e.g.
if @kbd{PARLOG_PATH} has the value
@example
	.:~/parlog:/usr/local/parlog/source
@end example
then filenames will be searched for in those three directories in the order
specified.  Note that if @code{`.'} is not included in @kbd{PARLOG_PATH},
then files in the current directory will not be visible.

The value of @kbd{PARLOG_PATH} may be changed dynamically by the @code{setenv/2}
primitive.


@node SystemOperatorDeclarations, SystemPredicates, FilenamesAndPaths, ReferenceManual
@comment  node-name,  next,  previous,  up
@section System Operator Declarations

The following list specifies the operators defined in the system
operator set.

@example
op(system, 1400, xfy, ';')  &
op(system, 1350, xfy, '..') &
op(system, 1300, xfy, '\\') &
op(system, 1250,  fx, (&&)) &
op(system, 1200, xfx, (<-)) &
op(system, 1200,  fx, (<-)) &
op(system, 1150,  fx, [(mode),(public),(prolog)]) &
op(system, 1150, xfx, :)    &
op(system, 1100, xfy, &)    &
op(system, 1050, xfy, and)  &
op(system, 1000, xfy, ',')  &
op(system,  700, xfx, [is,=,=..,\=,==,\==,<=,=@@=,\=@@=,@@<,@@>,
                       @@=<,@@>=,=:=,=\=,<,>,=<,>=])   &
op(system,  600, xf, [?,^])   &
op(system,  500, yfx, [+,-,/\,\/,\]) &
op(system,  500,  fx, [+,-,\])  &
op(system,  400, yfx, [*,/,//,<<,>>]) &
op(system,  300, xfx, [div,mod])      &
op(system,  200, xfx, #).
@end example

@node SystemPredicates, ForeignRoutines, SystemOperatorDeclarations, ReferenceManual
@comment  node-name,  next,  previous,  up
@section System Predicates

This section describes the behaviour of the predicates which are already
built into the system.  The predicates are grouped under categories
for easy reference.  For each predicate, the conditions for synchronisation
are also detailed.

@menu
* UnificationRelated::          Unification Related
* TypeTests::                   Type Tests
* ArithmeticExpressions::       Arithmetic Expressions
* TermComparison::              Term Comparison
* TermManipulation::            Term Manipulation
* Metalevel::                   Metalevel
* InputOutput::                 Input and Output
* ChannelIO::                   Channels
* CompilationAndLoading::       Compilation and Loading
* Operators::                   Operators Related
* Spypoints::                   Spypoints
* Miscellaneous::               Miscellaneous
@end menu

@node UnificationRelated, TypeTests,  , SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Unification Related

@table @code
@item Term1 = Term2
@findex =/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Output unification.  Attempts to unify Term1 with Term2.
Succeeds if Term1 and Term2 unify; else fails.

@item Term1 == Term2
@findex ==/2
@dfn{synchronisation:} Suspends if Term1 and Term2 can be unified only by
binding variables in both of them.

@dfn{behaviour:} Test unification. It unifies Term1 and Term2 without binding
variables in either term. Succeeds if Term1 and Term2 are identical
terms; fails as soon as Term1 and Term2 fail to match.

@item Term1 \== Term2
@findex \==/2
@dfn{synchronisation:} As for @code{==/2 } above.

@dfn{behaviour:} Tests Term1 and Term2 without binding variables in either.
Fails if Term1 and Term2 are identical terms; succeeds as soon as Term1
and Term2 fail to match.  Note that there is a subtle difference with
@code{\=@@=/2 } as shown by the following examples.
@example
	g(X) \== g(Y)
@end example
suspends since X and Y may potentially be different, but
@example
	g(X) \=@@= g(Y)
@end example
succeeds since the variable X is different from the variable Y.

@item Term1 <= Term2
@findex <=/2
@dfn{synchronisation:} Suspends if Term1 and Term2 could only be unified by
binding variables in Term2

@dfn{behaviour:} Input matching.  Unifies Term1 and Term2 without binding
variables in Term2.  Succeeds if Term2 is a substitution instance of
Term1.  Fails as soon as Term1 and Term2 fail to match.

@item var(X)
@findex var/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Succeeds if X is an unbound variable.  Fails if it is
instantiated.

@item nonvar(X)
@findex nonvar/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Fails if X is an unbound variable.  Succeeds if it is
instantiated.

@item ground(X)
@findex ground/1
@dfn{synchronisation:} Suspends until X is ground.

@dfn{behaviour:} Succeeds when X is ground.

@item data(X)
@findex data/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds when X is instantiated.
@end table

@node TypeTests, ArithmeticExpressions, UnificationRelated, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Type Tests

@table @code
@item atom(X)
@findex atom/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds if X is an atom; otherwise fails.

@item atomic(X)
@findex atomic/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds if X is an atom or a number; otherwise fails.

@item integer(X)
@findex integer/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds if X is an integer; otherwise fails.

@item float(X)
@findex float/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds if X is a floating point number; otherwise fails.

@item number(X)
@findex number/1
@dfn{synchronisation:} Suspends until X is instantiated.

@dfn{behaviour:} Succeeds if X is an integer or a floating point number;
otherwise fails.
@end table

@node ArithmeticExpressions, TermComparison, TypeTests, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Arithmetic Expressions

@table @code
@item Value is Expression
@findex is/2
@dfn{synchronisation:} Suspends until Expression is ground.

@dfn{behaviour:} Expression is evaluated as an arithmetic expression, and the
resulting number is unified with Value. If any of the variables are
bound to non-numeric values, then the goal fails.  An arithmetic
expression is a term built from numbers, variables, and functors that
represent arithmetic functions. The functors available in Parlog are
given below.  In the following, X and Y are considered to be arithmetic
expressions.

@table @code
@item +X
Results in the positive value of X. The type of the result is the same
as the type of the operand.

@item -X
Results in the negative value of X. The type of the result is the same
as the type of the operand.

@item \X
Results in the complements of the bits in X.

@item integer(X)
Results in X if it is an integer. Otherwise, if it is a float, the
result is the nearest integer that is between it and 0.

@item float(X)
Results in X if it is a float. Otherwise, if it is an integer, the
result is the floating point equivalent.

@item X+Y
Results in the sum of X and Y. If both operands are integers, the result
is an integer; otherwise the result is a float.

@item X-Y
Results in the difference of X and Y. If both operands are integers, the
result is an integer; otherwise the result is a float.

@item X*Y
Results in the product of X and Y. If both operands are integers, the
result is an integer; otherwise the result is a float.

@item X/Y
Results in the quotient of X and Y. The resultant value is always a
float, regardless of the types of the operands.

@item X//Y
Results in the integer quotient of X and Y. The resultant value is
always a (truncated) integer.

@item X mod Y
Results in the remainder after the integer division of X by Y.  The
result always has the same sign as X.

@item X/\Y
Results in the bitwise conjunction of X and Y.

@item X\/Y
Results in the bitwise disjunction of X and Y.

@item X<<Y
X is left-shifted Y places.

@item X>>Y
X is right-shifted Y places with sign extension.
@end table
@end table

@node TermComparison, TermManipulation, ArithmeticExpressions, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Term Comparison

Term comparison is based on a lexical ordering.  The lexical ordering
provides a way of ordering all terms using the following criteria :
@example
	variables @@< numbers @@< atoms @@< structures
@end example

@itemize @bullet
@item
variables are compared using their addresses

@item
numbers are compared numerically e.g. -3 @@< 1 @@< 1.5 @@< 2

@item
atoms are compared using their ASCII codes

@item
structures are first ordered by arity, then functor, then
1st argument, 2nd argument etc.

@item
A list is considered as a structure with functor '.' and arity 2
e.g. f(1) @@< [1] @@< f(1,2)
@end itemize

@table @code
@item X=@@=Y
@findex =@@=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically equal to Y; else fails.

@item X\=@@=Y
@findex \=@@=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically not equal to Y; else fails.
Note that the suspension only occurs at the top level; e.g.
@example
	X \=@@= Y
@end example
suspends but
@example
	g(X) \=@@= g(Y)
@end example
succeeds.  This primitive can therefore be used as a non-suspending
equality test by wrapping the two term to be compared inside a structure
such as @code{g/1 }.

@item X@@<Y
@findex @@</2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically less than Y; else fails.

@item X@@>Y
@findex @@>Y/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically more than Y; else fails.

@item X@@=<Y
@findex @@=</2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically less than or equal to Y; else fails.

@item X@@>=Y
@findex @@>=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} Succeeds if X is lexically more than or equal to Y; else fails.

@item compare(Op,Term1,Term2)
@findex compare/3
@dfn{synchronisation:} Suspends until Term1 and Term2 are instantiated.

@dfn{behaviour:} Unifies Op with one of `@code{=}', `@code{<}' or `@code{>}'
depending on whether Term1 is lexically equal, less than or greater than
Term2 respectively.

@item X=:=Y
@findex =:=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers,
and the goal succeeds if they are equal.

@item X=\=Y
@findex =\=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers,
and the goal succeeds if they are not equal.

@item X<Y
@findex </2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers,
and the goal succeeds if X is strictly less than
Y.

@item X>Y
@findex >/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers,
and the goal succeeds if X is strictly greater than
Y.

@item X=<Y
@findex =</2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers, and
the goal succeeds if X is less than or
equal to Y.

@item X>=Y
@findex >=/2
@dfn{synchronisation:} Suspends until X and Y are instantiated.

@dfn{behaviour:} X and Y must be numbers, and
the goal succeeds if X is greater than or
equal to Y.
@end table

@node TermManipulation, Metalevel, TermComparison, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Term Manipulation

@table @code
@item Term =.. List
@findex =../2
@dfn{synchronisation:} Suspends until either Term or List is instantiated.

@dfn{behaviour:} List is a list whose head is the atom corresponding to the
principal functor of Term and whose tail is a list of the arguments of
Term. If Term is uninstantiated, then List must be instantiated either
to a list of determinate length whose head is an atom, or to a list of
length 1 whose head is a number.

@item functor(Term,Functor,Arity)
@findex functor/3
@dfn{synchronisation:} Suspends until Term is instantiated, or Functor and
Arity are instantiated.

@dfn{behaviour:} If Term is instantiated, Functor and Arity will be bound to
the functor and arity of Term. If Functor and Arity are instantiated,
Term will be bound to the most general Term having this name and arity.

@item arg(N,Term,Arg)
@findex arg/3
@dfn{synchronisation:} Suspends until N and Term are instantiated.

@dfn{behaviour:} Initially, N must be instantiated to a positive integer and
Term to a compound term. The result of the call is to unify Arg with the
Nth argument of Term. (The arguments are numbered from 1 upwards).  If
the initial conditions are not satisfied or N is out of range, the call
fails.

@item atom_chars(Atom,String)
@findex atom_chars/2
@dfn{synchronisation:} Suspends until either Atom or String is instantiated.

@dfn{behaviour:} If Atom is instantiated (it must be an atom),
then String is unified with the list of character codes in its name.  If
String is ground (it must be a list of character codes), Atom is
unified with the atom containing those
characters.  Note that in Parallel Parlog @code{"add"}, for example, is
shorthand for [97,100,100] (@pxref{Syntax}).

@item number_chars(Number,String)
@findex number_chars/2
@dfn{synchronisation:} Suspends until either Number or String is instantiated.

@dfn{behaviour:} If Number is instantiated (it must be an integer or
floating-point number),
then String is unified with the list of character codes in its name.  If
String is ground (it must be a list of character codes), Number is
unified with the number containing those characters.

@item name(Atomic,String)
@findex name/2
@dfn{synchronisation:} Suspends until either Atomic or String is instantiated.

@dfn{behaviour:} If Atomic is instantiated (it must be an atom or a number),
then String is unified with the list of character codes in its name.  If
String is ground (it must be a list of character codes), Atomic is
unified with the number if possible, otherwise the atom containing those
characters.

@item concat_atom(List,Atom)
@findex concat_atom/2
@dfn{synchronisation:} Suspends until List is instantiated.

@dfn{behaviour:} List must be instantiated to a list of atomics (numbers
or atoms).  Atom is unified with the concatenation of the names of
atomics in List.

@item varoccurs(Term,VarList)
@findex varoccurs/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Unifies VarList with a list of variable occurrences in Term.
A variable may appear in VarList more than once if there are multiple occurrences
of it in Term.

@item varsin(Term,VarList)
@findex varsin/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Unifies VarList with a list of variables that occur in Term.
This list may be different from @code{varoccurs/2} because duplicates are
removed.  Each variable occurs in VarList only once regardless of how many
occurrences there are in Term.

@item copy_term(Term1,Term2)
@findex copy_term/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} A copy of Term1 with new variables is unified with Term2.
@end table

@node Metalevel, InputOutput, TermManipulation, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Metalevel

@table @code
@item call(Call)
@findex call/1
@dfn{synchronisation:} Suspends until Call is instantiated.

@dfn{behaviour:} If Call is instantiated to an atom or compound term, then the
goal call(Call) is executed exactly as if that term appeared textually
in its place. If Call fails, then call(Call) fails.

@item call(Call,Status,Control)
@findex call/3
@dfn{synchronisation:} Suspends until Call is instantiated.

@dfn{behaviour:} This primitive always succeeds binding Status to
@code{success} or @code{failed} depending on whether Call
succeeded or not.  If Control is instantiated to @code{stop},
execution of Call is terminated, binding Status to @code{stopped}.

Note: Due to the nature of the implementation, there is an uncorrectable
bug such that when a process is @file{stopped} in this way, Call
continues to execute until it succeeds or fails.  Status will
still be bound correctly to the value @code{stopped}.  This bug
is manifested most evidently when Call writes output.

@item Module#Call
@findex #/2
@dfn{synchronisation:} Suspends until Module and Call are bound.

@dfn{behaviour:} Evaluates Call as it is defined in Module.  Succeeds if Call
succeeds.  Fails if Call fails.

@item fail
@findex fail/0
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Fails.

@item not(Call)
@findex not/1
@dfn{synchronisation:} Suspends until Call is bound.

@dfn{behaviour:} This fails if the goal Call has a solution, and succeeds
otherwise. This is not real negation, which is not possible in Parlog,
but negation-by-failure meaning that P is not provable.

@item halt
@findex halt/0
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Terminates the Parallel Parlog session.

@item true
@findex true/0
@dfn{synchronisation:} No suspension

@dfn{behaviour:} Always succeeds.
@end table

@node InputOutput, ChannelIO, Metalevel, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Input and Output

Input and output is dealt with by utilising @code{streams}.  A stream can
refer to a file or to a terminal, and must be either an input or an
output stream.  At any time, there is one @dfn{current input} stream and
one @dfn{current output} stream.  Input and output predicates fall into
two categories:

@enumerate
@item Those that use the current input and output stream.

@item Those which take an explicit stream argument.
@end enumerate

The standard streams are identified by @code{user_input},
@code{user_output}, or @code{user_error}. Other streams are identified by
the term returned by @code{open/3} in its Stream argument (see
below).

The current input and output streams are set to @code{user_input} and
@code{user_output} upon entry to the Parallel Parlog system.

@menu
* Streams::                     Streams
* CharacterIO::                 Character I/O
* TermIO::                      Term I/O
@end menu

@node Streams, CharacterIO,  , InputOutput
@comment  node-name,  next,  previous,  up
@subsubsection Streams

@table @code
@item open(File,Mode,Stream)
@findex open/3
@dfn{synchronisation:} Suspends until File and Mode are instantiated.

@dfn{behaviour:} If Mode is the atom @code{read}, and File is an existing file
for which the user has read permission then it succeeds, unifying Stream
with a term representing an input stream for File.  If mode is the atom
@code{write} and the user has permission to write to the file then it
succeeds, unifying Stream with a term representing an output stream for
File.  If mode is the atom @code{append} and File is an existing file for
which the user has write permission then it succeeds, unifying Stream
with a term representing an output stream for appending to File.
Otherwise the predicate fails.

@item close(Stream)
@findex close/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} If Stream is an open stream then it succeeds and closes the
stream; otherwise it fails. Failure will also occur if Stream is the
stream for standard input or output.

@item set_input(Stream)
@findex set_input/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} If Stream is an open stream then it succeeds, setting the
current input to the stream.  Otherwise it fails.

@item set_output(Stream)
@findex set_output/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} If Stream is an open stream then it succeeds, setting the
current output to the stream.  Otherwise it fails.

@item current_input(Stream)
@findex current_input/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} This causes Stream to be unified with the current input stream.

@item current_output(Stream)
@findex current_output/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} This causes Stream to be unified with the current output stream.

@item clear_input(Stream)
@findex clear_input/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Flushes the input buffer associated with the given stream.
For terminal input this means throwing away the rest of the current
line.  The current line being the sequence of characters input but not
yet read off the stream.

@item flush_output(Stream)
@findex flush_output/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Flushes the output buffer associated with the given stream.
@end table

@node CharacterIO, TermIO, Streams, InputOutput
@comment  node-name,  next,  previous,  up
@subsubsection Character I/O

@table @code
@item get0(Stream,N)
@itemx get0(N)
@findex get0/2
@findex get0/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Unifies N with the ASCII code of the next character from the
input stream Stream.  If end of file is encountered, N is unified with
the atom @code{end_of_file}. If the end of stream was reached on a
previous input command, then this call will give an error message and
abort the computation. The one argument version reads from the current
input stream.

@item get(Stream,N)
@itemx get(N)
@findex get/2
@findex get/1
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Unifies N with the ASCII code of the next non-space character
from the input stream Stream. Space characters are all those with ASCII
codes less than or equal to 32; this includes space, tab, linefeed and
all control characters.  If end of file is encountered, N is unified
with the atom @code{end_of_file}. If the end of stream was reached on a
previous input command, then this call will give an error message and
abort the computation.  @code{get/2} should not be used with
@code{user_input}. The one argument version reads from the current input
stream.

@item skip(Stream,N)
@itemx skip(N)
@findex skip/2
@findex skip/1
@dfn{synchronisation:} Suspends until Stream and N are instantiated.

@dfn{behaviour:} Advances the input stream Stream to immediately past the
character represented by the ASCII code N (N must be an integer). If end
of file is encountered N is unified with the atom @code{end_of_file}.  If
N is not an integer, or is an integer outside the range 0..127, then the
call fails after issuing an error. The one argument version reads from
the current input stream.

@item put(Stream,N)
@itemx put(N)
@findex put/2
@findex put/1
@dfn{synchronisation:} Suspends until Stream and N are instantiated.

@dfn{behaviour:} Writes the character represented by the ASCII code N to the
stream represented by Stream.  If N is not an integer, or is an integer
outside the range 0..127, then the call fails after reporting an error.
The one argument version writes to the current output stream.

@item nl(Stream)
@itemx nl
@findex nl/1
@findex nl/0
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Starts a new line on the output stream Stream.  It is
equivalent to @code{put(Stream,10)}. The zero argument version writes to
the current output stream.

@item tab(Stream,N)
@itemx tab(N)
@findex tab/2
@findex tab/1
@dfn{synchronisation:} Suspends until Stream and N are instantiated.

@dfn{behaviour:} Writes N spaces to the output stream Stream. N must be an
integer; otherwise an error is issued and the call fails.
The one argument version writes to the current output stream.
@end table

@node TermIO,  , CharacterIO, InputOutput
@comment  node-name,  next,  previous,  up
@subsubsection Term I/O

@table @code
@item read(Stream,Term)
@findex read/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Reads the next Parlog term from the input stream Stream and
unifies it with Term.  The term must be terminated by a full-stop
followed by a space character or a newline.  These will be consumed by
the call but not returned in Term.  When a syntax error is encountered,
an error message is printed which indicates where the error occurs in
the input, and the call then fails.  If the end of the file is
encountered then the atom @code{end_of_file} is unified with Term. If the
end of stream was reached on a previous input command, then this call
will produce an error message and abort the computation.

@item read(Stream,OpSet,Term,Variables)
@findex read/4
@dfn{synchronisation:} Suspends until Stream and Opset are bound.

@dfn{behaviour:} As for @code{read/2 } except that the operator set given by
OpSet is used to parse the term, and Variables is unified with a list of
(Atom,Variable) pairs giving the atom representation of each variable in
the term.

@item display(Stream,Term)
@findex display/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Writes the term Term to the output stream Stream in prefix
notation, with no quotes for atoms that need quoting in order to be read
back in.

@item write(Stream,Term)
@findex write/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Writes the term Term to the output stream Stream according to
the operator precedences of the @code{system} operator set, with no
quotes for atoms that need quoting in order to be read back in
(@pxref{SystemOperatorDeclarations}).

@item writeq(Stream,Term)
@findex writeq/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Writes in the same way as @code{write/2}, but with quotes
around atoms that need quoting in order to be read back in.

@item write_canonical(Stream,Term)
@findex write_canonical/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Writes the term Term to the output stream Stream, with quotes
around atoms that need quoting in order to be read back in.

@item print(Stream,Term)
@findex print/2
@dfn{synchronisation:} Suspends until Stream is instantiated.

@dfn{behaviour:} Writes the term Term to the output stream Stream.  If
a user-defined @code{portray/2} is defined in the user module,
@code{portray/2} is used to write the term.  If it is not defined or
if no clause matches, @code{print/2} behaves the same as @code{write/2}.
The two arguments of @code{portray/2} are the stream and the term to be
written.
@end table

The predicates below are equivalent to their counterparts above, except
that they act upon the current output stream :

@example
      display(Term)           write(Term)
      writeq(Term)            write_canonical(Term)
      print(Term)
@end example

@findex display/1
@findex write/1
@findex writeq/1
@findex write_canonical/1

As expected, @code{read/2} has a short form for reading from the current
input stream :
@example
      read(Term)
@end example

@findex read/1

@node ChannelIO, CompilationAndLoading, InputOutput, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Channels

Channels are a way of naming stream variables.  A channel is
associated with a stream variable via an identifier.  Terms
which are written to the channel successively instantiate the
tail of the stream variable.  This channel mechanism can therefore
be used as an efficient way of implementing @code{merge/3} since
many processes can write to the same channel identifier.

Another use of channels is as a means for process communication
without sharing variables explicitly.  One process may instantiate
a stream variable, which an independent process (i.e. does not share
any variables) can read by getting the channel via a pre-defined
channel identifier.

Since multiple processes may write to the same channel, and multiple
processes may get the channel, this provides a simple mechanism
for one-to-many, many-to-one and many-to-many process communication.

Channel identifiers are either numbers generated by the system or
atoms specified by the user.  User-defined channel identifiers
provide a way of accessing stream variables created by
other processes.

@table @code
@item create_channel(ID, Var)
@findex create_channel/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Create a new channel and assigns a name ID to a stream
variable Var.  Var must be an uninstantiated variable.  If ID
is a variable, it will be bound to a system generated channel
identifier (a number).  If ID is an atom, that atom will be used as the channel
identifer.  If ID is neither a variable nor an atom, the predicate
fails.

@item write_channel(Ch, Term)
@findex write_channel/2
@dfn{synchronisation:} Suspends until Ch is instantiated.

@dfn{behaviour:} The term Term is written to the channel Ch, or more precisely
the tail of the stream variable associated with the channel is instantiated
to @code{[Term|_]}.  Ch is either
a system generated channel identifier or a user-defined one.  The
channel must have been previously opened using @code{create_channel/2}
and it must not be closed yet, otherwise it fails.

@item get_channel(Ch, Var)
@findex get_channel/2
@dfn{synchronisation:} Suspends until Ch is instantiated.

@dfn{behaviour:} Var is unified with the stream variable associated with
the channel.  This primitive enables the programmer to access the
complete history of the stream variable.  The primitive fails if
the channel is not valid.

@item close_channel(Ch)
@findex close_channel/1
@dfn{synchronisation:} Suspends until Ch is instantiated.

@dfn{behaviour:} The channel Ch is closed.  The tail of the stream variable
associated with the channel is instantiated to @code{[]}.  The primitive
fails if the channel is not valid.
@end table


@node CompilationAndLoading, Operators, ChannelIO, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Compilation and Loading

@table @code
@item compile(File)
@findex compile/1
@dfn{synchronisation:} Suspends until File is instantiated.

@dfn{behaviour:} Compiles a Parlog source code file.  Initially, the name File
is sought as the input file; if that does not exist then File is tried
with @file{.par} appended to it. If still no match is found, an error is
issued and the call succeeds. If the compiler is not already loaded,
then a call to @code{compile/1 } will automatically load it.  The filename
is searched in a list of default directories (@pxref{FilenamesAndPaths}).

@item load(File)
@findex load/1
@dfn{synchronisation:} Suspends until File is instantiated.

@dfn{behaviour:} Loads a Parlog object code file.  Initially, the name File is
sought; if that does not exist then File with @file{.o} appended is tried.
If still no match is found, an error is issued and the call fails.
The filename is searched in a list of default directories
(@pxref{FilenamesAndPaths}).

@item load_foreign(Predicates,Obj,Libraries)
@findex load_foreign/3
@dfn{synchronisation:} Suspends until all three arguments are instantiated.

@dfn{behaviour:} Loads C predicates into the system.  See @pxref{ForeignRoutines}.

@item load_foreign(Predicates,Obj)
@findex load_foreign/2
@dfn{synchronisation:} Suspends until both arguments are instantiated.

@dfn{behaviour:} As for
@code{load_foreign/3 }
but with no libraries specified.

@item load_foreign_io(Predicates,Obj,Libraries)
@findex load_foreign_io/3
@dfn{synchronisation:} Suspends until all three arguments are instantiated.

@dfn{behaviour:} Loads C predicates into the system that can only be executed
by the master processor.   This makes a difference only on multiprocessor
implementations where Input/Output is handled by one master processor to
preserve ordering.  On uniprocessors (implementations on Suns), this
primitive is the same as @code{load_foreign/3} (@pxref{ForeignRoutines}).

@item load_foreign_io(Predicates,Obj)
@findex load_foreign_io/2
@dfn{synchronisation:} Suspends until both arguments are instantiated.

@dfn{behaviour:} As for
@code{load_foreign_io/3}
but with no libraries specified.

@item defined(Pred)
@findex defined/1
@dfn{synchronisation:} Suspends until Pred is instantiated.

@dfn{behaviour:} Succeeds if a definition for the predicate Pred exists,
fails otherwise.
Predicates may be system defined or loaded by the user.  A predicate
may be specified using the @code{Name/Arity} notation or a sample call.
@example
| ?- defined(append/3).

yes
| ?- defined(append(_,_,_)).

yes
| ?- defined(append(_,_)).

no
| ?- 
@end example

@item public Preds
@findex public/1
@dfn{synchronisation:} Suspends until Preds is ground.

@dfn{behaviour:} Preds is expected to be a sequence of Name/Arity pairs that
represent predicate names, otherwise the call fails.  If a call to
@code{public/1} succeeds, these predicates become visible to all other
modules.

@item export(Predicates)
@findex export/1
@dfn{synchronisation:} Suspends until Predicates is ground.

@dfn{behaviour:} The predicates list is expected to consist of Name/Arity
pairs that represent predicate names, otherwise the call fails. This
enables the predicates listed (which should be private to this module)
to be imported into other modules with @code{import/2}.

@item import(Module,Predicates)
@findex import/2
@dfn{synchronisation:} Suspends until Module and Predicates are ground.

@dfn{behaviour:} The Predicates list is expected to consist of Name/Arity
pairs that represent predicate names, otherwise the call fails. This
imports the definitions of Predicates from Module into the current
module and can be used by code subsequently loaded into the current
module.

@item module(Module)
@findex module/1
@dfn{synchronisation:} Suspends until Module is instantiated.

@dfn{behaviour:} Makes Module the current module.

@item current_module(Module)
@findex current_module/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Unifies Module with the current module.
@end table

@node Operators, Spypoints, CompilationAndLoading, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Operators Related

@table @code
@item op(OpSet,Precedence,Type,Op)
@findex op/4
@dfn{synchronisation:} Suspends until all four arguments are instantiated.

@dfn{behaviour:} Inserts atoms into the operator set OpSet with the specified
precedence and type.  Precedence should be an integer between 1 and
1200.  The lower the precedence, the tighter binding the operator.
Type should be one of fx, fy, xf, yf, xfx, xfy or yfx, and Op should
be an atom or a list of atoms.  The types are defined as follows :

@table @code
@item fx
non associative prefix operator
@item fy
associative prefix operator
@item xf
non associative postfix operator
@item yf
associative postfix operator
@item xfx
non associative infix operator
@item xfy
right-associative infix operator
@item yfx
left-associative infix operator
@end table

Note that an operator may be declared to be prefix, postfix and
infix all at the same time, though this is confusing and not
recommended.

The precedence and type of an operator may be changed by re-declaring
it.  To remove an operator, re-declare it with precedence 0
and the relevant non associative type (i.e. fx, xf or xfx).

@item current_op(OpSet,Precedence,Type,Op)
@findex current_op/4
@dfn{synchronisation:} Suspends until OpSet,Type and Op are instantiated.

@dfn{behaviour:} Returns the precedence of the Op operator declared in the
OpSet operator set.  Type should be one of fx, fy, yf, xfx, xfy or yfx,
Op should be an atom, and OpSet should be an operator set.  If no match
is found in OpSet, but an operator is found in the system operator
set, then the precedence of the system operator is returned.
@end table

The following two system predicates are equivalent to their counterparts
above, except that they act upon the operator set system :
@example
	op(Prec,Type,Op)          current_op(Prec,Type,Op)
@end example

@findex current_op/3
@findex op/3


@node Spypoints, Miscellaneous, Operators, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Spypoints

@table @code
@item spy(Pred)
@findex spy/1
@dfn{synchronisation:} Suspends until Pred is instantiated.

@dfn{behaviour:} Pred must be a Name/Arity pair representing a predicate that
has already been loaded. If this is the case, @code{spy/1} succeeds,
setting spypoints on the named predicate; otherwise it fails.

@item nospy(Pred)
@findex nospy/1
@dfn{synchronisation:} Suspends until Pred is instantiated.

@dfn{behaviour:} Pred must be a Name/Arity pair representing a predicate that
has already been loaded.  If this is the case, @code{nospy/1} succeeds,
removing spypoints from the named predicate; otherwise it fails.
@end table

@node Miscellaneous,  , Spypoints, SystemPredicates
@comment  node-name,  next,  previous,  up
@subsection Miscellaneous

@table @code
@item util(Package)
@findex util/1
@dfn{synchronisation:} Suspends until Package is bound.

@dfn{behaviour:} Loads predicates from the specified package in the utilities
directory; examples are the foreign interface package (@pxref{ForeignRoutines}),
the tracer (@pxref{AlternativeTracer}), the Parlog Shell (@pxref{ParlogShell})
and the SPM compatibility package (@pxref{SPMCompatibility}).

@item statistics(Key,Val)
@findex statistics/2
@dfn{synchronisation:} Suspends until Key is bound.

@dfn{behaviour:} When Key is one of the atoms @code{suspensions}, @code{gcs},
@code{heap}, @code{stack}, @code{process}, @code{program}, @code{memory},
@code{runtime} or @code{calls} the appropriate values will be unified with
Val and the predicate will succeed; otherwise it will fail.  For memory
values (when Key has the value @code{heap}, @code{stack}, @code{process},
@code{program} or @code{memory}), Val is bound to a term of the form
@code{[memory_used, memory_free]}. These values are given in `word'
(4 byte) units except for @code{process}, which is given in
`process' (32 byte) units, and @code{memory} which returns the
total size of the allocated and free memory segments in bytes.  When Key
is @code{runtime}, Val is bound to a list of the form @code{[total, Ilast]},
where @code{total} is the user cpu time since the Parallel
Parlog system was invoked, and @code{last} is the time since the last
call to @code{statistics/2 } or @code{statistics/0}.

@item statistics
@findex statistics/0
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Prints out all the values generated by
@code{statistics/2 }
onto the
current output stream.

@item unix(Command)
@findex unix/1
@dfn{synchronisation:} Suspends until Command is instantiated.

@dfn{behaviour:} Can be used in the following ways:

@example
unix(cd)                 % change working directory to home
unix(cd(Path))           % change working directory to Path
unix(shell)              % invoke an interactive shell
unix(system(Cmd))        % pass Cmd to sh(1)
unix(access(File))       % test whether File is readable
@end example

@item setenv(Env,Val)
@findex setenv/2
@dfn{synchronisation:} Suspends until Env and Val are instantiated.

@dfn{behaviour:} Set the environment variable Env to the value Val.
Env must be instantiated to an atom and Val must be either an atom
or a number.

@item getenv(Env,Val)
@findex getenv/2
@dfn{synchronisation:} Suspends until Env is instantiated.

@dfn{behaviour:} Val is unified with the value retrieved from the 
environment variable Env.  The value is either an atom or a number.
Note that Val is bound to a number if the value can be converted
to an integer or a floating point number.  This has the side
effect that atom values whose name resemble numbers (e.g.
@code{'123'}) cannot be retrieved successfully if stored in
an environment variable.

@item clock(T)
@findex clock/1
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} T is unified with the current time represented
as the number of seconds since 00:00:00 1st January, 1970.

@item absolute_file_name(F,Abs)
@findex absolute_file_name/2
@dfn{synchronisation:} Suspends until F is instantiated.

@dfn{behaviour:} Abs is unified with the absolute path name of
the file F.  The filename F is searched in the directories
specified in @kbd{PARLOG_PATH} (@pxref{Environment}).  Meta-characters
in F are recognised (@pxref{FilenamesAndPaths}).  The primitive
fails if F is not found.

@item stat(F,Abs,ModTime,Size,Mode,Uid,Gid)
@findex stat/7
@dfn{synchronisation:} Suspends until F is instantiated.

@dfn{behaviour:} This primitive retrieves information about the file
F.  The filename F is searched in the directories
specified in @kbd{PARLOG_PATH} (@pxref{Environment}).  Meta-characters
in F are recognised (@pxref{FilenamesAndPaths}).  The primitive
fails if F is not found.

If F is found, Abs is unified with the absolute path name, ModTime
is the time of last modification (see @code{clock/1}), Size is the
file size, Mode is the file permissions, Uid and Gid are unified
with the user and group ID of the file respectively.

The file permissions are represented by a single integer in which each
bit indicates whether the specified permission is set.  The permissions
and the corresponding bit values are as follows :
@example
   octal  decimal  permission
   =====  =======  ==========
    001       1    Execute (search) by others.
    002       2    Write by others.
    004       4    Read by others.
    010       8    Execute (search) by group.
    020      16    Write by group.
    040      32    Read by group.
    100      64    Execute (search in directory) by owner.
    200     128    Write by owner.
    400     256    Read by owner.
   1000     512    Sticky bit.
   2000    1024    Set group ID on execution.
   4000    2058    Set user ID on execution.
@end example

@item append(List1,List2,List3)
@findex append/3
@dfn{synchronisation:} Suspends until List1 is instantiated.

@dfn{behaviour:} List3 is unified with the result of appending List2
to the end of List1.

@item merge(List1,List2,List3)
@findex merge/3
@dfn{synchronisation:} Suspends until either List1 or List2 is instantiated.

@dfn{behaviour:} List3 is unified with the result of merging the two
lists List1 and List2.  This primitive implements a fair merge in
the sense that if elements are available on both List1 and List2,
then elements in List3 are taken alternately from List1 and List2.
@end table

@node ForeignRoutines, AlternativeTracer, SystemPredicates, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Foreign Routines

The Parallel Parlog system allows C predicates to be loaded dynamically
into the system either as predicates to be executed on any processor
(using @code{load_foreign/3 ),} or predicates only executable by the
master processor (using @code{load_foreign_io/3 ).}

To aid integration of C routines into the Parlog environment, a
@dfn{foreign} package is provided, for generating the interface
routines that convert Parlog data types into C data types and invokes
the C routines.  The interface routines are generated from a file of
@code{foreign/2} declarations, which have a similar format to those used
by Quintus Prolog.

@menu
* ForeignDeclarations::         Foreign Declarations
* AddingForeignRoutines::       Adding Foreign Routines
@end menu

@node ForeignDeclarations, AddingForeignRoutines,  , ForeignRoutines
@comment  node-name,  next,  previous,  up
@subsection Foreign Declarations

The syntax of the foreign declarations is as follows :

@example
foreign( Function, PredicateSpecification ).

PredicateSpecification = PredicateName(ArgSpec, ArgSpec,...)

ArgSpec =  Arg?         input argument
        |  Arg^         output argument
        |  [Arg^]       argument for the function return value

Arg = short | integer | float | string | atom
@end example

In this context, string refers to a Parlog atom which is converted to
a C string; whereas atom refers to the internal representation of a
Parlog atom (a tagged Word) which is passed directly to the C routine as
a long unsigned integer.

The following conversions are carried out according to the ArgSpec type :

@example
        Parlog: short?        -->        C: integer
        Parlog: integer?      -->        C: integer
        Parlog: float?        -->        C: double
        Parlog: string?       -->        C: char *
        Parlog: atom?         -->        C: Word

        Parlog: short^        <--        C: integer *
        Parlog: integer^      <--        C: integer *
        Parlog: float^        <--        C: double *
        Parlog: string^       <--        C: char **
        Parlog: atom^         <--        C: Word *

        Parlog: [short^]      <--        C: return (integer)
        Parlog: [integer^]    <--        C: return (integer)
        Parlog: [float^]      <--        C: return (double)
        Parlog: [string^]     <--        C: return (char *)
        Parlog: [atom^]       <--        C: return (Word)
@end example

Some examples of foreign declaration are :

@example
    foreign( sin, sin(float?, [float^]) ).
    foreign( rename, rename(string?, string?) ).
    foreign( test, tester(integer?, [integer^], atom?, atom^) ).
@end example

@node AddingForeignRoutines,  , ForeignDeclarations, ForeignRoutines
@comment  node-name,  next,  previous,  up
@subsection Adding Foreign Routines

The procedure for intergrating a C routine into the Parallel Parlog environment
is as follows:

@enumerate
@item
Consider a C routine @code{strcat()} which takes two strings as its
arguments and returns the concatenated string. It is defined in
@file{strcat.c} and is compiled to an object file in the usual way :
@example
cc -O -c strcat.c
@end example

@item
A foreign declaration for this C routine is then placed in a Parlog
file, called @file{iface.par} :
@example
foreign(strcat, strcat(string?, string?, [string^])).
@end example
This states that the Parlog predicate
@code{strcat/3}
will call the C routine
@code{strcat()}
and return its result as a Parlog atom in its 3rd argument.

@item
Now the interface file for this declaration can be generated by loading
the foreign package and calling @code{make_interface/1} in the following
way :
@example
| ?- util(foreign).
[loading foreign]

yes
| ?- make_interface(iface).

yes
@end example

This produces a C file called @file{iface.c} which must be then be
compiled to an object file :
@example
cc -O -c iface.c
@end example

@item
The interface and C routine object files can now be loaded in to the
Parlog system with the @code{load_foreign/3} command :
@example
| ?- load_foreign([strcat/3], 'iface.o', 'strcat.o').
@end example
@end enumerate

@code{strcat/3} is the name of the Parlog interface predicate,
@file{iface.o} is the object file for the C interface and
@file{strcat.o} is the object file for the original C routine.  Now the
@code{strcat/3} predicate can be invoked :
@example
| ?- strcat(foo, bar, X).
X = foobar

yes
@end example

In practise, an interface file can specify the interfaces to C routines
in several files. In that situation, the 3rd argument of
@code{load_foreign/3} or @code{load_foreign_io/3} will contain several
files and/or libraries, e.g.

@example
| ?- load_foreign_io([a/1, b/1, ..], 'iface.o', 'win1.o win2.o -lXlib').
@end example


@node AlternativeTracer, ParlogShell, ForeignRoutines, ReferenceManual
@comment  node-name,  next,  previous,  up
@section An Alternative Tracer

The @dfn{trace} utility provides a more comprehensive tracing facility
which allows the user to execute a Parlog program with set break points
and trace points.  At a trace point the user is informed of some action
which took place during execution.  At a break point execution is halted
and the user is able to investigate the current state of the system.

The basis behind this tracer is that each clause in a Parlog program may
be considered as a rewrite rule. Any point in the execution of a query
by the program may be represented by a list of goals. This list starts
as the initial query, and the rewrite rules are continually applied to
it until either it is empty, in which case the query succeeds, or no
rewrite rule may be applied, in which case the query fails. The tracer
also halts at deadlock, when no goal is sufficiently instantiated to
allow a commitment to a rewrite to take place.

@menu
* LoadingUsingTracer::          Loading and Using the Tracer
* TraceCommands::               Trace Commands
* DisplayingStateComputation::  Displaying State of Computation
@end menu

@node LoadingUsingTracer, TraceCommands,  , AlternativeTracer
@comment  node-name,  next,  previous,  up
@subsection Loading and Using the Tracer

The tracer is loaded with the command: @code{util(trace)}.  The program
to be traced should be in one or more files named @file{<name>.par}.  To
enter the tracer type :
@example
partrace([<name1>,<name2>, ..., <namen>]).
@end example
where @code{[<name1>,<name2>, ..., <namen]} is a list of the
filenames which contain the
program to be traced (without the @file{.par} suffix).  The brackets may
be omitted if there is only one file.  The program will then be parsed
by the tracer after which the tracer will query the user for the sort of
tracing required.

The system will first prompt with:
@example
 Full trace?
@end example

The user should reply `@kbd{y}' for yes or `@kbd{n}' for no.  In full trace
mode every time a goal commits to a clause the reduction made is printed
out, a break is made in computation, and the user is prompted for a
trace command.

If the user chooses not to use full trace mode the system will first ask
for a list of predicates to be traced on reduction. These should be
entered one to a line and followed by an empty line. If there is any
ambiguity over arity a predicate name may be followed by a slash and its
arity.  For example :
@example
pred1
pred2/2
pred2/3
pred3
@end example
If the user just types `@kbd{@key{<CR>}}' following the prompt no predicate
will be traced.  At any point in the computation when a goal for one of
the predicates listed for tracing commits to a clause the reduction will
be printed in the form:
@example
<goal> => <body of new clause with variable bindings passed through>
@end example
If output modes are used, any unifications giving output are also printed
in the form:
@example
<variable> <= <term>
@end example

Following the prompt for tracing, the user is prompted for a list of
predicates to break on reduction.  The list is entered in the same way
as above. When a goal for a predicate in this second list commits, the
reduction will be printed as before, but execution will also halt, and
the user will be prompted for a trace command.

Whether in full trace mode or not, the user will also be asked for a
list of predicates to be traced on completion. This is a form of tracing
based on the procedural view of Parlog. It prints out the final form of
a goal when it has completed execution. A goal has completed execution
either if it reduces to the empty list or if it has reduced to a list of
subgoals all of which have completed execution. A completion is
indicated by the trace:
@example
* Completed * <goal>
@end example

@node TraceCommands, DisplayingStateComputation, LoadingUsingTracer, AlternativeTracer
@comment  node-name,  next,  previous,  up
@subsection Trace Commands

At a break point, the user is asked for a command with the prompt:
@example
Trace command :
@end example

A `@kbd{@key{<CR>}}' typed at this point will display the state of
computation (see below), otherwise one of the following commands are can
be typed:

@table @kbd
@item c
continue execution until next trace point
@item f
give full display, including all goals following a sequential `@kbd{&}'
@item g
give standard display and allow user to investigate goals
@item h
give list of available commands
@item q
quit execution
@item t
reset trace information
@item u
undo trace points and continue execution until completion
@end table

@node DisplayingStateComputation,  , TraceCommands, AlternativeTracer
@comment  node-name,  next,  previous,  up
@subsection Displaying State of Computation

At any point in the computation goals in the list of current goals will be
of three types:

@enumerate
@item
Those on which no attempt has been made to reduce, but which could be
chosen for reduction.
@item
Those on which an attempt to reduce has been made, but which have not
yet committed, possibly due to a suspension while awaiting a variable
instantiation.
@item
Those which cannot be reduced as they follow a sequential `@kbd{&}', and the
goal before the `@kbd{&}' has not completed execution.
@end enumerate

The standard display only prints goals of the first two sorts, numbering
each goal.  The full display prints every goal and includes the
bracketing to indicate the mix of sequential and parallel execution.

Following the `investigate goals' command, `@kbd{g}', the list of
goals is displayed and the user may choose to investigate it in more
detail.  The system gives the following prompt:
@example
Enter goal number (0 to restart tracing) :
@end example

If an integer greater than 0 is entered, the system will give further
details on the goal with that number. If no attempt has been made to
reduce the goal, it will just be printed. Otherwise the current state of
reduction is given.  The current state of the guard computation, and any
input variables on which a possible commitment is suspended are given,
followed by the subgoals to which the goal would reduce if commitment
were made.  In the case of a sequential clause search, clauses which
would be tried if the current commitment cannot be made are displayed.

If `@kbd{0}' is entered instead of a goal number, the system returns to
the computation. Alternatively, the list of the goals can be redisplayed
by entering `@kbd{l}', and can be displayed in full form by entering
`@kbd{f}'.

@node ParlogShell, SPMCompatibility, AlternativeTracer, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Parlog Shell

To be written.

@node SPMCompatibility, MacParlogCompatibility, ParlogShell, ReferenceManual
@comment  node-name,  next,  previous,  up
@section SPM Compatibility

SPM [Foster et al. 1986] and Parallel Parlog are syntactically very
similar, and the system predicates in both languages offer much the same
functionality.  However, many SPM builtins are not present in Parallel
Parlog, but this obstacle can be overcome by loading the compatibility
package with the command @samp{util(spm)} It contains predicate
definitions for emulating certain SPM predicates from six broad
categories : I/O, unification, arithmetic, type testing, term
manipulation and utilities. The predicates defined in this package are :
@example
I/O.
        fcreate/2      fclose/1      fopen/3
        loutput/1      loutputnl/1   p/1
        pnl/1          print_term/1  print-term/2
        read_char/2    write_char/2  load_files/1

Unification.
        equal/2        unify/2       assign/2

Arithmetic.
        add/3          div/3         eq/2
        less/2         lesseq/2      mod/3
        mul/3          sub/3

Type testing.
        con/1          list/1        tuple/1

Term manipulation.
        a_to_s/2                     s_to_a/2
        list_to_struct/3             struct_to_list/3
        l_to_i/3                     i_to_l/2
        sappend/2                    predefined_op/1

Utilities.
        sleep/1

@end example

The SPM file manipulation primitives @code{access/1}, @code{assem/1} and
@code{edit/3 } are not supported.

In the area of I/O, the @code{get_term/2} and @code{put_term/3}
primitives for reading terms to and from a disk are not implemented in
Parallel Parlog, and @code{intok/3} and @code{iowait/2} are also not
available.

The @code{set/3} and @code{subset/3} all-solution primitives are absent
from Parallel Parlog, but all of the type testing primitives are present
(albeit after @samp{util(spm)} is loaded). However, care must be taken
when transferring user-defined predicates of this sort across from the
SPM, since SPM does not treat [] as an atom while Parallel Parlog does.

Parallel Prolog has neither a @code{freeze/2} nor a @code{melt/2}
primitive, but does offer @code{copy_term/2} for which they are most
often used.

Unavailable control primitives include @code{controlc/0}, @code{key/1}
and @code{space/3}.

Many SPM utilities are absent from Parallel Parlog, including
@code{date/3}, @code{show_date/0}, @code{time/3}, @code{instream/1},
@code{load_comp/0}, @code{sedit/0}, @code{sinput/2} and
@code{username/1}.  In addition, the utilities for type checking,
manipulating binary trees and the @dfn{xref} program are not supported.
Finally, Parallel Parlog does not support any window predicates,
although an X based window interface is planned for the future.

Parallel Parlog differs from SPM in having more predicates for testing
types, a set of lexical comparison primitives, a module system, a
spypoint mechanism, a C and UNIX interface, and statistic predicates. In
addition, Parallel Parlog enables extra operator sets to be defined, and
for commands to be included in source files.

Some SPM programs may need to be rewritten to take into account the
nonflat guard restriction of Parallel Parlog.  However, transformation
techniques exist to do this and these may be put into future releases.

@node MacParlogCompatibility, OldChanges, SPMCompatibility, ReferenceManual
@comment  node-name,  next,  previous,  up
@section MacParlog Compatibility

MacParlog [Conlon and Gregory 1989] is very similar to Parallel Parlog
except in the area of I/O, where it contains numerous primitives for
manipulating the Macintosh user interface.

Some versions of MacParlog can use arithmetic functions from MacProlog
[Clark et al. 1987], for such things as transcendental and exponential
calculations.

In the area of metalevel predicates, MacParlog allows terms to be
converted between ground and hollow versions using @code{toground/3} and
@code{tohollow/3}, and @code{varsin/2} permits the variables in a term
to be accessed.  @code{primitives/1} and
@code{private_macparlog_names/1} have no equivalents in Parallel Parlog.

I/O in MacParlog is based on @dfn{channels}, which are like Parallel
Parlog @dfn{streams} except that channels can be connected to Macintosh
windows. MacParlog input can utilise the mouse, and @code{key/0} is
available for waiting on input.  @code{gread/3} reads terms and returns
the variables contained within them, but is less flexible than
@code{read/4} in Parallel Parlog.  @code{skip/1} and @code{skip/2} are
slightly different in MacParlog since the 'N' argument can be a
character as well as an integer.

File handling in MacParlog utilises the Macintosh hierarchical filing
system rather than UNIX directories. However, the resulting predicates
are still quite similar to those in Parallel Parlog. The main difference
is the use of file dialogues in @code{create/2}, @code{new/3} and
@code{old/2} to access a particular file on a volume.

MacParlog has a number of extra utility predicates not present in
Parallel Parlog; namely @code{beep/1}, @code{recall/2},
@code{remember/2}, @code{ticks/1} and @code{time/3}.  Also, the language
permits deep guards to be tried in parallel, and so does not impose the
nonflat guard restriction found in Parallel Parlog.  MacParlog has a
number of window handling primitives and dialogue primitives, none of
which are available in Parallel Parlog.

Parallel Parlog has primitives for the lexical comparison of terms, for
gathering statistics, and accessing C and UNIX, which are not found in
MacParlog. Also, MacParlog does not support user-defined operator sets,
there is no module system, and compiling and loading is done via pull
down menus.  In addition, MacParlog does not allow commands to be
included in source files.

@node OldChanges, Changes, MacParlogCompatibility, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Changes Between V1.0 and V1.4

Most of the differences between the first and second releases of
Parallel Parlog are internal and transparent to the user.  This section
outlines the areas where the user may notice the changes.

As already mentioned, the memory management is quite different; in V1.0
the sizes of the four main data areas -- code, heap, argument stack
and process stack -- were determined at startup time, and controlled
by @code{-C}, @code{-H}, @code{-S} and @code{-P} options. In V1.4 each
area is made up of a linked list of segments or 64Kbyte blocks, which
are allocated from a pool of segments.  The initial number of segments
can be controlled by the @code{-m} option, but on machines in which
(shared) memory is expandable, the system will automatically allocate
more when needed.

C predicates can now be executed on any processor if loaded with
@code{load_foreign/3}, allowing Parlog to control the parallel execution
of C routines.  Predicates which must only run on the master processor
(e.g. I/O predicates or perhaps window predicates) should be loaded
using @code{load_foreign_io/3} instead.

There have been some changes to the compiler and the code it generates.
One noticeable change is that calls to @code{is/2} in the body can now
be executed `inline', with a full goal call only being made if the
inline call cannot proceed because input arguments are unbound. This
optimisation cannot be done if the call to @code{is/2} precedes a
sequential conjunction operator (`@kbd{&}') and is not in parallel with any
other goal calls - the compiler provides a warning message about this.

The @code{public/1} predicate has been changed so that it makes the
specified predicates visible in all modules. Before, only public
predicates in the system module were visible to all modules; public
predicates in other modules still had to be explicitly imported.

There were a few problems related to the use of floating point numbers
in V1.0 which have been fixed in V1.4.

@node Changes, BugsFeatures, OldChanges, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Changes Between V1.4 and V1.5

@table @code
@item *
``channel'' abstraction for merging streams (@pxref{ChannelIO})
@item *
recognition of escape characters within atoms (@pxref{EscapeSequences})
@item *
primitives to access environment variables (@pxref{Miscellaneous})
@item *
ability to define a search path for files (@pxref{Environment})
@item *
recognition of meta-characters in filenames (@pxref{FilenamesAndPaths})
@item *
background processing (@pxref{Running})
@item *
startup file processing (@pxref{StartupFile})
@item *
New primitives
@code{concat_atom/2},
@code{number_chars/2},
@code{atom_chars/2},
@code{append/3},
@code{merge/3},
@code{stat/7},
@code{absolute_file_name/2}
@code{defined/1},
@code{compare/3},
@code{clock/1},
@code{print/1},
@code{print/2},
@code{varoccurs/2},
@code{varsin/2}.
@item *
Improved compiler messages/warnings
@item *
Numerous bug fixes
@end table



@node BugsFeatures,  , Changes, ReferenceManual
@comment  node-name,  next,  previous,  up
@section Bugs/Features

Suspended guard calls for a candidate clause, which has been rejected in
favour of another clause, are not removed by the system. Such suspended
guard calls are also called @dfn{dead} processes.

Deadlock and interrupts do not kill or remove processes; they only
restart the top level command interpreter.

I/O predicates produce a segmentation error when called with an
inappropriate stream argument.

It is possible to overflow a heap by unifying a variable with a very
large term in the source code (e.g. a list of over 128 elements) when
the top heap segment is almost full. This can result in a segmentation
error.  There is no problem with terms constructed dynamically during
execution and a workaround is to break up the source code term into
smaller parts, e.g.
@example
g(X) <- X = [1,2,....,128|X1], g1(X1).
g1(X1) <- X1 = [129,130,....,256].
@end example

Similarly, it is possible to overflow an argument stack by calling a
large number of goals in a parallel conjunction when the top stack
segment is almost full, if the sum of all the arguments in the parallel
conjunction exceeds 256. The workaround is to replace some of the goals
in the conjunction with a single call to a predicate that invokes the
replaced goals.  In theory, the compiler could be made to detect and fix
both of these cases automatically.

Loading C predicates does not work on the Alliant and Multimax versions.

