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

This file documents the Parlog system.

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


File: parlog.info,  Node: Top,  Next: UserManual,  Prev: (dir),  Up: (dir)

PARLOG
******

This is Parlog.

* Menu:

* UserManual::                  User Manual
* ReferenceManual::             Reference Manual
* IC-PrologII::                 Interface with IC-Prolog II
* References::                  References
* PredicateIndex::              Predicate Index









 -- The Detailed Node Listing --

User Manual

* Introduction::                Introduction
* About::                       About Parallel Parlog
* EnteringExiting::             Entering and Exiting the Parallel Parlog System
* Running::                     Running Queries
* LoadingCompiling::            Loading and Compiling
* Tracing::                     Tracing
* Errors::                      Error Messages
* Modules::                     Modules
* GuardSafety::                 Guard Safety Considerations

Error Messages

* BuiltinErrors::               Builtin Errors
* SyntaxErrors::                Syntax Errors
* CompilerErrors::              Compiler Errors
* Deadlock::                    Deadlock

Reference Manual

* 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

System Predicates

* 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

Input and Output

* Streams::                     Streams
* CharacterIO::                 Character I/O
* TermIO::                      Term I/O

Foreign Routines

* ForeignDeclarations::         Foreign Declarations
* AddingForeignRoutines::       Adding Foreign Routines

An Alternative Tracer

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

Interface with IC-Prolog II

* CallingProlog::               Parlog calling Prolog
* PipeCommunication::           Inter thread/process communication
* NetworkCommunication::        TCP/IP and Mailboxes
* Other::                       Miscellaneous Additional Primitives


File: parlog.info,  Node: UserManual,  Next: ReferenceManual,  Prev: Top,  Up: Top

User Manual
***********

* Menu:

* Introduction::                Introduction
* About::                       About Parallel Parlog
* EnteringExiting::             Entering and Exiting the Parallel Parlog System
* Running::                     Running Queries
* LoadingCompiling::            Loading and Compiling
* Tracing::                     Tracing
* Errors::                      Error Messages
* Modules::                     Modules
* GuardSafety::                 Guard Safety Considerations


File: parlog.info,  Node: Introduction,  Next: About,  Up: UserManual

Introduction
============

The first part of this document is a user manual in tutorial form, and
may be read while trying out the examples at a terminal.  The second
part is a reference manual, and contains a definition of Parallel Parlog
and documentation on system predicates.  The reader is assumed to have
some knowledge of Parlog and Unix.  In the rest of document, we will use
the notation `pred/n' to denote a predicate with name `pred' and number
of arguments (also known as the "arity") `n'.  The notation ``<CR>''
indicates that the `return' key should be typed.


File: parlog.info,  Node: About,  Next: EnteringExiting,  Prev: Introduction,  Up: UserManual

About Parallel Parlog
=====================

Parallel Parlog is an implementation of Parlog for shared memory
multiprocessor machines. Versions currently exist for the Sequent
Balance and Symmetry, BBN Butterfly, Encore Multimax and Alliant FX/8.
Uniprocessor versions are also available for Sun3 and Sun4
workstations. The syntax is standard Parlog and is compatible with the
SPM [Foster et al. 1986] and MacParlog [Conlon and Gregory 1989]

The language is as defined in [Gregory 1987], except for the "non-flat
guard restriction" (*note GuardSafety::.), the restricted form of the
metacall (*note Metalevel::.), and the introduction of a simple module
scheme (*note Modules::.).

This manual describes the third release of the Parallel Parlog system,
V1.5, which contains a number of improvements over previous releases
V1.0 and V1.4.  Any program compiled on V1.0 will need to be recompiled
in order to be executed on the new release of the system.

The main feature of release V1.4 of the Parallel Parlog system is a new
memory management system that allows the different data areas within
the emulator [Crammond 1990] to dynamically expand (and contract) as
required. On machines that allow shared memory to be expanded during
execution this makes the new Parlog system somewhat more robust,
particularly when using many processors, and also more economical when
executing small programs, particularly on a single processor.  The
latest release V1.5 adds many useful primitives and fixes many of the
bugs reported by users (*note Changes::.).


File: parlog.info,  Node: EnteringExiting,  Next: Running,  Prev: About,  Up: UserManual

Entering and Exiting the Parallel Parlog System
===============================================

The system can be entered by typing the command `parlog'.  This command
has one option `-nx' which specifies that the system should execute on
`x' processors.  On startup, the Parlog system displays the following
message on the screen:
     Parallel Parlog V1.5  -  10 Jan 1993
     Copyright (C) 1993, Imperial College
     
     | ?-
To exit Parlog, type the end of file character (usually ``CTL-D'') or
the command ``halt.'' followed by <CR>.  Note that the full-stop must
be typed at the end of each command.


File: parlog.info,  Node: Running,  Next: LoadingCompiling,  Prev: EnteringExiting,  Up: UserManual

Running Queries
===============

In response to the ``| ?-'' prompt the user may enter any conjunction
of Parlog calls terminated by a full-stop.  This conjunction is
evaluated as a query, and if it is successful the bindings for the query
are printed out and the word ``yes'' appears.  Bindings are not printed
for void variables (denoted by an underscore). If the query fails then
this is indicated with ``no''.  This is illustrated by the following
simple example:

     | ?- X is 1 + 2.
      X = 3
     
     yes
     | ?- _ is 1 + 2.
     
     yes
     | ?- X is 1 + 2, X is 2 + 2.
     
     no
     | ?- halt.
     ncalls/utime = 461 / 0.02 = 23050.0 RPS

Normally a query is executed in the foreground which means that the
prompt for the next query will not appear until the last query has run
to completion (either succeeded, failed or deadlocked).  In some cases,
it is desirable to run background queries so that more than one query
can be executed in parallel.  This feature is particularly useful for
queries which are expected to suspend or take a long time to finish as
it allows the user to enter new queries without waiting for the result.
To execute a query in the background, prefix the query with a ``&&''.
Note that the whole query must be run in the background.  It is not
possible to mix foreground and background processing within a single
query.

     | ?- create_channel(ch1,X) & data(X) & X=[H|_] & name(H,List).
     data(_1511)
     [deadlock]
     
     | ?- && create_channel(ch2,X) & data(X) & X=[H|_] & name(H,List).
     
     | ?- write_channel(ch2,hello).
     
     yes
     | ?-  X = [hello|_2081]
      H = hello
      List = [104,101,108,108,111]
     
     yes

The evaluation of a query can be interrupted by typing the interrupt
character (usually ``CTL-C''). This should produce the prompt ``Parlog
interruption ?''.  By typing ``y<CR>'' to this prompt, the execution of
the query will be aborted; typing ``n<CR>'' will cause the execution to
resume.

Note: if the interrupt prompt does not appear on the screen within a few
seconds of typing an interrupt then the system has "hung" in some way.
The only rescue from this situation is to type the quit character
(usually ``CTL-\'').


File: parlog.info,  Node: LoadingCompiling,  Next: Tracing,  Prev: Running,  Up: UserManual

Loading and Compiling
=====================

Users may define their own Parallel Parlog predicates by placing them in
a text file. The correct syntax for predicates is defined in the
Reference Manual (*note Syntax::.).  To make them available within the
system, a Parallel Parlog object code file should be generated by using
the `compile/1' predicate, and this should then be loaded with the
`load/1' predicate.

It is usual for the Parlog text file to have a `.par' extension and the
object file an `.o' extension, as in the following example, but this is
optional (*note CompilationAndLoading::.).

     tutorial% cat tst.par
     
     mode biased_merge(?,?,^).
     biased_merge([A|As],Bs,[A|Cs])<-
         biased_merge(As,Bs,Cs).
     biased_merge(As,[B|Bs],[B|Cs])<-
         biased_merge(As,Bs,Cs).
     biased_merge([],Bs,Bs).
     biased_merge(As,[],As).
     
     tutorial% parlog
     Parallel Parlog V1.5  -  10 Jan 1993
     Copyright (C) 1993, Imperial College
     
     | ?- biased_merge([1,2],[3,4],X).
     [Warning: the procedure biased_merge/3 is undefined]
     
     no
     | ?- compile(tst) & load(tst).
     [loading compiler]
     Compiling file tst.par
     biased_merge / 3
     File tst compiled.
     
     yes
     | ?- biased_merge([1,2],[3,4],X).
      X = [1,2,3,4]
     
     yes
     | ?- halt.
     
     ncalls/utime = 5432 / 0.56 = 9700.0 RPS
     tutorial% ls
     tst.o                tst.par
     tutorial%

Terms in the source file with the form ``<-ConjunctionOfGoals'' are
treated as commands, which are executed automatically as the object
file is loaded.


File: parlog.info,  Node: Tracing,  Next: Errors,  Prev: LoadingCompiling,  Up: UserManual

Tracing
=======

The Parallel Parlog system supports rudimentary tracing facilities,
through the use of spypoints.  A spypoint may be placed on a predicate
using the `spy/1' predicate.  Thereafter, each time the predicate is
called, the goal and the current state of its arguments is displayed on
the screen preceded by a ``Call:'' message. The user is then prompted,
and four kinds of response are possible.

  1. When the user types ``<CR>'', the traced call is executed and a
     further message is displayed on termination of the call. This
     message is either ``Exit:'' or ``Fail:'', followed by the goal and
     its arguments.

  2. Typing ``n<CR>'' will cause the spypoint to be removed before
     executing the call.  Thereafter, further calls to the predicate
     will not be traced (but existing calls will still be traced when
     they terminate).  Spypoints can also be removed with the `nospy/1'
     predicate.

  3. Typing ``a<CR>'' will abort the call.

  4. Typing ``c goal<CR>'' will cause `goal' to be executed. This can
     be useful for setting further spypoints before proceeding with
     this call. Once `goal' has completed, the user is prompted again
     for action on this call.

     | ?- spy(biased_merge/3).
     
     yes
     | ?- biased_merge([1,2], [], [1,3]).
     Call: biased_merge([1,2],[],[1,3]) ?
     Call: biased_merge([2],[],[3]) ?
     Fail: biased_merge([2],[],[3]) ?
     Fail: biased_merge([1,2],[],[1,3]) ?
     
     no
     | ?- biased_merge([1,2], [], X).
     Call: biased_merge([1,2],[],_2454) ?
     Call: biased_merge([2],[],_2546) ?
     Call: biased_merge([],[],_2594) ?
     Exit: biased_merge([],[],[]) ?
     Exit: biased_merge([2],[],[2]) ?
     Exit: biased_merge([1,2],[],[1,2]) ?
      X = [1,2]
     
     yes
     | ?- biased_merge([1,2], [], X).
     Call: biased_merge([1,2],[],_2911) ? a
     
     | ?- biased_merge([1,2], [], X).
     Call: biased_merge([1,2],[],_3102) ? n
      X = [1,2]
     
     yes
     | ?-

Notes:

  1. The emulator will continue to execute runnable goals while waiting
     for the prompt to a traced call; thus potentially altering the
     scheduling behaviour, particularly on one processor.

     A consequence of this is that parallel invocations of a spied
     predicate result in multiple ``Call:'' messages appearing, each
     requiring a response. This is rather unsightly at times.

  2. A common fault that causes programs that work on one processor to
     fail on multiple processors is the incorrect use of `var(X)' in a
     guard.  Such a guard may succeed `unexpectedly' because it runs in
     parallel with a goal that eventually binds X.  Remember, `var(X)'
     is time dependent and must be used with care in parallel programs.


File: parlog.info,  Node: Errors,  Next: Modules,  Prev: Tracing,  Up: UserManual

Error Messages
==============

There are four sorts of error messages which the user may encounter :

* Menu:

* BuiltinErrors::               Builtin Errors
* SyntaxErrors::                Syntax Errors
* CompilerErrors::              Compiler Errors
* Deadlock::                    Deadlock


File: parlog.info,  Node: BuiltinErrors,  Next: SyntaxErrors,  Up: Errors

Builtin Errors
--------------

When the system predicates are given incorrect input they generate
messages of the form :

     [Error:  message: builtin name and arguments]


File: parlog.info,  Node: SyntaxErrors,  Next: CompilerErrors,  Prev: BuiltinErrors,  Up: Errors

Syntax Errors
-------------

The `read' predicates (*note TermIO::.) return error messages when they
are used with input that does not conform to Parlog syntax.  Since the
compiler and the top level query evaluator use these predicates, the
user will find the same messages displayed here.  The format is:

     **Syntax Error: offending term

The offending term is listed, and the place where the error occurred is
marked by the word ``<<here>>''.


File: parlog.info,  Node: CompilerErrors,  Next: Deadlock,  Prev: SyntaxErrors,  Up: Errors

Compiler Errors
---------------

The compiler may generate the following messages :

`**Syntax Error: TERM'
     see above.

`**Mode Declaration Error:  MODE'
     The mode is wrongly formatted; usually a ``^'' or ``?'' is missing.

`**Compiler Error - Name/Arity mismatch:  NAME/ARITY'
     The clauses grouped together as one procedure with the sequential
     search operator ``;'' do not share the same name and arity.

`**Compiler Error:NAME/ARITY'
     Any other compiler error.

`warning: is/2 before "`&'" in body cannot be optimised'
     This indicates that a call to `is/2' can potentially be optimised
     by replacing the sequential conjunction operator ``&'' by the
     parallel conjuction operator ``.''.

`warning: parallel deep guards detected'
     The compiler has detected two or more parallel non-flat
     clauses(*note GuardSafety::.).  This warning may be ignored if the
     programmer is sure that only one of the clauses will commit.  If
     this cannot be guaranteed, then the clauses should be separated
     using ``&''.

`warning: some clause(s) have been ignored'
     The compiler has detected some redundant clauses.  For example, in
     the relation
          mode p(?).
          p(X) <- X > 0 : positive(X).
          p(X) <- X < 0 : negative(X).
          p(X) <- X == 0 , zero(X).
     the third clause can always commit since it has no guard.  The
     first two clauses are thus ignored.  This is probably not what the
     programmer intended so the compiler gives the warning.  The fix is
     to change the parallel clause separator ``.'' at the end of clause
     2 to a sequential one ``;'', or to put a commit operator ``:''
     between the two body goals in clause 3.

After processing the source file, a summary of all of the error messages
is displayed. This is illustrated by the example session given below,
which captures a syntax error in the first predicate of the
`kkqueen.par' file.

     tutorial% cat kkqueen.par
     
     mode gen(?, ^).
     gen(N, [N|Xs]) <-
       N > 0 :
       N1 is N-1,
       gen(N1, Xs).
     gen(0, []).
     
     mode count(?, ?, ^).
     count([], M M).
     count([X|Xs], M, Total) <-
       M1 is M + 1,
       count(Xs, M1, Total).
     
     tutorial% parlog
     Parallel Parlog V1.5  -  10 Jan 1993
     Copyright (C) 1993, Imperial College
     
     | ?- compile(kkqueen).
     [loading compiler]
     Compiling file kkqueen.par
     gen / 2
     
     ** Syntax Error: count([],M <<here>> M).
     count / 3
     File kkqueen partially compiled:
     One or more syntax errors in or before:
     count / 3
     These clauses missing from the object code!
     
     yes
     | ?- halt.
     
     ncalls/utime = 4978 / 0.51 = 9760.78 RPS
     tutorial%


File: parlog.info,  Node: Deadlock,  Prev: CompilerErrors,  Up: Errors

Deadlock
--------

When the evaluation of a query cannot terminate because there are calls
suspended on input matching constraints, the system prints out all the
suspended calls and then the message :
     [deadlock]

Note: goals which were suspended before a previous deadlock, or were
executing before an interrupt was typed, may be displayed among the list
of goals suspended during this deadlock.


File: parlog.info,  Node: Modules,  Next: GuardSafety,  Prev: Errors,  Up: UserManual

Modules
=======

Parallel Parlog supports a simple module system to control the name
space of predicates. This is based on the notion of a `current module',
which is the place where a query currently looks for predicate
definitions.  The predicate `current_module/1' returns the name of the
current module, and `module/1' changes it (*note
CompilationAndLoading::.).

When predicates are loaded into the system, they are placed in the
current module. Thus a command such as `<- module exmpl.' at the top of
the source file will cause the predicates in the object file to be
loaded into module `exmpl'. However, after the load is finished, the
current module becomes the module which was being used prior to the
load.

By default, predicates loaded into a module are private to that module
and can only be called by goals within that module. Predicates can be
made visible to all other modules by the `public/1' command, e.g.
`public a/1, b/2, c/3.', which means that it can be invoked from any
module. A public predicate is read-only in all modules other than the
one in which it is defined, so the definition of a public predicate not
in the current module cannot be replaced in subsequent loads by an
alternative (private) one.

Predicates can also be imported into modules without making them public
to all modules. This is a two stage process: firstly the predicates are
made exportable in the module in which they are defined with
`export/1', and secondly they are imported with `import/2', from the
module in which they are defined into the current module.  For example,
suppose the current module is set to `foo', then
`export([a/1,b/2,c/3])' makes predicates `a/1', `b/2' and `c/3' all
exportable. Now in module `bar', the predicate `b/2' can be imported
from `foo' using `import(foo,[b/2]).'.

There are two predefined modules: `system' and `user'.  All Parlog
systems predicates, as defined in the reference manual, are defined in
module `system' and are made public. In this way, the module mechanism
is transparent to the user who does not wish to use it.  The query
evaluator executes by default in module `user' so that private
predicates used by the system and compiler are invisible to the user.

The binding of a call to a predicate in the appropriate module is done
at load time, thus incurring no overhead at run time. However, the
binding for interpreted calls, using `call/1', is done at run time in
the context of the current module. Thus, the predicate must either be
in the current module or imported into it. A predicate within a given
module can be called explicitly using `module#goal' syntax, e.g.

     | ?- system#assemble(file).


File: parlog.info,  Node: GuardSafety,  Prev: Modules,  Up: UserManual

Guard Safety Considerations
===========================

The usual "guard safety" restrictions apply, which mean that bindings
of variables in a guard are not made visible to the body of the clause
until the guard has committed.

In addition, Parallel Prolog has a "non-flat guard restriction" which
means that OR-parallel search only works for clauses with flat guards.
Flat guards are guards which use only system predicates that can be
compiled in-line and include all unification primitives (except
`ground/1' and `\==/2'), all type tests, `is/2', term comparison and
arithmetic comparison.  A guard is non-flat if it contains user defined
predicates or non-flat system predicates.  Non-flat guards are also
called deep guards.  More details on flat and non-flat guards can be
found in [Gregory 1987].

The consequence of this non-flat guard restriction is that the
programmer should ensure that all clauses containing deep guards
(except the last) should end with a sequential clause separator ``;''.
This coding strategy will ensure that a candidate non-flat clause will
not be tried in parallel with other candidates.

With this restriction, the if-then-else form of deep guard is still
possible (as seen in examples 1 and 2), but the or-parallel search
technique - two alternative guards executing in parallel - is not
(example 3).

     (1) mode p1(?,^).
         p1(X,S) <- try(X) : S=ok ;
         p1(X,S) <- S=failed.
     
     (2) mode p2(?,?).
         p2([A|B],Y) <- g1(A), g2(A) : b1(B,Y);
         p2(X,[A|B]) <- g1(A), g2(A) : b2(B,X);
         p2(X,Y)     <- b3(X,Y).
     
     (3) % this is not allowed:
         mode p3(?,?,?,^).
         p3(X,L,R,T) <- find(X,L,T1) : T=T1.
         p3(X,L,R,T) <- find(X,R,T2) : T=T2.

A warning message is issued by the compiler when parallel deep guards
are detected, such as in example 3.

There are transformations that automatically convert general Parlog into
the restricted form, and future releases may perform these during
compilation.  At present, the user is responsible for any alterations to
his code.  Example 3 could be rewritten using `call/3' as :

     p3(X,L,R,T) <-
         call(find(X,L,T1),Res1,Con1),
         call(find(X,R,T2),Res2,Con2),
         wait_for_result(Res1,Res2,Con1,Con2,T1,T2,T).
     
     mode wait_for_result(?,?,^,^,?,?,^).
     wait_for_result(success,_,_,stop,T1,_,T) <- T=T1.
     wait_for_result(_,success,stop,_,_,T2,T) <- T=T2.

There is another programming restriction which is the result of the
compiler trying to optimize code by compiling flat system predicates to
in-line code.  A side-effect of this is that the ordering of calls in
the guard can sometimes be very important. e.g.

     	(4)	longer(L1,L2) <- length(L1,A), length(L2,B), A>B : ...
     	(5)	longer(L1,L2) <- length(L1,A), length(L2,B) & A>B : ...
     	(6)	p <- X==Y, X=1, Y=2 : ...
     	(7)	p <- X=1, Y=2, X==Y : ...

Examples 4 and 6 will deadlock under Parallel Parlog.  A workaround is
to either force a sequential evaluation (example 5) or re-order the
calls (example 7).  Note that since flat system predicates are compiled
in-line, the separators between the system predicates in example 7 are
notionally converted to ``&'' by the compiler.


File: parlog.info,  Node: ReferenceManual,  Next: IC-PrologII,  Prev: UserManual,  Up: Top

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


File: parlog.info,  Node: Syntax,  Next: EscapeSequences,  Up: ReferenceManual

Syntax
======

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

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

The clause head `H' and each of the `G1', ..., `G' and `B1', ..., `Bn'
are "goals".  A goal has the form:
     R(T1, ..., Tk)      (k >= 0)

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

A "mode declaration" is associated with a Parlog procedure. For a
relation `R/k' this has the form:
     mode R(m1, .., mk).

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

A "term" can be a variable, constant or structured term. A "variable"
is denoted by an identifier beginning with a capital letter or the
underscore character `_'. Examples are `X' and `Tree'.  The underscore
character may also be used on its own to denote a unique "anonymous" or
"singleton" variable.  A "constant" is either a number or an "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
`jim', `'Hello World'' and `'$primitive''.  Non-printable character may
be included in quoted atoms by using "escape characters" (*note
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 (`'') and the number in that
base.  Some examples will help to clarify this.
     	4'100 (base 4) = 16 (base 10)
     	8'123 (base 8) = 83 (base 10)
Radix 0 has a special meaning.  It performs character to ASCII code
conversion. e.g.
     	0'A = 65 (decimal)	'A' is ASCII 65
     	0'( = 40 (decimal)	'(' is ASCII 40

A "structured term" is denoted by:
     F(T1, ..., Tn)      (n >= 1)

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

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

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

A Parlog program is invoked by executing a "query".  A query is a
conjunction of goals:
     ?- Q1, ..., Qn      (n >= 1)

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

Programs may include comments, which are defined as any text following a
`%' character up to the next newline character.


File: parlog.info,  Node: EscapeSequences,  Next: Semantics,  Prev: Syntax,  Up: ReferenceManual

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 :

`\a'
     alarm/bell (ASCII 7)

`\b'
     backspace (ASCII 8)

`\t'
     tab (ASCII 9)

`\n'
     newline (ASCII 10)

`\v'
     vertical tab (ASCII 11)

`\f'
     formfeed (ASCII 12)

`\r'
     carriage return (ASCII 13)

`\e'
     escape (ASCII 27)

`\s'
     space (ASCII 32)

`\d'
     delete (ASCII 127)

`\<octal string>'
     the character with ASCII code `<octal string>' base 8.  e.g.
     `\007' is the bell character and `\040' is the space character
     (ASCII 32).

`\^<control char>'
     the character whose ASCII code is the `<control char>' mod 32.
     e.g. `\^P' is `CTL-P'.

`\<CR>'
     no character.  This is most useful when splitting atoms over two
     lines where the ignored newline character is preceded by a
     backslash.

`\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.

`\<other>'
     the character `<other>', where `<other>' is any character not
     defined above.


File: parlog.info,  Node: Semantics,  Next: CommandLine,  Prev: EscapeSequences,  Up: ReferenceManual

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 `r(a1,...,ak)', all of the clauses for
the predicate `r' can be searched in parallel for a candidate clause.
The clause :
     r(t1, . . ., tk)  <-  < guard >  :  < body >

is a candidate clause if the head `r(t1,...,tk)' matches the call
`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 "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 ``.'' or the sequential clause search
operator ``;'' between clauses. For instance, if a predicate is defined
by the clauses :
     Clause1  .
     Clause2  ;
     Clause3.

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.


File: parlog.info,  Node: CommandLine,  Next: Environment,  Prev: Semantics,  Up: ReferenceManual

Command Line Options
====================

`-n x'
     Specifies the number of processors to execute. The default value
     is `-n1'.

`-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 `n' is the number of processors.

`-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.

On machines that allow shared memory to be expanded during execution
there should be no reason to use the `-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 `-m'
option when you get the error message
     	can't extend shared memory, use -m option to get more


File: parlog.info,  Node: Environment,  Next: StartupFile,  Prev: CommandLine,  Up: ReferenceManual

Environment Variables
=====================

The Parallel Parlog system uses three environment variables -
`PARLOGDIR', `PARLOG_PATH' and `PARLOG_INIT'.

`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.

`PARLOG_PATH' is a colon-separated list of directories in the style of
the `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 `PARLOG_PATH',
then you will be able to access files in those directories by specifying
the filename only (*note FilenamesAndPaths::.).

`PARLOG_INIT' is the name of a file containing commands to be executed
at startup time (*note StartupFile::.).


File: parlog.info,  Node: StartupFile,  Next: FilenamesAndPaths,  Prev: Environment,  Up: ReferenceManual

Startup File Processing
=======================

When Parallel Parlog is started, commands in a startup file are
executed.  The commands should be of the form :
     	<- ConjunctionOfGoals.
For example, the following startup file will display a welcome message
and load a customised library file.  Note that lines not beginning with
a ``<-'' are ignored.
     	<- nl &
     	   write('Welcome to Parlog') & nl.
     
     	<- load(mylib).
     
     	load(otherlibs).	% this line is not executed.
The default startup file is `~/.parlog' but this may be altered by
setting the environment variable `PARLOG_INIT'.  If the file specified
by `PARLOG_INIT' does not exist, the system behaves as if the file was
empty.


File: parlog.info,  Node: FilenamesAndPaths,  Next: SystemOperatorDeclarations,  Prev: StartupFile,  Up: ReferenceManual

Filenames and Paths
===================

There are a few primitives which take a filename as an argument.  The
most commonly used are `open/3', `load/1' and `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 ``/'', ``.'' and ``~''.  In
accordance with Unix conventions, if the filename begins with a ``~''
character, the ``~'' is substituted by the home directory of the
current user.  If the filename begins with ``~<user>'' then the home
directory of `<user>' is substituted instead.  ``.'' signifies the
current directory and ``..'' 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 `PARLOG_PATH' (*note Environment::.), a list of
directories may be supplied for filename searching.  This list is a
colon-separated list of path names. e.g.  if `PARLOG_PATH' has the value
     	.:~/parlog:/usr/local/parlog/source
then filenames will be searched for in those three directories in the
order specified.  Note that if ``.'' is not included in `PARLOG_PATH',
then files in the current directory will not be visible.

The value of `PARLOG_PATH' may be changed dynamically by the `setenv/2'
primitive.


File: parlog.info,  Node: SystemOperatorDeclarations,  Next: SystemPredicates,  Prev: FilenamesAndPaths,  Up: ReferenceManual

System Operator Declarations
============================

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

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


File: parlog.info,  Node: SystemPredicates,  Next: ForeignRoutines,  Prev: SystemOperatorDeclarations,  Up: ReferenceManual

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


File: parlog.info,  Node: UnificationRelated,  Next: TypeTests,  Up: SystemPredicates

Unification Related
-------------------

`Term1 = Term2'
     "synchronisation:" No suspension.

     "behaviour:" Output unification.  Attempts to unify Term1 with
     Term2.  Succeeds if Term1 and Term2 unify; else fails.

`Term1 == Term2'
     "synchronisation:" Suspends if Term1 and Term2 can be unified only
     by binding variables in both of them.

     "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.

`Term1 \== Term2'
     "synchronisation:" As for `==/2 ' above.

     "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 `\=@=/2 ' as shown by the following
     examples.
          	g(X) \== g(Y)
     suspends since X and Y may potentially be different, but
          	g(X) \=@= g(Y)
     succeeds since the variable X is different from the variable Y.

`Term1 <= Term2'
     "synchronisation:" Suspends if Term1 and Term2 could only be
     unified by binding variables in Term2

     "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.

`var(X)'
     "synchronisation:" No suspension.

     "behaviour:" Succeeds if X is an unbound variable.  Fails if it is
     instantiated.

`nonvar(X)'
     "synchronisation:" No suspension.

     "behaviour:" Fails if X is an unbound variable.  Succeeds if it is
     instantiated.

`ground(X)'
     "synchronisation:" Suspends until X is ground.

     "behaviour:" Succeeds when X is ground.

`data(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds when X is instantiated.


File: parlog.info,  Node: TypeTests,  Next: ArithmeticExpressions,  Prev: UnificationRelated,  Up: SystemPredicates

Type Tests
----------

`atom(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds if X is an atom; otherwise fails.

`atomic(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds if X is an atom or a number; otherwise fails.

`integer(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds if X is an integer; otherwise fails.

`float(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds if X is a floating point number; otherwise
     fails.

`number(X)'
     "synchronisation:" Suspends until X is instantiated.

     "behaviour:" Succeeds if X is an integer or a floating point
     number; otherwise fails.


File: parlog.info,  Node: ArithmeticExpressions,  Next: TermComparison,  Prev: TypeTests,  Up: SystemPredicates

Arithmetic Expressions
----------------------

`Value is Expression'
     "synchronisation:" Suspends until Expression is ground.

     "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.

    `+X'
          Results in the positive value of X. The type of the result is
          the same as the type of the operand.

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

    `\X'
          Results in the complements of the bits in X.

    `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.

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

    `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.

    `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.

    `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.

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

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

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

    `X/\Y'
          Results in the bitwise conjunction of X and Y.

    `X\/Y'
          Results in the bitwise disjunction of X and Y.

    `X<<Y'
          X is left-shifted Y places.

    `X>>Y'
          X is right-shifted Y places with sign extension.


File: parlog.info,  Node: TermComparison,  Next: TermManipulation,  Prev: ArithmeticExpressions,  Up: SystemPredicates

Term Comparison
---------------

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

   * variables are compared using their addresses

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

   * atoms are compared using their ASCII codes

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

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

`X=@=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically equal to Y; else fails.

`X\=@=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically not equal to Y; else fails.
     Note that the suspension only occurs at the top level; e.g.
          	X \=@= Y
     suspends but
          	g(X) \=@= g(Y)
     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 `g/1 '.

`X@<Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically less than Y; else fails.

`X@>Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically more than Y; else fails.

`X@=<Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically less than or equal to Y;
     else fails.

`X@>=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" Succeeds if X is lexically more than or equal to Y;
     else fails.

`compare(Op,Term1,Term2)'
     "synchronisation:" Suspends until Term1 and Term2 are instantiated.

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

`X=:=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" X and Y must be numbers, and the goal succeeds if
     they are equal.

`X=\=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" X and Y must be numbers, and the goal succeeds if
     they are not equal.

`X<Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" X and Y must be numbers, and the goal succeeds if X
     is strictly less than Y.

`X>Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" X and Y must be numbers, and the goal succeeds if X
     is strictly greater than Y.

`X=<Y'
     "synchronisation:" Suspends until X and Y are instantiated.

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

`X>=Y'
     "synchronisation:" Suspends until X and Y are instantiated.

     "behaviour:" X and Y must be numbers, and the goal succeeds if X
     is greater than or equal to Y.

