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

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

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


File: icp.info,  Node: StreamHandling,  Prev: IOChars,  Up: IO

File and Stream Handling
------------------------

Input and output streams are represented as unique prolog terms having
the following form where `N' is an integer.

`stream(N)'
     refers to the terminal or files

`memory(N)'
     refers to ram files, which can be converted to and from prolog
     atoms.

There are also three streams which are opened automatically by the
system

`user_input'
     The standard input channel (`C' `stdin')

`user_output'
     The standard output channel (`C' `stdout')

`user_error'
     The standard error channel (`C' `stderr')

`open(+F,+M,-STREAM)'
     Opens file F in mode M on file-stream STREAM. M must be one of
     `read', `write' and `append'.

`close(+STREAM)'
     Closes the stream corresponding to STREAM.

`set_input(+STREAM)'
     Makes STREAM the current input stream.

`set_output(+STREAM)'
     Makes STREAM the current output stream.

`current_input(-STREAM)'
     Instantiates STREAM with the current input stream.

`current_output(-STREAM)'
     Instantiates STREAM with the current output stream.

`open_ram(+C,+M,-STREAM)'
     Opens ram-file C in mode M on memory-stream STREAM.  M must be one
     of `read', `write' and `append'.  When opening a ram-file in
     `read' or `append' mode C must be an atom representing the file's
     contents.   This atom is usually the result of a `ram_const/2'
     call.  When opening the file in `write' mode, argument C is
     ignored and the file is created empty.

`open_ram(+C, +M, -STREAM, +SIZE)'
     As `open_ram/3' but allows the size of the ram file to be
     specified.

`ram_const(+F, -C)'
     Converts the contents of the ram-file +F into an atom -C.
     Typically, -C is subsequently used as the first argument of an
     `open_ram/3' call to access the contents of the ram-file.

`ram_pipe(-OUT,-IN)'
     Creates a pseudo-pipe by allocating a ram file with two references
     to it.  The first reference OUT is opened in write mode, and the
     second reference IN is opened in read mode.  This allows one
     thread to pass terms to another.  It is the responsiblity of the
     programmer to make sure that there is data available before it is
     read.  For pipes with blocking read and write, see `pipe/2' in
     chapter 14.  The advantage of ram pipes is that they can be made
     the subject of current input and current output.

`tty(+NAME,-READ,-WRITE)'
     Creates a new window with title NAME and two streams -- READ and
     WRITE.  Input typed in the new window can be read from stream
     READ.  Output written to stream WRITE will appear in the window.

`flush_output(+STREAM)'
     STREAM must be a stream open for output. OUTPUT to a stream is not
     necessarily sent immediately; it is buffered. This predicate
     flushes the output buffer for the specified stream and thus
     ensures that everything that has been written to the stream is
     actually sent at that point.

`flush'
     Same as `flush_output/1' except that the flushed stream is the
     current output stream.

`file_exists(+F)'
     Succeeds if file F exists.


File: icp.info,  Node: Arithmetic,  Next: TypePrimitives,  Prev: IO,  Up: Builtin Predicates

Arithmetic
==========

`-X is +Y'
     X is the result of evaluating arithmetic expression Y.

     An arithmetic expression is either an number, or a variable which
     is bound to a number, or a singleton list whose head is an integer
     (in this case the value of the expression is the integer itself),
     or a single character in double quotes (in this case the value of
     the expression is the ASCII code of the character), or a compound
     expression. A compound expression is a tuple whose functor is an
     arithmetic operator and whose arguments are arithmetic
     expressions. A description of the allowed compound expressions,
     together with the result of their evaluation follows:

    `-E'
          negative of E

    `E1 + E2'
          sum of E1 and E2

    `E1 ++ E2'
          integer sum of integers E1 and E2

    `E1 - E2'
          difference of E1 and E2

    `E1 -- E2'
          integer difference of integers E1 and E2

    `E1 * E2'
          product of E1 and E2

    `E1 ** E2'
          integer product of integers E1 and E2

    `E1 / E2'
          quotient of E1 and E2

    `E1 // E2'
          integer part of quotient of integers E1 and E2

    `E1 mod E2'
          remainder of the integer division of E1 and E2

    `E1 ^ E2'
          E1 raised to the power E2

    `E1 << E2'
          integer E1 shifted left by E2 bits

    `E1 >> E2'
          integer E1 shifted right by E2 bits

    `\E'
          bitwise logical negation of integer E

    `E1 /\ E2'
          bitwise logical And of integers E1 and E2

    `E1 \/ E2'
          bitwise logical Or of integers E1 and E2

    `int(E)'
          integer truncation of E towards 0

    `abs(E)'
          absolute value of E

    `sign(E)'
          sign of E: -1 if negative, 1 if positive and 0 if 0

    `ceil(E)'
          round up to next higher integer

    `floor(E)'
          round down to next lower integer

    `sin(E)'
          sine of an angle E in radians

    `cos(E)'
          cosine of an angle E in radians

    `tan(E)'
          tangent of an angle E in radians

    `sin(E)'
          arcsine of E (in radians) in the range -pi/2 to pi/2

    `acos(E)'
          arcosine of E (in radians) in the range 0 to pi

    `atan(E)'
          arctangent of E (in radians) in the range -pi/2 to pi/2

    `atan2(E1, E2)'
          arctangent of E1/E2 (in radians) in the range -pi to pi

    `sinh(E)'
          hyperbolic sine of an angle E in radians

    `cosh(E)'
          hyperbolic cosine of an angle E in radians

    `tanh(E)'
          hyperbolic tangent of an angle E in radians

    `exp(E)'
          natural anti-logarithm of E

    `log(E)'
          natural logarithm of E

    `log10(E)'
          logarithm (base 10) of E

    `sqrt(E)'
          square root of E

    `pow(E1, E2)'
          E1 raised to the power E2

    `pi'
          value of pi

    `rand'
          random integer in the range 0 to 32767

    `deg2rad(E)'
          number of radians in E degrees

    `rad2deg(E)'
          number of degrees in E radians

    `integer(E)'
          the integer component (integer closest to 0) of E's value.

    `float(E)'
          E's value.

* Menu:

* ArithmeticComparison::        Arithmetic Comparison


File: icp.info,  Node: ArithmeticComparison,  Up: Arithmetic

Arithmetic Comparison
---------------------

`+X =:= +Y'
     X is equal to Y.

`+X =\= +Y'
     X is not equal to Y.

`+X < +Y'
     X is less than Y.

`+X > +Y'
     X is greater than Y.

`+X =< +Y'
     X is less than or equal to Y.

`+X >= +Y'
     X is greater than or equal to Y.


File: icp.info,  Node: TypePrimitives,  Next: Term Comparison,  Prev: Arithmetic,  Up: Builtin Predicates

Type Primitives
===============

`tag(+TERM,-TAG)'
     TAG is bound to an integer in the range 0-6 which uniquely
     identifies TERM's type. The tag values are as follows:

    `TAG=0'
          variable

    `TAG=1'
          integer

    `TAG=2'
          floating point

    `TAG=3'
          atom

    `TAG=4'
          nil (empty list)

    `TAG=5'
          list

    `TAG=6'
          tuple

`var(?X)'
     Succeeds if X is an uninstantiated variable.

`nonvar(?X)'
     Succeeds if X is instantiated.

`atom(?X)'
     Succeeds if X is an atom.

`integer(?X)'
     Succeeds if X is an integer.

`float(?X)'
     Succeeds if X is a floating point number.

`number(?X)'
     Succeeds if X is a number (integer or floating point).

`atomic(?X)'
     Succeeds if X is an atom or a number.

`list(?X)'
     Succeeds if X is a list (empty or non-empty).

`compound(?X)'
     The call succeeds if and only if X is bound to a tuple or a
     non-empty list.

`tuple(?X)'
     Succeeds if X is a tuple.

`tuple(?X,-N)'
     Succeeds if X is a functor of arity N-1 (N >= 1).

`length(?TERM,?N)'
     If TERM is a list with a non variable length, N will be bound to
     its length.

     If N is an integer then TERM will be instantiated to a list with N
     elements.

     If TERM is a tuple, N will be unified with the tuple's arity plus
     one.

`?T1 = ?T2'
     Defined as if by the clause "`Z=Z.'"; that is, T1 and T2 are
     unified.

`?T1 \= ?T2'
     Succeeds if an only if the call `T1=T2' fails; that is, if T1 and
     T2 are not unifiable.

`functor(?TERM,?NAME,?ARITY)'
     TERM is a term with functor NAME and arity ARITY.  Atomic terms
     are taken to have arity 0 and functor identical to the term. If
     TERM is a variable the arity must be an integer >= 0 and NAME a
     valid ICP tuple functor.
          | ?- functor(foo(a1, a2, a3), Name, Arity).
          
          Name = foo
          Arity = 3
          
          | ?- functor(Term, foo, 3).
          
          Term = foo(_132,_133,_134)
          
          | ?- functor(foo, Name, Arity).
          
          Name = foo
          Arity = 0
          
          | ?- functor(T, f(Z), 2).
          
          Unbound variable : Z
          T = f(Z)(_113,_114)

`arg(+N,+TUP,-ARG)'
     If N is a positive integer less than or equal to the arity of tuple
     TUP then ARG is unified with TUP's Nth argument.
          | ?- arg(2, foo(a1, a2, a3), Arg).
          
          Arg = a2

`nth0(?N,+LIST,?EL)'
     If N is a positive integer, this finds the nth element ?EL in a
     list +LIST, counting the first element as 0.  If N is a variable,
     then the position of the element ?EL is calculated.

`nth1(?N,+LIST,?EL)'
     If N is a positive integer, this finds the nth element ?EL in a
     list +LIST, counting the first element as 1.  If N is a variable,
     then the position of the element ?EL is calculated.

     If N is a positive integer less than or equal to the arity of tuple
     TUP then ARG is unified with TUP's Nth argument.

`?X =.. ?Y'
     Y is a list. Its head is the functor of X and its (possibly empty)
     tail is a list of X's arguments.


File: icp.info,  Node: Term Comparison,  Next: ProgramState,  Prev: TypePrimitives,  Up: Builtin Predicates

Term Comparison
===============

* Menu:

* StandardOrderTerms::          The Standard Order on Terms
* TermComparisonPreds::         Term Comparison Predicates


File: icp.info,  Node: StandardOrderTerms,  Next: TermComparisonPreds,  Up: Term Comparison

The Standard Order on Terms
---------------------------

If two terms are of a different type, then the ordering is as follows:
variable < number < symbol < nil < list < tuple

If two terms have the same type then:

   * variables are compared by their machine address

   * numbers are compared using ``</2''.

   * symbols are compared lexicographically, using the ASCII ordering.

   * lists are compared by their first element.  If equal, the tails are
     compared.

   * tuples are compared first by arity, then by each of the arguments.


File: icp.info,  Node: TermComparisonPreds,  Prev: StandardOrderTerms,  Up: Term Comparison

Term Comparison Predicates
--------------------------

`compare(?OP,?T1,?T2)'
     The result of comparing terms T1 and T2 is OP, where the possible
     values of OP are:

    ``=''
          If T1 is identical to T2,

    ``<''
          If T1 is before T2 in the Standard Order

    ``>''
          If T1 is after T2 in the Standard Order

`?T1 == ?T2'
     Succeeds if the terms currently instantiating T1 and T2 are
     literally identical (in particular, variables in equivalent
     positions in the two terms must be identical).

`?T1 \== ?T2'
     Succeeds if the terms currently instantiating T1 and T2 are not
     literally identical.

`?T1 @> ?T2'
     Succeeds if term T1 is after term T2 in the Standard Order.

`?T1 @< ?T2'
     Succeeds if term T1 is before term T2 in the Standard Order.

`?T1 @>= ?T2'
     Succeeds if term T1 is not before term T2 in the Standard Order.

`?T1 @=< ?T2'
     Succeeds if term T1 is not after term T2 in the Standard Order.


File: icp.info,  Node: ProgramState,  Next: ExecutionAndError,  Prev: Term Comparison,  Up: Builtin Predicates

Examining the Program State
===========================

`defined(+PREDARITY)'
     Succeeds if PREDARITY is currently defined.
          | ?- defined(defined/1).
          
          yes

`predicate(?PRED,?TERM)'
     Succeeds if it can unify PRED with the name of a currently defined
     predicate and TERM with the most general tuple with the same arity
     (i.e. a tuple with distinct variables for all of its arguments) and
     having PRED as its functor and the predicate's arity as its arity.
          | ?- predicate(Pred, Term).
          
          Pred = mod%f
          Term = mod%f(_149,_150,_151)
          
          | ?- predicate(predicate, Term).
          
          Term = predicate(_143,_144)

`current_predicate(?PRED,?TERM)'
     Succeeds if it can unify PRED with the name of a user-defined
     predicate and TERM with the most general tuple (i.e. a tuple with
     distinct variables for all of its arguments) having PRED as its
     functor and the predicate's arity as its arity.
          | ?- current_predicate(Pred, Term).
          
          Pred = system_file
          Term = system_file(_153)
          
          | ?- current_predicate(foo, Term).
          
          no
          | ?- assert(foo(1,2)), current_predicate(foo, Term).
          
          Term = foo(_466,_467)

`system_predicate(?PRED,?TERM)'
     Attempts to unify PRED with the name of a system-predicate and
     TERM with the most general tuple with the same arity (i.e. a tuple
     with distinct variables for all of its arguments) having PRED as
     its functor.
          | ?- system_predicate(Pred, Term).
          
          Pred = mod%f
          Term = mod%f(_153,_154,_155)
          
          | ?- system_predicate(listing, Term).
          
          Term = listing ;
          
          Term = listing(_145) ;
          
          no

`predicate_property(?TERM, ?PROPERTY)'
     Finds the property associated with predicate TERM. A predicate can
     have more than one property. The possible properties are

    `static'
          The predicate is static (i.e. compiled).

    `dynamic'
          The predicate is dynamic (i.e. consulted or asserted).

    `system'
          The predicate is a system predicate.

    `user'
          The predicate is a user defined predicate.

     A predicate can have more than one property
          | ?- predicate_property(predicate_property(_,_), Property).
          
          Property = static ;
          
          Property = system ;
          
          no

`clause(?HEAD,?BODY)'
     Searches the database for a clause whose head matches HEAD and
     whose body matches BODY. This predicate is non-determinate and can
     be used to backtrack through all the clauses matching HEAD and
     BODY. It fails when there are no (further) matching clauses in the
     database.

     For the purpose of this matching, unit clauses (clauses with no
     body) are treated as if they had a body consisting of the single
     goal `true/0'.

`listing'
     Lists to the current output channel all the relations (if any)
     which are in the data base.

`listing(+PRED)'
     All forms of `listing/1' can only be used for dynamic predicates.

     If PRED is an atom, lists to the current output channel all the
     relations (if any) which are in the data base and have PRED as
     name.

     If PRED is a term of the form NAME/ARITY then the predicates of
     the specified name and arity are listed.

     If PRED is a term of the form NAME/ARITY1-ARITY2, then listing
     lists the relations with name Name and arities in the specified
     range to the current output channel.

     PRED may also be a list of terms of the above form. Thus the goal
          ?- listing([foo, bar/2]).
     is equivalent to the goal
          ?- listing(foo), listing(bar/2).

`listfile(+FILE)'
     Lists to the current output channel all predicates in file FILE.
     If FILE does not end in `.pl' this extension is appended to the
     file name.


File: icp.info,  Node: ExecutionAndError,  Next: ModifyingDatabase,  Prev: ProgramState,  Up: Builtin Predicates

Execution and Error Handling
============================

Error handling in ICP is based on the idea of catch-and-throw.  The
query
     	catch(Goal)
behaves in exactly the same way as
     	call(Goal)
if GOAL succeeds or fails.  However, if an error occurs during the
execution of GOAL, then the behaviour is as if `system_error/2' was
called, with the first argument being GOAL and the second argument
bound to the error number.  The error numbers are listed in the
appendix.

Note that `system_error/2' is called with the argument GOAL even though
the error might have occurred in a subgoal of GOAL. e.g.  in the
program,
     	p :- q, r.
     	q :- s, t.
and the call
     	catch(p)
the system error handler will report the error occurring in P even
though the error might have occurred in the subgoal T.  This has the
advantage that the low-level definition of P can be hidden.  If the
user really wanted to report T as the culprit goal, this can be
specified by changing the definition of Q to be
     	q :- s, catch(t).
This introduces another nesting level of `catch'.  Errors are always
reported at the innermost catch level.

Errors are normally generated from the execution of built-in
primitives.  Typically, a primitive is called with the wrong arguments.
However, it is possible to manually force errors by using `throw/1',
where the argument specifies the error number.  This is also the
mechanism for generating any user-defined errors.

There are cases when we would like to call the system error handler
with a different goal from the one which `caught' the error.  We can do
this using `catch/2'.

If the user wishes to handle specific errors but default to the system
error handler for all other cases, then the `user_error/2' hook should
be used.

There is yet another form `catch/3' which offers the most control in
error-handling.  In this form, any goal may be called as the error
handler to be used.

These different options are described in more detail below.

`catch(+GOAL)'
     This defines a catch point.  GOAL is executed. If GOAL succeeds
     without any errors, the call to `catch/1' succeeds. If GOAL fails
     without any errors, the call to `catch/1' fails.  Otherwise, if an
     error occurs during the execution of GOAL, the system error
     handler of ICP is invoked with GOAL and the error number.

`throw(+ERROR)'
     An error with error code ERROR is forced. The error is handled by
     the error handler associated with the most recent call to catch.

`catch(+GOAL,+BADGOAL)'
     Same as `catch/1' except that the ICP error handler is invoked
     with BADGOAL, rather than GOAL, being the culprit goal.

`catch(+GOAL,+ERRORHANDLER,-ERROR)'
     GOAL is executed. If GOAL succeeds without any errors, the call to
     `catch/3' succeeds. If GOAL fails without any errors, the call to
     `catch/3' fails. Otherwise, if an error occurs during the
     execution of GOAL, ERROR is bound to the appropriate error code
     and then ERRORHANDLER is executed.  This predicate is a hook for
     enabling user-defined error handling.  This is very powerful
     because the user-defined error handler may contain any number of
     arguments.  For simple cases where the error goal and the error
     number are sufficient, the `user_error/2' hook described next is
     better.

`user_error(+GOAL, +ERRNO)'
     Error handlers may be defined by `user_error/2', where the first
     argument is the goal at the catch point (not necessarily the goal
     that caused the error) and the second argument is the error number.

     Here is a sample error handler.  Note the use of cut for each
     clause, and the final catch-all clause that passes the error to
     the error handler at the next level up (typically the system error
     handler).
          user_error(Goal, 403) :- !,	/* predicate not defined error */
          	writeseqnl([Goal, 'not defined yet']),
          	fail.
          user_error(Goal, 600) :- !,	/* divide by 0 error */
          	writenl('divide by zero is not possible'),
          	fail.
          user_error(Goal, Error) :- !,	/* throw to the next level up */
          	throw(Error).

     For convenience, access to the system error handlers is provided
     via `system_error/2' and `system_fail/2'.  The difference between
     the two is that `system_error/2' will cause a return to the top
     level ICP prompt, whereas `system_fail/2' will simply fail and
     cause a backtrack.  Typically, these will be used in user-defined
     error handlers for the `uninteresting' cases.

`system_error(+GOAL, +ERROR)'
     Display an error message for the error number ERROR and return to
     the top level prompt.

`system_fail(+GOAL, +ERROR)'
     Display an error message for the error number ERROR and then fail.

     Undefined predicates are handled slightly differently.  Initially
     they are not errors as such, but you may define them to be errors.
     So what is so special about undefined predicates ?  Recall that a
     call
          	catch(p)
     creates a catch point.   Any errors that occur while executing p
     will cause a throw to the most recent catch point where it is
     reported.  The part of the search tree between the catch and the
     throw (where the error occurred) is discarded.  This is important
     because it means that whatever action we can take to recover from
     the error, it can only proceed from the `catch' and not from the
     point where the error occurred (which may be deep down the search
     tree).  This is fine for most errors where we want to continue
     from a known point, however for undefined predicates it is not
     ideal.  Consider the following program :
          	p :- q.
          	q :- r.
          	r :- s.
     and the call
          	| ?- catch(p).
     (Actually the `catch' is redundant here because all top-level
     queries are automatically caught)  The system will report the
     error as
          	ERROR 403 : undefined predicate : p/0
     This is confusing because it is 's' that is undefined, not 'p'.
     However, this is what happens because the only catch point created
     was at 'p'.  Moreover, even if we defined our own error handler to
     try to recover, we cannot continue from 's', but instead we are
     forced to restart from 'p' again.  The solution is `obvious' -
     catch everything !  This solution is very expensive, because it
     means we use meta-call for everything.  There must be a better way
     ...

     The solution we adopted in ICP is to consider undefined predicates
     as interrupts rather than errors.  With interrupts, we always know
     the exact point of interruption and we have the option to continue
     execution.  This is more general than the above, because we can get
     the same behaviour by making the default action of the interrupt
     handler to throw error 403 (undefined predicate error).  Of course,
     we can also do other things like load/consult files which may
     contain definitions for the culprit goal, or even arbitrarily
     succeed, fail or bind the culprit goal interactively to continue
     the execution.  The interrupt handler just described is exactly
     the default action in ICP.

     This default action may be changed by setting the `undefined'
     property of the thread.  Each thread has a thread identifier which
     may be retrieved by the call
          	thread(-Id)
     By default, this property is not set and the interactive handler is
     invoked whenever an undefined predicate is encountered.  If the
     property is set as follows :
          	set_prop(Id, undefined, fail)
     then all undefined predicates are assumed to fail silently.
          	set_prop(Id, undefined, warning)
     causes all undefined predicates to fail, but a warning message is
     displayed.
          	set_prop(Id, undefined, error)
     treats all undefined predicates as errors, which means that an
     error is thrown to the most recent catch point.  Note that in this
     case the exact location of the undefined predicate will be lost as
     explained previously.

     Even if we installed our own `user_error/2', undefined predicates
     will not call the new error handler because undefined predicates
     are not (by default) errors.  To invoke the user-defined error
     handler, you will need to specify undefined predicates as being
     errors.  We do this like so :
          	thread(Id), set_prop(Id, undefined, error)
     as discussed previously.

     Now this invokes our error handler as expected.  However, we still
     have the problem of the catch point not being where the undefined
     predicate occurred.  (This may not be a problem if the programmer
     has taken care to put catch calls around all potentially undefined
     predicates.  In this case, no more action is required.)   What we
     need is not just a replacement for the error handler, we need a
     replacement for the `undefined-predicate-interrupt-handler' too !

     This interrupt handler is specified using the `user_undefined/1'
     hook.

`user_undefined(+GOAL)'
     This is a hook to allow users to trap undefined predicate errors.
     The argument is the undefined goal.  The user may specify actions
     to take and perhaps retry the goal.  Note that this is independent
     of any error handler since undefined predicates are not errors
     unless explicitly thrown as in the example below.
          user_undefined(Goal) :-
          	functor(Goal, Pred, Arity),
          	writeseqnl(['missing predicate :', Pred/Arity]),
          	throw(403).	/* error code for undefined predicate */

`system_undefined(+GOAL)'
     For convenience, access to the system undefined predicate interrupt
     handler is provided.  This will typically be called from a
     `user_undefined/1' relation.

`halt'
     Exits ICP.

`abort'
     Aborts execution and, after warning the user, returns control to
     the top-level query handler.

`op(+PRIORITY,+TYPE,+OPNAME)'
     Declares an operator with name OPNAME.  PRIORITY should be an
     integer between 1 and 1200, which will determine the operator
     precedence when the operator's arguments are themselves operator
     expressions. The lower the priority number, the tighter binding the
     operator.  The type argument is one of

    `fx'
          non associative prefix operator. The subexpression forming the
          argument of the operator must have lower precedence than the
          operator itself.

    `fy'
          associative prefix operator. The subexpression forming the
          argument can have the same precedence as the 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 for the relevant type.

     When several operators have the same declaration, the OPNAME
     argument can be a list of operator names.

`current_op(?PRIORITY,?TYPE,?OPNAME)'
     If OPNAME is an atom, the call can be used to find the priority and
     type of a given operator. If OPNAME is a variable then the call to
     current_op may be used to backtrack through operators, and in this
     case if either TYPE or PRIORITY is an atom then only operators of
     that TYPE and/or PRIORITY will be retrieved.


File: icp.info,  Node: ModifyingDatabase,  Next: Properties,  Prev: ExecutionAndError,  Up: Builtin Predicates

Modifying the Database
======================

`assert(+CLAUSE)'
     Adds the specified CLAUSE to the database as the last clause of its
     procedure.

`asserta(+CLAUSE)'
     Adds the specified CLAUSE to the database as the first clause of
     its procedure.

`assertz(+CLAUSE)'
     Same as `assert/1'.

`assertx(+CLAUSE,+INDEX)'
     Adds the specified CLAUSE to the database. If Index is positive
     then the clause is asserted as the INDEXth clause of its
     procedure. If INDEX is negative then the clause is asserted as the
     last but INDEXth of its procedure. If INDEX is zero, or too large
     a positive integer, then the clause is asserted as the last one.
     If INDEX is too large a negative number then the clause is
     asserted as the first one.

`retract(+CLAUSE)'
     If there is a clause in the data base that matches CLAUSE, then
     that clause is deleted and any variables in CLAUSE are
     instantiated by the match. On backtracking there is an attempt to
     find another matching clause.  The search always starts at the
     beginning of the list of clauses for the relation name of CLAUSE.
     The call fails when there is no matching clause.

`retractx(+NAME,+ARITY,+INDEX)'
     If the dynamic predicate NAME/ARITY is defined, then one of its
     clauses, as specified by index, is deleted. If INDEX is positive,
     then the INDEXth clause of the procedure is deleted. If INDEX is
     negative then the last but INDEXth clause of the procedure is
     deleted. If INDEX is too large a positive integer then the last
     clause of the procedure is deleted. If INDEX is zero, or too large
     a negative number, then the first clause of the procedure is
     deleted.

`retractall(+CLAUSE)'
     All the data base clauses which match CLAUSE are deleted, with any
     variables in CLAUSE left uninstantiated. `retractall/1' always
     succeeds.

`abolish(+PRED)'
     If predicate PRED is currently defined, then it becomes undefined.
     This can be used to remove definitions for both static and dynamic
     predicates.

`kill(+PRED)'
     If predicate PRED is currently defined, then it becomes undefined.
     If predicate PRED is currently defined by a static segment, then
     all the predicates which are currently defined by that segment
     become undefined.  This gives an easy method to remove all
     associated predicate definitions e.g. normally all predicates
     defined in the same file.

`save(+PRED,+FILE)'
     Saves the object code for predicate(s) PRED to file FILE.  PRED is
     either a single predicate or a list of predicates. Only those
     predicates which are defined are saved.

`save(+PRED,+FILE,+MODE)'
     Opens the file FILE in MODE mode and saves the object code for
     predicate(s) PRED.  PRED is either a single predicate or a list of
     predicates. Only those predicates which are defined are saved.
     MODE must be either `write' or `append'.


File: icp.info,  Node: Properties,  Next: Metalogical,  Prev: ModifyingDatabase,  Up: Builtin Predicates

Property Management
===================

`set_prop(+OBJECT,+PROPERTY,?VALUE)'
     Sets a property value; VALUE becomes the remembered value of the
     property PROPERTY of the object OBJECT. Any previously remembered
     value of the PROPERTY of the OBJECT is lost.

`get_prop(+OBJECT,+PROPERTY,-VALUE)'
     Retrieves the value of a property; VALUE is instantiated with the
     current value of the PROPERTY of OBJECT. If there is no remembered
     value, the call fails.

`del_prop(+OBJECT,+PROPERTY)'
     Removes a property value; the remembered PROPERTY value of OBJECT
     is forgotten. A subsequent call to
     `get_prop(Object,Property,Value)' will fail. `del_prop/2' does
     nothing and succeeds if there is no such OBJECT or PROPERTY.

`del_props(+OBJECT)'
     Deletes all properties for a symbol; All the property-value pairs
     for the given OBJECT are forgotten.

`del_cons(+PROPERTY)'
     Deletes all symbol values for a property. All the property-value
     pairs for the given PROPERTY are forgotten.

`remember(+ATOM,?VALUE)'
     Stores VALUE as the currently stored value of ATOM. Any previously
     assigned value is lost.

`recall(+ATOM,-VALUE)'
     VALUE is instantiated with the currently stored value of atom.
     `recall/2' fails if ATOM has no currently stored value.

`default_prop(+ATOM,-VALUE,?DEFAULT)'
     VALUE is instantiated with the currently stored value of ATOM, if
     there is one. It will be instantiated with DEFAULT if there is no
     currently stored value.

`forget(+ATOM)'
     Deletes the stored value associated with ATOM. A `recall/2' on
     ATOM will now fail.  A call to forget always succeeds, even if
     there is no stored value.

`get_cons(+PROPERTY,-LIST)'
     LIST is bound to to the list of all the atoms that currently have a
     value for the property PROPERTY.

`get_props(+OBJECT,-LIST)'
     LIST is bound to the list of all the names of the properties
     currently associated with OBJECT.

`list_props(+OBJECT,-LIST)'
     LIST is bound to the list of all the `Property=Value' pairs
     currently associated with OBJECT.


File: icp.info,  Node: Metalogical,  Next: GrammarRules,  Prev: Properties,  Up: Builtin Predicates

Metalogical Primitives
======================

`ntpl(+LEN,-TPL)'
     TPL is instantiated to the most general tuple having LEN as its
     positive (>=1) arity, that is, a tuple with distinct variables for
     its functor and all of its arguments.
          | ?- ntpl(3, Tpl).
          
          Tpl = _125(_126,_127)

`tohollow(+GROUND,-HOLLOW,+VARNAMES)'
     VARNAMES a list of atoms. Only the atoms in the VARNAMES list of
     atoms are replaced by variables in the HOLLOW copy of GROUND.  Any
     atom can be on the VARNAMES list. The main use of this call is to
     convert a term and its associated list of variable names that has
     been read in using `gread/1', `gread/2' or `gread/3' into a hollow
     term that can be used in an evaluation.
          | ?- tohollow(foo(a,b,c), Hollow, [a,c]).
          
          Hollow = foo(_175,b,_178)

`tohollow(+GROUND,-HOLLOW,+VARNAMES,-VARS)'
     Essentially the same as the above three argument use except that
     the list of variables in HOLLOW that have replaced the atoms on
     VARNAMES is also returned. The i*th* variable on VARS is the
     replacement for the i*th* variable name on VARNAMES.  This is
     useful if you want to subsequently output bindings for these
     variables using the original variable names.
          | ?- tohollow(foo(a,b,c), Hollow, [a,c], Vars).
          
          Hollow = foo(_189,b,_192)
          Vars = [_189,_192]

`toground(?HOLLOW,-GROUND)'
     Simple use to convert any term into a variable free term. GROUND
     is bound to a copy of HOLLOW in which all the variables are
     replaced by new atoms beginning with underscores. Different
     variables are replaced by different underscore names, and there
     will be no clash with any atom that begins with underscore which
     already appears in HOLLOW.
          | ?- toground(foo(A,B,C), Ground).
          
          Unbound variables : A, B, C
          Ground = foo('_0','_1','_2')

`toground(?HOLLOW,-GROUND,-VARNAMES)'
     VARNAMES will be bound to the list of all the underscore variable
     names that have been used to replace variables in HOLLOW.
          | ?- toground(foo(A,B,C), Ground, Varnames).
          
          Unbound variables : A, B, C
          Ground = foo('_0','_1','_2')
          Varnames = ['_0','_1','_2']

`toground(?HOLLOW,-GROUND,-VARS,-VARNAMES)'
     Same as the three argument use except that the corresponding list
     of the replaced variables is also returned as the binding for VARS.

     If there are more variables in HOLLOW than given in VARS, new
     underscore names are given to the extra variables.  More generally,
     the elements of VARS can be any terms. Non-variable terms on VARS,
     and the corresponding atoms on VARNAMES are ignored - but the
     lists must still be of the same length. This relaxation allows
     lists of names and variables returned by some previous use of
     `tohollow/3' or `tohollow/4' to be used as arguments to
     `toground/4' without having to remove variables that may have been
     bound by the intervening evaluation.
          | ?- toground(foo(A,B,C), Ground, Vars, Varnames).
          
          Unbound variables : A, B, C
          Ground = foo('_0','_1','_2')
          Vars = [A,B,C]
          Varnames = ['_0','_1','_2']

`toground(?HOLLOW,-GROUND,+VARS,+VARNAMES,-USEDNAMES)'
     VARNAMES a list of atoms, VARS a list of variables which may
     appear in HOLLOW. The VARNAMES list of atoms will be used to
     replace the variables of VARS in HOLLOW in the order in which they
     are given - the first variable of VARS is replaced by the first
     atom on the VARNAMES list, and so on.

     Finally, USEDNAMES is bound to the complete list of the actual
     variable names that have been used to replace variables in HOLLOW.
          | ?- toground(foo(A,B,C),Ground,[A,B,C],['W','X','Y'],Usednames).
          
          Unbound variables : A, B, C
          Ground = foo(W,X,Y)
          Usednames = [W,X,Y]

`varsin(?TERM, -VARS)'
     VARS is a list of the variables appearing in term TERM
          | ?- varsin((foo(X,Y) :- bar(X,Y,1,Z)), Vars).
          
          Unbound variables : X, Y, Z
          Vars = [X,Y,Z]

`forall(+GEN,+TEST)'
     This call succeeds if for all the solutions of GEN, TEST is true.
          | ?- forall(member(X, [1,2,1,3,5,2,-1]), X<3).
          
          no
          | ?- forall(member(X, [1,2,1,3,5,2,-1]), write(X)).
          121352-1
          Unbound variable : X

`findall(?TERM,+CALL,-LIST)'
     LIST will be unified with a list of instantiations of TERM, one
     for each successful evaluation of CALL.
          | ?- findall(X, (member(X, [1,2,1,3,5,2,-1]), X < 3), List).
          
          Unbound variable : X
          List = [1,2,1,2,-1]

     The instantiations of term correspond to the different solution
     bindings for the variables in CALL. At the end of the evaluation no
     variable in CALL will be bound. All the `local' variables in CALL,
     the variables which do not appear in TERM, or in any other
     condition in the clause or query in which the `findall/3' is used,
     are implicitly existentially quantified.  All `global' variables
     of CALL, variables that are also used in other conditions in the
     clause or query, should be bound to variable free terms before the
     `findall/3' is evaluated.

     Note that `findall/3' is faster then `bagof/3' (see below) and
     should be used instead of `bagof/3' when there will be no unbound
     global variables in the CALL for which solutions are to be found.
          | ?- findall(Y, (member(X, [1,2]), Y is X+1), List).
          
          Unbound variables : X, Y
          List = [2,3] ;
          
          no

`bagof(?ETERM,+EXISTENTIALCALL,?LIST)'
     EXISTENTIALCALL must be a term of the form `V1^V2^...VK^CALL'
     where CALL is a call term, and `V1,...,VK' (k>=0) are variables in
     CALL (when k=0 just the CALL is given).  At the time of the call,
     CALL will generally contain variables.  The variables in CALL that
     are not in either ETERM or the sequence `V1,...,VK' of variables
     preceding CALL are the global variables of the `bagof/3' call.
     `V1,...,VK' are the existentially quantified variables of CALL.

     `bagof/3' partitions the list of all the values of ETERM for all
     the solutions of CALL by different solution values for these global
     variables.

     That is, suppose that in the space of all the successful
     evaluations of CALL there are *n* different sets of bindings for
     its global variables.  Then `bagof/3' will backtrack giving *n*
     different answers.  Each answer will comprise a set of bindings
     for the global variables, and a corresponding value for LIST which
     comprises the instances of ETERM for different solutions of CALL
     that make this assignment to the global variables.
          | ?- bagof(Y, (member(X, [1,2]), Y is X+1), List).
          
          Unbound variable : Y
          X = 1
          List = [2] ;
          
          Unbound variable : Y
          X = 2
          List = [3] ;
          
          no
          | ?- bagof(Y, X^(member(X, [1,2]), Y is X+1), List).
          
          Unbound variables : X, Y
          List = [2,3] ;
          
          no

`setof(?ETERM,+EXISTENTIALCALL,?LIST)'
     Same as `bagof/3' except that the bindings for LIST will be
     ordered lists of terms without duplicates. The terms are ordered
     by the `@</2' primitive as a list of increasing terms.
          | ?- bagof(Y, X^(member(X, [2,1,2,3,0,4]), Y is X+1), List).
          
          Unbound variables : X, Y
          List = [3,2,3,4,1,5]
          
          | ?- setof(Y, X^(member(X, [2,1,2,3,0,4]), Y is X+1), List).
          
          Unbound variables : X, Y
          List = [1,2,3,4,5]

`map(+REL,+INLIST)'
     For each use of `map/2', the term REL may be either a relation
     name or a call term of the form reln(arg1, ..., argn) whose
     principal functor reln is a relation name.

     If REL is a unary relation name, this call will test if all the
     elements of a list INLIST satisfy REL.  If REL is a compound term
     of the form `reln(ARG1,...,ARGN)' then the call tests if all the
     elements EL of the list INLIST satisfy `reln(`Arg1',...,ARGN,EL)'.

`map(+REL,?INLIST,?OUTLIST)'
     If INLIST is given, `map/3' will produce a list OUTLIST such that
     each element of OUTLIST is in the relation REL to the
     corresponding element of INLIST. Alternatively, `map/3' may be
     used to check that a given OUTLIST is in this relationship to
     INLIST.

`map(+REL,+INLIST,+INVALUE,?OUTVALUE)'
     The given REL is applied to `accumulate' the elements of INLIST
     using INVALUE as the initial value of the cumulated term.  The
     variable OUTVALUE is bound to the final cumulated term.

`map(+REL,+INLIST,+OUTLIST,+INVALUE,?OUTVALUE)'
     The given REL is applied both to produce an OUTLIST from INLIST,
     and to `accumulate' the elements of INLIST using INVALUE as the
     initial value of the cumulated term.


File: icp.info,  Node: GrammarRules,  Next: ListHandling,  Prev: Metalogical,  Up: Builtin Predicates

Transformations on Reading
==========================

There are two forms of program transformations which can be done by ICP
when reading in files.

The first is using `term_expansion/2' is based on a clause by clause
transformation and is primarily used for converting grammar rules.  The
implementation of grammar rules is the same as that of Quintus Prolog
`Quintus Prolog Development Environment', Quintus Computer Systems,
Inc., Mountain View, California, USA.  The grammar rule translator used
is based on a public domain program written by Richard O'Keefe.

The second method allows users to define a complete transformation on a
file determined by the file name extension.

* Menu:

* Dcg::                         Definite Clause Grammars
* FileTrans::                   File Transformations


File: icp.info,  Node: Dcg,  Next: FileTrans,  Up: GrammarRules

Definite Clause Grammars
------------------------

A grammar rule takes the form
     head --> body

`expand_term(+TERM1, -TERM2)'
     This predicate is used by `consult/1' and `compile/1' to determine
     the transformation of terms before they are asserted or compiled.
     TERM1 is the input term and TERM2 the output term.  By default,
     only terms corresponding to grammar rules are transormed; in all
     other cases TERM2 is identical to TERM1. This performance may be
     changed if the user predicate `term_expansion/2' is defined.

`phrase(+PHRASE, ?LIST)'
     This predicate determines whether a list LIST is a phrase of type
     PHRASE

`phrase(+PHRASE, ?LIST, ?REST)'
`'C'(?S1, ?TERMINAL, ?S2)'
     This predicate is used in expessing grammar rules and is defined
     by the clause
          'C'([X|S], X, S).

`term_expansion(+TERM1, -TERM2)'
     The standard transformation of terms before compilation or
     consultation can be overridden by defining this predicate. It can
     be used to define different `sugared' syntaxes.

`query_expansion(+TERM1, -TERM2)'
     A user query may be transformed before calling the goal by
     defining this predicate. If it succeeds, TERM2 will be executed
     but the variable bindings will be printed as usual upon completion.


File: icp.info,  Node: FileTrans,  Prev: Dcg,  Up: GrammarRules

File Transformations
--------------------

The transformations in the previous section are at the clause level.  A
more powerful method of transformation is at the level of files, since
this allows contextual transformation of clauses.  For example, when
writing a preprocessor for an object-oriented extension to Prolog, we
may wish to generate default inheritance clauses for objects depending
on whether the object has an explicit superclass defined in the same
file.  This requires a global view of all the clauses in a file rather
than the simple clause-level transformations.

File-level transformations are specified by defining a new file
extension type and a user hook relation to read (and transform) the new
file type.   The user hook relation is either `user_consult/3' or
`user_compile/3'.  An example of the use of these predicates is shown in
`$ICP_INSTALLDIR/skilaki/source/icp_comp.pl'.

`user_file_type(?EXT, ?TYPE)'
     This declaration allows the user to define an alternative
     compilation or consultation for files with the extension EXT. The
     term TYPE may be used to select which paticular transformations to
     perform on reading the file.

`read_prolog_file(-PREDS)'
     This predicate reads an entire file using any user-defined hooks,
     returning the predicates in the list PREDS.

`user_consult(+TYPE, +FILENAME, -PREDS)'
     On consultation, if a `user_file_type/2' declaration exists for the
     file, the system calls this predicate having already opened the
     file FILENAME and set current input to it.  This should read and
     process the file returning a list of predicates as specified below.
     These predicates will then be asserted into the database
     automatically.

     The file may be read using `read_prolog_file/1' and post-processed
     into the list PREDS.  The intended usage is to allow more flexible
     transformations than grammer rules would allow.

          user_file_type('.foo', foo_type).
          
          user_consult(foo_type, File, Preds) :-
          	read_prolog_file(Source),
          	process(Source, Preds).

`user_compile(+TYPE, +FILENAME, -PREDS)'
     As `user_consult/3' but  PREDS are automatically compiled rather
     than asserted.

In all the above predicates, PREDS is a list of terms of the form
`pr(PRED/ARITY,LIST)' where PRED is the predicate name (an atom), ARITY
is an integer and LIST is a list representing the clauses for this
predicate. Each term in this list is of the form
`VARNAMES-GROUNDCLAUSE', where VARNAMES is a list of atoms representing
the variable names in the ground clause GROUNDCLAUSE.


File: icp.info,  Node: ListHandling,  Next: StringsAndAtoms,  Prev: GrammarRules,  Up: Builtin Predicates

List Handling
=============

`qsort(+LIST,-SORTED,+TEST)'
     Test must be the name of a binary relation. The call succeeds if
     SORTED can be unified with the result of sorting LIST with respect
     to TEST.

`append(?LIST1,?LIST2,?LIST3)'
     Succeeds if LIST3 is LIST1 followed by LIST2.

`member(?EL,?LIST)'
     Succeeds if EL is a member of list LIST.  This may be used to
     backtrack over the whole list.

`memberchk(?EL,?LIST)'
     Succeeds if EL is a member of list LIST.  This is different from
     `member/2' since it does not backtrack.

`on(?EL,?LIST)'
     Same as `member/2'

`occ(?X,?L)'
     Succeeds if term X occurs in unsafe list L. An unsafe list is one
     which has a variable as the tail. If X is not in L then it is put
     there.

`no_occ(?X,?L)'
     Succeeds if term X is not in unsafe list L.

`remove(?ITEM,-LIST,-REMAINDER)'
     Succeeds if REMAINDER is the list LIST with the element ITEM
     removed. If ITEM does not occur in LIST, the call to remove fails.
     If ITEM occurs in LIST more than once, subsequent occurrences will
     be removed on backtracking.

`delete(?ITEM,-LIST,-REMAINDER)'
     Same as `remove/2'

`reverse(?LIST,?REVLIST)'
     Succeeds if REVLIST is the list LIST with the order of its
     elements reversed.

