home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-10-23 | 147.9 KB | 4,287 lines |
- .ds f. init
- .nr _0 \n(c.
- .\" Setup for thesis.
- .\" This file should be modified to keep up with the standard
- .\" for a doctoral thesis at Berkeley. Other macros which may
- .\" be useful for a thesis are defined here.
- .\" @(#)thesis.me 2.1 8/18/80
- .
- .\" This version is updated to reflect the ridiculous margin requirements of
- .\" the graduate school at Stony Brook.
- .\" It also has comments supplied by PKH to allow for easier upgrading in the
- .\" future.
- .
- .
- .if n .if \n(_o \
- .po 1.00i \" nroff with page offset, reset to 1.5 inches
- .if t .po 1.0i \" want 1.5 Canon and Troff loose .25
- .ll 6.5i \" for precise 1.5 margins right and left
- .if n .if 1n=0.1i \
- . ll 8.8i \" for nroff and pica, line has even # of char
- .lt 7.5i \" pageno close as possible to 1" off rt edge
- .if n .ls 2 \" double space for nroff (was orig. for both)
- .
- .\" time to reset some "PARAMETRIC INITIALIZATIONS"
- .
- .ie t \
- \{\
- . \" for troff and Canon printer--fudges
- .nr hm 5i/12 \" page number offset 5/12{8} inch top{8}
- .nr tm 1.00i \" margins 1.00{1.5} inches top{1.5}
- .nr bm 1.00i \" and 1.00{1.5} bottom{1.5}
- .nr fm 5i/12 \" page number offset 5/12{8} inch bottom{8}
- . \" nullify cut mark macro for canon
- .rm @m
- .\}
- .el \
- \{\
- .nr hm 5i/12 \" page number offset 5/12{8} inch top{8}
- .nr tm 1.00i \" margins 1.00{1.5} inches top{1.5}
- .nr bm 1.00i \" and 1.00{1.5} bottom{1.5}
- .nr fm 5i/12 \" page number offset 5/12{8} inch bottom{8}
- .\}
- .if t \
- \{\
- .nr pp 10 \" set pointsize
- .nr sp 10 \" set header pointsize
- .vs 16 \" line spacing 1-1/2 [12=single @ 10 points]
- .nr $r \n(.v/\n(.s \" ratio of vert space to point size
- .nr $R \n($r \" same, but for another use
- .nr fp 10
- .\}
-
- .de IP
- .ip \\$1 \\$2
- ..
- .de LP
- .lp
- ..
- .de SH
- .sp
- .ti \\n(.iu
- .if \\n(1T .sp
- .ne 3.1
- .ft B
- ..
-
- .EQ
- .nr 99 \n(.s
- .nr 98 \n(.f
- .ps 10
- .ft 2
- .ps 11
- .ps \n(99
- .ft \n(98
- .EN
- .de $0
- \\*(st
- .(x c
- .if '\\$3'1' \
- .if '\\$3'2' \ \ \
- .if '\\$3'3' \ \ \ \ \ \
- .if '\\$3'4'\ \ \ \ \ \ \ \ \
- .if '\\$3'5'\ \ \ \ \ \ \ \ \ \ \ \
- \\$2
- .if !'\\$3'' :\
- \\$1 \\fR
- .)x \\n%
- ..
-
- .de $1
- .ds co " \\fB
- .ds st \\fR
- .br
- ..
- .de $2
- .ds co "
- .ds st \\fR
- .br
- ..
- .de $3
- .ds co " \\fB
- .ds st \\fR
- .br
- ..
- .de $4
- .ds co " \\fB
- .ds st \\fR
- .br
- ..
-
- \" .de lf
- \" Figure \\n($1.\\n+(fn\\$1
- \" .ds \\$4 Figure \\n($1.\\n(fn
- \" .ie '\\$3'p' \{\
- \" .nr % +1 \}
- \" .el \{\
- \" .ie '\\$3'n' \{\\}
- \" .el \{\
- \" .(z
- \" .sp \\$3
- \" .ce 100
- \" \\$2
- \" Figure \\n($1.\\n(fn
- \" .ce 0
- \" .)z \} \}
- \" .(x F
- \" Figure \\n($1.\\n(fn
- \" \\$2
- \" .)x \\n%
- \" ..
- .ds f. sec0.t
- .tp
- .nr pp 10
- .nr $r 10
- .fo ''''
- .EQ
- .nr 99 \n(.s
- .nr 98 \n(.f
- .ps 11
- .ft 2
- .ps 11
- .ps \n(99
- .ft \n(98
- .EN
- .pp
- \ \ \
- \ \
- .(l
- \
- \
- .nr pp 10
- .nr fp 8
- .lp
- .ce 20
- \fBThe SB-Prolog System, Version 3.1
- .sp
- A User Manual\fR
-
- edited by
- \fISaumya K. Debray\fR
- .sp
- from material by
- .sp
- \fIDavid Scott Warren
- Suzanne Dietrich\fR
- SUNY at Stony Brook
- .sp
- \fIFernando Pereira\fR
- SRI International
- .sp 3
- \fIDecember 1989\fR
- .sp 2
- Department of Computer Science
- University of Arizona
- Tucson, AZ 85721
- .)l
- .ce 0
- .fo ''%'' \" page number on middle of bottom
- .bp
- .pp
- \ \ \
- \ \
- .(l
- \
- \
- \
- \
- .ce 20
- \fBThe SB-Prolog System, Version 3.1
- .sp
- A User Manual\fR
- .)l
- .ce 0
- .sp 3
- .lp
- \fBAbstract\fR: SB-Prolog is a Prolog system for Unix\(dg based systems.
- The core of the system is an emulator, written in C for portability, of a
- Prolog virtual machine that is an extension of the Warren Abstract Machine.
- The remainder of the system, including the translator from
- Prolog to the virtual machine instructions, is written in Prolog.
- Parts of this
- manual, specifically the sections on Prolog syntax and descriptions of some
- of the builtins, are based on the C-Prolog User Manual by Fernando Pereira.
- .(f
- \(dg Unix is a trademark of AT&T.
- .)f
- .fo ''%'' \" page number on middle of bottom
- .nr % 1
- .bp
- .ds f. sec1.t
- .lp
- .bp
- .lp
- .sh 1 "Introduction"
- .lp
- SB-Prolog is a Prolog system based on an extension of the Warren
- Abstract Machine\**.
- .(f
- \** D. H. D. Warren, ``An Abstract Prolog Instruction Set'',
- Tech. Note 309, SRI International, 1983.
- .)f
- The WAM simulator is written in C to enhance
- portability. Prolog source programs can be compiled into \fIbyte code\fR
- files, which contain encodings of WAM instructions and are
- interpreted by the simulator. Programs can also be interpreted via \fIconsult\fR.
- .pp
- SB-Prolog offers several features that are not found on most Prolog systems
- currently available. These include: compilation to object files; dynamic
- loading of predicates; provision for generating executable code on the
- global stack, which can be later be reclaimed; an \fIextension table\fR
- facility that permits memoization of relations. Other features include
- full integration between compiled and interpreted code, and a facility for the
- definition and expansion of macros that is fully compatible with the runtime system.
- .pp
- The system incorporates tail recursion optimization, and performs clause
- indexing in both compiled and interpreted code. However, there is no garbage
- collector for the global stack. This may be incorporated into a later
- version.
- .pp
- One of the few luxuries afforded to a person giving software away for free is
- the ability to take philosophical stances without hurting his wallet.
- Based on our faith in the ``declarative ideal'', viz. that pure
- programs with declarative readings are Good, we have attempted to encourage,
- where possible, a more declarative style of programming. To this end, we
- have deliberately chosen to not reward programs containing cuts in some
- situations where more declarative code is possible (see Appendix 2, \(sc 3).
- We have also resisted the temptation to make \fIassert\fR less expensive.
- We hope this will help promote a better programming style.
- .ds f. sec2.t
- .sh 1 "Getting Started"
- .lp
- This section is intended to give a broad overview of the SB-Prolog system,
- so as to enable the new user to begin using the system with a minimum of
- delay. Many of the topics touched on here are covered in greater depth
- in later sections.
- .sh 2 "The Dynamic Loader Search Path"
- .lp
- In SB-Prolog, it is not necessary for the user to load all the
- predicates necessary to execute a program. Instead, if an undefined predicate \fIfoo\fR is encountered during execution, the
- system searches the user's directories in the order specified by
- the environment variable SIMPATH until it finds a directory containing a file \fIfoo\fR
- whose name is that of the undefined predicate. It then dynamically loads and
- links the file \fIfoo\fR (which is expected to be a byte code file
- defining the predicate \fIfoo\fR), and continues with execution; if no such file can be found, an error message is given and execution fails.
- This feature makes it unnecessary for the user to have to explicitly
- link in all the predicates that might be necessary in a
- program: instead, only those files are loaded which are necessary to have the
- program execute. This can significantly reduce the memory requirements of
- programs.
- .pp
- The key to this dynamic search-and-load behaviour is the SIMPATH environment
- variable, which specifies the order in which directories are to be searched.
- It may be set by adding the following line to the user's .\fIcshrc\fR file:
-
- .(l
- setenv SIMPATH \fIpath\fR
- .)l
-
- where \fIpath\fR is a sequence of directory names separated by colons:
-
- .(l
- \fIdir\fR\*<1\*>:\fIdir\fR\*<2\*>: ... :\fIdir\*<n\*>\fR
- .)l
-
- and \fIdir\*<i\*>\fR are \fIfull path names\fR to the respective
- directories.
- For example, executing the command
- .(l
- setenv SIMPATH .:$HOME/prolog/modlib:$HOME/prolog/lib
- .)l
-
- sets the search order for undefined predicates to the following: first, the
- directory in which the program is executing is searched; if the appropriate file is not found in this
- directory, the directories searched are, in order, ~/prolog/modlib and
- ~/prolog/lib. If the appropriate file is not found in any
- of these directories, the system gives an error message and execution fails.
- .pp
- The beginning user is advised to include the system directories (listed in
- the next section) in his SIMPATH, in order to be able to access the system
- libraries (see below).
- .sh 2 "System Directories"
- .lp
- There are four basic system directories: cmplib, lib, modlib and sim.
- \fIcmplib\fR contains the Prolog to byte code translator;
- \fIlib\fR and \fImodlib\fR contain library routines. The \fIsrc\fR
- subdirectory in each of these contains the corresponding Prolog source programs. The
- directory \fIsim\fR contains the simulator, the subdirectory \fIbuiltin\fR
- contains code for the builtin predicates of the system.
- .pp
- It is recommended that the beginning user include the system directories in
- his SIMPATH, by setting SIMPATH to
- .(l C
- .\|:\|\fISBP\fR/modlib\|:\|\fISBP\fR/lib\|:\|\fISBP\fR/cmplib
- .)l
- where \fISBP\fR denotes the path to the root of the SB-Prolog system directories.
- .sh 2 "Invoking the Simulator"
- .lp
- The simulator is invoked by the command
- .(l
- sbprolog \fIbc_\|\^file\fR
- .)l
- where \fIbc_\|\^file\fR is a byte code file resulting from the compilation of a
- Prolog program. In almost all cases, the user will wish to interact with the
- SB-Prolog \fIquery evaluator\fR, in which case \fIbc_\|file\fR will be
- \fI$readloop\fR, and the command will be
- .(l C
- sbprolog \fIPath\fR/$readloop
- .)l
- where \fIPath\fR is the path to the directory containing the
- command interpreter \fI$readloop\fR. This directory, typically, is \fImodlib\fR
- (see Section 2.2 above).
- .pp
- The command interpreter reads in a query typed in by the user, evaluates it and
- prints the answer(s), repeating this until it encounters an end-of-file
- (the standard end-of-file character on the system, e.g. ctrl-D), or the user types
- in \fIend_\|of_\|file\fR or \fIhalt\fR.
- .pp
- The user should ensure that the the directory containing the executable file \fIsim\fR
- (typically, the system directory \fIsim\fR: see Section 2.2
- above) is included in the shell variable \fIpath\fR; if not, the full path
- to the simulator will have to be specified.
- .pp
- In general, the simulator may be invoked with a variety of options, as
- follows:
- .(l
- sbprolog \-\fIoptions\fR \fIbc_\|\^file\fR
- or
- sbprolog \-\fIoption\fR\*<1\*> \-\fIoption\fR\*<2\*> ... \-\fIoption\*<n\*>\fR \fIbc_\|\^file\fR
- .)l
- The options recognized by the simulator are described in Section 4.2.
- .pp
- When called with a byte code file \fIbc_\|\^file\fR, the simulator begins
- execution with the first clause in that file. The first clause in such a
- file, therefore, should be a clause without any arguments in the head
- (otherwise, the simulator will attempt to dereference argument pointers
- in the head
- that are really pointing into deep space, and usually come to a sad end).
- If the user is executing a file in this manner rather than using the
- command interpreter, he should also be careful to include the undefined
- predicate handler, consisting of the predicates `_$\fIinterrupt\fR/2 and
- `_\|\fI$undefined_\|pred\fR'/1, which is normally defined in the files
- \fImodlib/src/$init_\|sys.P\fR and \fImodlib/src/$readloop\fR.
- .(x Z
- (L) _\|$undefined_\|pred/1
- .)x
- .sh 2 "Executing Programs"
- .lp
- There are two ways of executing a program: a source file may be compiled
- into a byte-code file, which can then be loaded and executed; or, the source file may be
- interpreted via \fIconsult\fR. The system supports full integration of compiled and
- interpreted code, so that some predicates of a program may be compiled, while
- others may be interpreted. However, the unit of compilation or consulting
- remains the file. The remainder of this section describes each of these procedures in
- more detail.
- .sh 3 "Compiling Programs"
- .lp
- The compiler is invoked through the Prolog predicate \fIcompile\fR. It translates Prolog
- source programs into byte code that can then be executed on the simulator.
- .(x C
- (L) compile/1
- .)x
- .(x C
- (L) compile/2
- .)x
- .(x C
- (L) compile/3
- .)x
- .(x C
- (L) compile/4
- .)x
- The compiler may be invoked as follows:
-
- .(l
- | ?- compile(\fIInFile\fR [, \fIOutFile\fR ] [, \fIOptionsList\fR ]).
- or
- | ?- compile(\fIInFile\fR, \fIOutFile\fR, \fIOptionsList\fR, \fIPredList\fR).
- .)l
-
- where optional parameters are enclosed in brackets.
- \fIInFile\fR is the name of the input (i.e. source) file; \fIOutFile\fR is the
- name of the output file (i.e. byte code) file; \fIOptionsList\fR is a list of compiler options,
- and \fIPredList\fR is a list of terms \fIP\fR/\fIN\fR denoting the
- predicates defined in \fIInFile\fR, where \fIP\fR is a predicate name and \fIN\fR
- its arity.
- .pp
- The input and output file names must be Prolog atoms, i.e. either
- begin with a lower case letter and consist only of letters, digits,
- dollar signs and underscores; or, be enclosed within single quotes.
- If the output file name is not specified, it defaults to
- \fIInFile\fB.out\fR. The list of options, if specified, is
- a Prolog list, i.e. a term of the form
-
- .(l
- [ \fIoption\fR\*<1\*>, \fIoption\fR\*<2\*>, ..., \fIoption\*<n\*>\fR ].
- .)l
-
- If left unspecified, it defaults to the empty list [\^].
- \fIPredList\fR, if specified, is usually given as an uninstantiated
- variable; its principal use is for setting trace points on the predicates in the file (see Sections 6 and 8).
- Notice that \fIPredList\fR can only appear in \fIcompile\fR/4.
- .pp
- A list of compiler options appears in Section 8.3.
- .sh 3 "Loading Byte Code Files"
- .lp
- Byte code files may be loaded into the simulator using the
- predicate \fIload\fR:
-
- .(l
- | ?- load(\fIByteCode_\|File\fR).
- .)l
-
- where \fIByteCode_\|File\fR is a Prolog atom (see Section 3.1) that is the name of a byte code
- file.
- .(x L
- (B) load/1
- .)x
- .pp
- The \fIload\fR predicate invokes the dynamic loader, which carries out a search according to
- the sequence specified by the environment variable SIMPATH (see Section
- 2.1). It is therefore not necessary to always specify the full path name to the file to be
- loaded.
- .pp
- Byte code files may be concatenated together to produce other byte code files. Thus,
- for example, if \fIfoo1\fR and \fIfoo2\fR are byte code files resulting
- from the compilation of two Prolog source programs, then the file \fIfoo\fR,
- obtained by executing the shell command
- .(l
- cat foo1 foo2 > foo
- .)l
- is a byte code file as well, and may be loaded and executed. In this case,
- loading and executing the file \fIfoo\fR would give the same result as
- loading \fIfoo1\fR and \fIfoo2\fR separately, which in turn would be the same as
- concatenating the original source files and compiling this larger file. This
- makes it easier to compile large programs: one need only break them into smaller
- pieces, compile the individual pieces, and concatenate the resulting byte code files together.
- .sh 3 "Consulting Programs"
- .lp
- Instead of compiling a file to generate a byte code file which then has to be loaded,
- a program may be executed interpretively by ``consulting'' the corresponding
- source file:
- .(x C
- (L) consult/1
- .)x
- .(x C
- (L) consult/2
- .)x
- .(l
- | ?- consult(\fISourceFile\fR [, \fIOptionList\fR ] ).
- or
- | ?- consult(\fISourceFile\fR, \fIOptionList\fR, \fIPredList\fR).
- .)l
- where \fISourceFile\fR is a Prolog atom which is the name of a file
- containing a Prolog source program; \fIOptionList\fR is a list of options
- to consult; and \fIPredList\fR is a list of terms \fIP\fR/\fIN\fR, where \fIP\fR is a
- predicate name and \fIN\fR its arity, specifying which predicates have been consulted
- from \fISourceFile\fR; its principal use is for setting trace points
- on the predicates in the file (see Section 6). Notice that \fIPredList\fR can only appear in \fIconsult\fR/3.
- .pp
- At this point, the options recognized for \fIconsult\fR are
- the following:
- .in 0.25i
- .ip \fBt\fR
- ``trace''. Causes a trace point to be set on any predicate in the current
- file that does not already have a trace point set.
- .ip \fBv\fR
- ``verbose''. Causes information regarding which predicates have been
- consulted to be printed out. Default: off.
- .lp
- In addition to the above, options for the macro expander
- are also recognized (see Section 10)).
- .in 0
- .lp
- \fIconsult\fR will create an index on the printipal functor of the
- first argument of the predicates being consulted, unless this is changed
- using the \fIindex\fR/3 directive. In particular, note that if no index is
- desired on a predicate \fIfoo\fR/\fIn\fR, then the directive
- .(l
- :\- index(\^\fIfoo\fR, \fIn\fR, 0).
- .)l
- should be given.
- .pp
- It is important to note that SB-Prolog's \fIconsult\fR predicate is similar
- to that of Quintus Prolog, and behaves like C-Prolog's \fIreconsult\fR.
- This means that if a predicate is defined across two or more files,
- consulting them will result in only the clauses in the file consulted last
- being used.
- .sh 2 "Execution Directives"
- .lp
- Execution directives may be specified to \fIcompile\fR and \fIconsult\fR through :\-/1. If, in the read
- phase of \fIcompile\fR or \fIconsult\fR, a term with principal
- functor :\-/1 is read in, this term is executed directly via \fIcall\fR/1.
- This enables the user to dynamically modify the environment, e.g. via
- \fIop\fR declarations (see Section 3.2), \fIassert\fRs etc.
- .(x Z
- (P) :\-/1
- .)x
- .pp
- A point to note is that if the environment is modified as a result of an execution
- directive, the modifications are visible only in that environment. This
- means that consulted code, which runs in the environment in which
- the source program is read in (and which is modified by such execution directives) feel the effects of such
- execution directives. However, byte code resulting from compilation, which,
- in general, executes in an environment different from that in which the
- source was compiled, does not inherit the effects of such directives. Thus,
- an \fIop\fR declaration can be used in a source file to change the syntax and
- allow the remainder of the program to be parsed according to the modified
- syntax; however, these modifications will not, in general, manifest themselves
- if the byte code is executed in another environment. Of course, if the byte code
- is loaded into the same environment as that in which the source program was
- compiled, e.g. through
- .(l
- | ?- compile(foo, bar), load(bar).
- .)l
- the effects of execution directives will continue to be felt.
- .sh 1 "Syntax"
- .lp
- .sh 2 "Terms"
- .lp
- The syntax of SB-Prolog is by and large compatible with that of
- C-Prolog.
- The data objects of the language are called \fIterm\fPs.
- A term is either a \fIconstant\fP, a \fIvariable\fP or a \fIcompound term\fP.
- Constants can be \fIintegers\fR or \fIatoms\fR.
- The symbol for an atom must begin with a lower case letter or the dollar
- sign $, and consist of any number of letters, digits, underscores
- and dollar signs; if it contains any character other than these, it must be
- enclosed within single quotes.\**
- .(f
- \** Users are advised against using symbols beginning with `$' or `_\|$',
- however, in order to minimize the possibility of conflicts with symbols
- internal to the system.
- .)f
- As in other programming languages, constants are definite elementary objects.
- .pp
- Variables are distinguished by an initial capital letter or by
- the initial character \*(lq\(ul\|\*(rq, for example
- .(l
- X Value A A1 \(ul\|3 \(ul\|RESULT \(ul\|result
- .)l
- If a variable is only referred to once, it does not need to be named
- and may be written as an \fIanonymous\fP variable, indicated by the
- underline character \*(lq\(ul\|\*(rq.
- .pp
- A variable should be thought of as standing for some definite but
- unidentified object.
- A variable is not simply a writeable
- storage location as in most programming languages; rather it is a
- local name for some data object, cf. the variable of pure LISP and
- constant declarations in Pascal.
- .pp
- The structured data objects of the language are the compound terms. A
- compound term comprises a \fIfunctor\fP (called the \fIprincipal\fP functor of
- the term) and a sequence of one or more terms called \fIarguments\fP.
- A functor is characterised by its \fIname\fP, which is an atom, and its
- \fIarity\fP or number of arguments.
- For example the compound term whose functor is
- named `point' of arity 3, with arguments X, Y and Z, is written
- .(l
- point(X,Y,Z)
- .)l
- An atom is considered to be a functor of arity 0.
- .pp
- A functor or predicate symbol is uniquely identified by its name and arity
- (in other words, it is possible for different symbols having different
- arities to share the same name). A functor or predicate symbol \fIp\fR
- with arity \fIn\fR is usually written \fIp\fR/\fIn\fR.
- .pp
- One may think of a functor as a record type and the
- arguments of a compound term as the fields of a record. Compound
- terms are usefully pictured as trees. For example, the term
- .(l
- s(np(john),vp(v(likes),np(mary)))
- .)l
- would be pictured as the structure
- .(b C
- s
- / \e
- np vp
- | / \e
- john v np
- | |
- likes mary
- .)b
- .pp
- Sometimes it is convenient to write certain functors as \fIoperators\fP
- \*- 2-ary functors may be declared as \fIinfix\fP operators and 1-ary functors
- as \fIprefix\fP or \fIpostfix\fP operators.
- Thus it is possible to write
- .(l
- X+Y (P;Q) X<Y +X P;
- .)l
- as optional alternatives to
- .(l
- +(X,Y) ;(P,Q) <(X,Y) +(X) ;(P)
- .)l
- Operators are described fully in the next section.
- .pp
- \fIList\fPs form an important class of data structures in Prolog.
- They are essentially the same as the lists of LISP:
- a list either is the atom
- [],
- representing the empty list, or is a compound term with functor `.'/2
- and two arguments which are respectively the head and tail of the
- list. Thus a list of the first three natural numbers is the
- structure
- .(b C
- .
- / \e
- 1 .
- / \e
- 2 .
- / \e
- 3 []
- .)b
- which could be written, using the standard syntax, as .(1,.(2,.(3,[]))),
- but which is normally written, in a special list notation, as [1,2,3].
- The special list notation in the case when the tail of a list is a
- variable is exemplified by
- .(l C
- [X|L] [a,b|L]
- .)l
- representing
- .(b C
- . .
- / \e / \e
- X L a .
- / \e
- b L
- .)b
- respectively.
- .pp
- Note that this list syntax is only syntactic sugar for terms of the form
- \&`.'(\(ul\|, \(ul\|) and does not provide any new facilities that were not
- available otherwise.
- .pp
- For convenience, a further notational variant is allowed for
- lists of integers which correspond to ASCII character codes. Lists
- written in this notation are called \fIstring\fPs.
- For example,
- .(l
- "Prolog"
- .)l
- represents exactly the same list as
- .(l
- [80,114,111,108,111,103]
- .)l
- .sh 2 "Operators"
- .lp
- Operators in Prolog are simply a notational convenience.
- For example, the expression
- .(l
- 2 + 1
- .)l
- could also be written +(2,1).
- It should be noticed that this expression represents the structure
- .(b C
- +
- / \e
- 2 1
- .)b
- and not the number 3.
- The addition would only be performed if the structure was passed as an
- argument to an appropriate procedure (such as \fBeval\fP/2 \- see Section 5.2).
- .pp
- The Prolog syntax caters for operators of three main kinds \-
- \fIinfix\fR, \fIprefix\fR and \fIpostfix\fR.
- An infix operator appears between its two arguments, while a prefix operator
- precedes its single argument and a postfix operator is written after its
- single argument.
- .pp
- Each operator has a \fIprecedence\fP, which is a
- number from 1 to 1200. The precedence is used to disambiguate
- expressions where the structure of the term denoted is not made
- explicit through parenthesization. The general rule
- is that the operator with the
- \fIhighest\fP precedence is the principal functor. Thus if `+' has a
- higher precedence than `/', then ``a+b/c'' and ``a+(b/c)''
- are equivalent and denote the term \*(lq+(a,/(b,c))\*(rq.
- Note that the infix
- form of the term \*(lq/(+(a,b),c)\*(rq must be written with explicit
- parentheses, ``(a+b)/c''.
- .pp
- If there are two operators in the subexpression having the same
- highest precedence, the ambiguity must be resolved from the \fItypes\fP of
- the operators. The possible types for an infix operator are
- .(l
- xfx xfy yfx
- .)l
- With an operator of type `xfx', it is a requirement that both of the
- two subexpressions which are the arguments of the operator must be of
- \fIlower\fR precedence than the operator itself, i.e. their principal
- functors must be of lower precedence, unless the subexpression is
- explicitly bracketed (which gives it zero precedence). With an
- operator of type `xfy', only the first or left-hand subexpression must
- be of lower precedence; the second can be of the \fIsame\fP precedence as
- the main operator; and vice versa for an operator of type `yfx'.
- .pp
- For example, if the operators `+' and `\-' both have type `yfx'
- and are of the same precedence, then the expression
- ``a\-b+c'' is valid, and means ``(a\-b)+c'', i.e. ``+(\-(a,b),c)''.
- Note that the expression would be invalid if the operators had type
- \&`xfx', and would mean ``a\-(b+c)'', i.e. ``\-(a,+(b,c))'',
- if the types were both `xfy'.
- .pp
- The possible types for a prefix operator are
- .(l
- fx fy
- .)l
- and for a postfix operator they are
- .(l
- xf yf
- .)l
- The meaning of the types should be clear by analogy with those for
- infix operators. As an example, if `not' were declared as a prefix
- operator of type `fy', then
- .(l
- not not P
- .)l
- would be a permissible way to write \*(lqnot(not(P))\*(rq. If the type were
- \&`fx', the preceding expression would not be legal, although
- .(l
- not P
- .)l
- would still be a permissible form for \*(lqnot(P)\*(rq.
- .pp
- In SB-Prolog, a functor named \fIname\fP is declared as an
- operator of type \fItype\fP and precedence \fIprecedence\fP by calling
- the evaluable predicate \fBop\fP:
- .(l
- | ?- op(\fIprecedence\fP, \fItype\fP, \fIname\fP).
- .)l
- .(x O
- (L) op/3
- .)x
- The argument \fIname\fP can also be a list of names of operators of the same
- type and precedence.
- .pp
- It is possible to have more than one operator of the same name,
- so long as they are of different kinds, i.e. infix, prefix or postfix.
- An operator of any kind may be redefined by a new declaration of the
- same kind. This applies equally to operators which are provided as
- \fIstandard\fP in SB-Prolog, namely:
- .(l L
- .TS
- r r r l.
- :\- op( 1200, xfx, [ :\-, --> ]).
- :\- op( 1200, fx, [ :\- ]).
- :\- op( 1198, xfx, [ ::\- ]).
- :\- op( 1150, fy, [ mode, public, dynamic ]).
- :\- op( 1100, xfy, [ ; ]).
- :\- op( 1050, xfy, [ \-> ]).
- :\- op( 1000, xfy, [ ',' ]). /* See note below */
- :\- op( 900, fy, [ not, \e+, spy, nospy ]).
- :\- op( 700, xfx, [ =, is, =.., ==, \e==, @<, @>, @=<, @>=,
- \& \& \& =:=, =\e=, <, >, =<, >=, ?=, \e= ]).
- :\- op( 661, xfy, [ `.' ]).
- :\- op( 500, yfx, [ +, \-, /\e, \e/ ]).
- :\- op( 500, fx, [ +, \- ]).
- :\- op( 400, yfx, [ *, /, //, <<, >> ]).
- :\- op( 300, xfx, [ mod ]).
- :\- op( 200, xfy, [ ^ ]).
- .TE
- .)l
- .pp
- Operator declarations are most usefully placed in directives at the top
- of your program files. In this case the directive should be a command as
- shown above. Another common method of organisation is to have one file
- just containing commands to declare all the necessary operators. This file
- is then always consulted first.
- .pp
- Note that a comma written literally as a punctuation character
- can be used as though it were an infix operator of precedence 1000 and
- type `xfy':
- .(l
- X,Y ','(X,Y)
- .)l
- represent the same compound term. But note that a comma written as a
- quoted atom is \fInot\fP a standard operator.
- .pp
- Note also that the arguments of a compound term written in
- standard syntax must be expressions of precedence \fIbelow\fP 1000. Thus it
- is necessary to parenthesize the expression \*(lqP :\- Q\*(rq in
- .(l
- assert((P :\- Q))
- .)l
- The following syntax restrictions serve to
- remove potential ambiguity associated with prefix operators.
- .ip \d\(de\u
- In a term written in standard syntax, the principal functor and
- its following \*(lq(\*(rq must \fInot\fP be separated by any whitespace. Thus
- .(l
- point (X,Y,Z)
- .)l
- is invalid syntax (unless \fIpoint\fR were declared as a prefix operator).
- .ip \d\(de\u
- If the argument of a prefix operator starts with a \*(lq(\*(rq, this \*(lq(\*(rq
- must be separated from the operator by at least one space or other
- non-printable character. Thus
- .(l
- :\-(p;q),r.
- .)l
- (where `:\-' is the prefix operator) is invalid syntax, and must be written as
- .(l
- :\- (p;q),r.
- .)l
- .ip \d\(de\u
- If a prefix operator is written without an argument, as an
- ordinary atom, the atom is treated as an expression of the same
- precedence as the prefix operator, and must therefore be bracketed
- where necessary. Thus the brackets are necessary in
- .(l
- X = (?-)
- .)l
- .sh 1 "SB-Prolog: Operational Semantics"
- .sh 2 "Standard Execution Behaviour"
- .lp
- The normal execution behaviour of SB-Prolog follows the usual left to right
- order of literals within a clause, and the textual top to bottom order of
- clauses for a predicate. This corresponds to a depth first search of the
- leftmost SLD-tree for the program and the given query. Unification without
- occurs check is used, and execution backtracks to the most recent choice
- point when unification fails.
- .sh 2 "Cuts and If-Then-Else"
- .lp
- This standard execution behaviour of SB-Prolog can be changed using
- constructs like \fIcut\fR (`!') and \fIif-then-else\fR (\^`\->'\^). In
- SB-Prolog, cuts are usually treated as \fIhard\fR, i.e. discard choice points
- of all the literals to the left of the cut in the clause containing the cut
- being executed, and also the choice point for the parent predicate, i.e.
- any remaining clauses for the predicate containing the cut being executed.
- There are some situations, however, where the scope of a cut is restricted
- to be smaller than this. Restrictions apply under the following conditions:
- .np
- The cut occurs in a term which has been constructed at runtime and called
- through \fIcall\fR/1, e.g. in
- .(l C
- ..., X = (p(Y), !, q(Y)), ..., call(X), ...
- .)l
- In this case, the scope of the cut is restricted to be within the \fIcall\fR,
- unless one of the following cases also apply and serve to restrict its
- scope further.
- .np
- The cut occurs in a negated goal, or within the scope of the test of
- an if-then-else (in an if-then-else of the form ``\fITest\fR \-> \fITruePart\fR
- ; \fIFalsePart\fR'', the test is the goal \fITest\fR). In these cases, the
- scope of the cut is restricted to be within the negation or the test of
- the if-then-else, respectively.
- .lp
- In cases involving nested occurrences of these situations, the scope of the
- cut is restricted to that for the deepest such nested construct, i.e. most
- restricted. For example, in the construct
- .(l C
- ..., not( (p(X) \-> not( (q(X), (r(X) \-> s(X) ; (t(X), !, u(X)))) )) ), ...
- .)l
- the scope of the cut is restricted to the inner negation, and does not
- affect any choice point that may have been set up for p(X).
- .sh 2 "Unification of Floating Point Numbers"
- .lp
- As far as unification is concerned, no type distinction is made between
- integers and floating point numbers, and no explicit type conversion is
- necessary when unifying an integer with a float.
- However, due to the finite precision
- representation of floating point numbers and cumulative round-off errors in
- floating point arithmetic, comparisons involving floating point numbers may
- not always give the expected results. For the same reason, users are warned
- that indexing on predicate arguments (see Section 15) may not give the
- expected results if floating point numbers are involved.
- .sh 1 "Evaluable Predicates"
- .lp
- This section describes (most of) the evaluable predicates provided by
- SB-Prolog. These can be divided into three classes: \fIinline\fR
- predicates, \fIbuiltin\fR predicates and \fIlibrary\fR predicates.
- .pp
- Inline predicates represent ``primitive'' operations in the WAM.
- Calls to inline predicates are compiled into a sequence of WAM
- instructions in-line, i.e. without actually making a call to the predicate. Thus, for
- example, relational predicates (>/2, >=/2, etc.) compile to, essentially, a
- subtraction and a conditional branch. Inline predicates cannot be redefined by the
- user. Table 1 lists the SB-Prolog inline predicates.
- .(z
- .TS
- center tab(%) ;
- l l l l.
- arg/3%=/2%</2%=</2
- >=/2%>/2%/\e/2%`\e/'/2
- <</2%>>/2%=:=/2%=\e=/2
- is/2%?=/2%\e=%\e/1
- `_\|$builtin'/1%`_\|$call'/1%nonvar/1%var/1
- integer/1%real/1%halt/0%true/0
- fail/0% % %
- .TE
- .sp
- .ce
- Table 1: Inline Predicates of SB-Prolog
- .sp 2
- .)z
- .pp
- Unlike inline predicates, builtin predicates are implemented by C
- functions in the simulator, and accessed via the inline predicate
- `\fI_\|\|$builtin\fR'/1.
- Thus, if a builtin predicate \fIfoo\fR/3 was defined
- as builtin number 38, there would be a definition in the system
- of the form
-
- .(l
- foo(X,Y,Z) :\- '_\|\|$builtin'(38).
- .)l
-
- .pp
- In effect, a builtin is simply a segment of code in a large case
- (i.e. \fIswitch\fR) statement. Each builtin is identified internally by an
- integer, referred to as its ``builtin number'', associated with it. The code for a builtin with
- builtin number \fIk\fR corresponds to the \fIk\*[th.\*]\fR case in the switch
- statement.
- SB-Prolog limits the total number of builtins to 256.
- .pp
- Builtins, unlike inline predicates, can be redefined by the user. For example, the
- predicate \fIfoo\fR/3 above can be redefined simply by compiling the new definition into a
- directory such that during dynamic loading, the new definition would be
- encountered first and loaded.
- .pp
- A list of the builtins currently provided is listed in Appendix 1.
- Section 7.4 describes the procedure to be followed in order to define new
- builtin predicates.
- .pp
- Like builtin predicates, library predicates may also be redefined by the
- user. The essential difference between builtin and library predicates is
- that whereas the former are coded into the simulator in C, the latter are
- written in Prolog.
- .sh 2 "Input and Output"
- .lp
- Input and output are done with respect to the current input and output
- streams. These can be set, reset or checked using the file handling
- predicates described below. The default input and output streams are
- denoted by \fBuser\fR, and refer to the user's terminal.
- .sh 3 "File Handling"
- .lp
- \fBsee\fR(\fIF\fR\|)
- .ip
- \fIF\fR becomes the current input stream. \fIF\fR must be instantiated to
- an atom at the time of the call.
- .(x S
- (B) see/1
- .)x
- .lp
- \fBseeing\fR(\fIF\fR\|)
- \fIF\fR is unified with the name of the current input file.
- .ip \fBseen\fR
- Closes the current input stream.
- .(x S
- (B) seen
- .)x
- .ip \fBtell\fR(\fIF\fR\^)
- \fIF\fR becomes the current output stream. \fIF\fR must be instantiated to
- an atom at the time of the call.
- .(x T
- (B) tell/1
- .)x
- .ip \fBtelling\fR(\fIF\fR\^)
- \fIF\fR is unified with the name of the current output file.
- .(x T
- (B) telling/1
- .)x
- .lp
- \fBtold\fR
- .ip
- Closes the current output stream.
- .(x T
- (B) told/0
- .)x
- .ip \fB$exists\fR(\fIF\fR\^)
- Succeeds if file \fIF\fR exists.
- .(x Z
- (B) $exists/1
- .)x
- .sh 3 "Term I/O"
- .lp
- \fBread\fR(\fIX\fR\^)
- .ip
- The next term, delimited by a full stop (i.e. a \*(lq.\*(rq followed by a carriage-return
- or a space), is read from the current input stream and
- unified with \fIX\fP. The syntax of the term must accord with current
- operator declarations. If a call \fBread\fP(\fIX\fP) causes the end of the
- current input stream to be reached, \fIX\fP is unified with the atom
- \&`end\(ul\|of\(ul\|file'. Further calls to \fBread\fP for the same stream will then
- cause an error failure.
- .(x R
- (L) read/1
- .)x
- .ip \fBwrite\fP(\fIX\fP)
- The
- term \fIX\fP is written to the current output stream according to
- operator declarations in force.
- .(x W
- (L) write/1
- .)x
- .ip \fBdisplay\fP(\fIX\fP)
- .(x D
- (L) display/1
- .)x
- The
- term \fIX\fP is displayed on the terminal.
- .ip \fBwriteq\fP(\fITerm\fP)
- Similar
- to \fBwrite\fP(\fITerm\fP), but the names of atoms and functors
- are quoted where necessary to make the result acceptable as input to \fBread\fP.
- .(x W
- (L) writeq/1
- .)x
- .ip \fBprint\fP(\fITerm\fP)
- Prints out the term \fITerm\fR onto the current output stream. This predicate
- provides a handle for user-defined pretty-printing. If \fITerm\fR is a
- variable then it is written using \fBwrite\fR/1; otherwise,, if a
- user-defined predicate \fBportray\fR/1 is defined, then a call is made to
- \fI\fBportray\fR(Term\fR); otherwise, \fBprint\fR/1 is equivalent to
- \fBwrite\fR/1.
- .(x P
- (L) print/1
- .)x
- .ip \fBwritename\fR(\fITerm\fR\^)
- .(x W
- (B) writename/1
- .)x
- If \fITerm\fR is an uninstantiated variable, its name, which
- looks a lot like an address in memory, is written out; otherwise, the
- principal functor of \fITerm\fR is written out.
- .ip \fBwriteqname\fR(\fITerm\fR)
- .(x W
- (B) writeqname/1
- .)x
- As for \fBwritename\fR, but the names are quoted where necessary.
- .lp
- \fBprint_al\fR(\fIN\fR, \fIA\fR)
- .(x P
- (L) print_al/2
- .)x
- .ip
- Prints \fIA\fR (which must be an atom or a number) left-aligned in a field
- of width \fIN\fR, with blanks padded to the right. If \fIA\fR's print name
- is longer than the field width \fIN\fR, then \fIA\fR is printed but with no
- right padding.
- .lp
- \fBprint_ar\fR(\fIN\fR, \fIA\fR)
- .(x P
- (L) print_ar/2
- .)x
- .ip
- Prints \fIA\fR (which must be an atom or a number) right-aligned in a field
- of width \fIN\fR, with blanks padded to the left. If \fIA\fR's print name
- is longer than the field width \fIN\fR, then \fIA\fR is printed but with no
- left padding.
- .lp
- \fBportray_term\fR(\fITerm\fR)
- .(x P
- (L) portray_\|term/2
- .)x
- .ip
- Writes out the term \fITerm\fR on the current output stream. Variables are
- treated specially: an uninstantiated variable is printed out as V\fIn\fR,
- where \fIn\fR is a number.
- .lp
- \fBportray_clause\fR(\fITerm\fR)
- .(x P
- (L) portray_\|clause/2
- .)x
- .ip
- Writes out the term \fITerm\fR, interpreted as a clause, on the current
- output stream. Variables are treated as in \fIportray_\|term\fR/1.
- .sh 3 "Character I/O"
- .lp
- \fBnl\fP
- .ip
- A new line is started on the current output stream.
- .(x N
- (B) nl/0
- .)x
- .ip \fBget0\fP(\fIN\fP)
- \fIN\fP
- is the ASCII code of the next character from the current input
- stream. If the current input stream reaches its end of file,
- a \-1 is returned (however, unlike in C-Prolog, the input stream is not closed on encountering
- end-of-file).
- .(x G
- (B) get0/1
- .)x
- .ip \fBget\fP(\fIN\fP)
- \fIN\fP is the ASCII code of the next non-blank printable character
- from the current input stream. It has the same behaviour as \fBget0\fP
- on end of file.
- .(x G
- (B) get/1
- .)x
- .ip \fBput\fP(\fIN\fP)
- ASCII character code \fIN\fP is output to the current output stream.
- \fIN\fP must be an integer.
- .(x P
- (B) put/1
- .)x
- .ip \fBtab\fP(\fIN\fP)
- \fIN\fP
- spaces are output to the current output stream. \fIN\fP
- must be an integer.
- .(x T
- (B) tab/1
- .)x
- .sh 2 "Arithmetic"
- .lp
- Arithmetic is performed by evaluable predicates which take as
- arguments \fIarithmetic expressions\fP and \fIevaluate\fP them.
- An arithmetic expression is a term built from \fIevaluable functors\fP,
- numbers and variables.
- At the time of evaluation, each variable in an arithmetic
- expression must be bound to a number or
- to an arithmetic expression.
- Each evaluable functor stands for an arithmetic operation.
- .pp
- The
- evaluable functors are as follows, where \fIX\fP and \fIY\fP are
- arithmetic expressions.
- .lp
- \fIX\fP\ +\ \fIY\fP
- .ip
- addition.
- .lp
- \fIX\fP\ \-\ \fIY\fP
- .ip
- subtraction.
- .lp
- \fIX\fP\ *\ \fIY\fP
- .ip
- multiplication.
- .lp
- \fIX\fP\ /\ \fIY\fP
- .ip
- division.
- .lp
- \fIX\fP\ //\ \fIY\fP
- .ip
- integer division.
- .lp
- \fIX\fP\ mod\ \fIY\fP
- .ip
- \fIX\fP (integer) modulo \fIY\fP.
- .lp
- \-\fIX\fP
- .ip
- unary minus.
- .lp
- \fIX\fP\ /\e\ \fIY\fP
- .ip
- integer bitwise conjunction.
- .lp
- \fIX\fP\ \e/\ \fIY\fP
- .ip
- integer bitwise disjunction.
- .lp
- \fIX\fP\ <<\ \fIY\fP
- .ip
- integer bitwise left shift of \fIX\fP by \fIY\fP places.
- .lp
- \fIX\fP\ >>\ \fIY\fP
- .ip
- integer bitwise right shift of \fIX\fP by \fIY\fP places.
- .lp
- \e\fIX\fP
- .ip
- integer bitwise negation.
- .lp
- \fBinteger\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is bound to a floating point number, this evaluates to the
- smallest integer not greater than \fIX\fR. (Syntactic sugar for
- \fBfloor\fR/2 below.)
- .lp
- \fBfloat\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is bound to an integer, evaluates to the smallest float not
- greater than \fIX\fR. (Syntactic sugar for \fBfloor\fR/2 below.)
- .lp
- \fBexp\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is instantiated to a number, evaluates to
- \fIe\fR\*[\fIX\fR\*], where \fIe\fR = 2.71828 ... (Syntactic sugar for
- \fBexp\fR/2 below.)
- .lp
- \fBln\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is instantiated to a positive number, this evaluates to the
- natural logarithm of \fIX\fR. (Syntactic sugar for
- \fBexp\fR/2 below.)
- .lp
- \fBsin\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is instantiated to a number (representing an angle in radians),
- evaluates to \fIsin\fR(\fIX\fR\^). (Syntactic sugar for
- \fBsin\fR/2 below.)
- .lp
- \fBarcsin\fR(\fIX\fR\^)
- .ip
- If \fIX\fR is instantiated to a number between \-\(*p/2 and \(*p/2, evaluates
- to \fIsin\fR\*[\-1\*](\fIX\fR\^). (Syntactic sugar for
- \fBsin\fR/2 below.)
- .pp
- As far as unification is concerned, no type distinction is made between
- integers and floating point numbers, and no explicit type conversion is necessary
- when unifying an integer with a float. However, due to the finite precision
- representation of floating point numbers and cumulative round-off errors in
- floating point arithmetic, comparisons involving floating point numbers may
- not always give the expected results.
- .pp
- The arithmetic evaluable predicates are as follows, where \fIX\fP and
- \fIY\fP stand for arithmetic expressions, and \fIZ\fP for some term.
- Note that this means that \fBis\fP only evaluates one of its arguments
- as an arithmetic expression (the right-hand side one),
- whereas all the comparison
- predicates evaluate both their arguments.
- .lp
- \fIZ\fP \fBis\fP \fIX\fP
- .(x I
- (I) is/2
- .)x
- .ip
- Arithmetic expression \fIX\fP is evaluated and the result, is unified with
- \fIZ\fP. Fails if \fIX\fP is not an arithmetic expression. Unlike many other
- Prolog systems, variables in the expression \fIX\fR may be bound to other
- arithmetic expressions as well as to numbers.
- .ip \fBeval\fR(\fIE\fR,\ \fIX\fR\^)
- .(x E
- (L) eval/2
- .)x
- Evaluates the arithmetic expression \fIE\fR and unifies the result with the term
- \fIX\fR. Fails if \fIE\fR is not an arithmetic expression.
- (Thus, \fBeval\fR/2 is, except for the switched argument order, the
- same as \fBis\fR/2. It's around mainly for historical reasons.)
- .lp
- \fIX\fP \fB=:=\fP \fIY\fP
- .(x Z
- (I) =:=/2
- .)x
- .ip
- The values of \fIX\fP and \fIY\fP are equal. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fIX\fP \fB=\\=\fP \fIY\fP
- .ip
- .(x Z
- (I) =\e=/2
- .)x
- The values of \fIX\fP and \fIY\fP are not equal. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fIX\fP\fB < \fP\fIY\fP
- .(x Z
- (I) </2
- .)x
- .ip
- The
- value of \fIX\fP is less than the value of \fIY\fP. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fIX\fP\fB > \fP\fIY\fP
- .(x Z
- (I) >/2
- .)x
- .ip
- The
- value of \fIX\fP is greater than the value of \fIY\fP. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fIX\fP\fB =<\fP \fIY\fP
- .(x Z
- (I) =</2
- .)x
- .ip
- The
- value of \fIX\fP is less than or equal to the value of \fIY\fP. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fIX\fP\fB >=\fP \fIY\fP
- .(x Z
- (I) >=/2
- .)x
- .ip
- The
- value of \fIX\fP is greater than or equal to the value of \fIY\fP. If either \fIX\fR or \fIY\fR
- involve compound subexpressions that are created at runtime, they should first be evaluated
- using \fBeval\fR/2.
- .lp
- \fBfloor\fR(\fIX\fR, \fIY\fR\^)
- .(x F
- (B) floor/2
- .)x
- .ip
- If \fIX\fR is a floating point number in the call and \fIY\fR is free,
- then \fIY\fR is instantiated to the largest integer whose absolute value
- is not greater than the absolute value of \fIX\fR; if \fIX\fR is
- uninstantiated in the call and \fIY\fR is an integer, then \fIX\fR is instantiated to
- the smallest float not less than \fIY\fR.
- .lp
- \fBfloatc\fR(\fIF\fR, \fIM\fR, \fIE\fR\^)
- .(x F
- (B) floatc/3
- .)x
- .ip
- If \fIF\fR is a number while \fIM\fR and \fIE\fR are uninstantiated in the call, then
- \fIM\fR is instantiated to a float \fIm\fR (of magnitude less than 1), and \fIE\fR to an
- integer \fIn\fR, such that
- .(l C
- \fIF\fR = \fIm\fR * 2\*[\fIn\fR\*].
- .)l
- If \fIF\fR is uninstantiated in the call while \fIM\fR is a float and \fIE\fR
- an integer, then \fIF\fR becomes instantiated to \fIM\fR * 2\*[\fIE\fR\*].
- .lp
- \fBexp\fR(\fIX\fR, \fIY\fR\^)
- .(x E
- (B) exp/2
- .)x
- .ip
- If \fIX\fR is instantiated to a number and \fIY\fR is uninstantiated in the call, then \fIY\fR
- is instantiated to \fIe\*[X\*]\fR (where \fIe\fR = 2.71828...); if \fIX\fR
- is uninstantiated in the call while \fIY\fR is instantiated to a positive
- number, then \fIX\fR is instantiated to \fIlog\*<e\*>\fR(\fIY\fR\^).
- .lp
- \fBsquare\fR(\fIX\fR, \fIY\fR\^)
- .(x S
- (B) square/2
- .)x
- .ip
- If \fIX\fR is instantiated to a number while \fIY\fR is uninstantiated in
- the call, then \fIY\fR becomes instantiated to \fIX\fR\^\*[2\*]; if \fIX\fR
- is uninstantiated in the call while \fIY\fR is instantiated to a positive number, then
- \fIX\fR becomes instantiated to the positive square root of \fIY\fR (if \fIY\fR
- is negative in the call, \fIX\fR becomes instantiated to 0.0).
- .lp
- \fBsin\fR(\fIX\fR, \fIY\fR\^)
- .(x S
- (B) sin/2
- .)x
- .ip
- If \fIX\fR is instantiated to a number (representing an angle in radians)
- and \fIY\fR is uninstantiated in the call, then \fIY\fR becomes
- instantiated to \fIsin\fR(\fIX\fR\^) (the user should check the magnitude
- of \fIX\fR to make sure that the result is meaningful). If \fIY\fR is
- instantiated to a number between \-\(*p/2 and \(*p/2 and \fIX\fR is
- uninstantiated in the call, then \fIX\fR becomes instantiated to
- \fIsin\fR\*[\-1\*](\fIY\fR\^).
- .lp
- .sh 2 "Convenience"
- .lp
- \fIP\fP\ \fB,\fP\ \fIQ\fP
- .ip
- \fIP\fP and then \fIQ\fP.
- .(x Z
- (I) `,'/2
- .)x
- .lp
- \fIP\fP\ \fB;\fP\ \fIQ\fP
- .ip
- \fIP\fP or \fIQ\fP.
- .(x Z
- (I) `;'/2
- .)x
- .lp
- \fBtrue\fP
- .ip
- Always succeeds.
- .(x T
- (I) true/0
- .)x
- .lp
- \fIX\fP\ \fB=\fP\ \fIY\fP
- .ip
- Defined as if by the clause \*(lq Z=Z \*(rq, i.e. \fIX\fP and \fIY\fP are unified.
- .(x Z
- (I) =/2
- .)x
- .lp
- \fIX\fP\ \fB\e=\fP\ \fIY\fP
- .ip
- Succeeds if \fIX\fR and \fIY\fR are not unifiable, fails if \fIX\fR and
- \fIY\fR are unifiable. It is thus equivalent to
- \fInot\fR\^(\fIX\fR = \fIY\fR\^), but is significantly more efficient.
- .(x Z
- (I) \e=/2
- .)x
- .lp
- \fIX\fP\ \fB?=\fP\ \fIY\fR
- .ip
- Succeeds if \fIX\fR and \fIY\fR are unifiable and fails if they are not,
- but does not instantiate any variables. Thus, it tests whether \fIX\fR
- and \fIY\fR are unifiable. Equivalent to
- \fInot\fR\^(\fInot\fR\^(\fIX\fR = \fIY\fR\^)\^), but is significantly more
- efficient.
- .(x Z
- (I) ?=/2
- .)x
- .sh 2 "Extra Control"
- .lp
- \fB!\fP
- .ip
- Cut (discard) all choice points made since
- the parent goal started execution. (The scope of cut in different contexts is discussed in Section 4.2).
- .(x Z
- (P) !/0
- .)x
- .lp
- \fBnot\fP\ \fIP\fP
- .ip
- If the goal \fIP\fP has a solution, fail, otherwise succeed. It is
- defined as if by
- .(l
- not(P) :\- P, !, fail.
- not(\(ul\|\|).
- .)l
- .(x N
- (P) not/1
- .)x
- .ip \fIP\fP\ \fB\->\fP\ \fIQ\fP\ \fB;\fP\ \fIR\fP
- Analogous to
- \*(lqif \fIP\fP then \fIQ\fP else \fIR\fP\*(rq
- i.e. defined as if by
- .(l
- P \-> Q ; R :\- P, !, Q.
- P \-> Q ; R :\- R.
- .)l
- .ip \fIP\fP\ \fB\->\fP\ \fIQ\fP
- When
- occurring other than as one of the alternatives of a
- disjunction, is equivalent to
- .(l
- \fIP\fP \-> \fIQ\fP ; fail.
- .)l
- .(x Z
- (P) \->/2
- .)x
- .ip \fBrepeat\fP
- Generates an infinite sequence of backtracking choices. It
- is defined by the clauses:
- .(l
- repeat.
- repeat :\- repeat.
- .)l
- .(x R
- (L) repeat/0
- .)x
- .ip \fBfail\fP
- Always fails.
- .(x F
- (I) fail/0
- .)x
- .sh 2 "Meta-Logical"
- .lp
- \fBvar\fP(\fIX\fP\^)
- .ip
- Tests whether \fIX\fP is currently instantiated to a variable.
- .(x V
- (I) var/1
- .)x
- .ip \fBnonvar\fP(\fIX\fP\^)
- Tests whether \fIX\fP is currently instantiated to a non-variable term.
- .(x N
- (I) nonvar/1
- .)x
- .ip \fBatom\fP(\fIX\fP\^)
- .(x A
- (B) atom/1
- .)x
- Checks
- that \fIX\fP is currently instantiated to an atom (i.e. a
- non-variable term of arity 0, other than a number).
- .ip \fBinteger\fP(\fIX\fP\^)
- Checks that \fIX\fP is currently instantiated to an integer.
- .(x I
- (I) integer/1
- .)x
- .lp
- \fBreal\fR(\fIX\fR\^)
- .(x R
- (I) real/1
- .)x
- .ip
- Checks that \fIX\fP is currently instantiated to a floating point number.
- .)x
- .lp
- \fBfloat\fR(\fIX\fR\^)
- .(x F
- (I) float/1
- .)x
- .ip
- Same as \fBreal\fR/1,
- checks that \fIX\fP is currently instantiated to a floating point number.
- .)x
- .ip \fBnumber\fP(\fIX\fP\^)
- Checks that \fIX\fP is currently instantiated to a number, i.e. that it is
- either an integer or a real.
- .(x N
- (B) number/1
- .)x
- .ip \fBatomic\fP(\fIX\fP\^)
- Checks that \fIX\fP is currently instantiated to an atom or number.
- .(x A
- (B) atomic/1
- .)x
- .lp
- \fBstructure\fR(\fIX\fR\^)
- .(x S
- (B) structure/1
- .)x
- .ip
- Checks that \fIX\fP is currently instantiated to a compound term, i.e. to a
- nonvariable term that is not atomic.
- .lp
- \fBis_buffer\fR(\fIX\fR\^)
- .(x I
- (B) is_buffer/1
- .)x
- .ip
- Succeeds if \fIX\fR is instantiated to a buffer.
- .lp
- \fBfunctor\fP(\fIT\fP, \fIF\fP, \fIN\fP\^)
- .ip
- The principal functor of term \fIT\fP has name \fIF\fP and arity
- \fIN\fP, where \fIF\fP
- is either an atom or, provided \fIN\fP is 0, a number.
- Initially,
- either \fIT\fP must be instantiated to a non-variable, or \fIF\fP and
- \fIN\fP must
- be instantiated to, respectively, either an atom and a
- non-negative integer or an integer and 0. If these conditions are
- not satisfied, an error message is given. In the case where \fIT\fP is
- initially instantiated to a variable, the result of the call is
- to instantiate \fIT\fP to the most general term having the principal
- functor indicated.
- .(x F
- (L) functor/3
- .)x
- .lp
- \fBarg\fP(\fII\fP, \fIT\fP, \fIX\fP\^)
- .ip
- Initially, \fII\fP must be instantiated to a positive integer and
- \fIT\fP to
- a compound term. The result of the call is to unify \fIX\fP with the
- \fII\fPth argument of term \fIT\fP. (The arguments are numbered
- from 1
- upwards.) If the initial conditions are not satisfied or \fII\fP is out
- of range, the call merely fails.
- .(x A
- (I) arg/3
- .)x
- .ip \fIX\fP\ \fB=..\fP\ \fIY\fP
- \fIY\fP is a list whose head is the atom corresponding to the principal
- functor of \fIX\fP and whose tail is the argument list of that functor
- in \fIX\fP. E.g.
- .(x Z
- (L) =../2
- .)x
- .(l
- product(0,N,N\-1) =.. [product,0,N,N\-1]
-
- N\-1 =.. [\-,N,1]
-
- product =.. [product]
- .)l
- If \fIX\fP is instantiated to a variable, then \fIY\fP 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.
- .ip \fBname\fP(\fIX\fP,\fIL\fP)
- If \fIX\fP is an atom or a number then \fIL\fP is a list of the
- ASCII codes of the characters comprising the name of \fIX\fP. E.g.
- .(x N
- (B) name/2
- .)x
- .(l
- name(product,[112,114,111,100,117,99,116])
- .)l
- i.e. name(product,"product").
- .lp
- If \fIX\fP is instantiated to a variable, \fIL\fP must be instantiated
- to a list of ASCII character codes. E.g.
- .(l
- | ?- name(X,[104,101,108,108,111])).
- X = hello
-
- | ?- name(X,"hello").
- X = hello
- .)l
- .ip \fBcall\fP(\fIX\fP\^)
- If \fIX\fR is a nonvariable term in the program text, then it is executed exactly as if \fIX\fR appeared in the program
- text instead of \fIcall\fR(\fIX\fR\^), e.g.
- .(x C
- (P) call/1
- .)x
- .(l
- ..., p(a), call( (q(X), r(Y)) ), s(X), ...
- .)l
- is equivalent to
- .(l
- ..., p(a), q(X), r(Y), s(X), ...
- .)l
- However, if X is a variable in the program text, then if at runtime
- \fIX\fP is instantiated to a term which would be acceptable as the body
- of a clause, the goal \fBcall\fP(\fIX\fP) is executed as if that
- term appeared textually in place of the \fBcall\fP(\fIX\fP), \fIexcept that\fR
- any cut (`!') occurring in \fIX\fP will remove only those choice points
- in \fIX\fP.
- If \fIX\fP is not instantiated as
- described above, an error message is printed and \fBcall\fP fails.
- .ip \fIX\fP
- (where
- \fIX\fP is a variable) Exactly the same as \fBcall\fP(\fIX\fP). However, we prefer the
- explicit usage of \fIcall\fR/1 as good programming practice, and the use of a
- top level variable subgoal elicits a warning from the compiler.
- .lp
- \fBconlength\fR(\fIC\fR, \fIL\fR\^)
- .ip
- Succeeds if the length of the print name of the constant
- \fIC\fR (which can be an atom, buffer or integer), in bytes, is \fIL\fR.
- .(x C
- (B) conlength/2
- .)x
- If \fIC\fR is a buffer (see Section 5.8), it
- is the length of the buffer; if \fIC\fR is an integer, it is the
- length of the decimal representation of that integer, i.e., the
- number of bytes that a $\fIwritename\fR will use.
- .sh 2 "Sets"
- .lp
- When there are many solutions to a problem, and when all those solutions are
- required to be collected together, this can be achieved by repeatedly
- backtracking and gradually building up a list of the solutions. The following
- evaluable predicates are provided to automate this process.
- .lp
- \fBsetof\fP(\fIX\fP, \fIP\fP, \fIS\fP)
- .ip
- Read this as \*(lq\fIS\fP is the set of all instances of \fIX\fP such that
- \fIP\fP is
- provable''. If \fIP\fR is not provable, \fBsetof\fP(\fIX\fP,\fIP\fP,\fIS\fP)
- succeeds with \fIS\fR instantiated to the empty list [\^].
- .(x S
- (L) setof/3
- .)x
- The term \fIP\fP specifies a
- goal or goals as in \fBcall\fP(\fIP\fP).
- \fIS\fP is a set of terms represented as a
- list of those terms, without duplicates, in the standard order for
- terms (see Section 5.7).
- If there are uninstantiated variables in \fIP\fP which do not also appear
- in \fIX\fP, then a call to this evaluable predicate may backtrack,
- generating alternative values for \fIS\fP corresponding to different
- instantiations of the free variables of \fIP\fP. Variables occurring in \fIP\fP will not be treated as free if they are
- explicitly bound within \fIP\fP by an existential quantifier. An
- existential quantification is written:
- .(l
- \fIY\fP^\fIQ\fP
- .)l
- meaning \*(lqthere exists a \fIY\fP such that \fIQ\fP is true\*(rq,
- where \fIY\fP is some Prolog term (usually, a variable, or tuple or list of
- variables).
- .lp
- \fBbagof\fP(\fIX\fP, \fIP\fP, \fIBag\fP)
- .ip
- This is the same as \fBsetof\fP except that the list (or
- alternative lists) returned will not be ordered, and may contain
- duplicates. If \fIP\fR is unsatisfiable, \fIbagof\fR succeeds binding
- \fIBag\fR to the empty list.
- .(x B
- (L) bagof/3
- .)x
- The effect of this relaxation is to save considerable
- time and space in execution.
- .lp
- \fBfindall\fR(\fIX\fR, \fIP\fR, \fIL\fR)
- .ip
- Similar to \fIbagof\fR/3, except that variables in \fIP\fR that do not occur in \fIX\fR are
- treated as local, and alternative lists are not returned for different bindings of such
- variables. The list \fIL\fR is, in general, unordered, and may contain duplicates. If \fIP\fR
- is unsatisfiable, \fIfindall\fR succeeds binding \fIS\fR to the empty list.
- .lp
- \fIX\fP\fB^\fP\fIP\fP
- .ip
- The system recognises this as meaning \*(lqthere exists an \fIX\fP such
- that \fIP\fP is true\*(rq, and treats it as equivalent to \fBcall\fP(\fIP\fP).
- The use of this explicit existential
- quantifier outside the \fBsetof\fP and \fBbagof\fP
- constructs is superfluous.
- .sh 2 "Comparison of Terms"
- .lp
- These evaluable predicates are meta-logical. They treat uninstantiated
- variables as objects with values which may be compared, and they never
- instantiate those variables. They should \fInot\fP be used when what you
- really want is arithmetic comparison (Section 5.2) or unification.
- The predicates make reference to a standard total ordering of terms, which is
- as follows:
- .ip \(de
- variables, in a standard order (roughly, oldest first \- the order is
- \fInot\fP related to the names of variables);
- .ip \(de
- numbers, from \-\*(lqinfinity\*(rq to +\*(lqinfinity\*(rq;
- .ip \(de
- atoms, in alphabetical (i.e. ASCII) order;
- .ip \(de
- complex terms, ordered first by arity, then by the name of principal
- functor, then by the arguments (in left-to-right order).
- .lp
- For example, here is a list of terms in the standard order:
- .(l
- [ X, \-9, 1, fie, foe, fum, X = Y, fie(0,2), fie(1,1) ]
- .)l
- The basic predicates for comparison of arbitrary terms are:
- .lp
- \fIX\fP \fB==\fP \fIY\fP
- .ip
- Tests if the terms currently instantiating \fIX\fP and \fIY\fP
- are literally
- identical (in particular, variables in equivalent positions in the
- two terms must be identical).
- .(x Z
- (B) ==/2
- .)x
- For example, the question
- .(l
- | ?- X == Y.
- .)l
- fails (answers \*(lqno\*(rq) because \fIX\fP and \fIY\fP
- are distinct uninstantiated
- variables. However, the question
- .(l
- | ?- X = Y, X == Y.
- .)l
- succeeds because the first goal unifies the two variables (see page 42).
- .lp
- \fIX\fP \fB\e==\fP \fIY\fP
- .ip
- Tests if the terms currently instantiating \fIX\fP and \fIY\fP are
- not literally identical.
- .(x Z
- (B) \e==/2
- .)x
- .lp
- \fIT1\fP \fB@<\fP \fIT2\fP
- .ip
- Term \fIT1\fP is before term \fIT2\fP in the standard order.
- .(x Z
- (B) @</2
- .)x
- .lp
- \fIT1\fP \fB@>\fP \fIT2\fP
- .ip
- Term \fIT1\fP is after term \fIT2\fP in the standard order.
- .(x Z
- (B) @>/2
- .)x
- .lp
- \fIT1\fP \fB@=<\fP \fIT2\fP
- .ip
- Term \fIT1\fP is not after term \fIT2\fP in the standard order.
- .(x Z
- (B) @=</2
- .)x
- .lp
- \fIT1\fP \fB@>=\fP \fIT2\fP
- .ip
- Term \fIT1\fP is not before term \fIT2\fP in the standard order.
- .(x Z
- (B) @>=/2
- .)x
- .sp
- .lp
- Some further predicates involving comparison of terms are:
- .lp
- \fBcompare\fP(\fIOp\fP, \fIT1\fP, \fIT2\fP)
- .ip
- The result of comparing terms \fIT1\fP and \fIT2\fP is \fIOp\fP,
- where the possible
- values for \fIOp\fP are:
- .(l
- \&`=' if \fIT1\fP is identical to \fIT2\fP,
-
- \&`<' if \fIT1\fP is before \fIT2\fP in the standard order,
-
- \&`>' if \fIT1\fP is after \fIT2\fP in the standard order.
- .)l
- Thus \fBcompare\fP(=,\fIT1\fP,\fIT2\fP) is equivalent to
- \fIT1\fP \fB==\fP \fIT2\fP.
- .(x C
- (B) compare/3
- .)x
- .lp
- \fBsort\fP(\fIL1\fP, \fIL2\fP)
- .ip
- The elements of the list \fIL1\fP are sorted into the standard order, and
- any identical (i.e. `==') elements are merged, yielding the list
- \fIL2\fP.
- .(x S
- (L) sort/2
- .)x
- .lp
- \fBkeysort\fR(\fIL1\fR, \fIL2\fR)
- .(x K
- (L) keysort/2
- .)x
- .ip
- The list \fIL1\fR must consist of items of the form \fIKey\fR\-\fIValue\fR.
- These items are sorted into order according to the value of \fIKey\fR,
- yielding the list \fIL2\fR. No merging takes place.
- .EQ
- .nr 99 \n(.s
- .nr 98 \n(.f
- .ps 11
- .ft 2
- .ps \n(99
- .ft \n(98
- .EN
- .sh 2 "Buffers"
- .lp
- SB-Prolog supports the concept of buffers. A buffer is actually a
- constant and the characters that make up the buffer is the name of
- the constant. However, the
- symbol table entry for a buffer is not hashed and thus is not added to
- the obj-list, so two different buffers will never unify.
- Buffers can be allocated either in permanent space or
- on the heap. Buffers in permanent space stay there forever; buffers
- on the heap are deallocated when the ``allocate buffer'' goal is
- backtracked over.
- .pp
- A buffer allocated on the heap can either be a simple buffer, or it
- can be allocated as a subbuffer of another buffer already on the
- heap. A subbuffer will be deallocated when its superbuffer is
- deallocated.
- .pp
- There are occasions when it is not known, in advance, exactly how much
- space will be required and so how big a buffer should be allocated.
- Sometimes this problem can be overcome by allocating a large buffer
- and then, after using as much as is needed, returning the rest of the
- buffer to the system. This can be done, but only under \fIvery\fR limited
- circumstances: a buffer is allocated from the end of the permanent space,
- the top of the heap, or from the next available space in the superbuffer;
- if no more space has been used beyond the end of the buffer, a tail
- portion of the buffer can be returned to the system. This operation
- is called ``trimming'' the buffer.
- .pp
- The following is a list of library predicates for buffer management:
- .sp
- .ip \fBalloc_\|perm\fR(\fISize\fR,\ \fIBuff\fR)
- Allocates a buffer with a length \fISize\fR in the permanent (i.e. program) area. \fISize\fR must be bound to
- a number. On successful return, \fIBuff\fR will be bound to the allocated buffer.
- .(x A
- (L) alloc_\|perm/2
- .)x
- The buffer, being in the permanent area, is never de-allocated.
- .ip \fBalloc_\|heap\fR(\fISize\fR,\ \fIBuff\fR)
- Allocates a buffer of size \fISize\fR on the heap and binds \fIBuff\fR to
- it. Since it is on the heap, it will be deallocated on backtracking.
- .(x A
- (L) alloc_\|heap/2
- .)x
- .ip \fBtrimbuff\fR(\fIType\fR,\ \fIBuff\fR,\ \fINewlen\fR)
- This allows (in some very restricted circumstances) the changing of
- the size of a buffer. \fIType\fR is 0 if the buffer is permanent, 1 if the buffer
- is on the heap. \fIBuff\fR is the buffer.
- .(x T
- (L) trimbuff/3
- .)x
- \fINewlen\fR is an integer: the size (which
- should be smaller than the original length of the buffer) to make
- the buffer. If the buffer is at the top of the heap (if heap buffer) or the
- end of the program area (if permanent) then the heap-top (or program area top)
- will be readjusted down. The length of the buffer will be modified to
- \fINewlen\fR. This is (obviously) a very low-level
- primitive and is for hackers only to implement grungy stuff.
- .\" .lp
- .\" \fB$trim_\|buff\fR(\fISize\fR,\fIBuff\fR,\fIType\fR,\fISupbuff\fR\^)
- .\" .ip
- .\" Trims the buffer \fIBuff\fR (possibly contained in superbuffer
- .\" \fISupbuff\fR) of type \fIType\fR to \fISize\fR bytes.
- .\" .(x Z
- .\" (L) $trim_\|buff/4
- .\" .)x
- .\" The value of
- .\" \fIType\fR indicates where the buffer is located: a value of 0 denotes a buffer in permanent
- .\" space, a value of 1 a buffer on the heap, and a value of 2 a buffer within
- .\" another buffer (the superbuffer).
- .\" All the arguments are input arguments,
- .\" and should be instantiated at the time of call (with the possible exception
- .\" of \fISupbuff\fR, which is looked at only if \fIType\fR is 2).
- .\" The internal length of the buffer \fIBuff\fR is changed to
- .\" \fISize\fR.
- .lp
- \fBconlength\fR(\fIConstant\fR,\fILength\fR\^)
- .ip
- Succeeds if the length of the print name of the constant
- \fIConstant\fR (which can be an atom, buffer
- or integer), in bytes, is \fILength\fR.
- If \fIConstant\fR is a buffer, it
- is the length of the buffer; if \fIConstant\fR is an integer, it is the
- length of the decimal representation of that integer, i.e., the
- number of bytes that a $\fIwritename\fR will use.
- .sh 2 "Modification of the Program"
- .lp
- The predicates defined in this section allow modification of the program
- as it is actually running.
- Clauses can be added to the program (\fIasserted\fP) or removed from the program
- (\fIretracted\fP).
- At the lowest level, the system supports the asserting of clauses with upto
- one literal in the body. It
- does this by allocating a buffer and compiling code for the clause into
- that buffer. Such a buffer is called a ``clause reference'' (\fIclref\fR\|).
- The clref is then added to a chain of clrefs. The chain of clrefs
- has a header, which is a small buffer called a ``predicate reference''
- (\fIprref\fR\|), which contains pointers to the beginning and end of its
- chain of clrefs. Clause references are quite similar to ``database references'' of C-Prolog, and can be called.
- .pp
- When clauses are added to the program through \fIassert\fR, an index is
- normally created on the principal functor of the first argument in the head
- of the clause. The argument on which the index is being created may be
- changed via the \fIindex\fR/3 directive. In particular, if no index is
- desired on a predicate, this should be specified using the \fIindex\fR/3
- directive with the argument number set to zero, e.g. if no index is desired
- on a predicate \fIfoo\fR/3, then the directive
- .(l
- :\- index(\fIfoo\fR, 3, 0).
- .)l
- should be specified.
- .pp
- The predicates that can be used to modify the program are the following:
- .sp
- .lp
- \fBassert\fP(\fIC\fP)
- .(x A
- (L) assert/1
- .)x
- .ip
- The
- current instance of \fIC\fP is interpreted as a clause and is added
- to the program (with new private variables
- replacing any uninstantiated variables), at the end of the list of
- clauses for that predicate.
- \fIC\fP must be instantiated to a non-variable.
- .lp
- \fBassert\fR(\fIC\fR, \fIRef\fR\^)
- .(x A
- (L) assert/2
- .)x
- .ip
- As for \fIassert\fR/1, but also unifies \fIRef\fR with the clause reference
- of the clause asserted.
- .lp
- \fBasserti\fR(\fIC\fR,\fIN\fR\^)
- .(x A
- (L) asserti/2
- .)x
- .ip
- The current instance of \fIC\fR, interpreted as a clause, is asserted to
- the program with an index on its \fIN\^\*[th\*]\fR argument. If \fIN\fR is
- zero, no index is created.
- .lp
- \fBasserta\fR(\fIC\fR\^)
- .(x A
- (L) asserta/1
- .)x
- .ip
- Similar to \fBassert\fR(\fIC\fR\^), except that the new clause becomes the
- \fIfirst\fR clause of the procedure concerned.
- .lp
- \fBasserta\fR(\fIC\fR, \fIRef\fR\^)
- .(x A
- (L) asserta/2
- .)x
- .ip
- Similar to \fBasserta\fR(\fIC\fR\^), but also unifies \fIRef\fR with the
- clause reference of the clause asserted.
- .lp
- \fBassertz\fR(\fIC\fR\^)
- .(x A
- (L) assertz/1
- .)x
- .ip
- Similar to \fBassert\fR(\fIC\fR\^), except that the new clause becomes the
- \fIlast\fR clause of the procedure concerned.
- .lp
- \fBassertz\fR(\fIC\fR, \fIRef\fR\^)
- .(x A
- (L) assertz/2
- .)x
- .ip
- Similar to \fBassertz\fR(\fIC\fR\^), but also unifies \fIRef\fR with the
- clause reference of the clause asserted.
- .lp
- \fBassert_\|union\fR(\fIP\fR, \fIQ\fR)
- .ip
- The clauses for \fIQ\fR are added to the clauses for \fIP\fR.
- .(x A
- (L) assert_\|union/2
- .)x
- For example, the call
- .(l
- | ?- assert_\|union(p(X,Y),q(X,Y)).
- .)l
- has the effect of adding the rule
- .(l
- p(X,Y) :\- q(X,Y).
- .)l
- as the last rule defining \fIp\fR/2. If \fIP\fR is not defined, it results
- in the call to \fIQ\fR being the only clause for \fIP\fR.
-
- The variables in the arguments to
- \fIassert_\^union\fR/2 are not significant, e.g. the above would have been
- equivalent to
- .(l
- | ?- assert_\|union(p(Y,X),q(X,Y)).
- or
- | ?- assert_\|union(p(_\|,_\|),q(_\|,_\|)).
- .)l
- However, the arities of the two predicates involved must match, e.g.
- even though the goal
- .(l
- | ?- assert_\|union(p(X,Y), r(X,Y,Z)).
- .)l
- will succeed, the predicate \fIp\fR/2 will not in any way depend on the
- clauses for \fIr\fR/3.
- .lp
- \fBassert\fR(\fIClause\fR,\fIAZ\fR,\fIIndex\fR,\fIClref\fR\^)
- .ip
- Asserts a clause to a predicate. \fIClause\fR is the clause to assert.
- .(x A
- (L) assert/4
- .)x
- \fIAZ\fR is 0 for insertion as the first clause, 1 for insertion as the last clause.
- \fIIndex\fR is the number of the argument on which to index (0 for
- no indexing). \fIClref\fR is returned as the clause reference of
- the fact newly asserted. If the main functor symbol of \fIClause\fR has
- been declared (by \fI$assertf_\|alloc_\|t\fR/2, see below) to have its
- clauses on the heap, the clref will be allocated there. If the predicate
- symbol of \fIClause\fR is undefined, it will be initialized and \fIClause\fR
- added. If the predicate symbol has compiled clauses, it is first
- converted to be dynamic (see \fIsymtype\fR/2, Section 5.10) by adding a special clref that calls the
- compiled clauses. \fIFact\fR, \fIAZ\fR and \fIIndex\fR are input arguments,
- and should be instantiated at the time of call; \fIClref\fR is an output
- argument, and should be uninstantiated at the time of call.
- .lp
- \fBclause\fP(\fIP\fP,\fIQ\fP)
- .(x C
- (L) clause/2
- .)x
- .ip
- \fIP\fP
- must be bound to a non-variable term, and the
- program is searched for a clause \fICl\fR whose head matches \fIP\fP.
- The head and body of the clause \fICl\fR is unified with \fIP\fP and \fIQ\fP
- respectively. If \fICl\fR is a unit clause, \fIQ\fP will be
- unified with `true'.
- Only interpreted clauses, i.e. those created through \fIassert\fR, can be
- accesed via clause/2.
- .lp
- \fBclause\fP(\fIHead\fP,\fIBody\fP,\fIRef\fP)
- .(x C
- (L) clause/3
- .)x
- .ip
- Similar
- to \fBclause\fP(\fIHead\fP,\fIBody\fP) but also unifies \fIRef\fP with the
- database reference of the clause concerned. \fIclause\fR/3 can be executed
- in one of two modes: either \fIHead\fP must be instantiated to a non-variable
- term at the time of the call, or \fIRef\fR must be instantiated to a
- database reference. As in the case of clause/2,
- only interpreted clauses, i.e. those created through \fIassert\fR, can be
- accesed via clause/3.
- .lp
- \fBretract\fP(\fIClause\fP\^)
- .(x R
- (L) retract/1
- .)x
- .ip
- The first clause in the program that unifies with \fIClause\fP is deleted
- from the program.
- This predicate may be used in a non-deterministic fashion, i.e. it will
- successively backtrack to retract clauses whose heads match \fIHead\fR.
- \fIHead\fP must be initially instantiated to a non-variable. In the current
- implementation, \fIretract\fR works only for asserted (e.g. consulted)
- clauses.
- .lp
- \fBabolish\fP(\fIP\fP)
- .ip
- Completely
- remove all clauses for the procedure with head \fIP\fP (which should be
- a term).
- .(x A
- (L) abolish/1
- .)x
- For example, the goal
- .(l
- | ?- abolish( p(_\|, _\|, _\|) ).
- .)l
- removes all clauses for the predicate \fIp\fR/3.
- .lp
- \fBabolish\fR(\fIP\fR, \fIN\fR\^)
- .ip
- Completely remove all clauses for the predicate \fIP\fR (which should be an
- atom) with arity \fIN\fR (which should be an integer).
- .(x A
- (L) abolish/2
- .)x
- .sh 2 "Internal Database"
- .lp
- \fBrecorded(\fIKey\fR, \fITerm\fR, \fIRef\fR\^)
- .(x R
- (L) recorded/3
- .)x
- .ip
- The internal database is searched for terms recorded under the key
- \fIKey\fR. These terms are successively unified with \fITerm\fR in the
- order they occur in the database; at the same time, \fIRef\fR is unified
- with the database reference of the recorded item. The key must be given,
- and may be an atom or complex term. If it is a complex term, only the
- principal functor is significant.
- .lp
- \fBrecorda\fR(\fIKey\fR, \fITerm\fR, \fIRef\fR\^)
- .(x R
- (L) recorda/3
- .)x
- .ip
- The term \fITerm\fR is recorded in the internal database as the first item
- for the key \fIKey\fR, where \fIRef\fR is its database reference. The key
- must be given, and only its principal functor is significant.
- .lp
- \fBrecordz\fR(\fIKey\fR, \fITerm\fR, \fIRef\fR\^)
- .(x R
- (L) recordz/3
- .)x
- .ip
- The term \fITerm\fR is recorded in the internal database as the last item
- for the key \fIKey\fR, where \fIRef\fR is its database reference. The key
- must be given, and only its principal functor is significant.
- .lp
- \fBerase\fR(\fIClref\fR\^)
- .(x E
- (L) erase/1
- .)x
- .ip
- The recorded item or clause whose database reference is \fIClref\fR is
- deleted from the internal database or program.
- \fIClref\fR should be instantiated at the time of call.
- .lp
- \fBinstance\fR(\fIRef\fR, \fITerm\fR\^)
- .(x I
- (L) instance/2
- .)x
- .ip
- A (most general) instance of the recorded term whose database reference is
- \fIRef\fR is unified with \fITerm\fR. \fIRef\fR must be instantiated to a
- database reference. Note that \fIinstance\fR/2 will not be able to access
- terms that have been erased.
- .sh 2 "Information about the State of the Program"
- .lp
- \fBlisting\fR
- .(x L
- (L) listing/0
- .)x
- .ip
- Lists in the current output stream the clauses for all the interpreted
- predicates in the program, except predicates that are ``internal'', i.e. whose
- names begin with `$' or `_$', or which are provided as predefined (builtin or
- library) predicates. A bug in the current system is that even though the
- user is allowed to redefine such predicates, \fIlisting\fR/0 does not know
- about such redefinitions, and will not list such predicates (they may,
- however, be accessed through \fIlisting\fR/1 if they are interpreted).
- .lp
- \fBlisting\fP(\fIA\fP)
- .(x L
- (L) listing/1
- .)x
- .ip
- The argument \fIA\fP may be a predicate specification of
- the form \fIName\fP/\fIArity\fP in which case only the clauses for the
- specified predicate are listed.
- Alternatively, it is possible for \fIA\fP to be a list
- of predicate specifications, e.g.
- .(l
- | ?- listing([concatenate/3, reverse/2, go/0]).
- .)l
- Only \fIinterpreted\fR clauses, i.e. clauses created via \fIassert\fR,
- can be accessed through listing/1.
- .lp
- \fBcurrent_atom\fR(\fIAtom\fR)
- .(x C
- (L) current_atom/1
- .)x
- .(x Z
- (L) $current_atom/2
- .)x
- .ip
- Generates (through backtracking) all currently known atoms, and unifies
- each in turn with \fIAtom\fR. However, atoms considered ``internal''
- symbols, i.e. those whose names begin with \fB$\fR or \fB_$\fR are not
- returned. The intrepid user who wishes to access such internal atoms as
- well can use the goal
- .(l
- ?- $current_atom(\fIAtom\fR, 1).
- .)l
- .lp
- \fBcurrent_functor\fR(\fIName\fR, \fITerm\fR)
- .(x C
- (L) current_functor/2
- .)x
- .(x Z
- (L) $current_functor/3
- .)x
- .ip
- Generates (through backtracking) all currently known functors (which
- includes function and predicate symbols), and for each one returns its name
- and most general term as \fIName\fR and \fITerm\fR respectively.
- However, functors considered ``internal'' symbols, i.e. those whose names
- begin with \fB$\fR or \fB_$\fR, or which are provided as predefined
- predicates, are not returned if both arguments to \fIcurrent_functor\fR/2
- are variables. Internal symbols (of which there are a
- \fIgreat\fR many) as well as external ones may be accessed via
- .(l
- ?- $current_functor(\fIName\fR, \fITerm\fR, 1).
- .)l
- A bug in the current implementation is that even though the user is allowed
- to redefine ``internal'' (builtin or library) predicates,
- \fIcurrent_functor\fR/2 does not know whether they have been redefined,
- and hence will not return such predicates if both arguments to
- \fIcurrent_functor\fR/2 are variables.
- .lp
- \fBcurrent_predicate\fR(\fIName\fR, \fITerm\fR)
- .(x C
- (L) current_predicate/2
- .)x
- .(x Z
- (L) $current_predicate/3
- .)x
- .ip
- Generates (through backtracking) all currently known predicates, and for
- each one returns its name and most general term as \fIName\fR and \fITerm\fR
- respectively. However, predicates considered ``internal'', i.e. those whose
- names begin with \fB$\fR or \fB_$\fR, or which are provided as predefined
- predicates, are not returned if both arguments to \fIcurrent_predicate\fR/2
- are variables. Internal symbols (of which there are a
- \fIgreat\fR many) as well as external ones may be accessed via
- .(l
- ?- $current_predicate(\fIName\fR, \fITerm\fR, 1).
- .)l
- A bug in the current implementation is that even though the user is allowed
- to redefine ``internal'' (builtin or library) predicates,
- \fIcurrent_predicate\fR/2 does not know whether they have been redefined,
- and hence will not return such predicates if both arguments to
- \fIcurrent_predicate\fR/2 are variables.
- .lp
- \fBpredicate_property\fR(\fITerm\fR, \fIProperty\fR)
- .(x P
- (L) predicate_property/2
- .)x
- .ip
- If \fITerm\fR is a term whose principal functor is a predicate,
- \fIProperty\fR is unified with the currently known properties of the
- corresponding predicate. If \fITerm\fR is a variable, then it is unified
- (successively, through backtracking) with the most general term for a
- predicate whose known properties are unified with \fIProperty\fR. For
- example, all the interpreted predicates in the program may be enumerated
- using
- .(l
- ?- predicate_property(X, interpreted).
- .)l
- .ip
- If the first argument to \fIpredicate_property\fR/2 is uninstantiated at the
- time of the call, ``internal'' predicates will not be returned. A bug in
- the current implementation is that even though the user is allowed to redefine
- such ``internal'' predicates, \fIpredicate_property\fR/2 does not know about
- such redefinitions, and will not return such predicates if its first argument
- is uninstantiated.
- Currently, the only properties that are considered are \fBinterpreted\fR and
- \fBcompiled\fR.
- .lp
- .sh 2 "Environmental"
- .lp
- \fBop\fR(\fIpriority\fR, \fItype\fR, \fIname\fR\^)
- .ip
- Treat \fIname\fR as an operator of the stated \fItype\fR and \fIpriority\fR (see
- Section 3.2). \fIname\fR may also be a list of names, in which all are to
- be treated as operators of the stated \fItype\fR and \fIpriority\fR.
- .lp
- \fBbreak\fR
- .(x B
- (L) break/0
- .)x
- .ip
- Causes the current execution to be suspended at the next procedure call.
- Then the message ``[ Break (level 1) ]'' is displayed. The interpreter is
- then ready to accept input as though it was at the top level (except that
- at break level \fIn\fR > 0, the prompt is ``\fIn\fR: ?- ''). If another
- call of \fBbreak\fR is encountered, it moves up to level 2, and so on. To
- close the break and resume the execution which was suspended, type the
- \s-2END-OF-INPUT\s+2 character. Execution will be resumed at the procedure
- call where it had been suspended. Alternatively, the suspended execution
- can be aborted by calling the evaluable predicate \fBabort\fR, which
- causes a return to the top level.
- .lp
- \fBabort\fR
- .(x A
- (B) abort/0
- .)x
- .ip
- Aborts the current execution, taking you back to top level.
- .lp
- \fBsave\fR(\fIF\fR\^)
- .(x S
- (B) save/1
- .)x
- .ip
- The system saves the current state of the system into file \fIF\fR.
- .lp
- \fBrestore\fR(\fIF\fR\^)
- .(x R
- (B) restore/1
- .)x
- .ip
- The system restores the saved state in file \fIF\fR to be the current state.
- One restriction imposed by the current system is that various system parameters
- (e.g. stack sizes, permanent space, heap space, etc.) of the saved state
- have to be the same as that of the current invocation. Thus, it is not
- possible to save a state from an invocation where 50000 words of permanent
- space had been allocated, and then restore the same state in an invocation
- with 100000 words of permanent space.
- .lp
- \fBcputime\fR(\fIX\fR)
- .ip
- Unifies \fIX\fR with the time elapsed, in milliseconds, since
- the system was started up.
- .(x C
- (B) cputime/1
- .)x
- .lp
- \fB$getenv\fR(\fIVar\fR,\fIVal\fR\^)
- .ip
- \fIVal\fR is unified with the value of the Unix environment variable \fIVar\fR.
- Fails is \fIVar\fR is undefined.
- .(x Z
- (L) $getenv/2
- .)x
- .lp
- \fBstatistics\fR
- .ip
- Prints out the current allocations and amounts of space used for each of
- the four main areas: the permanent area, the local stack, the global stack
- and the trail stack.
- .(x S
- (B) statistics/0
- .)x
- Does not work well unless the simulator has been called
- with the -\fBs\fR option (see Section 7.2).
- .lp
- \fI\fBstatistics\fR(\fIKeyword\fR, \fIList\fR\^)
- .(x S
- (L) statistics/2
- .)x
- .ip
- Usually used with \fIKeyword\fR instantiated to a keyword, e.g.
- `runtime', and \fIList\fR unbound. It unifies \fIList\fR with a list of
- statistics determined by \fIKeyword\fR. The keys and values are summarized
- below. Times are given in milliseconds and sizes are given in bytes.
- .ip
- \fIKeyword List\fR
- .(l L
- runtime [cpu time used by Prolog, cpu time since
- last call to statistics/2]
- memory [total virtual memory, 0]
- core ( \fIsame as for the keyword\fR memory )
- program [program space in use, program space free]
- heap ( \fIsame as for the keyword\fR program )
- global_stack [global stack in use, global stack free]
- local_stack [local stack in use, local stack free]
- trail [trail stack in use, trail stack free]
- garbage_collection [0, 0]
- stack_shifts [0, 0]
- .)l
- \fBNote\fR:
- .in 0.25i
- .np
- For the keyword `memory' the second element of the returned list is always 0.
- .np
- For the keyword `trail', the second element of the returned list is the
- amount of trail stack free. This is similar to Sicstus Prolog (version 0.5),
- but different from Quintus Prolog (version 1.6).
- .np
- Currently, SB-Prolog does not have garbage collection or stack shifting,
- hence the list values returned for these are [0, 0].
- .in 0
- .lp
- \fBnodynload\fR(\fIP\fR, \fIN\fR\^)
- .(x N
- (L) nodynload/2
- .)x
- .ip
- Flags the predicate \fIP\fR with arity \fIN\fR as one that should not be
- attempted to be dynamically loaded if it is undefined. If a predicate so
- flagged is undefined when a call to it is encountered, the call fails
- quietly without trying to invoke the dynamic loader or giving an error
- message. \fIP\fR and \fIN\fR should be instantiated to an atom and an
- integer, respectively, at the time of call to \fInodynload\fR/2.
- .lp
- \fBsymtype\fR(\fIT\fR, \fIN\fR\^)
- .ip
- Unifies \fIN\fR with the ``internal type'' of the principal functor of the term \fIT\fR,
- which must be instantiated at the time of the call.
- .(x S
- (B) symtype/2
- .)x
- \fIN\fR is bound to 0 if
- \fIT\fR does not have an entry point defined (i.e. cannot be executed);
- to 1 if the principal functor of \fIT\fR is ``dynamic'', i.e. has asserted code; to 2
- if the principal functor for \fIT\fR is a compiled predicate; and
- 3 if \fIT\fR denotes a buffer. Thus, for example, if the predicate \fIp\fR/2
- is a compiled predicate which has been loaded into the system, the goal
- .(l
- | ?- symtype(p(_\|,_\|), X).
- .)l
- will succeed binding X to 2; on the other hand, the goal
- .(l
- | ?- assert(q(a,b,c)), symtype(q(_\|,_\|,_\|), X).
- .)l
- will succeed binding X to 1.
- .lp
- \fBsystem\fR(\fICall\fR)
- .ip
- Calls the operating system with the atom \fICall\fR as argument.
- .(x S
- (B) system/1
- .)x
- For example, the call
- .(l
- | ?- system('ls').
- .)l
- will produce a directory listing. Since \fIsystem\fR/1 is executed by
- forking off a shell process, it cannot be used, for example, to change the working
- directory of the simulator.
- .lp
- \fBsyscall\fR(\fIN\fR, \fIArgs\fR, \fIRes\fR)
- .ip
- Executes the Unix system call number \fIN\fR with
- arguments \fIArgs\fR, and returns the result in \fIRes\fR.
- .(x S
- (B) syscall/3
- .)x
- \fIN\fR is an integer, and \fIArgs\fR a Prolog
- list of the arguments to the system call. For example, to execute the system call
- ``\fIcreat\fR(\fIFile\fR,\fIMode\fR)'', knowing that the syscall number for
- the Unix command \fIcreat\fR(2) is 8, we execute the goal
- .(l
- | ?- syscall(8, [\fIFile\fR, \fIMode\fR], \fIDes\fR).
- .)l
- where \fIDes\fR is the file descriptor returned by \fIcreat\fR. The syscall numbers
- for some Unix system calls are given in Table 2.
- .(z
- .TS
- center box ;
- le n | le n.
- exit 1 fork 2
- read 3 write 4
- open 5 close 6
- creat 8 link 9
- unlink 10 chdir 12
- chmod 15 lseek 19
- access 33 kill 37
- wait 84 socket 97
- connect 98 accept 99
- send 101 recv 102
- bind 104 setsockopt 105
- listen 106 recvmsg 113
- sendmsg 114 getsockopt 118
- recvfrom 125 sendto 133
- socketpair 135 mkdir 136
- rmdir 137 getsockname 150
- .TE
- .sp
- .ce
- Table 2: Some Syscall Numbers for Unix Systems Calls
- .sp 2
- .)z
- .sh 2 "Global Values"
- .lp
- SB-Prolog has some primitives that permit the programmer to manipulate global
- values. These are provided primarily as an efficiency hack, and needless to say, should
- be used with a great deal of care.
- .lp
- \fBglobalset\fR(\fITerm\fR)
- .ip
- Allows the user to save a global value.
- .(x G
- (L) globalset/1
- .)x
- \fITerm\fR must be bound
- to a compound term, say \fIp\fR(\fIV\fR\^). \fIV\fR must be a number or
- a constant or a variable.
- If \fIV\fR is a number or a constant, the effect of \fIglobalset\fR(\fIp\fR(\fIV\fR\^)) can be
- described as:
- .(l
- retract(p(_\|)), assert(p(V)).
- .)l
- I.e., \fIp\fR is a predicate that when called will, from now on (until some other
- change by \fIglobalset\fR/1), deterministically return \fIV\fR.
- If \fIV\fR is a variable, the effect is to make \fIV\fR a global variable whose value is
- accessible by calling \fIp\fR. For example, executing
- ``\fIglobalset\fR(\fIp\fR(\fIX\fR\^))'' makes \fIX\fR a global
- variable. \fIX\fR can be set by unification with some other term.
- On backtracking, \fIX\fR will be restored to its earlier value.
- .lp
- \fBgennum\fR(\fINewnum\fR)
- .ip
- gennum/1 sets its argument to a new integer every time it is invoked.
- .(x G
- (L) gennum/1
- .)x
- .lp
- \fBgensym\fR(\fIC\fR, \fINewsym\fR)
- .ip
- gensym/2 sets its second argument to an atom whose name is made by
- concatenating the name of the atom \fIC\fR to the current gennum number.
- .(x G
- (L) gensym/2
- .)x
- This new constant is bound to \fINewsym\fR. For example, if the current
- \fIgennum\fR number is 37, then the call
- .(l
- | ?- gensym(aaa,X)
- .)l
- will succeed binding \fIX\fR to the atom `aaa37'.
- .ds f. sec3.t
- .sh 2 "Exotica"
- .lp
- This section describes some low level routines that are sometimes useful in
- mucking around with buffers. These are for serious hackers only.
- .lp
- \fB$alloc_\|buff\fR(\fISize\fR,\fIBuff\fR,\fIType\fR,\fISupbuff\fR,\fIRetcode\fR)
- .ip
- Allocates a buffer. \fISize\fR is the length (in bytes) of the buffer to
- allocate;
- .(x Z
- (L) $alloc_\|buff/5
- .)x
- \fIBuff\fR is the buffer allocated, and should be unbound at
- the time of the call; \fIType\fR indicates where to allocate the
- buffer: a value of 0 indicates that the buffer is to be allocated
- in permanent space, 1 that it should be on the heap, and 2 indicates
- that it should be allocated from a larger heap buffer; \fISupbuff\fR is
- the larger buffer to allocate a subbuffer out of, and is only looked at
- if the value of \fIType\fR is 2; \fIRetcode\fR is the return code: a
- value of 0 indicates that the buffer has been allocated, while a value
- of 1 indicates that the buffer could not be allocated due to lack of
- space. The arguments \fISize\fR, \fIType\fR, and \fISupbuff\fR (if
- \fIType\fR = 2) are input arguments, and should be bound at the time
- of the call; \fIBuff\fR and \fIRetcode\fR are output
- arguments, and should be unbound at the time of the call.
- .lp
- \fBcall_\^ref\fR(\fICall\fR, \fIRef\fR)
- .(x C
- (L) call_\|ref/2
- .)x
- .ip
- Calls the predicate whose database reference (prref) is \fIRef\fR, using the
- literal \fICall\fR as the call. This is similar to
- \fBcall_\|ref\fR(\fICall\fR, \fIRef\fR, 0).
- .lp
- \fBcall_\^ref\fR(\fICall\fR, \fIRef\fR, \fITr\fR\^)
- .(x C
- (L) call_\|ref/3
- .)x
- .ip
- Calls the predicate whose database reference (prref) is \fIRef\fR, using the
- literal \fICall\fR as the call. \fITr\fR must be either 0 or 1: if \fITr\fR
- is 0 then the call \fICall\fR is made assuming the ``trust'' optimization
- will be made; if \fITr\fR is 1 then the ``trust'' optimization is not used,
- so that any new fact added
- before final failure will be seen by \fICall\fR. (Also, this currently
- does not take advantage of any indexing that might have been constructed.)
- \fICall\fR, \fIRef\fR and \fITr\fR
- are all input arguments, and should be instantiated at the time of call.
- .lp
- \fB$assertf_\|alloc_\|t\fR(\fIPalist\fR,\fISize\fR)
- .ip
- Declares that each predicate in the list \fIPalist\fR of predicate/arity
- pairs (terms of the form `/'(\fIP\fR,\fIN\fR) where \fIP\fR is a
- predicate symbol and \fIN\fR the arity of \fIP\fR) is to have any
- facts asserted to them stored in a buffer on the heap, to be allocated
- here.
- .(x Z
- (L) $assertf_\|alloc_\|t
- .)x
- This allocates a superbuffer of size \fISize\fR on the heap.
- Future assertions to these predicates will have their clauses put in this
- buffer. When this call is backtracked over, any clauses asserted to
- these predicates are deallocated, and a subsequent call to any of those
- predicates will cause the simulator to report an error and fail.
- Both \fIPalist\fR and \fISize\fR are input arguments, and should be instantiated at
- the time of call.
- .lp
- \fB$db_\|new_\|prref\fR(\fIPrref\fR,\fIWhere\fR,\fISupbuff\fR\^)
- .ip
- Creates an empty Prref, i.e. one with no facts in it.
- .(x Z
- (L) $db_\|new_\|prref/3
- .)x
- If called, it will simply fail. \fIWhere\fR
- indicates where the prref should be allocated: a value of
- 0 indicates the permanent area, while a value of 2 indicates that
- it is to be allocated as a subbuffer. \fISupbuff\fR is the superbuffer
- from which to allocate \fIPrref\fR if \fIWhere\fR is 2. \fIWhere\fR
- should be instantiated at the time of call, while \fIPrref\fR should be
- uninstantiated; in addition, if \fIWhere\fR is 2, \fISupbuff\fR
- should be instantiated at the time of call.
- .lp
- \fB$db_\|assert_\|fact\fR(\fIFact\fR,\fIPrref\fR,\fIAZ\fR,\fIIndex\fR,\fIClref\fR,\fIWhere\fR,\fISupbuff\fR)
- .ip
- \fIFact\fR is a fact to be asserted; \fIPrref\fR is a predicate
- reference to which to add the asserted fact;
- .(x Z
- (L) $db_\|assert_\|fact/5
- .)x
- \fIAZ\fR is either 0,
- indicating the fact should be inserted as the first clause in \fIPrref\fR,
- or 1, indicating it should be inserted as the last; \fIIndex\fR is 0
- if no index is to be built, or \fIn\fR if an index on the \fIn\fR\*[th\*]
- argument of the fact is to be used. (Asserting at the beginning of the
- chain with indexing is not yet supported.) \fIWhere\fR indicates where
- the clref is to be allocated: a value of 0 indicates that it should be
- in the permanent area, while a value of 2 indicates that it should be
- allocated
- as a subbuffer of \fISupbuff\fR. \fIClref\fR is returned and
- it is the clause reference of the asserted fact. \fIFact\fR, \fIPrref\fR, \fIAZ\fR,
- \fIIndex\fR and \fIWhere\fR are input arguments, and should be instantiated at the
- time of call; in addition, if \fIWhere\fR is 2, then \fISupbuff\fR should also
- be instantiated. \fIClref\fR is an output argument, and should be uninstantiated at the
- time of call.
- .lp
- \fB$db_\|add_\|clref\fR(\fIFact\fR,\fIPrref\fR,\fIAZ\fR,\fIIndex\fR,\fIClref\fR,\fIWhere\fR,\fISupbuff\fR\^)
- .ip
- Adds the clref \fIClref\fR to the prref \fIPrref\fR.
- .(x Z
- (L) $db_\|add_\|clref/7
- .)x
- \fIFact\fR is the fact that has been compiled into \fIClref\fR
- (used only to get the arity and for indexing). The other parameters
- are as for \fI$db_\|assert_\|fact\fR/7.
- .lp
- \fB$db_\|call_\|prref\fR(\fICall\fR,\fIPrref\fR)
- .ip
- Calls the prref \fIPrref\fR using the literal \fICall\fR as the call.
- .(x Z
- (L) $db_\|call_\|prref/2
- .)x
- The call is done by simply branching to the first
- clause. New facts added to \fIPrref\fR after the last fact has been retrieved
- by \fICall\fR, but before \fICall\fR is failed through, will \fInot\fR
- be used. Both \fICall\fR and \fIPrref\fR are
- input arguments, and should be instantiated at the time of call.
- .lp
- \fB$db_\|call_\|prref_\|s\fR(\fICall\fR,\fIPrref\fR)
- .ip
- This also calls the prref \fIPrref\fR using \fICall\fR as the call.
- .(x Z
- (L) $db_\|call_\|prref_\|s/2
- .)x
- The difference from \fI$db_\|call_\|prref\fR is that this does not use
- the ``trust'' optimization, so that any new fact added
- before final failure will be seen by \fICall\fR. (Also, this currently
- does not take advantage of any indexing that might have been constructed,
- while \fI$db_\|call_\|prref\fR does.) Both \fICall\fR and \fIPrref\fR are
- input arguments, and should be instantiated at the time of call.
- .lp
- \fB$db_\|get_\|clauses\fR(\fIPrref\fR,\fIClref\fR,\fIDir\fR)
- .ip
- This returns, nondeterministically, all the clause references \fIClref\fR
- for clauses asserted to prref \fIPrref\fR.
- .(x Z
- (L) $db_\|get_\|clauses/3
- .)x
- If \fIDir\fR is 0, then the
- first clref on the list is returned first; if \fIDir\fR is 1, then they
- are returned in reverse order. \fIPrref\fR and \fIDir\fR are input
- arguments, and should be instantiated at the time of call; \fIClref\fR
- is an output argument, and should be uninstantiated at the time of call.
- .sh 1 "Debugging"
- .sh 2 "High Level Tracing"
- .pp
- The preferred method of tracing execution is through the predicate
- \fItrace\fR/1.
- .(x T
- (L) trace/1
- .)x
- This predicate takes as argument a term \fIP\fR/\fIN\fR, where
- \fIP\fR is a predicate name and \fIN\fR its arity, and sets a ``trace
- point'' on the corresponding predicate; it can also be given a
- list of such terms, in which case a trace point is set on each member of the list.
- For example, executing
- .(l
- | ?- trace(pred1/2), trace([pred2/3, pred3/2]).
- .)l
- sets trace points on predicates \fIpred1\fR/2, \fIpred2\fR/3 and
- \fIpred3\fR/2.
- Only those predicates are traced that have trace points set on them.
- .pp
- If all the predicates in a file are to be traced, it is usually convenient to use the
- \fIPredList\fR parameter of \fIcompile\fR/4 or \fIconsult\fR/3, e.g.:
- .(l
- | ?- compile(foo, 'foo.out', [t,v], Preds), load('foo.out'), trace(Preds).
- or
- | ?- consult(foo, [v], Preds), trace(Preds).
- .)l
- Notice that in the first case, the \fBt\fR compiler option (see Section 8.3)
- should be specified in
- order to turn off certain assembler optimizations and facilitate tracing.
- In the second case, the same effect may be achieved by specifying the
- \fBt\fR option to \fIconsult\fR.
- .pp
- The trace points set on predicates may be overwritten by loading byte code
- files via \fIload\fR/1, and in this case it may be necessary to explicitly
- set trace points again on the loaded predicates. This does not happen with
- \fIconsult\fR: predicates that were being traced continue to have trace points
- set after consulting.
- .pp
- The tracing facilities of SB-Prolog are in many ways very similar to those of
- C-Prolog. However, leashing is not supported, and only those predicates
- can be traced which have had trace points
- set on them through \fItrace\fR/1. This makes \fItrace\fR/1 and \fIspy\fR/1
- very similar: essentially, trace amounts to two levels of spy points.
- In SB-Prolog, tracing occurs at \fICall\fR (i.e. entry to a predicate),
- successful \fIExit\fR from a clause, and \fIFailure\fR of the entire call. The tracing options available during debugging are the following:
- .ip \fBc\fR,\ \s-2NEWLINE\s+2:\ Creep
- Causes the system to single-step to the next port (i.e. either the entry to a traced
- predicate called by the executed clause, or the success or failure exit from that
- clause).
- .ip \fBa\fR:\ Abort
- Causes execution to abort and control to return to the top level interpreter.
- .ip \fBb\fR:\ Break
- Calls the evaluable predicate \fIbreak\fR, thus invoking recursively
- a new incarnation of the system interpreter. The
- command prompt at break level \fIn\fR is
- .(l
- \fIn\fR: ?-
- .)l
- The user may return to the previous break level by entering the system end-of-file character (e.g. ctrl-D), or
- typing in the atom \fIend_\^of_\^file\fR; or to the top level interpreter by typing in \fIabort\fR.
- .lp
- \fBf\fR:\ Fail
- .ip
- Causes execution to fail, thus transferring control to the Fail port of the current execution.
- .ip \fBh\fR:\ Help
- Displays the table of debugging options.
- .ip \fBl\fR:\ Leap
- Causes the system to resume running the program, only stopping when a spy-point
- is reached or the program terminates. This allows the user to follow the execution at a higher level than
- exhaustive tracing.
- .ip \fBn\fR:\ Nodebug
- Turns off debug mode.
- .ip \fBq\fR:\ Quasi-skip
- This is like Skip except that it does not mask out spy points.
- .ip \fBr\fR:\ Retry\ (fail)
- Transfers to the Call port of the current goal. Note, however, that side effects, such as
- database modifications etc., are not undone.
- .ip \fBs\fR:\ Skip
- Causes tracing to be turned off for the entire execution of the procedure. Thus,
- nothing is seen until control comes back to that procedure, either at the Success or the Failure port.
- .sp
- .lp
- Other predicates that are useful in debugging are:
- .sp
- .ip \fBuntrace\fR(\fIPreds\fR)
- .(x U
- (L) untrace/1
- .)x
- where Preds is a term \fIP\fR/\fIN\fR, where \fIP\fR is a predicate name and \fIN\fR its arity,
- or a list of such terms. Turns off tracing on the specified predicates.
- \fIPreds\fR must be instantiated at the time of the call.
- .ip \fBspy\fR(\fIPreds\fR)
- .(x S
- (L) spy/1
- .)x
- where Preds is a term \fIP\fR/\fIN\fR, where \fIP\fR is a predicate name and \fIN\fR its arity,
- or a list of such terms. Sets spy points on the specified predicates.
- \fIPreds\fR must be instantiated at the time of the call.
- .ip \fBnospy\fR(\fBPreds\fR)
- .(x N
- (L) nospy/1
- .)x
- where Preds is a term \fIP\fR/\fIN\fR, where \fIP\fR is a predicate name and \fIN\fR its arity,
- or a list of such terms. Removes spy points on the specified predicates.
- \fIPreds\fR must be instantiated at the time of the call.
- .ip \fBdebug\fR
- Turns on debugging mode. This causes subsequent execution of predicates with trace or spy
- points to be traced, and is a no-op if there are no such predicates.
- .(x D
- (L) debug/0
- .)x
- The predicates \fItrace\fR/1 and \fIspy\fR/1 cause debugging mode to be turned on automatically.
- .ip \fBnodebug\fR
- Turns off debugging mode. This causes trace and spy points to be ignored.
- .(x N
- (L) nodebug/0
- .)x
- .ip \fBdebugging\fR
- Displays information about whether debug mode is on or not, and lists
- predicates that have trace points or spy points set on them.
- .(x D
- (L) debugging/0
- .)x
- .ip \fBtracepreds\fR(\fIL\fR\|)
- Binds \fIL\fR to a list of terms \fIP\fR/\fIN\fR where the predicate
- \fIP\fR of arity \fIN\fR has a trace point set on it.
- .(x T
- (L) tracepreds/1
- .)x
- .ip \fBspypreds\fR(\fIL\fR\|)
- Binds \fIL\fR to a list of terms \fIP\fR/\fIN\fR where the predicate
- \fIP\fR of arity \fIN\fR has a spy point set on it.
- .(x S
- (L) spypreds/1
- .)x
- .sp
- .pp
- There is one known bug in the package: attempts to set trace points, via
- \fItrace\fR/1, on system and library predicates that are used by the trace
- package can cause bizarre behaviour.
- .sh 2 "Low Level Tracing"
- .lp
- SB-Prolog also provides a facility for low level tracing of execution. This can
- be activated by invoking the simulator with the \-T option, or through the
- predicate \fI$trace\fR/0. It causes trace information to be printed out at every
- call (including those to system trap handlers). The volume of such trace information can very become large very
- quickly, so this method of tracing is not recommended in general.
- .(x Z
- (L) $trace/0
- .)x
- .pp
- Low level tracing may be turned off using the predicate \fIuntrace\fR/0.
- .(x Z
- (L) $untrace/0
- .)x
- .ds f. sec4.t
- .sh 1 "The Simulator"
- .lp
- The simulator resides in the SB-Prolog system directory \fIsim\fR. The following
- sections describe various aspects of the simulator.
- .sh 2 "Invoking the Simulator"
- .lp
- The simulator is invoked by the command
-
- .(l
- sbprolog \fIbc_\^file\fR
- .)l
-
- where \fIbc_\^file\fR is a byte code file resulting from the compilation of a
- Prolog program. In almost all cases, the user will wish to interact with the
- SB-Prolog \fIquery evaluator\fR, in which case \fIbc_\|file\fR will be
- \fI$readloop\fR, and the command will be
- .(l C
- sbprolog \fIPath\fR/$readloop
- .)l
- where \fIPath\fR is the path to the directory containing the
- command interpreter \fI$readloop\fR. This directory, typically, is the
- system directory \fImodlib\fR.
- .pp
- The command interpreter reads in a query typed in by the user, evaluates it and
- prints the answer(s), repeating this until it encounters an end-of-file
- (the standard end-of-file character on the system, e.g. ctrl-D), or the user types
- in \fIend_\|of_\|file\fR or \fIhalt\fR.
- .pp
- The user should ensure that the the directory containing the executable file \fIsim\fR
- (typically, the system directory \fIsim\fR) is included in the shell variable
- \fIpath\fR; if not, the full path to the simulator will have to be specified.
- .pp
- In general, the simulator may be invoked with a variety of options, as
- follows:
-
- .(l
- sbprolog \-\fIoptions\fR \fIbc_\^file\fR
- or
- sbprolog \-\fIoption\fR\*<1\*> \-\fIoption\fR\*<2\*> ... \-\fIoption\*<n\*>\fR \fIbc_\^file\fR
- .)l
-
- The options recognized by the simulator are described below.
- .pp
- When called with a byte code file \fIbc_\^file\fR, the simulator begins
- execution with the first clause in that file. The first clause in such a
- file, therefore, should be a clause without any arguments in the head
- (otherwise, the simulator will attempt to dereference argument pointers
- in the head
- that are really pointing into deep space, and usually come to a sad end).
- If the user is executing a file in this manner rather than using the
- command interpreter, he should also be careful to include the undefined
- predicate handler `_\|\fI$undefined_\|pred\fR'/1, which is normally defined
- in the file \fImodlib/$init_\|sys.P\fR.
- .sh 2 "Simulator Options"
- .lp
- The following is a list of options recognized by the simulator.
- .ip \fBT\fR
- Generates a trace at entry to each called routine.
- .ip \fBd\fR
- Produces a disassembled dump of \fIbc_\|file\fR into a file named
- `dump.pil' and exits.
- .ip \fBn\fR
- Adds machine addresses when producing trace and dump.
- .ip \fBs\fR
- Maintains information for the builtin \fIstatistics\fR/0. Default: off.
- .ip \fBm\fR\ \fIsize\fR
- Allocates \fIsize\fR words (4 bytes) of space to the local stack and heap
- together. Default: 100000.
- .ip \fBp\fR\ \fIsize\fR
- Allocates \fIsize\fR words of space to the program area. Default: 100000.
- .ip \fBb\fR\ \fIsize\fR
- Allocates \fIsize\fR words of space to the trail stack. Default: \fIm\fR/5,
- where \fIm\fR is the amount of space allocated to the local stack and heap
- together. This parameter, if specified, must follow the -m parameter.
- .sp
- .lp
- As an example, the command
- .(l
- sbprolog -s -p 60000 -m 150000 \e$readloop
- .)l
- starts the simulator executing the command interpreter with 60000 bytes of
- program space, 150000 bytes of local and global stack space and (by default)
- 30000 bytes of trail stack space; the \fIs\fR option also results in
- statistics information being maintained.
- .sh 2 "Interrupts"
- .lp
- SB-Prolog provides a facility for exception
- handling using user-definable interrupt handlers. This can be used both
- for external interrupts, e.g. those generated from the keyboard by the user
- or from signals other processes; or internal traps, e.g. those caused by stack overflows, encountering undefined predicates, etc.
- For example, the ``undefined predicate'' interrupt is handled, by default, by the
- predicate `\fI_\|$undefined_\|pred\fR'/1, which is defined in the files
- \fImodlib/src/$init_\|sys.P\fR and \fImodlib/src/$readloop.P\fR.
- The default action on encountering an undefined predicate is to attempt to
- dynamically load a file whose name matches that of the
- undefined predicate. However, the user may easily alter this behaviour by
- redefining the undefined predicate handler.
- .pp
- In general, interrupts are handled by the predicate `_$\fIinterrupt\fR'/2:
- .(x Z
- (L) `_$interrupt'/2
- .)x
- a call to this predicate is of the form `_$\fIinterrupt\fR'(\fICall\fR,
- Code\fR), where \fICall\fR is the call that generated the interrupt, and
- \fICode\fR is an integer indicating the nature of the interrupt. For each
- interrupt code, the interrupt handler then calls a handler that is
- designed to handle that particular kind of interrupt. At this
- point, the following interrupt codes have predefined meanings:
- .ip \fB0\fR
- undefined predicate;
- .ip \fB1\fR
- keyboard interrupt ( ^C );
- .ip \fB2\fR
- stack overflow.
- .lp
- Other interrupt codes may be incorporated by modifying the definition of
- the predicate `_$\fIinterrupt\fR'/2 in the file \fImodlib/src/$readloop.P\fR.
- .pp
- Interrupts during execution are signalled from within the WAM simulator.
- The general method for raising an interrupt is using the function
- \fIset_intercode\fR in the file \fIsim/sub_inst.c\fR: to raise an interrupt
- whose code is \fIn\fR, the line
- .(l
- lpcreg = set_intercode(\^\fIn\fR\^);
- .)l
- is added to the appropriate place in the main loop of the interpreter,
- defined in \fIsim/main.c\fR.
- .ds f. sec5.t
- .sh 1 "The Compiler"
- .lp
- The compiler translates Prolog source files into byte-code object files. It is written
- entirely in Prolog. The byte code for the compiler can be found in the
- SB-Prolog system directory \fIcmplib\fR, with the source code resident in
- \fIcmplib/src\fR.
- .pp
- Byte code files may be concatenated together to produce other byte code files. Thus,
- for example, if \fIfoo1\fR and \fIfoo2\fR are byte code files resulting
- from the compilation of two Prolog source programs, then the file \fIfoo\fR,
- obtained by executing the shell command
- .(l
- cat foo1 foo2 > foo
- .)l
- is a byte code file as well, and may be loaded and executed. In this case,
- loading and executing the file \fIfoo\fR would give the same result as
- loading \fIfoo1\fR and \fIfoo2\fR separately, which in turn would be the same as
- concatenating the original source files and compiling this larger file. This
- makes it easier to compile large programs: one need only break them into smaller
- pieces, compile the individual pieces, and concatenate the byte files together.
- .pp
- The following sections describe the various aspects of
- the compiler in more detail.
- .sh 2 "Invoking the Compiler"
- .lp
- The compiler is invoked through the Prolog predicate \fIcompile\fR:
- .(l
- | ?- compile(\fIInFile\fR [, \fIOutFile\fR ] [, \fIOptionsList\fR ]).
- .)l
- where optional parameters are enclosed in brackets.
- \fIInFile\fR is the name of the input (i.e. source) file; \fIOutFile\fR is the
- name of the output file (i.e. byte code) file; \fIOptionsList\fR is a list of compiler options (see
- below).
- .pp
- The input and output file names must be Prolog atoms, i.e. either
- begin with a lower case letter or dollar sign `$', and consist only of letters, digits,
- and underscores; or, be enclosed within single quotes.
- If the output file name is not specified, it defaults to
- \fIInFile\fB.out\fR. The list of options, if specified, is
- a Prolog list, i.e. a term of the form
- .(l
- [ \fIoption\fR\*<1\*>, \fIoption\fR\*<2\*>, ..., \fIoption\*<n\*>\fR ].
- .)l
- If left unspecified, it defaults to the empty list [\^].
- .pp
- In fact, the output file name and the options list may be specified in any order. Thus,
- for example, the queries
- .(l
- | ?- compile('/usr/debray/foo', foo_\|out, [v]).
- and
- | ?- compile('/usr/debray/foo', [v], foo_\|out).
- .)l
- are equivalent, and specify that the Prolog source file
- `\fI/usr/debray/foo\fR' is to be compiled in verbose mode (see ``Compiler
- Options'' below), and that the byte code is to be generated into the file
- \fIfoo_out\fR.
- .pp
- The \fIcompile\fR predicate may also be called with a fourth parameter:
- .(l
- | ?- compile(\fIInFile\fR, \fIOutFile\fR, \fIOptionsList\fR, \fIPredList\fR).
- .)l
- where \fIInFile\fR, \fIOutFile\fR and \fIOptionsList\fR are as before;
- \fIcompile\fR/4 unifies \fIPredList\fR with a list of terms \fIP\fR/\fIN\fR denoting the
- predicates defined in \fIInFile\fR, where \fIP\fR is a predicate name and \fIN\fR its arity.
- \fIPredList\fR, if specified, is usually given as an uninstantiated
- variable; its principal use is for setting trace points on the predicates in the file (see Section 6),
- e.g. by executing
- .(l
- | ?- compile('/usr/debray/foo', foo_\|out, [v], L), load(foo_\|out), trace(L).
- .)l
- Notice that \fIPredList\fR can only appear in \fIcompile\fR/4.
- .sh 2 "Compiler Options"
- .lp
- The following options are currently recognized by the compiler:
- .ip \fBa\fR
- Specifies that an ``assembler'' file is to be created. The name of the
- assembler file is obtained by appending ``.asl'' to the source file name.
- While the writing out of assembly code slows down the compilation process
- to some extent, it allows the assembler to do a better job of optimizing
- away indirect subroutine linkages (since in this case the assembler has
- assembly code for the entire program to work with at once, not just a single
- predicate). This results in code that is faster and more compact.
- .ip \fBd\fR
- Dumps expanded macros to the user (see Section 10).
- .ip \fBe\fR
- Expand macros (see Section 10).
- .ip \fBt\fR
- If specified, turns off assembler optimizations that eliminate indirect branches through the symbol table in
- favour of direct branches. This is useful in debugging compiled code. It
- is \fInecessary\fR if the extension table feature is to be used.
- .ip \fBv\fR
- If specified, compiles in ``verbose'' mode, which causes messages regarding progress
- of compilation to be printed out.
- .sh 2 "Assembly"
- .lp
- The SB-Prolog assembler can be invoked by loading the compiler and using the
- predicate \fI$asm\fR/3:
- .(l
- | ?- $asm(\fIInFile\fR, \fIOutFile\fR, \fIOptionsList\fR).
- .)l
- where \fIInFile\fR is a Prolog atom which is the name of a WAM assembly source file (e.g.
- the ``.asl'' file generated when a Prolog program is compiled with the ``a'' option),
- \fIOutFile\fR is an atom which is the name of the intended byte code file, and
- \fIOptionsList\fR is a list of options. The options recognized by the
- assembler are:
- .ip \fBv\fR
- ``Verbose'' mode. Prints out information regarding progress of assembly.
- .ip \fBt\fR
- ``Trace''. If specified, the assembler generates code to force procedure calls
- to branch indirectly via the symbol table, instead of using a direct branch.
- This is useful for tracing compiled code. It is \fInecessary\fR if the extension table
- feature is to be used.
- .lp
- The assembler is intended primarily to support the compiler, so the assembly language
- syntax is quirky in places. The interested reader is advised to look at
- the assembly files resulting from compilation with the ``a'' option for more on SB-Prolog assembler
- syntax.
- .sh 2 "Compiler Directives"
- .sh 3 "Mode Declarations"
- .pp
- The user may declare input and output arguments of predicates
- using mode declarations. These declarations, for an \fIn\fR-ary predicate
- \fIp\fR, are of the form
- .(l
- :\- mode \fIp\fR( \fIMode\fR ).
- .)l
- .(x M
- (D) mode/3
- .)x
- where \fIMode\fR consists of \fIn\fR mode values; or
- .(l
- :\- mode(\fIp\fR, \fIn\fR, \fIModeList\fR\^)
- .)l
- where \fIModeList\fR is a list of mode values of length \fIn\fR. Mode
- values may be the following:
- .lp
- \fBc\fR, \fB++\fR
- .ip
- Indicates that the corresponding argument position is always a ground term
- in any call to the predicate. The argument is therefore an input argument.
- .lp
- \fBnv\fR, \fB+\fR
- .ip
- Indicates that the corresponding argument position is always a nonvariable
- term (i.e. is instantiated) in any call in any call to the predicate.
- The argument is therefore an input argument.
- .lp
- \fBf\fR, \fB\-\fR
- .ip
- Indicates that the corresponding argument position is always an
- uninstantiated variable in any call to the predicate.
- The argument is therefore an output argument.
- .lp
- \fBd\fR, \fB?\fR
- .ip
- Indicates that the corresponding argument may be any term in calls to the
- predicate.
- .sp
- .lp
- For example, a 3-ary predicate \fIp\fR whose first argument is always a
- ground term in a call, whose second argument is always uninstantiated, and
- whose third argument can be any term, may have its mode declared as
- .(l
- :\- mode \fIp\fR(++, \-, d)
- .)l
- or as
- .(l
- :\- mode(p, 3, [c, f, d]).
- .)l
- Currently, mode information is used by the compiler in two ways. First, it
- often allows more compact code to be generated. The second use is in
- guiding program transformations that allow faster code to be generated.
- For example, the predicate
- .(l
- part([], _, [], []).
- part([E|L], M, [E|U1], U2) :\- E =< M, part(L, M, U1, U2).
- part([E|L], M, U1, [E|U2]) :\- E > M, part(L, M, U1, U2).
- .)l
- executes about 30% faster with the mode declaration
- .(l
- :\- mode part(++, ++, \-, \-).
- .)l
- than without.
- .sh 3 "Indexing Directives"
- .lp
- The compiler usually generates an index on the principal functor of the first
- argument of a predicate. The user may direct the compiler to generate an
- index on any other argument by means of an indexing directive. This is of
- the form
- .(l
- :\- index(\fIPred\fR, \fIArity\fR, \fIIndexArg\fR)
- .)l
- .(x I
- (D) index/3
- .)x
- indicating that an index should be created on the \fIIndexArg\fR\*[th.\*]
- argument of the predicate \fIPred\fR/\fIArity\fR. All of the values
- \fIPred\fR, \fIArity\fR and \fIIndexArg\fR should be bound in the directive:
- \fIPred\fR should be an atom, \fIArity\fR a nonnegative integer, and
- \fIIndexArg\fR an integer between 0 and \fIArity\fR. If \fIIndexArg\fR
- is 0, then no index is created for that predicate. As an example, if we
- wished to create an index on the third argument of a 5-ary predicate
- \fIfoo\fR, the compiler directive would be
- .(l
- :\- index(\fIfoo\fR, 5, 3).
- .)l
- An index directive may be placed anywhere in the file containing the
- predicate it refers to.
- .ds f. sec6.t
- .sh 1 "Libraries"
- .lp
- To describe how libraries are currently supported in our system,
- we must describe the \fI_\|$undefined_\|pred\fR/1
- interrupt handler. The system keeps a table of libraries and routines that
- are needed from each. When a predicate is found to be undefined, the table
- is searched to see if it is defined by some library file. If so, that file is
- loaded (if it hasn't been previously loaded) and the association is made
- between the routine name as defined in the library file, and the routine
- name as used by the invoker.
- .pp
- The table of libraries and needed routines is:
- .(l C
- defined_\|mods(\fIModname\fR, [\fIpred\fR\*<1\*>/\fIarity\fR\*<1\*>, ..., \fIpred\*<n\*>\fR/\fIarity\*<n\*>\fR]).
- .)l
- where \fIModname\fR is the name of the library. It exports \fIn\fR
- predicate definitions. The first exported pred is of arity \fIarity\fR\*<\*>1,
- and needs to be invoked by the name of \fIpred\fR\*<1\*>.
- .pp
- The table of libraries that have already been loaded is given by
- .(l
- loaded_\|mods(\fIModname\fR).
- .)l
- A library file is a file of predicate definitions, together with a fact defining a list
- of predicates exported by it; and a set of facts, each of which specifies, for some
- other library file, the predicates imported from that library file. For example, consider
- a library name `\fIp\fR'. It contains a single fact, named \fIp_\|export\fR,
- that is true of the list of predicate/arity's that are exported. E.g.
- .(l
- p_\|export([p1/2, p2/4])
- .)l
- indicates that the module \fIp\fR exports the predicates \fIp1\fR/2 and \fIp2\fR/4.
- For each library \fIm\fR which contains predicates needed by the library \fIp\fR, there
- is a fact for \fIp_use\fR, describing what library is needed and the names of the
- predicates defined there that are needed. For example, if library \fIp\fR needs
- to import predicates \fIip1\fR/2 and \fIip2\fR/3 from library \fIq\fR, there
- would be a fact
- .(l
- p_\|use(q,[ip1/2, ip2/3])
- .)l
- where \fIq\fR is a module that exports two predicates: one 2-ary and one
- 3-ary. This list corresponds to the export list of library \fIq\fR.
- .pp
- The correspondence between the predicates in the export list of an exporting
- library, and those in the import or \fIuse\fR list of a library which imports one or
- more of them, is by position, i.e. the predicate names at the exporting and importing names may be different, and
- the association between names in the two lists is by the position in the list.
- If the importing
- library does not wish to import one or more of the predicates exported by the
- exporting module, it may put an anonymous variable in the corresponding position in
- its \fIuse\fR list. Thus, for example, if library \fIp\fR above had wished to import only
- the predicate \fIip2\fR/3 from library \fIq\fR, the corresponding use fact would
- be
- .(l
- p_\|use(q, [_\|\|, ip2/3]).
- .)l
- .pp
- The initial set of predicates and the libraries from which they are to be
- loaded is set up by an initial call to \fI$prorc\fR/0 (see the SB-Prolog
- system file \fImodlib/src/$prorc.P\fR).
- This predicate makes initial calls to the predicate $define_\|mod which set up
- the tables described above so that the use of standard predicates will cause
- the correct libraries to be loaded in the \fI_\|$undefined_\|pred\fR routine, and the
- correct names to be used.
- .ds f. sec7.t
- .sh 1 "Macros"
- .lp
- SB-Prolog features a facility for the definition and expansion of macros that is fully compatible with
- the runtime system. Its basic mechanism is a simple partial evaluator. It
- is called by both \fIconsult\fR and \fIcompile\fR, so that macro expansion
- occurs independently of whether the code is interpreted or compiled (but not when
- asserted). Moreover, the macro definitions are retained as clauses at runtime, so
- that invocation of macros via \fIcall\fR/1 at runtime (or from asserted clauses)
- does not pose a problem. This means, however, that if the same macro is
- used in many different files, it will be loaded more than once, thus leading to
- wasetd space. This ought to be thought about and fixed.
- .pp
- The source for the macro expander is in the SB-Prolog system file
- \fImodlib/src/$mac.P\fR.
- .sh 2 "Defining Macros"
- .lp
- `Macros', or predicates to be evaluated at compile-time, are defined
- by clauses of the form
- .(l
- Head ::\- Body
- .)l
- where facts have `true' as their body.
- .(x Z
- (P) ::\-/2
- .)x
- The partial evaluator will expand any call to a
- predicate defined by ::\-/2 that
- unifies with the head of only one clause in ::\-/2. If a call unifies with the
- head of more than one clause in ::\-/2, it will not be expanded
- Notice that this is not a
- fundamental restriction, since `;' is permitted in the body of a
- clause. The partial evaluator also converts each definition of the form
- .(l
- Head ::\- Body.
- .)l
- to a clause of the form
- .(l
- Head :\- Body.
- .)l
- and adds this second clause to the other ``normal'' clauses that were read from
- the file. This ensures that calls to the macro at runtime, e.g. through
- \fIcall\fR/1 or from unexpanded calls in the program do not cause any
- problems.
- .pp
- The partial evaluator is actually a Prolog interpreter written
- `purely' in Prolog, i.e., variable assignments are explicitly
- handled. This is necessary to be able to handle impure constructs
- such as `var(X), X=a'. As a result this is a \fIvery slow\fR Prolog
- evaluator.
- .pp
- Since naive partial evaluation can go into an infinite loop, SB-Prolog's
- partial evaluator
- maintains a depth-bound and will not expand recursive calls deeper
- than that. The depth is determined by the globalset predicate
- \fI$mac_\|depth\fR. The default value for \fI$mac_\|depth\fR
- is 50 This can be changed to some other value \fIn\fR by executing
- .(l
- | ?- globalset($mac_\|depth(\fIn\fR)).
- .)l.
- .sh 2 "Macro Expander Options"
- .lp
- The following options are recognized by the macro expander:
- .ip \fBd\fR
- Dumps all clauses to the user after expansion. Useful for debugging.
- .ip \fBe\fR
- Expand macros. If omitted, the expander simply converts each ::\-/2 clause to a normal :\-/2 clause.
- .ip \fBv\fR
- ``Verbose'' mode. Prints macros that are/are not being expanded.
- .ds f. sec8.t
- .sh 1 "Extension Tables: Memo Relations"
- .lp
- Extension tables store the calls and answers for a predicate. If a
- call has been made before, answers are retrieved from the extension
- table instead of being recomputed. Extension tables provide a
- caching mechanism for Prolog. In addition, extension tables affect
- the termination characteristics of recursive programs. Some Prolog
- programs, which are logically correct, enter an infinite loop due
- to recursive predicates. An extension table saved on recursive
- predicates can find all answers (provided the set of such answers is
- finite) and terminate
- for some logic programs for which Prolog's evaluation strategy
- enters an infinite loop. Iterations over the extension table
- execution strategy provides complete evaluation of queries over
- function-free Horn clause programs.
- .pp
- To be able to use the simple extension table evaluation on a set of
- predicates, the source file should either be consulted, or
- compiled with the \fBt\fR option (the \fBt\fR option
- keeps the assembler from optimizing subroutine linkage and allows
- the extension table facility to intercept calls to predicates).
- .pp
- To use extension table execution, all predicates that are to be
- saved in the extension table must be passed to \fIet\fR/1. For example,
- .(l
- | ?\- et([pred1/1, pred2/2]), et(pred3/2)
- .)l
- will set up ``ET-points'' for the for predicates \fIpred1\fR/1, \fIpred2\fR/2 and
- \fIpred3\fR/2, which will cause extension tables for these predicates to be
- maintained during execution. At the time of the call to \fIet\fR/1, these predicates
- must be defined, either by having been loaded, or through \fIconsult\fR.
- .pp
- The predicate \fInoet\fR/1 takes a list of predicate/arity pairs for
- which ET-points should be deleted. Notice that
- once an ET-point has been set up for a predicate, it will be maintained
- unless explicitly deleted via \fInoet\fR/1.
- If the definition of a predicate which has an ET-point defined is to be updated,
- the ET-point must first be deleted via \fInoet\fR/1.
- The predicate can then be reloaded and a new ET-point established.
- This is enforced by the failure of the goal ``et(P/N)'' if an
- ET-point already exists for the argument predicate. In this case,
- the following error message will be displayed:
- .(l
- *et* already defined for: P/N
- .)l
- .pp
- There are, in fact, two extension table algorithms: a simple one, which
- simply caches calls to predicates which have ET-points defined; and a
- complete ET algorithm, which iterates the simple extension table algorithm until
- no more answers can be found. The simple algorithm is more efficient than the
- complete one; however, the simple algorithm is not complete for certain
- especially nasty forms of mutual recursion, while the complete
- algorithm is. To use the simple extension table algorithm,
- predicates can simply be called as usual.
- The complete extension table algorithm may be used via the query
- .(l
- | ?\- et_\|star(Query).
- .)l
- .lp
- The extension table algorithm is intended for predicates that are ``essentially
- pure'', and results are not guaranteed for code using impure code.
- The extension table algorithm saves only those answers which are
- not instances of what is already in the
- table, and uses these answers if the current call is an instance of a call
- already made. For example, if a call \fIp\fR(\fIX\fR, \fIY\fR\^), with
- \fIX\fR and \fIY\fR uninstantiated, is encountered and inserted into the
- extension table, then a subsequent call \fIp\fR(\fIX\fR, \fIb\fR) will be
- computed using the answers for \fIp\fR(\fIX\fR, \fIY\fR\^) already in the
- extension table. Notice that this might not work
- if var/nonvar tests are used on the second argument
- in the evaluation of \fIp\fR.
- .pp
- Another problem with using impure code is that if an ET predicate is cut
- over, then the saved call implies that all answers for that predicate were
- computed,
- but there are only partial results in the ET because of the cut.
- So on a subsequent call the incomplete extension table answers are used
- when all answers are expected.
- .(l
- Example:
- r(X,Y) :\- p(X,Y),q(Y,Z),!,fail.
- | ?\- r(X,Y) ; p(X,Y).
- .)l
- .lp
- Let p be an ET predicate whose evaluation yields many tuples.
- In the evaluation of the query, r(X,Y) makes a call to p(X,Y).
- Assuming that there is a tuple such that q(Y,Z) succeeds with the
- first p tuple then the evaluation of p is cut over. The call to p(X,Y)
- in the query uses the extension table because of the previous call
- in the evaluation of r(X,Y). Only one answer is found, whereas the
- relation p contains many tuples, so the computation is not complete.
- Note that "cuts" used within the evaluation of an ET predicate are ok,
- as long as they don't cut over the evaluation of another ET predicate.
- The evaluation of the predicate that uses cuts does not cut over any et
- processing (such as storing or retrieving answers) so that the tuples that
- are computed are saved. In the following example, the ET is used to generate
- prime numbers where an ET point is put on prime/1.
- .(l
- Example:
-
- prime(I) :\- globalset(globalgenint(2)),fail. /* Generating Primes */
- prime(I) :\- genint(I), not(div(I)).
- div(I) :\- prime(X), 0 is I mod X.
-
- genint(N) :\-
- repeat,
- globalgenint(N),
- N1 is N+1,
- globalset(globalgenint(N1)).
- .)l
- .lp
- The following summarizes the library predicates supporting the extension
- table facility:
- .sp
- .lp
- \fBet\fR(\fIL\fR)
- .ip
- Sets up an ET-point on the predicates \fIL\fR, which causes calls and
- anwers to these predicates to be saved in an ``extension table''.
- .(x E
- (L) et/1
- .)x
- \fIL\fR is either a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is a predicate
- symbol and \fIArity\fR its arity, or a set of such terms represented as a list.
- \fIL\fR must be
- instantiated, and the predicates specified in it defined, at the time of
- the call to \fIet\fR/1. Gives error messages and fails if any of
- the predicates in \fIL\fR is undefined, or if an ET-point
- already exists on any of them; in this case, no ET-point
- is set up on any of the predicates in \fIL\fR.
- .lp
- \fBet_\|\fBstar\fR(Goal\fR\^)
- .ip
- Invokes the complete extension table algorithm on the goal \fIGoal\fR.
- .(x E
- (L) et_\|star/1
- .)x
- .lp
- \fBet_\^points\fR(\fIL\fR)
- .ip
- Unifies \fIL\fR with a list of predicates for which an ET-point is
- defined. \fIL\fR is the empty list [] if there are no ET-points defined.
- .(x E
- (L) et_\^points/1
- .)x
- .lp
- \fBnoet\fR(\fIL\fR)
- .ip
- Deletes ET-points on the predicates specified in \fIL\fR.
- .(x N
- (L) noet/1
- .)x
- \fIL\fR is either a term \fIP\fR/\fIN\fR, where \fIP\fR is the name of a
- predicate and \fIN\fR its arity, or a set of such terms represented as a
- list. Gives error messages and
- fails if there is no ET-point on any of the predicates specified in
- \fIL\fR. Deleting an ET-point for a predicate also removes the calls and
- answers stored in the extension table for that predicate. The extension
- tables for all predicates for which ET-points are defined may be deleted
- using \fIet_\^points\fR/1 in cojnunction with \fInoet\fR/1.
-
- \fIL\fR must be instantiated at the time of the call to \fInoet\fR/1.
- .lp
- \fBet_\|remove(\fIL\^)
- .ip
- Removes both calls and answers for the predicates specified in \fIL\fR. In
- effect, this results in the extension table for these predicates to be set
- to empty. \fIL\fR must be instantiated at the time of the call to
- either a term \fIP\fR/\fIN\fR, where \fIP\fR is a
- predicate with arity \fIN\fR, or a list of such terms. An error occurs if
- any of the predicates in \fIL\fR does not have an ET-point set.
-
- All extension tables can be emptied by using \fIet_\^points\fR/1 in
- conjunction with \fIet_\^remove\fR/1.
- .(x E
- (L) et_\|remove/1
- .)x
- .lp
- \fBet_\|answers\fR\^(\fIP\fR/\fIN\fR, \fITerm\fR\^)
- .ip
- Retrieves the answers stored in the extension table for the predicate \fIP\fR/\fIN\fR
- in \fITerm\fR one at a time. \fITerm\fR is of the form
- \fIP\fR(\fIt\fR\*<1\*>, ..., \fIt\*<N\*>\fR). An error results and
- \fIet_\^answers\fR/2 fails if \fIP\fR/\fIN\fR is not fully specified (ground),
- or if \fIP\fR/\fIN\fR does not have an ET-point set.
- .lp
- \fBet_\|calls\fR(\fIP/N\fR, \fITerm\fR\^)
- .ip
- Retrieves the calls stored in the extension table for the predicate \fIP/N\fR
- in \fITerm\fR one at a time. \fITerm\fR is of the form
- \fIP\fR(\fIt\fR\*<1\*>, ..., \fIt\*<N\*>\fR). An error results and
- \fIet_\^calls\fR/2 fails if \fIP\fR/\fIN\fR is not fully specified (ground),
- or if \fIP\fR/\fIN\fR does not have an ET-point set.
- .(x E
- (L) et_\|calls/2
- .)x
- .lp
- .sh 1 "Definite Clause Grammars"
- .lp
- Definite clause grammars are an extension of context free grammars, and may
- be conveniently expressed in Prolog. A grammar rule in Prolog has the form
- .(l
- \fIHead\fR \-\^\-> \fIBody\fR.
- .)l
- with the interpretation ``a possible form for \fIHead\fR is \fIBody\fR''.
- Extra conditions, in the form of explicit Prolog literals or control
- constructs such as \fIif-then-else\fR (`\->') or \fIcut\fR (`!'), may be
- included in \fIBody\fR.
- .pp
- The syntax of DCGs supported by SB-Prolog is as follows:
- .np
- A non-terminal symbol may be any Prolog term other than a variable.
- .np
- A terminal symbol may be any Prolog term. To distinguish terminals from
- nonterminals, a sequence of terminal symbols
- .(l
- \fIa\fR, \fIb\fR, \fIc\fR, \fId\fR, . . .
- .)l
- is written as a Prolog list [\fIa\fR, \fIb\fR, \fIc\fR, \fId\fR, . . . ],
- with the empty sequence written as the empty list []. If the terminal
- symbols are ASCII character codes, they can be written (as elsewhere) as
- strings.
- .np
- Extra consitions, in the form of Prolog literals, can be included in
- the right-hand side of a rule by enclosing such conditions in curly
- braces, \fB{\fR and \fB}\fR. E.g., one can write
- .(l
- natnum(X) \-\^\-> {integer(X), X >= 0}.
- .)l
- .np
- The left hand side of a rule consists of a single nonterminal. Notice that
- ``push-back lists'' are thus not supported.
- .np
- The right hand side of a rule may contain alternatives (written using the
- disjunction operator `\fB;\fR' or `|'), and control primitives such as
- if-then-else (`\->'), \fInot\fR/1 and \fIcut\fR (`!'). The use of
- \fInot\fR/1 on the right hand side of grammar rules is not recommended,
- however, because their semantics in this context is murky at best. All
- other control primitives, e.g. \fIrepeat\fR/0, must explicitly be enclosed
- within curly braces if they are not to be interpreted as nonterminals.
- .pp
- Except for the restriction of lists of terminals in the left hand sides of
- rules, the translation of DCGs in SB-Prolog is very similar to that in
- Quintus Prolog.
- .sp
- .lp
- Library predicates supporting DCGs are the following:
- .sp
- \fBdcg\fR(\fIRule\fR, \fIClause\fR\^)
- .(x D
- (L) dcg/2
- .)x
- .ip
- Succeeds if the DCG rule \fIRule\fR corresponds to the Prolog clause
- \fIClause\fR. At the time of call, \fIRule\fR must be bound to a term
- whose principal functor is `\-\->'/2.
- .lp
- \fBphrase\fR(\fIPhrase\fR, \fIList\fR\^)
- .(x P
- (L) phrase/2
- .)x
- .ip
- The usual way to commence execution of grammar rules. The list \fIList\fR
- is a phrase (i.e., sequence of terminals) generated by \fIPhrase\fR
- according to the current grammar rules. \fIPhrase\fR is a nonterminal (in
- general, the right hand side of a grammar rule), and must be instantiated
- to a nonvariable term in the call. If \fIList\fR is bound to a list of
- terminals in the call, then the goal corresponds to parsing \fIList\fR; if
- \fIList\fR is unbound in the call, then the grammar is being used for
- generation.
- .lp
- \fBexpand_\|term\fR(\fIT1\fR, \fIT2\fR\^)
- .(x E
- (L) expand_\|term/2
- .)x
- .ip
- This predicate is used to transform terms that are read in, when a file is
- consulted or compiled. The usual use is to transform grammar rules into
- Prolog clauses: if \fIT1\fR is a grammar rule, then \fIT2\fR is the
- corresponding Prolog clause. Users may define their own transformations by
- defining the predicate \fIterm_\|expansion\fR/2.
- When a term \fIT1\fR is read in when a file is being compiled or consulted,
- \fIexpand_\|term\fR/2 first calls \fIterm_\|expansion\fR/2: if the
- expansion succeeds, the transformed term so obtained is used; otherwise, if
- \fIT1\fR is a grammar rule, then it is expanded using \fIdcg\fR/2; otherwise,
- \fIT1\fR is used as is.
- .(x T
- (U) term_\|expansion/2
- .)x
- .lp
- `\fBC\fR'(\fIS1\fR, \fITerminal\fR, \fIS2\fR\^)
- .(x C
- (L) `C'/3
- .)x
- .ip
- Used to handle terminal symbols in the expansion of grammar rules. Not
- usually of direct use to the user. This is defined as
- .(l
- `C'([X|S], X, S).
- .)l
- .sh 1 "Profiling Programs"
- .lp
- There is an experimental utility for profiling programs interactively. Two kinds of
- profiling are supported: one may count the number of calls to a predicate,
- or compute the time spent in a predicate. It is important that the
- predicates being profiled are either consulted, or compiled with the \fBt\fR
- option, so that calls to the relevant predicates can be intercepted by the
- profiler.
- .pp
- To use the profiler, predicates whose calls are to be counted must be
- passed to \fIcount\fR/1, e.g.
- .(l
- | ?\- count([\fIp\fR/1, \fIq\fR/2]), count(\fIr\fR/3).
- .)l
- will set up ``count-points'' on the predicates \fIp\fR/1, \fIq\fR/2 and
- \fIr\fR/3. Predicates whose calls are to be timed have to be passed to
- \fItime\fR/1, e.g.
- .(l
- | ?\- time([\fIs\fR/1, \fIt\fR/2]), time(\fIu\fR/3).
- .)l
- will set up ``time-points'' on the predicates \fIs\fR/1, \fIt\fR/2 and
- \fIu\fR/3. It is possible to set both count-points and time-points on the
- same predicate. After count-points and time-points have been set, the
- program may be executed as many times as desired: the profiling system will
- accumulate call counts and execution times for the appropriate predicates.
- Execution profiles may be obtained using the
- predicates \fIprof_\|stats\fR/0 or \fIprof_\|stats\fR/1. Using
- \fIprof_\|stats\fR/0 to display the execution profile will cause the call
- counts and execution times of predicates being profiled to be reset to 0
- (this may be avoided by using \fIprof_\|stats\fR/1).
- .pp
- It should be noted that in this context, the ``execution time'' for a predicate
- is an estimate of the total time spent in the subtrees below calls to that
- predicate (including failed subtrees): thus, the execution time figures may
- be dilated slightly if the subtree below a timed predicate contains
- predicates that are being profiled, because of the time taken for updating
- the call counts and execution times. For each predicate, the execution
- time is displayed as the fraction of time spent, in computation in subtrees
- under calls to that predicate, relative to the time elapsed from the last
- time profiling was timed on or the last time profiling statistics were
- taken, whichever was more recent.
- .lp
- \fBBugs\fR: May behave bizarrely if a predicate being profiled contains cuts.
- .pp
- The following summarizes the library predicates supporting
- profiling:
- .sp
- .lp
- \fBcount\fR(\fIL\fR)
- .(x C
- (L) count/1
- .)x
- .ip
- Sets up a count-point on the predicates \fIL\fR, which causes calls to
- these predicates to be counted, and turns profiling on. \fIL\fR is either
- a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is a predicate
- symbol and \fIArity\fR its arity, or a set of such terms represented as a list.
- \fIL\fR must be instantiated, and the predicates specified in it defined, at
- the time of the call to \fIcount\fR/1.
- .lp
- \fBtime\fR(\fIL\fR)
- .(x T
- (L) time/1
- .)x
- .ip
- Sets up a time-point on the predicates \fIL\fR, which causes execution times
- for calls to these predicates to be accumulated, and turns profiling on.
- \fIL\fR is either a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is a predicate
- symbol and \fIArity\fR its arity, or a set of such terms represented as a list.
- \fIL\fR must be instantiated, and the predicates specified in it defined, at
- the time of the call to \fItime\fR/1.
- .lp
- .lp
- \fBnocount\fR(\fIL\fR)
- .(x N
- (L) nocount/1
- .)x
- .ip
- Deletes the count-point on the predicates \fIL\fR. \fIL\fR is either a term
- \fIPred\fR/\fIArity\fR, where \fIPred\fR is a predicate
- symbol and \fIArity\fR its arity, or a set of such terms represented as a list.
- \fIL\fR must be instantiated, and the predicates specified in it defined, at
- the time of the call to \fInocount\fR/1.
- .lp
- \fBnotime\fR(\fIL\fR)
- .(x N
- (L) notime/1
- .)x
- .ip
- Deletes the time-point on the predicates \fIL\fR. \fIL\fR is either a term
- \fIPred\fR/\fIArity\fR, where \fIPred\fR is a predicate
- symbol and \fIArity\fR its arity, or a set of such terms represented as a list.
- \fIL\fR must be instantiated, and the predicates specified in it defined, at
- the time of the call to \fItime\fR/1.
- .lp
- \fBprofiling\fR
- .(x P
- (L) profiling/0
- .)x
- .ip
- Displays information about whether profile mode is on or not, and lists
- predicates that have count- and time-points set on them.
- .lp
- \fBprof_\|reset\fR(\fIL\fR)
- .(x P
- (L) prof_\|reset/1
- .)x
- .ip
- Resets call counts and/or execution times for the predicates \fIL\fR.
- \fIL\fR is either a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is
- a predicate symbol and \fIArity\fR its arity, or a set of such terms
- represented as a list. \fIL\fR must be instantiated, and the predicates
- specified in it defined, at the time of the call to \fIprof_\|reset\fR/1.
- .lp
- \fBresetcount\fR(\fIL\fR)
- .(x R
- (L) resetcount/1
- .)x
- .ip
- Resets call counts for the predicates \fIL\fR.
- \fIL\fR is either a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is
- a predicate symbol and \fIArity\fR its arity, or a set of such terms
- represented as a list. \fIL\fR must be instantiated, and the predicates
- specified in it defined, at the time of the call to \fIresetcount\fR/1.
- .lp
- \fBresettime\fR(\fIL\fR)
- .(x R
- (L) resettime/1
- .)x
- .ip
- Resets execution times for the predicates \fIL\fR.
- \fIL\fR is either a term \fIPred\fR/\fIArity\fR, where \fIPred\fR is
- a predicate symbol and \fIArity\fR its arity, or a set of such terms
- represented as a list. \fIL\fR must be instantiated, and the predicates
- specified in it defined, at the time of the call to \fBresettime\fR/1.
- .lp
- \fBprofile\fR
- .(x P
- (L) profile/0
- .)x
- .ip
- Turns profiling on. This causes subsequent execution of predicates with
- count- or time-points to be profiled, and is a no-op if there are no such
- predicates. The predicates \fIcount\fR/1 and \fItime\fR/1 cause profiling
- to be turned on automatically.
- .lp
- \fBnoprofile\fR
- .(x N
- (L) noprofile/0
- .)x
- .ip
- Turns profiling off. This causes count- and time-points to be ignored.
- .lp
- \fBtimepreds\fR(\fIL\fR)
- .(x T
- (L) timepreds/1
- .)x
- .ip
- Unifies \fIL\fR to a list of terms \fIP\fR/\fIN\fR where the predicate
- \fIP\fR of arity \fIN\fR has a time point set on it.
- .lp
- \fBcountpreds\fR(\fIL\fR)
- .(x C
- (L) countpreds/1
- .)x
- .ip
- Unifies \fIL\fR to a list of terms \fIP\fR/\fIN\fR where the predicate
- \fIP\fR of arity \fIN\fR has a count point set on it.
- .lp
- \fBprof_\|stats\fR
- .(x P
- (L) prof_\|stats/0
- .)x
- .ip
- Causes the call counts and/or execution times accumulated since the last
- call to \fIprof_\|stats\fR/0 to be printed out for predicates that are
- being profiled. The execution times are given as fractions of the total
- time elapsed since the last time profiling was turned on, or the last time
- \fIprof_\|stats\fR was called, whichever was most recent. This also
- results in the call counts and relative execution times of these predicates
- being reset to 0. Equivalent to \fIprof_\|stats\fR(1).
- .lp
- \fBprof_\|stats\fR(\fIN\fR\^)
- .(x P
- (L) prof_\|stats/1
- .)x
- .ip
- Causes the call counts and/or execution times accumulated since the last
- call to \fIprof_\|stats\fR/0 to be printed out for predicates that are
- being profiled. The execution times are given as fractions of the total
- time elapsed since the last time profiling was turned on, or the last time
- \fIprof_\|stats\fR was called, whichever was most recent. If \fIN\fR is
- 1, then this also results in the call counts and execution times of these
- predicates being reset to 0; otherwise, the call counts and execution times
- are not reset.
- .lp
- .ds f. sec9.t
- .sh 1 "Other Library Utilities"
- .lp
- The SB-Prolog library contains various other utilities, some of which are
- listed below.
- .lp
- \fBappend\fR(\fIX\fR, \fIY\fR, \fIZ\fR)
- .ip
- Succeeds if list \fIZ\fR is the concatenation of lists \fIX\fR and \fIY\fR.
- .(x A
- (L) append/3
- .)x
- .lp
- \fBmember\fR(\fIX\fR, \fIL\fR)
- .ip
- Checks whether \fIX\fR unifies with any element of list \fIL\fR, succeeding more than
- once if there are multiple such elements.
- .(x M
- (L) member/2
- .)x
- .lp
- \fB$memberchk\fR(\fIX\fR, \fIL\fR)
- .ip
- Similar to \fImember\fR/2, except that $\fImemberchk\fR/2 is
- deterministic, i.e. does not succeed more than once for any call.
- .lp
- \fB$reverse\fR(\fIL\fR, \fIR\fR)
- .ip
- Succeeds if \fIR\fR is the reverse of list \fIL\fR. If \fIL\fR is not a
- fully determined list, i.e. if the tail of \fIL\fR is a variable, this
- predicate can succeed arbitrarily many times.
- .(x Z
- (L) $reverse/2
- .)x
- .lp
- \fB$merge\fR(\fIX\fR, \fIY\fR, \fIZ\fR\^)
- .ip
- Succeeds if \fIZ\fR is the list resulting from ``merging'' lists
- \fIX\fR and \fIY\fR, i.e. the elements of \fIX\fR together with any
- element of \fIY\fR not occurring in \fIX\fR. If \fIX\fR or \fIY\fR contain
- duplicates, \fIZ\fR may also contain duplicates.
- .(x Z
- (L) $merge/3
- .)x
- .lp
- \fB$absmember\fR(\fIX\fR, \fIL\fR\^)
- .ip
- Similar to \fI$member\fR/2, except that it checks for identity (through ==/2)
- rather than unifiability (through =/2) of \fIX\fR with elements of \fIL\fR.
- .(x Z
- (L) $absmember/2
- .)x
- .lp
- \fB$nthmember\fR(\fIX\fR, \fIL\fR, \fIN\fR)
- .ip
- Succeeds if the \fIN\fR\*[th.\*] element of the list \fIL\fR unifies with
- \fIX\fR. Fails if \fIN\fR is greater than the length of \fIL\fR. Either
- \fIX\fR and \fIL\fR, or \fIL\fR and \fIN\fR, should be instantiated at the
- time of the call.
- .(x Z
- (L) $nthmember/3
- .)x
- .lp
- \fB$member2\fR(\fIX\fR, \fIL\fR)
- .ip
- Checks whether \fIX\fR unifies with any of the actual elements of \fIL\fR.
- The only difference between this and \fI$member\fR/2 is on lists with
- a variable tail, e.g. [a, b, c | _ ]: while \fI$member\fR/2 would insert
- \fIX\fR at the end of such a list if it did not find it, \fI$member2\fR/2
- only checks for membership but does not insert it into the list if it is
- not there.
- .lp
- \fBlength\fR(\fIL\fR, \fIN\fR\^)
- .(x L
- (L) length/2
- .)x
- .ip
- Succeeds if the length of the list \fIL\fR is \fIN\fR. This predicate is
- deterministic if \fIL\fR is instantiated to a list of definite length, but
- is nondeterministic if \fIL\fR is a variable or has a variable tail.
- .lp
- \fBsubsumes\fR(\fIX\fR, \fIY\fR\^)
- .(x S
- (L) subsumes/2
- .)x
- .ip
- Succeeds if the term \fIX\fR subsumes the term \fIY\fR (i.e. if \fIY\fR is
- an instance of \fIX\fR).
- .bp
- .lp
- .ce
- \fBCREDITS\fR
- .sp
- .lp
- .(x c
- Credits
- .)x
- The initial development of SB-Prolog, from 1984 to August 1986, was at
- SUNY at Stony Brook, where Versions 1.0 and 2.0 were developed. Since August
- 1986, its development has continued at the University of Arizona, Tucson.
- .pp
- A large number of people were involved, at some time or another, with the
- Logic Programming group at SUNY, Stony Brook, and deserve credit for
- helping to bring SB-Prolog to its present form. David Scott Warren
- led the project at Stony Brook. Most of the simulator and builtins were
- written by Jiyang Xu and David S. Warren (I added the later stuff, Versions
- 2.1 onwards).
- Much of the library was also by David, with some contributions from me.
- Weidong Chen did the work on clause indexing. Suzanne Dietrich
- wrote the Extension Table package. I wrote most of the compiler.
- .pp
- Several people helped debug previous versions, including Leslie Rohde;
- Bob Beck of Sequent Computers; and Mark Gooley of the University of
- Illinois at Urbana-Champaign.
- .pp
- Special thanks are due to Richard O'Keefe, who contributed the Prolog code for
- the parser (in the form of the predicates \fBread\fR/1 and \fBread\fR/2),
- the C code for the tokenizer, and the code for \fBsetof\fR/3 and
- \fBbagof\fR/3.
- .pp
- I am grateful to Fernando Pereira for permission to use material from the
- C-Prolog manual for the descriptions of Prolog syntax and many of the
- builtins in this User Manual.
- .in 5i
- \- S.K.D.
- .in 0
- .bp
- .uh "Appendix 1: Evaluable Predicates of SB-Prolog"
- .sp
- .pp
- An entry of ``B'' indicates a builtin predicate, ``I'' an inline predicate,
- and ``L'' a library predicate. A ``P'' indicates that the predicate is
- handled by the preprocessor during compilation and/or consulting. A ``D''
- denotes a compiler directive.
- .sp
- .2c
- .lp
- .xp Z
-
- .xp A
-
- .xp B
-
- .xp C
-
- .xp D
-
- .xp E
-
- .xp F
-
- .xp G
-
- .xp I
-
- .xp K
-
- .xp L
-
- .xp M
-
- .xp N
-
- .xp O
-
- .xp P
-
- .xp R
-
- .xp S
-
- .xp T
-
- .xp U
-
- .xp V
-
- .xp W
- .1c
- .lp
- .bp
- .lp
- .uh "Appendix 2: A Note on Coding for Efficiency"
- .pp
- The SB-Prolog system tends to favour programs that are relatively pure. Thus, for
- example, \fIassert\fRs tend to be quite expensive, encouraging the user to avoid them
- if possible. This section points out some syntactic constructs that lead to the generation
- of efficient code. These involve (\fIi\fR\^) avoiding the creation of backtrack points; and (\fIii\fR\^)
- minimizing data movement between registers.
- Optimization of logic programs is an area of ongoing research,
- and we expect to enhance the capabilities of the system further in future
- versions.
- .sh 1 "Avoiding Creation of Backtrack Points" 1
- .lp
- Since the creation of backtrack points is relatively expensive, program efficiency may
- be improved substantially by using constructs that avoid the creation of backtrack points where possible.
- The SB-Prolog compiler recognizes conditionals involving certain
- complementary inline tests, and generates code that does not create
- choice points for such cases.
- Two inline tests \fIp\fR(\fIt\fR\*<1\*>, . . ., \fIt\*<n\*>\fR) and
- \fIq\fR(\fIt\fR\*<1\*>, . . ., \fIt\*<n\*>\fR) are \fIcomplementary\fR
- if and only if \fIp\fR(\fIt\fR\*<1\*>, . . ., \fIt\*<n\*>\fR) \(==
- \fInot\fR(\fIq\fR(\fIt\fR\*<1\*>, . . ., \fIt\*<n\*>\fR)).
- For example, the literals `\fIX\fR > \fIY\fR\^' and `\fIX\fR =< \fIY\fR\^'
- are complementary. At this point, complementary tests are recognized as such only
- if their argument tuples are identical. The inline predicates that are
- treated in this manner, with their corresponding complementary literals,
- are shown in Table 3.
- .(z
- .sp
- .TS
- allbox center tab(%);
- ce ce
- le le.
- \fIInline Test%Complementary Test\fR
- >/2%=</2
- =</2%>/2
- >=/2%</2
- </2%>=/2
- =:=/2%=\e=/2
- =\e=/2%=:=/2
- ?=/2%\e=/2
- \e=/2%?=/2
- var/1%nonvar/1
- nonvar/1%var/1
- .TE
- .sp
- .ce
- Table 3: Complementary tests recognized by the compiler
- .sp
- .)z
- The syntactic constructs recognized are:
- .ip (\fIi\fR\^)
- Disjuncts of the form
- .(l
- \fIhead\fR( . . . ) :\- (( \fI\fItest\fR(t\fR\*<1\*>, . . ., \fIt\*<n\*>\fR), . . . ) ; (( not(\fItest\fR(\fIt\fR\*<1\*>. . . ., \fIt\*<n\*>\fR), . . .)).
- .)l
- or
- .(l
- \fIhead\fR( . . . ) :\- (( \fI\fItest\fR(t\fR\*<1\*>, . . ., \fIt\*<n\*>\fR), . . . ) ; (( \fIcomp_\|test\fR(\fIt\fR\*<1\*>. . . ., \fIt\*<n\*>\fR), . . .)).
- .)l
- where \fItest\fR is one of the inline tests in the table above, and
- \fIcomp_\|test\fR the corresponding complementary test (note that the
- arguments to \fItest\fR and \fIcomp_\|test\fR have to be identical).
- .ip (\fIii\fR\^)
- Conditionals of the form
- .(l
- \fIhead\fR :\- (\fItest\fR\*<1\*>\fB,\fR ... \fB,\fR \fItest\*<n\*>\fR) \-> \fITrue_\|Case\fR ; \fIFalse_\|Case\fR.
- .)l
- or
- .(l
- \fIhead\fR :\- (\fItest\fR\*<1\*>\fB;\fR ... \fB;\fR \fItest\*<n\*>\fR) \-> \fITrue_\|Case\fR ; \fIFalse_\|Case\fR.
- .)l
- where each \fItest\*<i\*>\fR is an inline test, as mentioned in the table
- above.
- .pp
- The code generated for these cases involves a test and conditional branch, and no
- choice point is created. We expect future versions of the translator to
- recognize a wider class of complementary tests.
- .pp
- Notice that this discourages the use of explicit cuts. For example,
- whereas a choice point will be created for
- .(l
- part(M,[E|L],U1,U2) :\-
- ((E =< M, !, U1 = [E|U1a], U2 = U2a) ;
- (U1 = U1a, U2 = [E|U2a])),
- part(M,L,U1a,U2a).
- .)l
- no choice point will be created for either
- .(l
- part(M,[E|L],U1,U2) :\-
- (E =< M \->
- (U1 = [E|U1a], U2 = U2a) ;
- (U1 = U1a, U2 = [E|U2a])),
- part(M,L,U1a,U2a).
- .)l
- or
- .(l
- part(M,[E|L],U1,U2) :\-
- ((E =< M, U1 = [E|U1a], U2 = U2a) ;
- (E > M, U1 = U1a, U2 = [E|U2a])),
- part(M,L,U1a,U2a).
- .)l
- Thus, either of the two later versions will be more efficient than the version
- with the explicit cut (this is a design decision we have consciously made, in
- the hope of discouraging blatantly non-declarative code where efficient
- declarative code can be written).
- .sh 1 "Minimizing Data Movement Between Registers" 2
- .lp
- Data movement between registers for parameter passing may be minimized by leaving variables in
- the same argument position wherever possible. Thus, the clause
- .(l
- p(X,Y) :\- p1(X,Y,0).
- .)l
- is preferable to
- .(l
- p(X,Y) :\- p1(0,X,Y).
- .)l
- because the first definition leaves the variables \fIX\fR and \fIY\fR
- in the same argument positions (first and second, respectively), while the second definition does
- not.
- .sh 1 "Processing All Arguments of a Term"
- .lp
- It is often the case that we wish to process each of the arguments of a
- term in turn. For example, to decide whether a compound term is ground,
- we have to check that each of its arguments is ground.
- One possibility is to create a list of those arguments, and
- traverse the list processing each element. Using this approach, a
- predicate to check for groundness would be
- .(l
- ground(T) :\- atomic(T).
- ground(T) :\- structure(T), T =.. [_ | Args], groundargs(Args).
- groundargs([]).
- groundargs([A | ARest]) :\- ground(A), groundargs(ARest).
- .)l
- This is not the most efficient way to process all the arguments of a term,
- because it involves the creation of intermediate lists, which is expensive
- both in space and time. A much better alternative is to use \fIarg\fR/3
- to index into the term and retrieve arguments. Using this approach, the
- \fIground\fR\^/1 predicate above would be written as
- .(l
- ground(T) :\- atomic(T).
- ground(T) :\- structure(T), functor(T, P, N), groundargs(1, N, T).
- groundargs(M, N, T) :\-
- M =< N \->
- (arg(M, T, A), ground(A), M1 is M + 1, groundargs(M1, N, T)) ;
- true.
- .)l
- The second approach is likely to be more efficient than the first in
- SB-Prolog.
- .pp
- If the arguments of the term do not need to be processed in ascending
- order, then it is more efficient to process them in descending order using
- \fIarg\fR/3 to access them. For example, the predicate for groundness
- checking could be written as
- .(l
- ground(T) :\- atomic(T).
- ground(T) :\- structure(T), functor(T, P, N), groundargs(N, T).
- groundargs(M, T) :\-
- M =:= 0 \->
- true ;
- (arg(M, T, A), ground(A), M1 is M \- 1, groundargs(M1, T)).
- .)l
- This is even more efficient than the earlier version, because (\fIi\fR\^)
- \fIgroundargs\fR needs to have one less parameter to be passed to it at
- each iteration; and (\fIii\fR\^) testing ``M =:= 0'' is simpler and more
- efficient than checking ``M =< N'', and takes fewer machine instructions.
- .sh 1 "Testing Unifiability"
- .lp
- Often, it is necessary to check whether or not a term has a particular value.
- If we know that the term will be bound to a number, we can use the
- evaluable predicates =:=/2 or =\e=/2, as explained earlier. For other
- values, it may often be cheaper, in the appropriate circumstances, to use
- the predicates ?=/2 or \e=/2. For example, consider a predicate \fIp\fR/2
- that calls \fIq\fR/1 with its second argument if its first argument unifies
- with \fIa\fR, and \fIr\fR/1 otherwise. A naive definition might be
- .(l
- p(a, X) :\- !, q(X).
- p(Y, X) :\- r(X).
- .)l
- However, the call to \fIp\fR/2 results in the (temporary) creation of a
- backtrack point. A solution that avoids this backtrack point creation is
- .(l
- p(Y, X) :\- Y ?= a -> q(X) ; r(X).
- .)l
- Of course, if the argument order in \fIp\fR/2 could be reversed in this
- case, then data movement would be reduced even further (see above), and
- the code would be even more efficient:
- .(l
- p(X, Y) :\- Y ?= a -> q(X) ; r(X).
- .)l
- .bp
- .lp
- .uh "Appendix 3: Adding Builtins to SB-Prolog"
- .lp
- Adding a builtin involves writing the C code for the desired case and installing
- it into the simulator. The files in the irectory \fIsim/builtin\fR
- contain the C code for the builtin predicates supported by the system.
- The following procedure is to be followed when adding a builtin to the system:
- .sp
- .lp
- \fII. Installing C Code\fR:
- .np
- Go to the directory \fIsim/builtin\fR.
- .np
- Look at the \fB#define\fRs in the file \fIbuiltin.h\fR, and choose a number \fIN1\fR
- (between 0 and 255) which is not in use to be the builtin number for the new builtin.
- .np
- Add to the file \fIbuiltin.h\fR the line
- .(l
- #define NEWBUILTIN \fIN1\fR
- .)l
- .np
- The convention is that the code for builtin will be in a parameterless
- procedure named \fIb_\|NEWBUILTIN\fR. Modify the file
- \fIinit_\|\^branch.c\fR in the directory \fIsim/builtin\fR by adding these lines:
- .(l
- extern int b_\|NEWBUILTIN();
- and
- set_\|b_\|inst ( NEWBUILTIN, b_\|NEWBUILTIN );
- .)l
- in the appropriate places.
- .np
- The builtins are compiled together into one object file, \fIbuiltin\fR.
- Update the file \fIMakefile\fR by appending the name of your object code file at the
- end of the line ``OBJS = ... '' and insert the appropriate commands to compile
- your C source file, e.g.:
- .(l
- OBJS = [ ... \fIother file names\fR ... ] newbuiltin.o
-
- ...
-
- newbuiltin.o: $(HS)
- cc $(CFLAGS) newbuiltin.c
- .)l
- .np
- Execute the updated make file to create an updated object file \fIbuiltin\fR.
- .np
- Go to the directory \fIsim\fR and execute \fImake\fR to install the new file \fIbuiltin\fR.
- .sp
- .lp
- \fIII. Installing Prolog Code\fR:
- .pp
- Assume that the builtin predicate to be added is \fInewbuiltin\fR/4. The
- procedure for installing the Prolog code for this is as follows:
- .np
- Go to the SB-Prolog system directory \fIlib/src\fR, where the Prolog source for
- the library routines is kept.
- .np
- Each builtin definition is of the form
-
- .(l
- pred( ... ) :\- '_\|$builtin'(\fIN\fR\^).
- .)l
-
- where \fIN\fR is an integer, the builtin number of \fIpred\fR.
- .np
- Create a Prolog source file \fInewbuiltin.P\fR (notice correspondence with
- the name of the predicate being defined) containing the definition
-
- .(l
- newbuiltin(A,B,C,D) :\- '_\|$builtin'(\fIN1\fR\^).
- .)l
-
- where \fIN1\fR is the builtin number of the predicate \fInewbuiltin\fR,
- obtained when installing the C code for the builtin (see above).
- .np
- Compile this Prolog predicate, using the simulator and the \fIcompile\fR
- predicate, into a file \fInewbuiltin\fR (notice correspondence with the name of
- the predicate being defined) in the SB-Prolog directory \fIlib\fR.
- .sp
- .fo ''''
- .bp
- .ce
- \fBTABLE OF CONTENTS\fR
- .sp
- .xp c
-