.\" ---------------------- sec5.4.t ---------------------- .sh 2 "Modification of the Program" .pp 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 (\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 A prref is normally associated with a predicate symbol and contains the clauses that have been asserted for that symbol. However, prrefs can be constructed and clrefs added to them, and such clauses can be can be constructed and clrefs added to them, and such clauses can be called, all without associating that prref with any particular predicate symbol. A predicate symbol that has an associated prref is called a ``dynamic'' predicate (other predicate types are ``compiled'' and ``undefined''). .pp There are options as to where clrefs are allocated and how they are linked to a chain of clrefs associated with a prref. A clref can either be allocated in permanent space (the normal arrangement) or as a sub-buffer of a superbuffer on the heap. When adding a clref to a prref chain, it can be be added at the beginning of the chain or at the end of the chain. In addition, one of the argument positions can be used to index, so that subsequent retrievals will try to index on that position. .sp .lp \fBassert\fP(\fIC\fP) .(x b (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, \fIOpts\fR) .(x b (L) assert/2 .)x .ip As for \fIassert\fR/1, with \fIOpts\fR a list of options. The options currently recognized are: .lp \fBfirst\fR .ip If on, causes the asserted clause to be added as the first clause of the database. Default: off. .lp \fBindex\fR .ip If on, causes an index to be generated on the first argument of the clause. Default: off. .lp \fBindex(N)\fR .ip If on, causes an index to be generated on the N\*[th\*] argument of the clause. Default: off. .lp \fBq\fR .ip ``quick''. If on, invokes an assertion algorithm that is simpler and more efficient than the general one. However, the code generated with the simpler algorithm may not be correct if there are repeated variables within compound terms in the body of the clause, e.g. in .(l p(X) :\- q([X, X]). .)l Default: off. .lp \fBasserti\fR(\fIC\fR,\fIN\fR\^) .(x b (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 b (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 b (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 b (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 b (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 b (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 \fI$assert_\^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 \fB$assert\fR(\fIClause\fR,\fIAZ\fR,\fIIndex\fR,\fIClref\fR\^) .ip Asserts a clause to a predicate. \fIClause\fR is the clause to assert. .(x b (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 \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 b (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 \fBretract\fP(\fIHead\fP\^) .(x b (L) retract/1 .)x .ip The first clause in the program whose head matches \fIHead\fP is erased. 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 b (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 b (L) abolish/2 .)x .lp \fBcall_\^ref\fR(\fICall\fR, \fIRef\fR) .(x b (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 b (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. .sp .lp The basic library predicates that support the manipulation of prrefs and clrefs are as follows: .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 b (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 b (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 b (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 b (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 b (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 b (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. .lp \fB$db_\|kill_\|clause\fR(\fIClref\fR\^) .ip This predicate retracts the fact referenced by clref \fIClref\fR. .(x b (L) $db_\|kill_\|clause/1 .)x It does this by simply making the first instruction of the clause a \fIfail\fR instruction. This means that this clause will fail whenever it is called in the future, no matter how it is accessed. \fIClref\fR should be instantiated at the time of call. .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 b (B) abort/0 .)x .ip Aborts the current execution, taking you back to top level. .lp \fBsave\fR(\fIF\fR\^) .(x b (B) save/1 .)x .ip The system saves the current state of the system into file \fIF\fR. .lp \fBrestore\fR(\fIF\fR\^) .(x b (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 b (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 b (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 b (B) statistics/0 .)x Does not work well unless the simulator has been called with the -\fBs\fR option (see Section 7.2). .lp \fBnodynload\fR(\fIP\fR, \fIN\fR\^) .(x b (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 b (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 b (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 b (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 expand 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" .pp 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 b (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 b (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 b (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'. .\" -------------------- end of section sec5.4.t --------------------