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: TermManipulation,  Next: Metalevel,  Prev: TermComparison,  Up: SystemPredicates

Term Manipulation
-----------------

`Term =.. List'
     "synchronisation:" Suspends until either Term or List is
     instantiated.

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

`functor(Term,Functor,Arity)'
     "synchronisation:" Suspends until Term is instantiated, or Functor
     and Arity are instantiated.

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

`arg(N,Term,Arg)'
     "synchronisation:" Suspends until N and Term are instantiated.

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

`atom_chars(Atom,String)'
     "synchronisation:" Suspends until either Atom or String is
     instantiated.

     "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 `"add"', for example, is shorthand for
     [97,100,100] (*note Syntax::.).

`number_chars(Number,String)'
     "synchronisation:" Suspends until either Number or String is
     instantiated.

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

`name(Atomic,String)'
     "synchronisation:" Suspends until either Atomic or String is
     instantiated.

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

`concat_atom(List,Atom)'
     "synchronisation:" Suspends until List is instantiated.

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

`varoccurs(Term,VarList)'
     "synchronisation:" No suspension.

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

`varsin(Term,VarList)'
     "synchronisation:" No suspension.

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

`copy_term(Term1,Term2)'
     "synchronisation:" No suspension.

     "behaviour:" A copy of Term1 with new variables is unified with
     Term2.


File: parlog.info,  Node: Metalevel,  Next: InputOutput,  Prev: TermManipulation,  Up: SystemPredicates

Metalevel
---------

`call(Call)'
     "synchronisation:" Suspends until Call is instantiated.

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

`call(Call,Status,Control)'
     "synchronisation:" Suspends until Call is instantiated.

     "behaviour:" This primitive always succeeds binding Status to
     `success' or `failed' depending on whether Call succeeded or not.
     If Control is instantiated to `stop', execution of Call is
     terminated, binding Status to `stopped'.

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

`Module#Call'
     "synchronisation:" Suspends until Module and Call are bound.

     "behaviour:" Evaluates Call as it is defined in Module.  Succeeds
     if Call succeeds.  Fails if Call fails.

`fail'
     "synchronisation:" No suspension.

     "behaviour:" Fails.

`not(Call)'
     "synchronisation:" Suspends until Call is bound.

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

`halt'
     "synchronisation:" No suspension.

     "behaviour:" Terminates the Parallel Parlog session.

`true'
     "synchronisation:" No suspension

     "behaviour:" Always succeeds.


File: parlog.info,  Node: InputOutput,  Next: ChannelIO,  Prev: Metalevel,  Up: SystemPredicates

Input and Output
----------------

Input and output is dealt with by utilising `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 "current input" stream and
one "current output" stream.  Input and output predicates fall into two
categories:

  1. Those that use the current input and output stream.

  2. Those which take an explicit stream argument.

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

The current input and output streams are set to `user_input' and
`user_output' upon entry to the Parallel Parlog system.

* Menu:

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


File: parlog.info,  Node: Streams,  Next: CharacterIO,  Up: InputOutput

Streams
.......

`open(File,Mode,Stream)'
     "synchronisation:" Suspends until File and Mode are instantiated.

     "behaviour:" If Mode is the atom `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 `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
     `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.

`close(Stream)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`set_input(Stream)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`set_output(Stream)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`current_input(Stream)'
     "synchronisation:" No suspension.

     "behaviour:" This causes Stream to be unified with the current
     input stream.

`current_output(Stream)'
     "synchronisation:" No suspension.

     "behaviour:" This causes Stream to be unified with the current
     output stream.

`clear_input(Stream)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`flush_output(Stream)'
     "synchronisation:" Suspends until Stream is instantiated.

     "behaviour:" Flushes the output buffer associated with the given
     stream.


File: parlog.info,  Node: CharacterIO,  Next: TermIO,  Prev: Streams,  Up: InputOutput

Character I/O
.............

`get0(Stream,N)'
`get0(N)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`get(Stream,N)'
`get(N)'
     "synchronisation:" Suspends until Stream is instantiated.

     "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 `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.
     `get/2' should not be used with `user_input'. The one argument
     version reads from the current input stream.

`skip(Stream,N)'
`skip(N)'
     "synchronisation:" Suspends until Stream and N are instantiated.

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

`put(Stream,N)'
`put(N)'
     "synchronisation:" Suspends until Stream and N are instantiated.

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

`nl(Stream)'
`nl'
     "synchronisation:" Suspends until Stream is instantiated.

     "behaviour:" Starts a new line on the output stream Stream.  It is
     equivalent to `put(Stream,10)'. The zero argument version writes to
     the current output stream.

`tab(Stream,N)'
`tab(N)'
     "synchronisation:" Suspends until Stream and N are instantiated.

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


File: parlog.info,  Node: TermIO,  Prev: CharacterIO,  Up: InputOutput

Term I/O
........

`read(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`read(Stream,OpSet,Term,Variables)'
     "synchronisation:" Suspends until Stream and Opset are bound.

     "behaviour:" As for `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.

`display(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`write(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

     "behaviour:" Writes the term Term to the output stream Stream
     according to the operator precedences of the `system' operator
     set, with no quotes for atoms that need quoting in order to be
     read back in (*note SystemOperatorDeclarations::.).

`writeq(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

     "behaviour:" Writes in the same way as `write/2', but with quotes
     around atoms that need quoting in order to be read back in.

`write_canonical(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

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

`print(Stream,Term)'
     "synchronisation:" Suspends until Stream is instantiated.

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

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

           display(Term)           write(Term)
           writeq(Term)            write_canonical(Term)
           print(Term)

As expected, `read/2' has a short form for reading from the current
input stream :
           read(Term)


File: parlog.info,  Node: ChannelIO,  Next: CompilationAndLoading,  Prev: InputOutput,  Up: SystemPredicates

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

`create_channel(ID, Var)'
     "synchronisation:" No suspension.

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

`write_channel(Ch, Term)'
     "synchronisation:" Suspends until Ch is instantiated.

     "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 `[Term|_]'.  Ch is either a system
     generated channel identifier or a user-defined one.  The channel
     must have been previously opened using `create_channel/2' and it
     must not be closed yet, otherwise it fails.

`get_channel(Ch, Var)'
     "synchronisation:" Suspends until Ch is instantiated.

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

`close_channel(Ch)'
     "synchronisation:" Suspends until Ch is instantiated.

     "behaviour:" The channel Ch is closed.  The tail of the stream
     variable associated with the channel is instantiated to `[]'.  The
     primitive fails if the channel is not valid.


File: parlog.info,  Node: CompilationAndLoading,  Next: Operators,  Prev: ChannelIO,  Up: SystemPredicates

Compilation and Loading
-----------------------

`compile(File)'
     "synchronisation:" Suspends until File is instantiated.

     "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 `.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 `compile/1 ' will
     automatically load it.  The filename is searched in a list of
     default directories (*note FilenamesAndPaths::.).

`load(File)'
     "synchronisation:" Suspends until File is instantiated.

     "behaviour:" Loads a Parlog object code file.  Initially, the name
     File is sought; if that does not exist then File with `.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 (*note FilenamesAndPaths::.).

`load_foreign(Predicates,Obj,Libraries)'
     "synchronisation:" Suspends until all three arguments are
     instantiated.

     "behaviour:" Loads C predicates into the system.  See *note
     ForeignRoutines::..

`load_foreign(Predicates,Obj)'
     "synchronisation:" Suspends until both arguments are instantiated.

     "behaviour:" As for `load_foreign/3 ' but with no libraries
     specified.

`load_foreign_io(Predicates,Obj,Libraries)'
     "synchronisation:" Suspends until all three arguments are
     instantiated.

     "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
     `load_foreign/3' (*note ForeignRoutines::.).

`load_foreign_io(Predicates,Obj)'
     "synchronisation:" Suspends until both arguments are instantiated.

     "behaviour:" As for `load_foreign_io/3' but with no libraries
     specified.

`defined(Pred)'
     "synchronisation:" Suspends until Pred is instantiated.

     "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
     `Name/Arity' notation or a sample call.
          | ?- defined(append/3).
          
          yes
          | ?- defined(append(_,_,_)).
          
          yes
          | ?- defined(append(_,_)).
          
          no
          | ?-

`public Preds'
     "synchronisation:" Suspends until Preds is ground.

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

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

     "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
     `import/2'.

`import(Module,Predicates)'
     "synchronisation:" Suspends until Module and Predicates are ground.

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

`module(Module)'
     "synchronisation:" Suspends until Module is instantiated.

     "behaviour:" Makes Module the current module.

`current_module(Module)'
     "synchronisation:" No suspension.

     "behaviour:" Unifies Module with the current module.


File: parlog.info,  Node: Operators,  Next: Spypoints,  Prev: CompilationAndLoading,  Up: SystemPredicates

Operators Related
-----------------

`op(OpSet,Precedence,Type,Op)'
     "synchronisation:" Suspends until all four arguments are
     instantiated.

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

    `fx'
          non associative prefix operator

    `fy'
          associative prefix operator

    `xf'
          non associative postfix operator

    `yf'
          associative postfix operator

    `xfx'
          non associative infix operator

    `xfy'
          right-associative infix operator

    `yfx'
          left-associative infix operator

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

`current_op(OpSet,Precedence,Type,Op)'
     "synchronisation:" Suspends until OpSet,Type and Op are
     instantiated.

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

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


File: parlog.info,  Node: Spypoints,  Next: Miscellaneous,  Prev: Operators,  Up: SystemPredicates

Spypoints
---------

`spy(Pred)'
     "synchronisation:" Suspends until Pred is instantiated.

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

`nospy(Pred)'
     "synchronisation:" Suspends until Pred is instantiated.

     "behaviour:" Pred must be a Name/Arity pair representing a
     predicate that has already been loaded.  If this is the case,
     `nospy/1' succeeds, removing spypoints from the named predicate;
     otherwise it fails.


File: parlog.info,  Node: Miscellaneous,  Prev: Spypoints,  Up: SystemPredicates

Miscellaneous
-------------

`util(Package)'
     "synchronisation:" Suspends until Package is bound.

     "behaviour:" Loads predicates from the specified package in the
     utilities directory; examples are the foreign interface package
     (*note ForeignRoutines::.), the tracer (*note
     AlternativeTracer::.), the Parlog Shell (*note ParlogShell::.) and
     the SPM compatibility package (*note SPMCompatibility::.).

`statistics(Key,Val)'
     "synchronisation:" Suspends until Key is bound.

     "behaviour:" When Key is one of the atoms `suspensions', `gcs',
     `heap', `stack', `process', `program', `memory', `runtime' or
     `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 `heap', `stack', `process', `program' or
     `memory'), Val is bound to a term of the form `[memory_used,
     memory_free]'. These values are given in `word' (4 byte) units
     except for `process', which is given in `process' (32 byte) units,
     and `memory' which returns the total size of the allocated and
     free memory segments in bytes.  When Key is `runtime', Val is
     bound to a list of the form `[total, Ilast]', where `total' is the
     user cpu time since the Parallel Parlog system was invoked, and
     `last' is the time since the last call to `statistics/2 ' or
     `statistics/0'.

`statistics'
     "synchronisation:" No suspension.

     "behaviour:" Prints out all the values generated by `statistics/2 '
     onto the current output stream.

`unix(Command)'
     "synchronisation:" Suspends until Command is instantiated.

     "behaviour:" Can be used in the following ways:

          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

`setenv(Env,Val)'
     "synchronisation:" Suspends until Env and Val are instantiated.

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

`getenv(Env,Val)'
     "synchronisation:" Suspends until Env is instantiated.

     "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.
     `'123'') cannot be retrieved successfully if stored in an
     environment variable.

`clock(T)'
     "synchronisation:" No suspension.

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

`absolute_file_name(F,Abs)'
     "synchronisation:" Suspends until F is instantiated.

     "behaviour:" Abs is unified with the absolute path name of the
     file F.  The filename F is searched in the directories specified
     in `PARLOG_PATH' (*note Environment::.).  Meta-characters in F are
     recognised (*note FilenamesAndPaths::.).  The primitive fails if F
     is not found.

`stat(F,Abs,ModTime,Size,Mode,Uid,Gid)'
     "synchronisation:" Suspends until F is instantiated.

     "behaviour:" This primitive retrieves information about the file
     F.  The filename F is searched in the directories specified in
     `PARLOG_PATH' (*note Environment::.).  Meta-characters in F are
     recognised (*note 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 `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 :
             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.

`append(List1,List2,List3)'
     "synchronisation:" Suspends until List1 is instantiated.

     "behaviour:" List3 is unified with the result of appending List2
     to the end of List1.

`merge(List1,List2,List3)'
     "synchronisation:" Suspends until either List1 or List2 is
     instantiated.

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


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

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 `load_foreign/3 ),' or predicates only executable by the master
processor (using `load_foreign_io/3 ).'

To aid integration of C routines into the Parlog environment, a
"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
`foreign/2' declarations, which have a similar format to those used by
Quintus Prolog.

* Menu:

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


File: parlog.info,  Node: ForeignDeclarations,  Next: AddingForeignRoutines,  Up: ForeignRoutines

Foreign Declarations
--------------------

The syntax of the foreign declarations is as follows :

     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

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
:

             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)

Some examples of foreign declaration are :

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


File: parlog.info,  Node: AddingForeignRoutines,  Prev: ForeignDeclarations,  Up: ForeignRoutines

Adding Foreign Routines
-----------------------

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

  1. Consider a C routine `strcat()' which takes two strings as its
     arguments and returns the concatenated string. It is defined in
     `strcat.c' and is compiled to an object file in the usual way :
          cc -O -c strcat.c

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

  3. Now the interface file for this declaration can be generated by
     loading the foreign package and calling `make_interface/1' in the
     following way :
          | ?- util(foreign).
          [loading foreign]
          
          yes
          | ?- make_interface(iface).
          
          yes

     This produces a C file called `iface.c' which must be then be
     compiled to an object file :
          cc -O -c iface.c

  4. The interface and C routine object files can now be loaded in to
     the Parlog system with the `load_foreign/3' command :
          | ?- load_foreign([strcat/3], 'iface.o', 'strcat.o').

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

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

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


File: parlog.info,  Node: AlternativeTracer,  Next: ParlogShell,  Prev: ForeignRoutines,  Up: ReferenceManual

An Alternative Tracer
=====================

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


File: parlog.info,  Node: LoadingUsingTracer,  Next: TraceCommands,  Up: AlternativeTracer

Loading and Using the Tracer
----------------------------

The tracer is loaded with the command: `util(trace)'.  The program to
be traced should be in one or more files named `<name>.par'.  To enter
the tracer type :
     partrace([<name1>,<name2>, ..., <namen>]).
where `[<name1>,<name2>, ..., <namen]' is a list of the filenames which
contain the program to be traced (without the `.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:
      Full trace?

The user should reply ``y'' for yes or ``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 :
     pred1
     pred2/2
     pred2/3
     pred3
If the user just types ``<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:
     <goal> => <body of new clause with variable bindings passed through>
If output modes are used, any unifications giving output are also
printed in the form:
     <variable> <= <term>

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:
     * Completed * <goal>


File: parlog.info,  Node: TraceCommands,  Next: DisplayingStateComputation,  Prev: LoadingUsingTracer,  Up: AlternativeTracer

Trace Commands
--------------

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

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

`c'
     continue execution until next trace point

`f'
     give full display, including all goals following a sequential ``&''

`g'
     give standard display and allow user to investigate goals

`h'
     give list of available commands

`q'
     quit execution

`t'
     reset trace information

`u'
     undo trace points and continue execution until completion


File: parlog.info,  Node: DisplayingStateComputation,  Prev: TraceCommands,  Up: AlternativeTracer

Displaying State of Computation
-------------------------------

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

  1. Those on which no attempt has been made to reduce, but which could
     be chosen for reduction.

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

  3. Those which cannot be reduced as they follow a sequential ``&'',
     and the goal before the ``&'' has not completed execution.

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, ``g'', the list of goals is
displayed and the user may choose to investigate it in more detail.
The system gives the following prompt:
     Enter goal number (0 to restart tracing) :

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 ``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 ``l'', and can be displayed in full form by entering ``f''.


File: parlog.info,  Node: ParlogShell,  Next: SPMCompatibility,  Prev: AlternativeTracer,  Up: ReferenceManual

Parlog Shell
============

To be written.


File: parlog.info,  Node: SPMCompatibility,  Next: MacParlogCompatibility,  Prev: ParlogShell,  Up: ReferenceManual

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

The SPM file manipulation primitives `access/1', `assem/1' and `edit/3
' are not supported.

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

The `set/3' and `subset/3' all-solution primitives are absent from
Parallel Parlog, but all of the type testing primitives are present
(albeit after `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 `freeze/2' nor a `melt/2' primitive, but
does offer `copy_term/2' for which they are most often used.

Unavailable control primitives include `controlc/0', `key/1' and
`space/3'.

Many SPM utilities are absent from Parallel Parlog, including `date/3',
`show_date/0', `time/3', `instream/1', `load_comp/0', `sedit/0',
`sinput/2' and `username/1'.  In addition, the utilities for type
checking, manipulating binary trees and the "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.


File: parlog.info,  Node: MacParlogCompatibility,  Next: OldChanges,  Prev: SPMCompatibility,  Up: ReferenceManual

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 `toground/3' and
`tohollow/3', and `varsin/2' permits the variables in a term to be
accessed.  `primitives/1' and `private_macparlog_names/1' have no
equivalents in Parallel Parlog.

I/O in MacParlog is based on "channels", which are like Parallel Parlog
"streams" except that channels can be connected to Macintosh windows.
MacParlog input can utilise the mouse, and `key/0' is available for
waiting on input.  `gread/3' reads terms and returns the variables
contained within them, but is less flexible than `read/4' in Parallel
Parlog.  `skip/1' and `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 `create/2', `new/3' and `old/2' to
access a particular file on a volume.

MacParlog has a number of extra utility predicates not present in
Parallel Parlog; namely `beep/1', `recall/2', `remember/2', `ticks/1'
and `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.


File: parlog.info,  Node: OldChanges,  Next: Changes,  Prev: MacParlogCompatibility,  Up: ReferenceManual

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
`-C', `-H', `-S' and `-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 `-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
`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 `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 `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 `is/2' precedes a sequential
conjunction operator (``&'') and is not in parallel with any other goal
calls - the compiler provides a warning message about this.

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

