University of Amsterdam Human-Computer Studies (HCS, formerly SWI) Kruislaan 419, 1098 VA Amsterdam The Netherlands Tel. (+31) 20 8884671 SSWWII--PPrroolloogg 55..66 RReeffeerreennccee MMaannuuaall _U_p_d_a_t_e_d _f_o_r _v_e_r_s_i_o_n _5_._6_._3_2_, _M_a_r_c_h _2_0_0_7 _J_a_n _W_i_e_l_e_m_a_k_e_r wielemak@science.uva.nl http://www.swi-prolog.org SWI-Prolog is a Prolog implementation based on a subset of the WAM (Warren Abstract Machine). SWI-Prolog was developed as an _o_p_e_n Prolog environment, providing a powerful and bi- directional interface to C in an era this was unknown to other Prolog implementations. This environment is required to deal with XPCE, an object-oriented GUI system developed at SWI. XPCE is used at SWI for the development of knowledge-intensive graphical applications. As SWI-Prolog became more popular, a large user-community provided requirements that guided its development. Compatibility, portability, scalability, stability and providing a powerful development environment have been the most important requirements. Edinburgh, Quintus, SICStus and the ISO-standard guide the development of the SWI-Prolog primitives. This document gives an overview of the features, system limits and built-in predicates. Copyright Oc 1990--2007, University of Amsterdam CChhaapptteerr 11.. IINNTTRROODDUUCCTTIIOONN 11..11 SSWWII--PPrroolloogg SWI-Prolog started back in 1986 with the requirement for a Prolog that could handle recursive interaction with the C-language: Prolog calling C and C calling Prolog recursively. Those days Prolog systems were very aware of its environment and we needed such a system to support interactive applications. Since then, SWI-Prolog's development has been guided by requests from the user community, especially focussing on (in arbitrary order) interaction with the environment, scalability, (I/O) performance, standard compliance, teaching and the program development environment. SWI-Prolog is based on a very restricted form of the WAM (Warren Abstract Machine) described in [Bowen & Byrd, 1983] which defines only 7 instructions. Prolog can easily be compiled into this language and the abstract machine code is easily decompiled back into Prolog. As it is also possible to wire a standard 4-port debugger in the WAM interpreter there is no need for a distinction between compiled and interpreted code. Besides simplifying the design of the Prolog system itself this approach has advantages for program development: the compiler is simple and fast, the user does not have to decide in advance whether debugging is required and the system only runs slightly slower when in debug mode. The price we have to pay is some performance degradation (taking out the debugger from the WAM interpreter improves performance by about 20%) and somewhat additional memory usage to help the decompiler and debugger. SWI-Prolog extends the minimal set of instructions described in [Bowen & Byrd, 1983] to improve performance. While extending this set care has been taken to maintain the advantages of decompilation and tracing of compiled code. The extensions include specialised instructions for unification, predicate invocation, some frequently used built-in predicates, arithmetic, and control (;/2, |/2), if-then (->/2) and negation-by-failure (\+/1). 11..11..11 BBooookkss aabboouutt PPrroolloogg This manual does not describe the full syntax and semantics of Prolog, nor how one should write a program in Prolog. These subjects have been described extensively in the literature. See [Bratko, 1986], [Sterling & Shapiro, 1986], and [Clocksin & Melish, 1987]. For more advanced Prolog material see [O'Keefe, 1990]. Syntax and standard operator declarations confirm to the `Edinburgh standard'. Most built in predicates are compatible with those described in [Clocksin & Melish, 1987]. SWI-Prolog also offers a number of primitive predicates compatible with Quintus Prolog [Qui, 1997] and BIM_Prolog [BIM, 1989]. ISO compliant predicates are based on ``Prolog: The Standard'', [Deransart _e_t _a_l_., 1996], validated using [Hodgson, 1998]. 11..22 SSttaattuuss This manual describes version 5.6 of SWI-Prolog. SWI-Prolog has been used now for many years. The application range includes Prolog course material, meta-interpreters, simulation of parallel Prolog, learning systems, natural language processing, complex interactive systems, web-server and web-server components. Although we experienced rather obvious and critical bugs can remain unnoticed for a remarkable long period, we assume the basic Prolog system is fairly stable. Bugs can be expected in infrequently used built-in predicates. Some bugs are known to the author. They are described as footnotes in this manual. 11..33 CCoommpplliiaannccee ttoo tthhee IISSOO ssttaannddaarrdd SWI-Prolog 3.3.0 implements all predicates described in ``Prolog: The Standard'' [Deransart _e_t _a_l_., 1996]. Exceptions and warning are still weak. Some SWI-Prolog predicates silently fail on conditions where the ISO specification requires an exception (functor/3 for example). Some predicates print warnings rather than raising an exception. All predicates where exceptions may be caused due to a correct program operating in an imperfect world (I/O, arithmetic, resource overflows) should behave according to the ISO standard. In other words: SWI-Prolog should be able to execute any program conforming to [Deransart _e_t _a_l_., 1996] that does not rely on exceptions generated by errors in the program. 11..44 SShhoouulldd yyoouu bbee uussiinngg SSWWII--PPrroolloogg?? There are a number of reasons why you better choose a commercial Prolog system, or another academic product: o _S_W_I_-_P_r_o_l_o_g _i_s _n_o_t _s_u_p_p_o_r_t_e_d Although I usually fix bugs shortly after a bug report arrives, I cannot promise anything. Now that the sources are provided, you can always dig into them yourself. o _M_e_m_o_r_y _r_e_q_u_i_r_e_m_e_n_t_s _a_n_d _p_e_r_f_o_r_m_a_n_c_e _a_r_e _y_o_u_r _f_i_r_s_t _c_o_n_c_e_r_n_s A number of commercial compilers are more keen on memory and performance than SWI-Prolog. I do not wish to sacrifice some of the nice features of the system, nor its portability to compete on raw performance. o _Y_o_u _n_e_e_d _f_e_a_t_u_r_e_s _n_o_t _o_f_f_e_r_e_d _b_y _S_W_I_-_P_r_o_l_o_g In this case you may wish to give me suggestions for extensions. If you have great plans, please contact me (you might have to implement them yourself however). On the other hand, SWI-Prolog offers some nice facilities: o _N_i_c_e _e_n_v_i_r_o_n_m_e_n_t This includes `Do What I Mean', automatic completion of atom names, history mechanism and a tracer that operates on single key-strokes. Interfaces to some standard editors are provided (and can be extended), as well as a facility to maintain programs (see make/0). o _V_e_r_y _f_a_s_t _c_o_m_p_i_l_e_r Even very large applications can be loaded in seconds on most machines. If this is not enough, there is a Quick Load Format that is slightly more compact and loading is almost always I/O bound. o _T_r_a_n_s_p_a_r_e_n_t _c_o_m_p_i_l_e_d _c_o_d_e SWI-Prolog compiled code can be treated just as interpreted code: you can list it, trace it, etc. This implies you do not have to decide beforehand whether a module should be loaded for debugging or not. Also, performance is much better than the performance of most interpreters. o _P_r_o_f_i_l_i_n_g SWI-Prolog offers tools for performance analysis, which can be very useful to optimise programs. Unless you are very familiar with Prolog and Prolog performance considerations this might be more helpful than a better compiler without these facilities. o _F_l_e_x_i_b_i_l_i_t_y SWI-Prolog can easily be integrated with C, supporting non- determinism in Prolog calling C as well as C calling Prolog (see section 9). It can also be _e_m_b_e_d_d_e_d embedded in external programs (see section 9.7). System predicates can be redefined locally to provide compatibility with other Prolog systems. o _I_n_t_e_g_r_a_t_i_o_n _w_i_t_h _X_P_C_E SWI-Prolog offers a tight integration to the Object Ori- ented Package for User Interface Development, called XPCE [Anjewierden & Wielemaker, 1989]. XPCE allows you to implement graphical user interfaces that are source-code compatible over Unix/X11, Win32 (Windows 95/98/ME and NT/2000/XP) and MacOS X (darwin). 11..55 TThhee XXPPCCEE GGUUII ssyysstteemm ffoorr PPrroolloogg The XPCE GUI system for dynamically typed languages has been with SWI-Prolog for a long time. It is developed by Anjo Anjewierden and Jan Wielemaker from the department of SWI, University of Amsterdam. It aims at a high-productive development environment for graphical applications based on Prolog. Object oriented technology has proven to be a suitable model for implementing GUIs, which typically deal with things Prolog is not very good at: event-driven control and global state. With XPCE, we designed a system that has similar characteristics that make Prolog such a powerful tool: dynamic typing, meta-programming and dynamic modification of the running system. XPCE is an object-system written in the C-language. It provides for the implementation of methods in multiple languages. New XPCE classes may be defined from Prolog using a simple, natural syntax. The body of the method is executed by Prolog itself, providing a natural interface between the two systems. Below is a very simple class definition. :- pce_begin_class(prolog_lister, frame, "List Prolog predicates"). initialise(Self) :-> "As the C++ constructor":: send_super(Self, initialise, 'Prolog Lister'), send(Self, append, new(D, dialog)), send(D, append, text_item(predicate, message(Self, list, @arg1))), send(new(view), below, D). list(Self, From:name) :-> "List predicates from specification":: ( catch(term_to_atom(Term, From), _, fail) -> get(Self, member, view, V), current_output(Old), pce_open(V, write, Fd), set_output(Fd), listing(Term), close(Fd), set_output(Old) ; send(Self, report, error, 'Syntax error') ). :- pce_end_class. test :- send(new(prolog_lister), open). Its 165 built-in classes deal with the meta-environment, data- representation and---of course---graphics. The graphics classes concentrate on direct-manipulation of diagrammatic representations. AAvvaaiillaabbiilliittyy.. XPCE runs on most Unixtm platforms, Windows 95/98/ME, Windows NT/2000/XP and MacOS X (using X11). In the past, versions for Quintus- and SICStus Prolog as well as some Lisp dialects have existed. After discontinuing active Lisp development at SWI the Lisp versions have died. Active development on the Quintus and SICStus versions has been stopped due to lack of standardisation in the the Prolog community. If adequate standards emerge we are happy to actively support other Prolog implementations. IInnffoo.. further information is available from http://www.swi- prolog.org/packages/xpce/ or by E-mail to info@www.swi-prolog.org. 11..66 RReelleeaassee NNootteess Collected release-notes. This section only contains some highlights. Smaller changes to especially older releases have been removed. For a complete log, see the file ChangeLog from the distribution. 11..66..11 VVeerrssiioonn 11..88 RReelleeaassee NNootteess Version 1.8 offers a stack-shifter to provide dynamically expanding stacks on machines that do not offer operating-system support for implementing dynamic stacks. 11..66..22 VVeerrssiioonn 11..99 RReelleeaassee NNootteess Version 1.9 offers better portability including an MS-Windows 3.1 version. Changes to the Prolog system include: o _R_e_d_e_f_i_n_i_t_i_o_n _o_f _s_y_s_t_e_m _p_r_e_d_i_c_a_t_e_s Redefinition of system predicates was allowed silently in older versions. Version 1.9 only allows it if the new definition is headed by a :- redefine_system_predicate/1 directive.top-level o _`_A_n_s_w_e_r_' _r_e_u_s_e The top-level maintains a table of bindings returned by top-level goals and allows for reuse of these bindings by prefixing the variables with the $ sign. See section 2.8. o _B_e_t_t_e_r _s_o_u_r_c_e _c_o_d_e _a_d_m_i_n_i_s_t_r_a_t_i_o_n Allows for proper updating of multifile predicates and finding the sources of individual clauses. 11..66..33 VVeerrssiioonn 22..00 RReelleeaassee NNootteess New features offered: o _3_2_-_b_i_t _V_i_r_t_u_a_l _M_a_c_h_i_n_e Removes various limits and improves performance. o _I_n_l_i_n_e _f_o_r_e_i_g_n _f_u_n_c_t_i_o_n_s `Simple' foreign predicates no longer build a Prolog stack-frame, but are directly called from the VM. Notably provides a speedup for the test predicates such as var/1, etc. o _V_a_r_i_o_u_s _c_o_m_p_a_t_i_b_i_l_i_t_y _i_m_p_r_o_v_e_m_e_n_t_s o _S_t_r_e_a_m _b_a_s_e_d _I_/_O _l_i_b_r_a_r_y All SWI-Prolog's I/O is now handled by the stream-package defined in the foreign include file SWI-Stream.h. Physical I/O of Prolog streams may be redefined through the foreign language interface, facilitating much simpler integration in window environments. 11..66..44 VVeerrssiioonn 22..55 RReelleeaassee NNootteess Version 2.5 is an intermediate release on the path from 2.1 to 3.0. All changes are to the foreign-language interface, both to user- and system-predicates implemented in the C-language. The aim is twofold. First of all to make garbage-collection and stack-expansion (stack-shifts) possible while foreign code is active without the C-programmer having to worry about locking and unlocking C-variables pointing to Prolog terms. The new approach is closely compatible to the Quintus and SICStus Prolog foreign interface using the +term argument specification (see their respective manuals). This allows for writing foreign interfaces that are easily portable over these three Prolog platforms. Apart from various bug fixes listed in the ChangeLog file, these are the main changes since 2.1.0: o _I_S_O _c_o_m_p_a_t_i_b_i_l_i_t_y Many ISO compatibility features have been added: open/4, arithmetic functions, syntax, etc. o _W_i_n_3_2 Many fixes for the Win32 (NT, '95 and win32s) platforms. Notably many problems related to pathnames and a problem in the garbage collector. o _P_e_r_f_o_r_m_a_n_c_e Many changes to the clause indexing system: added hash-tables, lazy computation of the index information, etc. o _P_o_r_t_a_b_l_e _s_a_v_e_d_-_s_t_a_t_e_s The predicate qsave_program/[1,2] allows for the creating of machine independent saved-states that load very quickly. 11..66..55 VVeerrssiioonn 22..66 RReelleeaassee NNootteess Version 2.6 provides a stable implementation of the features added in the 2.5.x releases, but at the same time implements a number of new features that may have impact on the system stability. o _3_2_-_b_i_t _i_n_t_e_g_e_r _a_n_d _d_o_u_b_l_e _f_l_o_a_t _a_r_i_t_h_m_e_t_i_c The biggest change is the support for full 32-bit signed integers and raw machine-format double precision floats. The internal data representation as well as the arithmetic instruction set and interface to the arithmetic functions has been changed for this. o _E_m_b_e_d_d_i_n_g _f_o_r _W_i_n_3_2 _a_p_p_l_i_c_a_t_i_o_n_s The Win32 version has been reorganised. The Prolog kernel is now implemented as Win32 DLL that may be embedded in C-applications. Two front ends are provided, one for window-based operation and one to run as a Win32 console application. o _C_r_e_a_t_i_n_g _s_t_a_n_d_-_a_l_o_n_e _e_x_e_c_u_t_a_b_l_e_s Version 2.6.0 can create stand-alone executables by attaching the saved-state to the emulator. See qsave_program/2. 11..66..66 VVeerrssiioonn 22..77 RReelleeaassee NNootteess Version 2.7 reorganises the entire data-representation of the Prolog data itself. The aim is to remove most of the assumption on the machine's memory layout to improve portability in general and enable embedding on systems where the memory layout may depend on invocation or on how the executable is linked. The latter is notably a problem on the Win32 platforms. Porting to 64-bit architectures is feasible now. Furthermore, 2.7 lifts the limits on arity of predicates and number of variables in a clause considerably and allow for further expansion at minimal cost. 11..66..77 VVeerrssiioonn 22..88 RReelleeaassee NNootteess With version 2.8, we declare the data-representation changes of 2.7.x stable. Version 2.8 exploits the changes of 2.7 to support 64-bit processors like the DEC Alpha. As of version 2.8.5, the representation of recorded terms has changed, and terms on the heap are now represented in a compiled format. SWI-Prolog no longer limits the use of malloc() or uses assumptions on the addresses returned by this function. 11..66..88 VVeerrssiioonn 22..99 RReelleeaassee NNootteess Version 2.9 is the next step towards version 3.0, improving ISO compliance and introducing ISO compliant exception handling. New are catch/3, throw/1, abolish/1, write_term/[2,3], write_canonical/[1,2] and the C-functions PL_exception() and PL_throw(). The predicates display/[1,2] and displayq/[1,2] have been moved to backcomp, so old code referring to them will autoload them. The interface to PL_open_query() has changed. The _d_e_b_u_g argument is replaced by a bitwise or'ed _f_l_a_g_s argument. The values FALSE and TRUE have their familiar meaning, making old code using these constants compatible. Non-zero values other than TRUE (1) will be interpreted different. 11..66..99 VVeerrssiioonn 33..00 RReelleeaassee NNootteess Complete redesign of the saved-state mechanism, providing the possibility of `program resources'. See resource/3, open_resource/3, and qsave_program/[1,2]. 11..66..1100 VVeerrssiioonn 33..11 RReelleeaassee NNootteess Improvements on exception-handling. Allows relating software interrupts (signals) to exceptions, handling signals in Prolog and C (see on_signal/3 and PL_signal()). Prolog stack overflows now raise the resource_error exception and thus can be handled in Prolog using catch/3. 11..66..1111 VVeerrssiioonn 33..33 RReelleeaassee NNootteess Version 3.3 is a major release, changing many things internally and externally. The highlights are a complete redesign of the high-level I/O system, which is now based on explicit streams rather then current input/output. The old Edinburgh predicates (see/1, tell/1, etc.) are now defined on top of this layer instead of the other way around. This fixes various internal problems and removes Prolog limits on the number of streams. Much progress has been made to improve ISO compliance: handling strings as lists of one-character atoms is now supported (next to character codes as integers). Many more exceptions have been added and printing of exceptions and messages is rationalised using Quintus and SICStus Prolog compatible print_message/2, message_hook/3 and print_message_lines/3. All predicates described in [Deransart _e_t _a_l_., 1996] are now implemented. As of version 3.3, SWI-Prolog adheres the ISO _l_o_g_i_c_a_l _u_p_d_a_t_e _v_i_e_w for dynamic predicates. See section 4.13.1 for details. SWI-Prolog 3.3 includes garbage collection on atoms, removing the last serious memory leak especially in text-manipulation applications. See section 9.6.2.1. In addition, both the user-level and foreign interface supports atoms holding _0_-_b_y_t_e_s. Finally, an alpha version of a multi-threaded SWI-Prolog for Linux is added. This version is still much slower than the single-threaded version due to frequent access to `thread-local-data' as well as some too detailed mutex locks. The basic thread API is ready for serious use and testing however. See section 8. 11..66..1111..11 IInnccoommppaattiibbllee cchhaannggeess A number of incompatible changes result from this upgrade. They are all easily fixed however. o !/0_, call/1 The cut now behaves according to the ISO standard. This implies it works in compound goals passed to call/1 and is local to the _c_o_n_d_i_t_i_o_n part of if-then-else as well as the argument of \+/1. o _a_t_o_m___c_h_a_r_s_/_2 This predicate is now ISO compliant and thus generates a list of one-character atoms. The behaviour of the old predicate is available in the ---also ISO compliant--- atom_codes/2 predicate. Safest repair is a replacement of all atom_chars into atom_codes. If you do not want to change any source-code, you might want to use user:goal_expansion(atom_chars(A,B), atom_codes(A,B)). o _n_u_m_b_e_r___c_h_a_r_s_/_2 Same applies for number_chars/2 and number_codes/2. o feature/2_, set_feature/2 These are replaced by the ISO compliant current_prolog_flag/2 and set_prolog_flag/2. The library backcomp provides definitions for these predicates, so no source mmuusstt be updated. o _A_c_c_e_s_s_i_n_g _c_o_m_m_a_n_d_-_l_i_n_e _a_r_g_u_m_e_n_t_s This used to be provided by the undocumented '$argv'/1 and Quintus compatible library unix/1. Now there is also documented current_prolog_flag(_a_r_g_v_, _A_r_g_v). o _d_u_p___s_t_r_e_a_m_/_2 Has been deleted. New stream-aliases can deal with most of the problems for which dup_stream/2 was designed and dup/2 from the _c_l_i_b package can with most others. o _o_p_/_3 Operators are now llooccaall ttoo mmoodduulleess. This implies any modification of the operator-table does not influence other modules. This is consistent with the proposed ISO behaviour and a necessity to have any usable handling of operators in a multi-threaded environment. o _s_e_t___p_r_o_l_o_g___f_l_a_g_(_c_h_a_r_a_c_t_e_r___e_s_c_a_p_e_s_, _B_o_o_l_) This prolog flag is now an interface to changing attributes on the current source-module, effectively making this flag module-local as well. This is required for consistent handling of sources written with ISO (obligatory) character-escape sequences together with old Edinburgh code. o _c_u_r_r_e_n_t___s_t_r_e_a_m_/_3 _a_n_d _s_t_r_e_a_m___p_o_s_i_t_i_o_n These predicates have been moved to quintus. 11..66..1122 VVeerrssiioonn 33..44 RReelleeaassee NNootteess The 3.4 release is a consolidation release. It consolidates the improvements and standard conformance of the 3.3 releases. This version is closely compatible with the 3.3 version except for one important change: o _A_r_g_u_m_e_n_t _o_r_d_e_r _i_n select/3 The list-processing predicate select/3 somehow got into a very early version of SWI-Prolog with the wrong argument order. This has been fixed in 3.4.0. The correct order is select(?Elem, ?List, ?Rest). As select/3 has no error conditions, runtime checking cannot be done. To simplify debugging, the library module checkselect will print references to select/3 in your source code and install a version of select that enters the debugger if select is called and the second argument is not a list. This library can be loaded explicitly or by calling check_old_select/0. 11..66..1133 VVeerrssiioonn 44..00 RReelleeaassee NNootteess As of version 4.0 the standard distribution of SWI-Prolog is bundled with a number of its popular extension packages, among which the now open source XPCE GUI toolkit (see section 1.5). No significant changes have been made to the basic SWI-Prolog engine. Some useful tricks in the integrated environment: o _R_e_g_i_s_t_e_r _t_h_e _G_U_I _t_r_a_c_e_r Using a call to guitracer/0, hooks are installed that replace the normal command-line driven tracer with a graphical front-end. o _R_e_g_i_s_t_e_r _P_c_e_E_m_a_c_s _f_o_r _e_d_i_t_i_n_g _f_i_l_e_s From your initialisation file. you can load emacs/swi_prolog that cause edit/1 to use the built-in PceEmacs editor. 11..66..1144 VVeerrssiioonn 55..00 RReelleeaassee NNootteess Version 5.0 marks a breakpoint in the philosophy, where SWI-Prolog moves from a dual GPL/proprietary to a uniform LGPL (Lesser GNU Public Licence) schema, providing a widely usable Free Source Prolog implementation. On the technical site the development environment, consisting of source-level debugger, integrated editor and various analysis and navigation tools progress steadily towards a mature set of tools. Many portability issues have been improved, including a port to MacOS X (Darwin). For details, please visit the new website at http://www.swi-prolog.org 11..66..1155 VVeerrssiioonn 55..11 RReelleeaassee NNootteess Version 5.1 is a beta-serie introducing portable multi-threading. See chapter 8. In addition it introduces many new facilities to support server applications, such as the new rlimit library to limit system resources and the possibility to set timeouts on input streams. 11..66..1166 VVeerrssiioonn 55..22 RReelleeaassee NNootteess Version 5.2 consolidates the 5.1.x beta series that introduced threading and many related modifications to the kernel. 11..66..1177 VVeerrssiioonn 55..33 RReelleeaassee NNootteess Version 5.3.x is a development series for adding coroutining, constraints, global variables, cyclic terms (infinite trees) and other goodies to the kernel. The package JPL, providing a bidirectional Java/Prolog interface is added to the common source-tree and common binary packages. 11..66..1188 VVeerrssiioonn 55..44 RReelleeaassee NNootteess Version 5.4 consolidates the 5.3.x beta series. 11..66..1199 VVeerrssiioonn 55..55 RReelleeaassee NNootteess Version 5.5.x provides support for _w_i_d_e _c_h_a_r_a_c_t_e_r_s with UTF-8 and UNICODE I/O (section 2.17.1). On both 32 and 64-bit hardware Prolog integers are now at minimum 64-bit integers. If available, SWI-Prolog arithmetic uses the GNU GMP library to provided _u_n_b_o_u_n_d_e_d integer arithmetic as well as rational arithmetic. Adding GMP support is sponsored by Scientific Software and Systems Limited, www.sss.co.nz. This version also incorporates clp(r) by Christian Holzbaur, brought to SWI-Prolog by Tom Schrijvers and Leslie De Koninck (section 11.14). 11..66..2200 VVeerrssiioonn 55..66 RReelleeaassee NNootteess Version 5.6 consolidates the 5.5.x beta series. 11..77 DDoonnaattee ttoo tthhee SSWWII--PPrroolloogg pprroojjeecctt If you are happy with SWI-Prolog, you care it to be around for much longer while it becomes faster, more stable and with more features you should consider to donate to the SWI-Prolog foundation. Please visit the page below. http://www.swi-prolog.org/donate.html 11..88 AAcckknnoowwlleeddggeemmeennttss Some small parts of the Prolog code of SWI-Prolog are modified versions of the corresponding Edinburgh C-Prolog code: grammar rule compilation and writef/2. Also some of the C-code originates from C-Prolog: finding the path of the currently running executable and some of the code underlying absolute_file_name/2. Ideas on programming style and techniques originate from C-Prolog and Richard O'Keefe's _t_h_i_e_f editor. An important source of inspiration are the programming techniques introduced by Anjo Anjewierden in PCE version 1 and 2. I also would like to thank those who had the fade of using the early versions of this system, suggested extensions or reported bugs. Among them are Anjo Anjewierden, Huub Knops, Bob Wielinga, Wouter Jansweijer, Luc Peerdeman, Eric Nombden, Frank van Harmelen, Bert Rengel. Martin Jansche (jansche@novell1.gs.uni-heidelberg.de) has been so kind to reorganise the sources for version 2.1.3 of this manual. Horst von Brand has been so kind to fix many typos in the 2.7.14 manual. Thanks! Bart Demoen and Tom Schrijvers have helped me adding coroutining, constraints, global variables and support for cyclic terms to the kernel. Tom has provided the integer interval constraint solver, the CHR compiler and some of the coroutining predicates. Paul Singleton has integrated Fred Dushin's Java-calls-Prolog side with his Prolog-calls-Java side into the current bidirectional JPL interface package. Richard O'Keefe is gratefully acknowledged for his efforts to educate beginners as well as valuable comments on proposed new developments. Scientific Software and Systems Limited, www.sss.co.nz has sponsored the development if the SSL library as well as unbounded integer and rational number arithmetic. Leslie de Koninck has made clp(QR) available to SWI-Prolog. Markus Triska has contributed to various libraries. Paulo Moura's great experience in maintaining Logtalk for many Prolog systems including SWI-Prolog has helped in many places fixing compatibility issues. He also worked on the MacOS port and fixed many typos in the 5.6.9 release of the documentation. CChhaapptteerr 22.. OOVVEERRVVIIEEWW 22..11 GGeettttiinngg ssttaarrtteedd qquuiicckkllyy 22..11..11 SSttaarrttiinngg SSWWII--PPrroolloogg 22..11..11..11 SSttaarrttiinngg SSWWII--PPrroolloogg oonn UUnniixx By default, SWI-Prolog is installed as `pl', though some administrators call it `swipl' or `swi-prolog'. The command-line arguments of SWI-Prolog itself and its utility programs are documented using standard Unix man pages. SWI-Prolog is normally operated as an interactive application simply by starting the program: machine% pl Welcome to SWI-Prolog (Version 5.6.26) Copyright (c) 1990-2007 University of Amsterdam. SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). 1 ?- After starting Prolog, one normally loads a program into it using consult/1, which --- for historical reasons --- may be abbreviated by putting the name of the program file between square brackets. The following goal loads the file likes.pl containing clauses for the predicates likes/2: ?- [likes]. % likes compiled, 0.00 sec, 596 bytes. Yes ?- After this point, Unix and Windows users unite, so if you are using Unix please continue at section 2.1.2. 22..11..11..22 SSttaarrttiinngg SSWWII--PPrroolloogg oonn WWiinnddoowwss After SWI-Prolog has been installed on a Windows system, the following important new things are available to the user: o A folder (called _d_i_r_e_c_t_o_r_y in the remainder of this document) called pl containing the executables, libraries, etc. of the system. No files are installed outside this directory. o A program plwin.exe, providing a window for interaction with Prolog. The program plcon.exe is a version of SWI-Prolog that runs in a DOS-box. o The file-extension .pl is associated with the program plwin.exe. Opening a .pl file will cause plwin.exe to start, change directory to the directory in which the file-to-open resides and load this file. The normal way to start with the likes.pl file mentioned in section 2.1.1.1 is by simply double-clicking this file in the Windows explorer. 22..11..22 EExxeeccuuttiinngg aa qquueerryy After loading a program, one can ask Prolog queries about the program. The query below asks Prolog what food `sam' likes. The system responds with X = <_v_a_l_u_e> if it can prove the goal for a certain _X. The user can type the semi-colon (;) if (s)he wants another solution, or return if (s)he is satisfied, after which Prolog will say YYeess. If Prolog answers NNoo, it indicates it cannot find any (more) answers to the query. Finally, Prolog can answer using an error message to indicate the query or program contains an error. ?- likes(sam, X). X = dahl ; X = tandoori ; ... X = chips ; No ?- 22..22 TThhee uusseerr''ss iinniittiiaalliissaattiioonn ffiillee After the necessary system initialisation the system consults (see consult/1) the user's startup file. The base-name of this file follows conventions of the operating system. On MS-Windows, it is the file pl.ini and on Unix systems .plrc. The file is searched using the file_search_path/2 clauses for user_profile. The table below shows the default value for this search-path. _______________________________________________________________ |________________|UUnniixx__||WWiinnddoowwss________________________________________________________________________________|| || llooccaall ||. |. | | hhoommee ||~ |%HOME% or %HOMEDRIVE%\%HOMEPATH% | |_global_|____|SWI-Home_directory_or_%WINDIR%_or_%SYSTEMROOT%_|_ After the first startup file is found it is loaded and Prolog stops looking for further startup files. The name of the startup file can be changed with the `-f file' option. If _F_i_l_e denotes an absolute path, this file is loaded, otherwise the file is searched for using the same conventions as for the default startup file. Finally, if _f_i_l_e is none, no file is loaded. 22..33 IInniittiiaalliissaattiioonn ffiilleess aanndd ggooaallss Using command-line arguments (see section 2.4), SWI-Prolog can be forced to load files and execute queries for initialisation purposes or non-interactive operation. The most commonly used options are -f file or -s file to make Prolog load a file, -g goal to define an initialisation goal and -t goal to define the _t_o_p_-_l_e_v_e_l _g_o_a_l. The following is a typical example for starting an application directly from the command-line. machine% pl -s load.pl -g go -t halt It tells SWI-Prolog to load load.pl, start the application using the _e_n_t_r_y_-_p_o_i_n_t go/0 and ---instead of entering the interactive top-level--- exit after completing go/0. The -q may be used to suppress all informational messages. In MS-Windows, the same can be achieved using a short-cut with appropriately defined command-line arguments. A typically seen alternative is to write a file run.pl with content as illustrated below. Double-clicking run.pl will start the application. :- [load]. % load program :- go. % run it :- halt. % and exit Section 2.10.2.1 discusses further scripting options and chapter 10 discusses the generation of runtime executables. Runtime executables are a mean to deliver executables that do not require the Prolog system. 22..44 CCoommmmaanndd--lliinnee ooppttiioonnss The full set of command-line options is given below: --hheellpp When given as the only option, it summarises the most important options. --vv When given as the only option, it summarises the version and the architecture identifier. --aarrcchh When given as the only option, it prints the architecture identifier (see current_prolog_flag(arch, Arch)) and exits. See also -dump-runtime-variables. --dduummpp--rruunnttiimmee--vvaarriiaabblleess When given as the only option, it prints a sequence of variable settings that can be used in shell-scripts to deal with Prolog parameters. This feature is also used by plld (see section 9.7). Below is a typical example of using this feature. eval `pl -dump-runtime-variables` cc -I$PLBASE/include -L$PLBASE/runtime/$PLARCH ... --qq Set the prolog-flag verbose to silent, suppressing informational and banner messages. --LL_s_i_z_e_[_k_m_] Give local stack limit (2 Mbytes default). Note that there is no space between the size option and its argument. By default, the argument is interpreted in Kbytes. Postfixing the argument with m causes the argument to be interpreted in Mbytes. The following example specifies 32 Mbytes local stack. % pl -L32m A maximum is useful to stop buggy programs from claiming all memory resources. -L0 sets the limit to the highest possible value. See section 2.18. --GG_s_i_z_e_[_k_m_] Give global stack limit (4 Mbytes default). See -L for more details. --TT_s_i_z_e_[_k_m_] Give trail stack limit (4 Mbytes default). This limit is relatively high because trail-stack overflows are not often caused by program bugs. See -L for more details. --AA_s_i_z_e_[_k_m_] Give argument stack limit (1 Mbytes default). The argument stack limits the maximum nesting of terms that can be compiled and executed. SWI-Prolog does `last-argument optimisation' to avoid many deeply nested structure using this stack. Enlarging this limit is only necessary in extreme cases. See -L for more details. --cc _f_i_l_e _._._. Compile files into an `intermediate code file'. See section 2.10. --oo _o_u_t_p_u_t Used in combination with -c or -b to determine output file for compilation. --OO Optimised compilation. See current_prolog_flag/2flag optimise for details. --nnooddeebbuugg Disable debugging. See the current_prolog_flag/2 flag generate_debug_info for details. --ss _f_i_l_e Use _f_i_l_e as a script-file. The script file is loaded after the initialisation file specified with the -f file option. Unlike -f file, using -s does not stop Prolog from loading the personal initialisation file. --ff _f_i_l_e Use _f_i_l_e as initialisation file instead of the default .plrc (Unix) or pl.ini (Windows). `-f none' stops SWI-Prolog from searching for a startup file. This option can be used as an alternative to -s file that stops Prolog from loading the personal initialisation file. See also section 2.2. --FF _s_c_r_i_p_t Selects a startup-script from the SWI-Prolog home directory. The script-file is named <_s_c_r_i_p_t>.rc. The default _s_c_r_i_p_t name is deduced from the executable, taking the leading alphanumerical characters (letters, digits and underscore) from the program-name. -F none stops looking for a script. Intended for simple management of slightly different versions. One could for example write a script iso.rc and then select ISO compatibility mode using pl -F iso or make a link from iso-pl to pl. --gg _g_o_a_l _G_o_a_l is executed just before entering the top level. Default is a predicate which prints the welcome message. The welcome message can thus be suppressed by giving -g true. _g_o_a_l can be a complex term. In this case quotes are normally needed to protect it from being expanded by the Unix shell. --tt _g_o_a_l Use _g_o_a_l as interactive top-level instead of the default goal prolog/0. _g_o_a_l can be a complex term. If the top-level goal succeeds SWI-Prolog exits with status 0. If it fails the exit status is 1. This flag also determines the goal started by break/0 and abort/0. If you want to stop the user from entering interactive mode start the application with `-g goal' and give `halt' as top-level. --ttttyy Unix only. Switches controlling the terminal for allowing single-character commands to the tracer and get_single_char/1. By default manipulating the terminal is enabled unless the system detects it is not connected to a terminal or it is running as a GNU-Emacs inferior process. This flag is sometimes required for smooth interaction with other applications. --nnoossiiggnnaallss Inhibit any signal handling by Prolog, a property that is sometimes desirable for embedded applications. This option sets the flag signals to false. See section 9.6.20.1 for details. --xx _b_o_o_t_f_i_l_e Boot from _b_o_o_t_f_i_l_e instead of the system's default boot file. A bootfile is a file resulting from a Prolog compilation using the -b or -c option or a program saved using qsave_program/[1,2]. --pp _a_l_i_a_s_=_p_a_t_h_1_[_:_p_a_t_h_2 _._._._] Define a path alias for file_search_path. _a_l_i_a_s is the name of the alias, _p_a_t_h_1 _._._. is a list of values for the alias. On Windows the list-separator is ;. On other systems it is :. A value is either a term of the form alias(value) or pathname. The computed aliases are added to file_search_path/2 using asserta/1, so they precede predefined values for the alias. See file_search_path/2 for details on using this file-location mechanism. -- Stops scanning for more arguments, so you can pass arguments for your application after this one. See current_prolog_flag/2 using the flag argv for obtaining the command-line arguments. The following options are for system maintenance. They are given for reference only. --bb _i_n_i_t_f_i_l_e _._._.-c _f_i_l_e _._._. Boot compilation. _i_n_i_t_f_i_l_e _._._. are compiled by the C-written bootstrap compiler, _f_i_l_e _._._. by the normal Prolog compiler. System maintenance only. --dd _l_e_v_e_l Set debug level to _l_e_v_e_l. Only has effect if the system is compiled with the -DO_DEBUG flag. System maintenance only. 22..55 GGNNUU EEmmaaccss IInntteerrffaaccee The default Prolog mode for GNU-Emacs can be activated by adding the following rules to your Emacs initialisation file: (setq auto-mode-alist (append '(("\\.pl" . prolog-mode)) auto-mode-alist)) (setq prolog-program-name "pl") (setq prolog-consult-string "[user].\n") ;If you want this. Indentation is either poor or I don't use ;it as intended. ;(setq prolog-indent-width 8) Unfortunately the default Prolog mode of GNU-Emacs is not very good. An alternative prolog.el file for GNU-Emacs 20 is available from http://www.freesoft.cz/ pdm/software/emacs/prolog-mode/ and for GNU- Emacs 19 from http://w1.858.telia.com/ u85810764/Prolog-mode/index.html 22..66 OOnnlliinnee HHeellpp Online help provides a fast lookup and browsing facility to this manual. The online manual can show predicate definitions as well as entire sections of the manual. The online help is displayed from the file 'MANUAL'. The file helpidx provides an index into this file. 'MANUAL' is created from the LaTeX sources with a modified version of dvitty, using overstrike for printing bold text and underlining for rendering italic text. XPCE is shipped with swi_help, presenting the information from the online help in a hypertext window. The prolog-flag write_help_with_overstrike controls whether or not help/1 writes its output using overstrike to realise bold and underlined output or not. If this prolog-flag is not set it is initialised by the help library to true if the TERM variable equals xterm and false otherwise. If this default does not satisfy you, add the following line to your personal startup file (see section 2.2): :- set_prolog_flag(write_help_with_overstrike, true). hheellpp Equivalent to help(help/1). hheellpp((_+_W_h_a_t)) Show specified part of the manual. _W_h_a_t is one of: <_N_a_m_e>/<_A_r_i_t_y> Give help on specified predicate <_N_a_m_e> Give help on named predicate with any arity or C interface function with that name <_S_e_c_t_i_o_n> Display specified section. Section numbers are dash-separated numbers: 2-3 refers to section 2.3 of the manual. Section numbers are obtained using apropos/1. Examples: ?- help(assert). Give help on predicate assert ?- help(3-4). Display section 3.4 of the manual ?- help('PL_retry'). Give help on interface function PL_retry() See also apropos/1, and the SWI-Prolog home page at http://www.swi- prolog.org, which provides a FAQ, an HTML version of manual for online browsing and HTML and PDF versions for downloading. aapprrooppooss((_+_P_a_t_t_e_r_n)) Display all predicates, functions and sections that have _P_a_t_t_e_r_n in their name or summary description. Lowercase letters in _P_a_t_t_e_r_n also match a corresponding uppercase letter. Example: ?- apropos(file). Display predicates, functions and sec- tions that have `file' (or `File', etc.) in their summary description. eexxppllaaiinn((_+_T_o_E_x_p_l_a_i_n)) Give an explanation on the given `object'. The argument may be any Prolog data object. If the argument is an atom, a term of the form _N_a_m_e_/_A_r_i_t_y or a term of the form _M_o_d_u_l_e_:_N_a_m_e_/_A_r_i_t_y, explain will try to explain the predicate as well as possible references to it. eexxppllaaiinn((_+_T_o_E_x_p_l_a_i_n_, _-_E_x_p_l_a_n_a_t_i_o_n)) Unify _E_x_p_l_a_n_a_t_i_o_n with an explanation for _T_o_E_x_p_l_a_i_n. Backtracking yields further explanations. 22..77 CCoommmmaanndd--lliinnee hhiissttoorryy SWI-Prolog offers a query substitution mechanism called `history'. The availability of this feature is controlled by set_prolog_flag/2, using the history prolog-flag. By default, history is available if the prolog-flag readline is false. To enable this feature, remembering the last 50 commands, put the following into your startup file (see section 2.2): :- set_prolog_flag(history, 50). The history system allows the user to compose new queries from those typed before and remembered by the system. The available history commands are shown in table 2.1. History expansion is not done if these sequences appear in quoted atoms or strings. ______________________________________________ | !!. |Repeat last query | | !nr. |Repeat query numbered <_n_r> | | !str. |Repeat last query starting with <_s_t_r> | | h. |Show history of commands | |_!h.___|Show_this_list_______________________ | Table 2.1: History commands 22..88 RReeuussee ooff ttoopp--lleevveell bbiinnddiinnggss Bindings resulting from the successful execution of a top-level goal are asserted in a database. These values may be reused in further top-level queries as $Var. Only the latest binding is available. Example: 1 ?- maplist(plus(1), "hello", X). X = [105,102,109,109,112] Yes 2 ?- format('~s~n', [$X]). ifmmp Yes 3 ?- Figure 2.1: Reusing top-level bindings Note that variables may be set by executing =/2: 6 ?- X = statistics. X = statistics Yes 7 ?- $X. 28.00 seconds cpu time for 183,128 inferences 4,016 atoms, 1,904 functors, 2,042 predicates, 52 modules 55,915 byte codes; 11,239 external references Limit Allocated In use Heap : 624,820 Bytes Local stack : 2,048,000 8,192 404 Bytes Global stack : 4,096,000 16,384 968 Bytes Trail stack : 4,096,000 8,192 432 Bytes Yes 8 ?- 22..99 OOvveerrvviieeww ooff tthhee DDeebbuuggggeerr SWI-Prolog has a 6-port tracer, extending the standard 4-port tracer [Clocksin & Melish, 1987] with two additional ports. The optional _u_n_i_f_y port allows the user to inspect the result after unification of the head. The _e_x_c_e_p_t_i_o_n port shows exceptions raised by throw/1 or one of the built-in predicates. See section 4.9. The standard ports are called call, exit, redo, fail and unify. The tracer is started by the trace/0 command, when a spy point is reached and the system is in debugging mode (see spy/1 and debug/0) or when an exception is raised. The interactive top-level goal trace/0 means ``trace the next query''. The tracer shows the port, displaying the port name, the current depth of the recursion and the goal. The goal is printed using the Prolog predicate write_term/2. The style is defined by the prolog-flag debugger_print_options and can be modified using this flag or using the w, p and d commands of the tracer. 1 ?- visible(+all), leash(-exit). Yes 2 ?- trace, min([3, 2], X). Call: ( 3) min([3, 2], G235) ? creep Unify: ( 3) min([3, 2], G235) Call: ( 4) min([2], G244) ? creep Unify: ( 4) min([2], 2) Exit: ( 4) min([2], 2) Call: ( 4) min(3, 2, G235) ? creep Unify: ( 4) min(3, 2, G235) Call: ( 5) 3 < 2 ? creep Fail: ( 5) 3 < 2 ? creep Redo: ( 4) min(3, 2, G235) ? creep Exit: ( 4) min(3, 2, 2) Exit: ( 3) min([3, 2], 2) Yes [trace] 3 ?- Figure 2.2: Example trace On _l_e_a_s_h_e_d _p_o_r_t_s (set with the predicate leash/1, default are call, exit, redo and fail) the user is prompted for an action. All actions are single character commands which are executed wwiitthhoouutt waiting for a return, unless the command-line option -tty is active. Tracer options: + ((SSppyy)) Set a spy point (see spy/1) on the current predicate. - ((NNoo ssppyy)) Remove the spy point (see nospy/1) from the current predicate. / ((FFiinndd)) Search for a port. After the `/', the user can enter a line to specify the port to search for. This line consists of a set of letters indicating the port type, followed by an optional term, that should unify with the goal run by the port. If no term is specified it is taken as a variable, searching for any port of the specified type. If an atom is given, any goal whose functor has a name equal to that atom matches. Examples: /f Search for any fail port /fe solve Search for a fail or exit port of any goal with name solve /c solve(a, _) Search for a call to solve/2 whose first argument is a variable or the atom a /a member(_, _) Search for any port on member/2. This is equivalent to setting a spy point on member/2. . ((RReeppeeaatt ffiinndd)) Repeat the last find command (see `/'). A ((AAlltteerrnnaattiivveess)) Show all goals that have alternatives. C ((CCoonntteexxtt)) Toggle `Show Context'. If on the context module of the goal is displayed between square brackets (see section 5). Default is off. L ((LLiissttiinngg)) List the current predicate with listing/1. a ((AAbboorrtt)) Abort Prolog execution (see abort/0). b ((BBrreeaakk)) Enter a Prolog break environment (see break/0). c ((CCrreeeepp)) Continue execution, stop at next port. (Also return, space). d ((DDiissppllaayy)) Set the max_depth(_D_e_p_t_h) option of debugger_print_options, limiting the depth to which terms are printed. See also the w and p options. e ((EExxiitt)) Terminate Prolog (see halt/0). f ((FFaaiill)) Force failure of the current goal. g ((GGooaallss)) Show the list of parent goals (the execution stack). Note that due to tail recursion optimization a number of parent goals might not exist any more. h ((HHeellpp)) Show available options (also `?'). i ((IIggnnoorree)) Ignore the current goal, pretending it succeeded. l ((LLeeaapp)) Continue execution, stop at next spy point. n ((NNoo ddeebbuugg)) Continue execution in `no debug' mode. p ((PPrriinntt)) Set the prolog-flag debugger_print_options to [quoted(true), portray(true), max_depth(10), priority(699)]. This is the default. r ((RReettrryy)) Undo all actions (except for database and i/o actions) back to the call port of the current goal and resume execution at the call port. s ((SSkkiipp)) Continue execution, stop at the next port of tthhiiss goal (thus skipping all calls to children of this goal). u ((UUpp)) Continue execution, stop at the next port of tthhee ppaarreenntt goal (thus skipping this goal and all calls to children of this goal). This option is useful to stop tracing a failure driven loop. w ((WWrriittee)) Set the prolog-flag debugger_print_options to [quoted(true), attributes(write), priority(699)], bypassing portray/1, etc. The ideal 4 port model as described in many Prolog books [Clocksin & Melish, 1987] is not visible in many Prolog implementations because code optimisation removes part of the choice- and exit-points. Backtrack points are not shown if either the goal succeeded deterministically or its alternatives were removed using the cut. When running in debug mode (debug/0) choice points are only destroyed when removed by the cut. In debug mode, tail recursion optimisation is switched off. Reference information to all predicates available for manipulating the debugger is in section 4.38. 22..1100 CCoommppiillaattiioonn 22..1100..11 DDuurriinngg pprrooggrraamm ddeevveellooppmmeenntt During program development, programs are normally loaded using consult/1, or the list abbreviation. It is common practice to organise a project as a collection of source files and a _l_o_a_d_-_f_i_l_e, a Prolog file containing only use_module/[1,2] or ensure_loaded/1 directives, possibly with a definition of the _e_n_t_r_y_-_p_o_i_n_t of the program, the predicate that is normally used to start the program. This file is often called load.pl. If the entry-point is called _g_o, a typical session starts as: % pl 1 ?- [load]. Yes 2 ?- go. When using Windows, the user may open load.pl from the Windows explorer, which will cause plwin.exe to be started in the directory holding load.pl. Prolog loads load.pl before entering the top-level. 22..1100..22 FFoorr rruunnnniinngg tthhee rreessuulltt There are various options if you want to make your program ready for real usage. The best choice depends on whether the program is to be used only on machines holding the SWI-Prolog development system, the size of the program and the operating system (Unix vs. Windows). 22..1100..22..11 UUssiinngg PPrroollooggSSccrriipptt New in version 4.0.5 is the possibility to use a Prolog source file directly as a Unix script-file. the same mechanism is useful to specify additional parameters for running a Prolog file on Windows. If the first letter of a Prolog file is #, the first line is treated as comment. To create a Prolog script, make the first line start like this: #!/path/to/pl <_o_p_t_i_o_n_s> -s Prolog recognises this starting sequence and causes the interpreter to receive the following argument-list: /path/to/pl <_o_p_t_i_o_n_s> -s <_s_c_r_i_p_t> -- <_S_c_r_i_p_t_A_r_g_u_m_e_n_t_s> Instead of -s, the user may use -f to stop Prolog from looking for a personal initialisation file. Here is a simple script doing expression evaluation: #!/usr/bin/pl -q -t main -f eval :- current_prolog_flag(argv, Argv), append(_, [--|Args], Argv), concat_atom(Args, ' ', SingleArg), term_to_atom(Term, SingleArg), Val is Term, format('~w~n', [Val]). main :- catch(eval, E, (print_message(error, E), fail)), halt. main :- halt(1). And here are two example runs: % eval 1+2 3 % eval foo ERROR: Arithmetic: `foo/0' is not a function % TThhee WWiinnddoowwss vveerrssiioonn supports the #! construct too, but here it serves a rather different role. The Windows shell already allows the user to start Prolog source files directly through the Windows file-type association. Windows however makes it rather complicated to provide additional parameters, such as the required stack-size for an individual Prolog file. The #! line provides for this, providing a more flexible approach then changing the global defaults. The following starts Prolog with unlimited stack-size on the given source file: #!/usr/bin/pl -L0 -T0 -G0 -s .... Note the use of /usr/bin/pl, which specifies the interpreter. This argument is ignored in the Windows version, but required to ensure best cross-platform compatibility. 22..1100..22..22 CCrreeaattiinngg aa sshheellll--ssccrriipptt With the introduction of _P_r_o_l_o_g_S_c_r_i_p_t (see section 2.10.2.1), using shell-scripts as explained in this section has become redundant for most applications. Especially on Unix systems and not-too-large applications, writing a shell-script that simply loads your application and calls the entry-point is often a good choice. A skeleton for the script is given below, followed by the Prolog code to obtain the program arguments. #!/bin/sh base= PL=pl exec $PL -f none -g "load_files(['$base/load'],[silent(true)])" \ -t go -- $* go :- current_prolog_flag(argv, Arguments), append(_SytemArgs, [--|Args], Arguments), !, go(Args). go(Args) :- ... On Windows systems, similar behaviour can be achieved by creating a shortcut to Prolog, passing the proper options or writing a .bat file. 22..1100..22..33 CCrreeaattiinngg aa ssaavveedd--ssttaattee For larger programs, as well as for programs that are required to run on systems that do not have the SWI-Prolog development system installed, creating a saved state is the best solution. A saved state is created using qsave_program/[1,2] or using the linker plld(1). A saved state is a file containing machine-independent intermediate code in a format dedicated for fast loading. Optionally, the emulator may be integrated in the saved state, creating a single-file, but machine-dependent, executable. This process is described in chapter 10. 22..1100..22..44 CCoommppiillaattiioonn uussiinngg tthhee --cc ccoommmmaanndd--lliinnee ooppttiioonn This mechanism loads a series of Prolog source files and then creates a saved-state as qsave_program/2 does. The command syntax is: % pl [option ...] [-o output] -c file ... The _o_p_t_i_o_n_s argument are options to qsave_program/2 written in the format below. The option-names and their values are described with qsave_program/2. --_o_p_t_i_o_n_-_n_a_m_e=_o_p_t_i_o_n_-_v_a_l_u_e For example, to create a stand-alone executable that starts by executing main/0 and for which the source is loaded through load.pl, use the command % pl --goal=main --stand_alone=true -o myprog -c load.pl This performs exactly the same as executing % pl ?- [load]. ?- qsave_program(myprog, [ goal(main), stand_alone(true) ]). ?- halt. 22..1111 EEnnvviirroonnmmeenntt CCoonnttrrooll ((PPrroolloogg ffllaaggss)) The predicates current_prolog_flag/2 and set_prolog_flag/2 allow the user to examine and modify the execution environment. It provides access to whether optional features are available on this version, operating system, foreign-code environment, command-line arguments, version, as well as runtime flags to control the runtime behaviour of certain predicates to achieve compatibility with other Prolog environments. ccuurrrreenntt__pprroolloogg__ffllaagg((_?_K_e_y_, _-_V_a_l_u_e)) The predicate current_prolog_flag/2 defines an interface to installation features: options compiled in, version, home, etc. With both arguments unbound, it will generate all defined prolog-flags. With the `Key' instantiated it unify the value of the prolog-flag. Flag values are typed. Flags marked as bool can have the values true and false. Some prolog flags are not defined in all versions, which is normally indicated in the documentation below as _`_`_i_f _p_r_e_s_e_n_t _a_n_d _t_r_u_e_'_'. A boolean prolog-flag is true iff the prolog-flag is present aanndd the _V_a_l_u_e is the atom true. Tests for such flags should be written as below. ( current_prolog_flag(windows, true) -> ; ) aabboorrtt__wwiitthh__eexxcceeppttiioonn _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) Determines how abort/0 is realised. See the description of abort/0 for details. aaggcc__mmaarrggiinn _(_i_n_t_e_g_e_r_, _c_h_a_n_g_e_a_b_l_e_) If this amount of atoms has been created since the last atom-garbage collection, perform atom garbage collection at the first opportunity. Initial value is 10,000. May be changed. A value of 0 (zero) disables atom garbage collection. See also PL_register_atom(). aallllooww__vvaarriiaabbllee__nnaammee__aass__ffuunnccttoorr _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default is false), Functor(arg) is read as if it was written 'Functor'(arg). Some applications use the Prolog read/1 predicate for reading an application defined script language. In these cases, it is often difficult to explain to non-Prolog users of the application that constants and functions can only start with a lowercase letter. Variables can be turned into atoms starting with an uppercase atom by calling read_term/2 using the option variable_names and binding the variables to their name. Using this feature, F(x) can be turned into valid syntax for such script languages. Suggested by Robert van Engelen. SWI-Prolog specific. aarrggvv _(_l_i_s_t_) List is a list of atoms representing the command-line arguments used to invoke SWI-Prolog. Please note that aallll arguments are included in the list returned. aarrcchh _(_a_t_o_m_) Identifier for the hardware and operating system SWI-Prolog is running on. Used to select foreign files for the right architecture. See also section 9.4 and file_search_path/2. aassssoocciiaattee _(_a_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) On Windows systems, this is set to the filename-extension (e.g. pl or pro associated with plwin.exe. aauuttoollooaadd _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default) autoloading of library functions is enabled. Note that autoloading only works if the flag unknown is _n_o_t set to fail. See section 2.13. bbaacckkqquuootteedd__ssttrriinngg _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default false), read translates text between backquotes into a string object (see section 4.23). This flag is mainly for compatibility to LPA Prolog. bboouunnddeedd _(_b_o_o_l_) ISO prolog-flag. If true, integer representation is bound by min_integer and max_integer. If false integers can be arbitrary large and the min_integer and max_integer are not present. See section 4.26.2.1. cc__cccc _(_a_t_o_m_) Name of the C-compiler used to compile SWI-Prolog. Normally either gcc or cc. See section 9.7. cc__llddffllaaggss _(_a_t_o_m_) Special linker flags passed to link SWI-Prolog. See section 9.7. cc__lliibbss _(_a_t_o_m_) Libraries passed to the C-linker when SWI-Prolog was linked. May be used to determine the libraries needed to create statically linked extensions for SWI-Prolog. See section 9.7. cchhaarr__ccoonnvveerrssiioonn _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) Determines whether character-conversion takes place while reading terms. See also char_conversion/2. cchhaarraacctteerr__eessccaappeess _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default), read/1 interprets \ escape sequences in quoted atoms and strings. May be changed. This flag is local to the module in which it is changed. ccoommppiilleedd__aatt _(_a_t_o_m_) Describes when the system has been compiled. Only available if the C-compiler used to compile SWI-Prolog provides the __DATE__and __TIME__macros. ccoonnssoollee__mmeennuu _(_b_o_o_l_) Set to true in plwin.exe to indicate the console supports menus. See also section 4.34.2. ddddee _(_b_o_o_l_) Set to true if this instance of Prolog supports DDE as described in section 4.42. ddeebbuugg _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) Switch debugging mode on/off. If debug mode is activated the system traps encountered spy-points (see spy/1) and trace-points (see trace/1). In addition, tail-recursion optimisation is disabled and the system is more conservative in destroying choice-points to simplify debugging. Disabling these optimisations can cause the system to run out of memory on programs that behave correctly if debug mode is off. ddeebbuugg__oonn__eerrrroorr _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, start the tracer after an error is detected. Otherwise just continue execution. The goal that raised the error will normally fail. See also fileerrors/2 and the prolog-flag report_error. May be changed. Default is true, except for the runtime version. ddeebbuuggggeerr__pprriinntt__ooppttiioonnss _(_t_e_r_m_, _c_h_a_n_g_e_a_b_l_e_) This argument is given as option-list to write_term/2 for printing goals by the debugger. Modified by the `w', `p' and `<_N> d' commands of the debugger. Default is [quoted(true), portray(true), max_depth(10), attributes(portray)]. ddeebbuuggggeerr__sshhooww__ccoonntteexxtt _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, show the context module while printing a stack-frame in the tracer. Normally controlled using the `C' option of the tracer. ddoouubbllee__qquuootteess _(_c_o_d_e_s_,_c_h_a_r_s_,_a_t_o_m_,_s_t_r_i_n_g_, _c_h_a_n_g_e_a_b_l_e_) This flag determines how double-quotes strings are read by Prolog and is ---like character_escapes--- maintained for each module. If codes (default), a list of character-codes is returned, if chars a list of one-character atoms, if atom double quotes are the same as single-quotes and finally, string reads the text into a Prolog string (see section 4.23). See also atom_chars/2 and atom_codes/2. ddyynnaammiicc__ssttaacckkss _(_b_o_o_l_) If true, the system uses some form of `sparse-memory manage- ment' to realise the stacks. If false, malloc()/realloc() are used for the stacks. In earlier days this had consequences for foreign code. As of version 2.5, this is no longer the case. Systems using `sparse-memory management' are a bit faster as there is no stack-shifter. On most systems using sparse-memory management memory is actually returned to the system after a garbage collection or call to trim_stacks/0 (called by prolog/0 after finishing a user-query). eeddiittoorr _(_a_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) Determines the editor used by edit/1. See section 4.4 for details on selecting the editor used. eemmaaccss__iinnffeerriioorr__pprroocceessss _(_b_o_o_l_) If true, SWI-Prolog is running as an _i_n_f_e_r_i_o_r _p_r_o_c_e_s_s of (GNU/X-)Emacs. SWI-Prolog assumes this is the case if the environment variable EMACS is t and INFERIOR is yes. eennccooddiinngg _(_a_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) Default encoding used for opening files in text mode. The initial value is deduced from the environment. See section 2.17.1 for details. eexxeeccuuttaabbllee _(_a_t_o_m_) Path-name of the running executable. Used by qsave_program/2 as default emulator. ffiillee__nnaammee__vvaarriiaabblleess _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default false), expand $varname and ~ in arguments of built-in predicates that accept a file name (open/3, exists_file/1, access_file/2, etc.). The predicate expand_file_name/2 should be used to expand environment variables and wildcard patterns. This prolog-flag is intended for backward compatibility with older versions of SWI-Prolog. ffllooaatt__ffoorrmmaatt _(_a_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) C-library printf() format specification used by write/1 and friends to determine how floating point numbers are printed. The default is %g. The specified value is passed to printf() without further checking. For example, if you want more digits printed, %.12g will print all floats using 12 digits instead of the default 6. When using quoted-write, the output is guaranteed to contain a decimal dot or exponent, so read/1 reads a floating point number. See also format/[1,2], write_term/[2,3]. ggcc _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default), the garbage collector is active. If false, neither garbage-collection, nor stack-shifts will take place, even not on explicit request. May be changed. ggeenneerraattee__ddeebbuugg__iinnffoo _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default) generate code that can be debugged using trace/0, spy/1, etc. Can be set to false using the -nodebug. The predicate load_files/2 restores the value of this flag after loading a file, causing modifications to be local to a source file. Many of the libraries have :- set_prolog_flag(generate_debug_info, false) to hide their details from a normal trace. ggmmpp__vveerrssiioonn _(_i_n_t_e_g_e_r_) If Prolog is linked with GMP, this flag gives the major version of the GMP library used. See also section 9.6.7. ggnnuu__lliibbpptthhrreeaadd__vveerrssiioonn _(_a_t_o_m_) Linux systems only. Reports the version of the Linux thread library used. See section 8.2.1 for how it may affect you. gguuii _(_b_o_o_l_) Set to true if XPCE is around and can be used for graphics. hhiissttoorryy _(_i_n_t_e_g_e_r_, _c_h_a_n_g_e_a_b_l_e_) If _i_n_t_e_g_e_r >0, support Unix csh(1) like history as described in section 2.7. Otherwise, only support reusing commands through the command-line editor. The default is to set this prolog-flag to 0 if a command-line editor is provided (see prolog-flag readline) and 15 otherwise. hhoommee _(_a_t_o_m_) SWI-Prolog's notion of the home-directory. SWI-Prolog uses its home directory to find its startup file as <_h_o_m_e>/boot32.prc(32-bit machines) or <_h_o_m_e>/boot64.prc (64-bit machines) and to find its library as <_h_o_m_e>/library. hhwwnndd _(_i_n_t_e_g_e_r_) In plwin.exe, this refers to the MS-Windows window-handle of the console window. iinntteeggeerr__rroouunnddiinngg__ffuunnccttiioonn _(_d_o_w_n_,_t_o_w_a_r_d___z_e_r_o_) ISO prolog-flag describing rounding by // and rem arithmetic functions. Value depends on the C-compiler used. iissoo _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) Include some weird ISO compatibility that is incompatible to normal SWI-Prolog behaviour. Currently it has the following effect: o The //2 (float division) _a_l_w_a_y_s return a float, even if applied to integers that can be divided. o In the standard order of terms (see section 4.6.1), all floats are before all integers. o atom_length/2 yields an instantiation error if the first argument is a number. o clause/[2,3] raises a permission error when accessing static predicates. o abolish/[1,2] raises a permission error when accessing static predicates. llaarrggee__ffiilleess _(_b_o_o_l_) If present and true, SWI-Prolog has been compiled with _l_a_r_g_e _f_i_l_e _s_u_p_p_o_r_t (LFS) and is capable to access files larger than 2GB on 32-bit hardware. Large file-support is default on installations built using configure that support it and may be switched off using the configure option --disable-largefile. mmaaxx__aarriittyy _(_u_n_b_o_u_n_d_e_d_) ISO prolog-flag describing there is no maximum arity to compound terms. mmaaxx__iinntteeggeerr _(_i_n_t_e_g_e_r_) Maximum integer value if integers are _b_o_u_n_d_e_d. See also the flag bounded and section 4.26.2.1. mmaaxx__ttaaggggeedd__iinntteeggeerr _(_i_n_t_e_g_e_r_) Maximum integer value represented as a `tagged' value. Tagged integers require 1 word storage. Larger integers are represented as `indirect data' and require significantly more space. mmaaxx__tthhrreeaaddss _(_i_n_t_e_g_e_r_) Provided on multi-threaded versions to indicate the maximum number of Prolog threads supported. Currently (version 5.6.27) the limit is 100. mmiinn__iinntteeggeerr _(_i_n_t_e_g_e_r_) Minimum integer value if integers are _b_o_u_n_d_e_d. See also the flag bounded and section 4.26.2.1. mmiinn__ttaaggggeedd__iinntteeggeerr _(_i_n_t_e_g_e_r_) Start of the tagged-integer value range. ooppeenn__sshhaarreedd__oobbjjeecctt _(_b_o_o_l_) If true, open_shared_object/2 and friends are implemented, providing access to shared libraries (.so files) or dynamic link libraries (.DLL files). ooppttiimmiissee _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, compile in optimised mode. The initial value is true if Prolog was started with the -O command-line option. Currently optimise compilation implies compilation of arithmetic, and deletion of redundant true/0 that may result from expand_goal/2. Later versions might imply various other optimisations such as integrating small predicates into their callers, eliminating constant expressions and other predictable constructs. Source code optimisation is never applied to predicates that are declared dynamic (see dynamic/1). ppiidd _(_i_n_t_) Process identifier of the running Prolog process. Existence of this flag is implementation dependent. ppiippee _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, open(pipe(command), mode, Stream), etc. are sup- ported. Can be changed to disable the use of pipes in applications testing this feature. Not recommended. pprroommpptt__aalltteerrnnaattiivveess__nnoo__bbiinnddiinnggss _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If present and true, the top-level prints for alternatives if the query succeeded with pending choice-point, regardless of whether or not the query has variables. As there are no variables to bind it prints the answer _M_o_r_e_?. Here is an example ?- set_prolog_flag(prompt_alternatives_no_bindings, true). ?- (write(hello);write(world)). hello More? ; world rreeaaddlliinnee _(_b_o_o_l_) If true, SWI-Prolog is linked with the readline library. This is done by default if you have this library installed on your system. It is also true for the Win32 plwin.exe version of SWI-Prolog, which realises a subset of the readline functionality. rreessoouurrccee__ddaattaabbaassee _(_a_t_o_m_) Set to the absolute-filename of the attached state. Typically this is the file boot32.prc, the file specified with -x or the running executable. See also resource/3. rreeppoorrtt__eerrrroorr _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, print error messages, otherwise suppress them. May be changed. See also the debug_on_error prolog-flag. Default is true, except for the runtime version. rruunnttiimmee _(_b_o_o_l_) If present and true, SWI-Prolog is compiled with -DO_RUNTIME, disabling various useful development features (currently the tracer and profiler). ssaavveedd__pprrooggrraamm _(_b_o_o_l_) If present and true, Prolog is started from a state saved with qsave_program/[1,2]. sshhaarreedd__oobbjjeecctt__eexxtteennssiioonn _(_a_t_o_m_) Extension used by the operating system for shared objects. .so for most Unix systems and .dll for Windows. Used for locating files using the file_type executable. See also absolute_file_name/3. sshhaarreedd__oobbjjeecctt__sseeaarrcchh__ppaatthh _(_a_t_o_m_) Name of the environment variable used by the system to search for shared objects. ssiiggnnaallss _(_b_o_o_l_) Determine whether Prolog is handling signals (software interrupts). This flag is false if the hosting OS does not support signal handling or the command-line option -nosignals is active. See section 9.6.20.1 for details. ssyysstteemm__tthhrreeaadd__iidd _(_i_n_t_) On MT systems (section 8, refers to the thread-identifier used by the system for the calling thread. See also thread_self/1. ttaaiill__rreeccuurrssiioonn__ooppttiimmiissaattiioonn _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) Determines whether or not tail-recursion optimisation is enabled. Normally the value of this flag is equal to the debug flag. As programs may run out of stack if tail-recursion optimisation is omitted, it is sometimes necessary to enable it during debugging. ttiimmeezzoonnee _(_i_n_t_e_g_e_r_) Offset in seconds west of GMT of the current time-zone. Set at initialization time from the timezone variable associated with the POSIX tzset() function. See also convert_time/2. ttoopplleevveell__pprriinntt__aannoonn _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true, top-level variables starting with an underscore (_) are printed normally. If false they are hidden. This may be used to hide bindings in complex queries from the top-level. ttoopplleevveell__pprriinntt__ooppttiioonnss _(_t_e_r_m_, _c_h_a_n_g_e_a_b_l_e_) This argument is given as option-list to write_term/2 for printing results of queries. Default is [quoted(true), portray(true), max_depth(10), attributes(portray)]. ttoopplleevveell__vvaarr__ssiizzee _(_i_n_t_, _c_h_a_n_g_e_a_b_l_e_) Maximum size counted in literals of a term returned as a binding for a variable in a top-level query that is saved for re-use using the $ variable reference. See section 2.8. ttrraaccee__ggcc _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (false is the default), garbage collections and stack-shifts will be reported on the terminal. May be changed. ttttyy__ccoonnttrrooll _(_b_o_o_l_) Determines whether the terminal is switched to raw mode for get_single_char/1, which also reads the user-actions for the trace. May be set. See also the +/-tty command-line option. uunniixx _(_b_o_o_l_) If present and true, the operating system is some version of Unix. Defined if the C-compiler used to compile this version of SWI-Prolog either defines __unix__ or unix. On other systems this flag is not available. uunnkknnoowwnn _(_f_a_i_l_,_w_a_r_n_i_n_g_,_e_r_r_o_r_, _c_h_a_n_g_e_a_b_l_e_) Determines the behaviour if an undefined procedure is encountered. If fail, the predicates fails silently. If warn, a warning is printed, and execution continues as if the predicate was not defined and if error (default), an existence_error exception is raised. This flag is local to each module. Switching this flag to fail disables autoloading and thus forces complete and consistent use of use_module/[1,2] to load the required libraries. vveerrbboossee _(_A_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) This flags is used by print_message/2. If its value is silent, messages of type informational and banner are suppressed. The -q switches the value from the initial normal to silent. vveerrbboossee__aauuttoollooaadd _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true the normal consult message will be printed if a library is autoloaded. By default this message is suppressed. Intended to be used for debugging purposes. vveerrbboossee__llooaadd _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If false normal consult messages will be suppressed. Default is true. The value of this flag is normally controlled by the option silent(_B_o_o_l) privided by load_files/2. vveerrbboossee__ffiillee__sseeaarrcchh _(_b_o_o_l_, _c_h_a_n_g_e_a_b_l_e_) If true (default false), print messages indicating the progress of absolute_file_name/[2,3] in locating files. Intended for debugging complicated file-search paths. See also file_search_path/2. vveerrssiioonn _(_i_n_t_e_g_e_r_) The version identifier is an integer with value: 10000_*Major+ 100_*Minor+_P_a_t_c_h Note that in releases up to 2.7.10 this prolog-flag yielded an atom holding the three numbers separated by dots. The current representation is much easier for implementing version-conditional statements. wwiinnddoowwss _(_b_o_o_l_) If present and true, the operating system is an implementation of Microsoft Windows (NT/2000/XP, etc.). This flag is only available on MS-Windows based versions. wwrriittee__aattttrriibbuutteess _(_a_t_o_m_, _c_h_a_n_g_e_a_b_l_e_) Defines how write/1 an friends write attributed variables. The option values are described with the attributes option of write_term/3. Default is ignore. wwrriittee__hheellpp__wwiitthh__oovveerrssttrriikkee _(_b_o_o_l_) Internal flag used by help/1 when writing to a terminal. If present and true it prints bold and underlined text using _o_v_e_r_s_t_r_i_k_e. xxppccee _(_b_o_o_l_) Available and set to true if the XPCE graphics system is loaded. xxppccee__vveerrssiioonn _(_a_t_o_m_) Available and set to the version of the loaded XPCE system. sseett__pprroolloogg__ffllaagg((_+_K_e_y_, _+_V_a_l_u_e)) Define a new prolog-flag or change its value. _K_e_y is an atom. If the flag is a system-defined flag that is not marked _c_h_a_n_g_e_a_b_l_e above, an attempt to modify the flag yields a permission_error. If the provided _V_a_l_u_e does not match the type of the flag, a type_error is raised. In addition to ISO, SWI-Prolog allows for user-defined prolog flags. The type of the flag is determined from the initial value and cannot be changed afterwards. 22..1122 AAnn oovveerrvviieeww ooff hhooookk pprreeddiiccaatteess SWI-Prolog provides a large number of hooks, mainly to control handling messages, debugging, startup, shut-down, macro-expansion, etc. Below is a summary of all defined hooks with an indication of their portability. o _p_o_r_t_r_a_y_/_1 Hook into write_term/3 to alter the way terms are printed (ISO). o _m_e_s_s_a_g_e___h_o_o_k_/_3 Hook into print_message/2 to alter the way system messages are printed (Quintus/SICStus). o _l_i_b_r_a_r_y___d_i_r_e_c_t_o_r_y_/_1 Hook into absolute_file_name/3 to define new library directories. (most Prolog system). o _f_i_l_e___s_e_a_r_c_h___p_a_t_h_/_2 Hook into absolute_file_name/3 to define new search-paths (Quintus/SICStus). o _t_e_r_m___e_x_p_a_n_s_i_o_n_/_2 Hook into load_files/2 to modify read terms before they are compiled (macro-processing) (most Prolog system). o _g_o_a_l___e_x_p_a_n_s_i_o_n_/_2 Same as term_expansion/2 for individual goals (SICStus). o _p_r_o_l_o_g___l_o_a_d___f_i_l_e_/_2 Hook into load_files/2 to load other data-formats for Prolog sources from `non-file' resources. The load_files/2 predicate is the ancestor of consult/1, use_module/1, etc. o _p_r_o_l_o_g___e_d_i_t_:_l_o_c_a_t_e_/_3 Hook into edit/1 to locate objects (SWI). o _p_r_o_l_o_g___e_d_i_t_:_e_d_i_t___s_o_u_r_c_e_/_1 Hook into edit/1 to call some internal editor (SWI). o _p_r_o_l_o_g___e_d_i_t_:_e_d_i_t___c_o_m_m_a_n_d_/_2 Hook into edit/1 to define the external editor to use (SWI). o _p_r_o_l_o_g___l_i_s_t___g_o_a_l_/_1 Hook into the tracer to list the code associated to a particular goal (SWI). o _p_r_o_l_o_g___t_r_a_c_e___i_n_t_e_r_c_e_p_t_i_o_n_/_4 Hook into the tracer to handle trace-events (SWI). o _p_r_o_l_o_g_:_d_e_b_u_g___c_o_n_t_r_o_l___h_o_o_k_/_1 Hook in spy/1, nospy/1, nospyall/0 and debugging/0 to extend these control-predicates to higher-level libraries. o _p_r_o_l_o_g_:_h_e_l_p___h_o_o_k_/_1 Hook in help/0, help/1 and apropos/1 to extend the help-system. o _r_e_s_o_u_r_c_e_/_3 Defines a new resource (not really a hook, but similar) (SWI). o _e_x_c_e_p_t_i_o_n_/_3 Old attempt to a generic hook mechanism. Handles undefined predicates (SWI). o _a_t_t_r___u_n_i_f_y___h_o_o_k_/_2 Unification hook for attributed variables. Can be defined in any module. See section 6.1 for details. 22..1133 AAuuttoommaattiicc llooaaddiinngg ooff lliibbrraarriieess If ---at runtime--- an undefined predicate is trapped the system will first try to import the predicate from the module's default module. If this fails the _a_u_t_o _l_o_a_d_e_r is activated. On first activation an index to all library files in all library directories is loaded in core (see library_directory/1 and file_search_path/2). If the undefined predicate can be located in the one of the libraries that library file is automatically loaded and the call to the (previously undefined) predicate is restarted. By default this mechanism loads the file silently. The current_prolog_flag/2verbose_autoload is provided to get verbose loading. The prolog-flag autoload can be used to enable/disable the entire auto load system. The auto-loader only works if the unknown flag (see unknown/2) is set to trace (default). A more appropriate interaction with this flag should be considered. Autoloading only handles (library) source files that use the module mechanism described in chapter 5. The files are loaded with use_module/2 and only the trapped undefined predicate will be imported to the module where the undefined predicate was called. Each library directory must hold a file INDEX.pl that contains an index to all library files in the directory. This file consists of lines of the following format: index(Name, Arity, Module, File). The predicate make/0 updates the autoload index. It searches for all library directories (see library_directory/1 and file_search_path/2) holding the file MKINDEX.pl or INDEX.pl. If the current user can write or create the file INDEX.pl and it does not exist or is older than the directory or one of its files, the index for this directory is updated. If the file MKINDEX.pl exists updating is achieved by loading this file, normally containing a directive calling make_library_index/2. Otherwise make_library_index/1is called, creating an index for all *.pl files containing a module. Below is an example creating a completely indexed library directory. % mkdir ~/lib/prolog % cd !$ % pl -g true -t 'make_library_index(.)' If there are more than one library files containing the desired predicate the following search schema is followed: 1. If there is a library file that defines the module in which the undefined predicate is trapped, this file is used. 2. Otherwise library files are considered in the order they appear in the library_directory/1 predicate and within the directory alphabetically. mmaakkee__lliibbrraarryy__iinnddeexx((_+_D_i_r_e_c_t_o_r_y)) Create an index for this directory. The index is written to the file 'INDEX.pl' in the specified directory. Fails with a warning if the directory does not exist or is write protected. mmaakkee__lliibbrraarryy__iinnddeexx((_+_D_i_r_e_c_t_o_r_y_, _+_L_i_s_t_O_f_P_a_t_t_e_r_n_s)) Normally used in MKINDEX.pl, this predicate creates INDEX.pl for _D_i_r_e_c_t_o_r_y, indexing all files that match one of the file-patterns in _L_i_s_t_O_f_P_a_t_t_e_r_n_s. Sometimes library packages consist of one public load file and a number of files used by this load-file, exporting predicates that should not be used directly by the end-user. Such a library can be placed in a sub-directory of the library and the files containing public functionality can be added to the index of the library. As an example we give the XPCE library's MKINDEX.pl, including the public functionality of trace/browse.pl to the autoloadable predicates for the XPCE package. :- make_library_index('.', [ '*.pl', 'trace/browse.pl' ]). rreellooaadd__lliibbrraarryy__iinnddeexx Force reloading the index after modifying the set of library directories by changing the rules for library_directory/1, file_search_path/2, adding or deleting INDEX.pl files. This predicate does _n_o_t update the INDEX.pl files. Check make_library_index/[1,2] and make/0 for updating the index files. Normally, the index is reloaded automatically if a predicate cannot be found in the index and the set of library directories has changed. Using reload_library_index/0 is necessary if directories are removed or the order of the library directories is changed. 22..1144 GGaarrbbaaggee CCoolllleeccttiioonn SWI-Prolog provides garbage-collection, last-call optimization and atom garbage collection. These features are controlled using prolog flags (see current_prolog_flag/2). 22..1155 SSyynnttaaxx NNootteess SWI-Prolog uses ISO-Prolog standard syntax, which is closely compatible to Edinburgh Prolog syntax. A description of this syntax can be found in the Prolog books referenced in the introduction. Below are some non-standard or non-common constructs that are accepted by SWI-Prolog: o 0'<_c_h_a_r> This construct is not accepted by all Prolog systems that claim to have Edinburgh compatible syntax. It describes the character code of <_c_h_a_r>. To test whether C is a lower case character one can use between(0'a, 0'z, C). If character codes are enabled (default) <_c_h_a_r> can use \ escape sequences. The sequence 0'\t represents the tab character using symbolic notation. o /* .../* ...*/ ...*/ The /* ...*/ comment statement can be nested. This is useful if some code with /* ...*/ comment statements in it should be commented out. 22..1155..11 IISSOO SSyynnttaaxx SSuuppppoorrtt SWI-Prolog offers ISO compatible extensions to the Edinburgh syntax. 22..1155..11..11 PPrroocceessssoorr CChhaarraacctteerr SSeett The processor character set specifies the class of each character used for parsing Prolog source text. Character classification is fixed to use UCS/Unicode as provided by the C-library wchar_t based primitives. See also section 2.17. 22..1155..11..22 CChhaarraacctteerr EEssccaappee SSyynnttaaxx Within quoted atoms (using single quotes: '<_a_t_o_m>'special characters are represented using escape-sequences. An escape sequence is lead in by the backslash (\) character. The list of escape sequences is compatible with the ISO standard, but contains one extension and the interpretation of numerically specified characters is slightly more flexible to improve compatibility. \a Alert character. Normally the ASCII character 7 (beep). \b Backspace character. \c No output. All input characters up to but not including the first non-layout character are skipped. This allows for the specification of pretty-looking long lines. For compatibility with Quintus Prolog. Not supported by ISO. Example: format('This is a long line that would look better if it was \c split across multiple physical lines in the input') \ No output. Skips input till the next non-layout character or to the end of the next line. Same intention as \c but ISO compatible. \f Form-feed character. \n Next-line character. \r Carriage-return only (i.e. go back to the start of the line). \t Horizontal tab-character. \v Vertical tab-character (ASCII 11). \xXX..\ Hexadecimal specification of a character. The closing \ is obligatory according to the ISO standard, but optional in SWI-Prolog to enhance compatibility to the older Edinburgh standard. The code \xa\3 emits the character 10 (hexadecimal `a') followed by `3'. Characters specified this way are interpreted as Unicode characters. See also \u. \uXXXX Unicode character specification where the character is specified using _e_x_a_c_t_l_y 4 hexadecimal digits. This is an extension to the ISO standard fixing two problems. First of all, where \x defines a numeric character code, it doesn't specify the character set in which the character should be interpreted. Second, it is not needed to use the idiosyncratic closing \ ISO Prolog syntax. \UXXXXXXXX Same as \uXXXX, but using 8 digits to cover the whole Unicode set. \40 Octal character specification. The rules and remarks for hexadecimal specifications apply to octal specifications as well. \<_c_h_a_r_a_c_t_e_r> Any character immediately preceded by a \ and not covered by the above escape sequences is copied verbatim. Thus, '\\' is an atom consisting of a single \ and '\'' and '''' both describe the atom with a single '. Character escaping is only available if the current_prolog_flag(character_escapes, true) is active (default). See current_prolog_flag/2. Character escapes conflict with writef/2 in two ways: \40 is interpreted as decimal 40 by writef/2, but character escapes handling by read has already interpreted as 32 (40 octal). Also, \l is translated to a single `l'. It is advised to use the more widely supported format/[2,3] predicate instead. If you insist upon using writef/2, either switch character_escapes to false, or use double \\, as in writef('\\l'). 22..1155..11..33 SSyynnttaaxx ffoorr nnoonn--ddeecciimmaall nnuummbbeerrss SWI-Prolog implements both Edinburgh and ISO representations for non-decimal numbers. According to Edinburgh syntax, such numbers are written as <_r_a_d_i_x>'<_n_u_m_b_e_r>, where <_r_a_d_i_x> is a number between 2 and 36. ISO defines binary, octal and hexadecimal numbers using 0[bxo]<_n_u_m_b_e_r>. For example: A is 0b100 \/ 0xf00 is a valid expression. Such numbers are always unsigned. 22..1155..11..44 UUnniiccooddee PPrroolloogg ssoouurrccee The ISO standard specifies the Prolog syntax in ASCII characters. As SWI-Prolog supports Unicode in source files we must extend the syntax. This section describes the implication for the source files, while writing international source files is described in section 3.1.3. The SWI-Prolog Unicode character classification is based on version 4.1.0 of the Unicode standard. Please that char_type/2 and friends, intended to be used with all text except Prolog source code is based on the C-library locale-based classification routines. o _Q_u_o_t_e_d _a_t_o_m_s _a_n_d _s_t_r_i_n_g_s Any character of any script can be used in quoted atoms and strings. The escape sequences \uXXXX and \UXXXXXXXX (see section 2.15.1.2) were introduced to specify Unicode code points in ASCII files. o _A_t_o_m_s _a_n_d _V_a_r_i_a_b_l_e_s We handle them in one item as they are closely related. The Unicode standard defines a syntax for identifiers in computer languages. In this syntax identifiers start with ID_Start followed by a sequence of ID_Continue codes. Such sequences are handled as a single token in SWI-Prolog. The token is a _v_a_r_i_a_b_l_e iff it starts with an uppercase character or an underscore (_). Otherwise it is an atom. Note that many languages do not not have the notion of character-case. In such languages variables _m_u_s_t be written as _name. o _W_h_i_t_e _s_p_a_c_e All characters marked as separators in the Unicode tables are handled as layout characters. o _O_t_h_e_r _c_h_a_r_a_c_t_e_r_s The first 128 characters follow the ISO Prolog standard. All other characters not covered by the rules above are considered `solo' characters: they form single-character atoms. We would like to have a more appropriate distinction between what is known to Prolog as `solo' characters and `symbol' characters. 22..1155..11..55 SSiinngglleettoonn vvaarriiaabbllee cchheecckkiinngg A singleton variable is a variable that appears only one time in a clause. It can always be replaced by _, the _a_n_o_n_y_m_o_u_s variable. In some cases however people prefer to give the variable a name. As mistyping a variable is a common mistake, Prolog systems generally give a warning (controlled by style_check/1) if a variable is used only once. The system can be informed a variable is known to appear once by _s_t_a_r_t_i_n_g it with an underscore. E.g. _Name. Please note that any variable, except plain _ shares with variables of the same name. The term t(_X, _X) is equivalent to t(X, X), which is _d_i_f_f_e_r_e_n_t from t(_, _). As Unicode requires variables to start with an underscore in many languages this schema needs to be extended. First we define the two classes of named variables. o _N_a_m_e_d _s_i_n_g_l_e_t_o_n _v_a_r_i_a_b_l_e_s Named singletons start with a double underscore (__) or a single underscore followed by an uppercase letter. E.g. __var or _Var. o _N_o_r_m_a_l _v_a_r_i_a_b_l_e_s All other variables are `normal' variables. Note this makes _var a normal variable. Any normal variable appearing exactly ones in the clause _a_n_d any named singleton variables appearing more than once are reported. Below are some examples with warnings in the right column. ___________________________________________________________________________ | test(_). | | | test(_a). |Singleton variables: [_a] | | test(A). |Singleton variables: [A] | | test(_A). | | | test(__a). | | | test(_, _). | | | test(_a, _a). | | | test(__a, __a).S|ingleton-marked variables appearing more than once: [__a] | | test(_A, _A). |Singleton-marked variables appearing more than once: [_A] | |_test(A,_A).__|__________________________________________________________|_ 22..1166 IInnffiinniittee ttrreeeess ((ccyycclliicc tteerrmmss)) SWI-Prolog has limited support for infinite trees, also known as cyclic terms. Full support requires special code in all built-in predicates that require recursive exploration of a term. The current version supports cycles terms in the pure Prolog kernel including the garbage collector and in the following predicates: =../2, ==/2, =@=/2, =/2, @=/2, @>/2, \==/2, \=@=/2, \=/2, acyclic_term/1, bagof/3, compare/3, copy_term/2, cyclic_term/1, dif/2, duplicate_term/2, findall/3, ground/1, hash_term/2, numbervars/[3,4], recorda/3, recordz/3, setof/3, term_variables/2, throw/1, when/2, write/1 (incomplete) . 22..1177 WWiiddee cchhaarraacctteerr ssuuppppoorrtt SWI-Prolog supports _w_i_d_e _c_h_a_r_a_c_t_e_r_s, characters with character codes above 255 that cannot be represented in a single _b_y_t_e. _U_n_i_v_e_r_s_a_l _C_h_a_r_a_c_t_e_r _S_e_t (UCS) is the ISO/IEC 10646 standard that specifies a unique 31-bits unsigned integer for any character in any language. It is a superset of 16-bit Unicode, which in turn is a superset of ISO 8859-1 (ISO Latin-1), a superset of US-ASCII. UCS can handle strings holding characters from multiple languages and character classification (uppercase, lowercase, digit, etc.) and operations such as case-conversion are unambiguously defined. For this reason SWI-Prolog has two representations for atoms and string objects (see section 4.23. If the text fits in ISO Latin-1, it is represented as an array of 8-bit characters. Otherwise the text is represented as an array of 32-bit numbers. This representational issue is completely transparent to the Prolog user. Users of the foreign language interface as described in section 9 sometimes need to be aware of these issues though. Character coding comes into view when characters of strings need to be read from or written to file or when they have to be communicated to other software components using the foreign language interface. In this section we only deal with I/O through streams, which includes file I/O as well as I/O through network sockets. 22..1177..11 WWiiddee cchhaarraacctteerr eennccooddiinnggss oonn ssttrreeaammss Although characters are uniquely coded using the UCS standard internally, streams and files are byte (8-bit) oriented and there are a variety of ways to represent the larger UCS codes in an 8-bit octet stream. The most popular one, especially in the context of the web, is UTF-8. Bytes 0 ... 127 represent simply the corresponding US-ASCII character, while bytes 128 ... 255 are used for multi-byte encoding of characters placed higher in the UCS space. Especially on MS-Windows the 16-bit Unicode standard, represented by pairs of bytes is also popular. Prolog I/O streams have a property called _e_n_c_o_d_i_n_g which specifies the used encoding that influence get_code/2 and put_code/2 as well as all the other text I/O predicates. The default encoding for files is derived from the Prolog flag encoding, which is initialised from the environment. If the environment variable LANG ends in "UTF-8", this encoding is assumed. Otherwise the default is text and the translation is left to the wide-character functions of the C-library. The encoding can be specified explicitly in load_files/2 for loading Prolog source with an alternative encoding, open/4 when opening files or using set_stream/2 on any open stream. For Prolog source files we also provide the encoding/1 directive that can be used to switch between encodings that are compatible to US-ASCII (ascii, iso_latin_1, utf8 and many locales). See also section 3.1.3 for writing Prolog files with non-US-ASCII characters and section 2.15.1.4 for syntax issues. For additional information and Unicode resources, please visit http://www.unicode.org/. SWI-Prolog currently defines and supports the following encodings: oocctteett Default encoding for binary streams. This causes the stream to be read and written fully untranslated. aasscciiii 7-bit encoding in 8-bit bytes. Equivalent to iso_latin_1, but generates errors and warnings on encountering values above 127. iissoo__llaattiinn__11 8-bit encoding supporting many western languages. This causes the stream to be read and written fully untranslated. tteexxtt C-library default locale encoding for text files. Files are read and written using the C-library functions mbrtowc() and wcrtomb(). This may be the same as one of the other locales, notably it may be the same as iso_latin_1 for western languages and utf8 in a UTF-8 context. uuttff88 Multi-byte encoding of full UCS, compatible to ascii. See above. uunniiccooddee__bbee Unicode _B_i_g _E_n_d_i_a_n. Reads input in pairs of bytes, most significant byte first. Can only represent 16-bit characters. uunniiccooddee__llee Unicode _L_i_t_t_l_e _E_n_d_i_a_n. Reads input in pairs of bytes, least significant byte first. Can only represent 16-bit characters. Note that not all encodings can represent all characters. This implies that writing text to a stream may cause errors because the stream cannot represent these characters. The behaviour of a stream on these errors can be controlled using set_stream/2. Initially the terminal stream write the characters using Prolog escape sequences while other streams generate an I/O exception. 22..1177..11..11 BBOOMM:: BByyttee OOrrddeerr MMaarrkk From section 2.17.1, you may have got the impression text-files are complicated. This section deals with a related topic, making live often easier for the user, but providing another worry to the programmer. BBOOMM or _B_y_t_e _O_r_d_e_r _M_a_r_k_e_r is a technique for identifying Unicode text-files as well as the encoding they use. Such files start with the Unicode character 0xFEFF, a non-breaking, zero-width space character. This is a pretty unique sequence that is not likely to be the start of a non-Unicode file and uniquely distinguishes the various Unicode file formats. As it is a zero-width blank, it even doesn't produce any output. This solves all problems, or ... Some formats start of as US-ASCII and may contain some encoding mark to switch to UTF-8, such as the encoding="UTF-8" in an XML header. Such formats often explicitly forbid the the use of a UTF-8 BOM. In other cases there is additional information telling the encoding making the use of a BOM redundant or even illegal. The BOM is handled by SWI-Prolog open/4 predicate. By default, text-files are probed for the BOM when opened for reading. If a BOM is found, the encoding is set accordingly and the property bom(_t_r_u_e) is available through stream_property/2. When opening a file for writing, writing a BOM can be requested using the option bom(_t_r_u_e) with open/4. 22..1188 SSyysstteemm lliimmiittss 22..1188..11 LLiimmiittss oonn mmeemmoorryy aarreeaass SWI-Prolog has a number of memory areas which are only enlarged to a certain limit. The default sizes for these areas should suffice for most applications, but big applications may require larger ones. They are modified by command-line options. The table below shows these areas. The first column gives the option name to modify the size of the area. The option character is immediately followed by a number and optionally by a k or m. With k or no unit indicator, the value is interpreted in Kbytes (1024 bytes), with m, the value is interpreted in Mbytes (10241* 024 bytes). The local-, global- and trail-stack are limited to 128 Mbytes on 32 bit processors, or more generally to 2 to the power bits-per-long - 5 bytes. The PrologScript facility described in section 2.10.2.1 provides a mechanism for specifying options with the load-file. On Windows the default stack-sizes are controlled using the Windows registry on the key HKEY_CURRENT_USER\Software\SWI\Prolog using the names localSize, globalSize and trailSize. The value is a DWORD expressing the default stack size in Kbytes. A GUI for modifying these values is provided using the XPCE package. To use this, start the XPCE manual tools using manpce/0, after which you find _P_r_e_f_e_r_e_n_c_e_s in the _F_i_l_e menu. ___________________________________________________________ |_Option_|Default_|Area_name______|Description____________|_||-L||2Mllooccaa||llTssttaacckkhe|l||||ocal|stack is used | | to store the execu- | | || | | tion environments of | | || | | procedure invocations. | | || | | The space for an en- | | || | | vironment is reclaimed | | || | | when it fails, exits | | || | | without leaving choice | | || | | points, the alterna- | | || | | tives are cut of with | | || | | | | || | | the !/0 predicate or | | || | | no choice points have | | || | | been created since the | | || | | invocation and the last | | || | | subclause is started | | || | | (tail recursion optimi- | | || || || | ||sation). || | || | -G | 4M |gglloobbaall ssttaacckk ||Theusglobaled stacktois store| terms | | | ||created during Prolog's | | | | ||execution. Terms on | | | | || | | | | ||this stack will be re- | | | | ||claimed by backtracking | | | | ||to a point before the | | | | ||term was created or | | | | ||by garbage collection | | | | ||(provided the term is | || || || ||no||longer referenced). || | -T | 4M |ttrraaiill ssttaacckk ||Theusetraild stackto isstore| as- | | | ||signments during execu- | | | | || | | | | ||tion. Entries on this | | | | ||stack remain alive un- | | | | ||til backtracking before | | | | ||the point of creation | | | | ||or the garbage collec- | || || || ||tor determines||they are || ||| -A |||1M |||aarrgguummeenntt ssttaacc||norkkneeded||any||longer.Th|e||argument stack is | | | used || to store one | | | | of ||the intermediate| | | | code ||interpreter's reg-| | | | ister||s. The amount| | | | of sp||ace needed on this| | | | stack||is determined en- | | | | tirel||y by the depth in| | | | which||terms are nested | | | | in t||he clauses that| | | | const||itute the program.| | | | Overf||low is most likely| | | | when ||using long strings| | | | in a ||clause. | | | | In ad||dition, this stack| | | | is us||ed by some built-| | | | || | | | | in pr||edicates to handle| | | | cycli||c terms. Its de-| | | | fault|| size limit is | | | | propo||rtional to the| | | | globa||l stack limit such| | | | that || it will never | |________|________|_______________overf||low.______________|_ Table 2.2: Memory areas 22..1188..11..11 TThhee hheeaapp With the heap, we refer to the memory area used by malloc() and friends. SWI-Prolog uses the area to store atoms, functors, predicates and their clauses, records and other dynamic data. As of SWI-Prolog 2.8.5, no limits are imposed on the addresses returned by malloc() and friends. On some machines, the runtime stacks described above are allocated using `sparse allocation'. Virtual space up to the limit is claimed at startup and committed and released while the area grows and shrinks. On Win32 platform this is realised using VirtualAlloc() and friends. On Unix systems this is realised using mmap(). 22..1188..22 OOtthheerr LLiimmiittss CCllaauusseess The only limit on clauses is their arity (the number of arguments to the head), which is limited to 1024. Raising this limit is easy and relatively cheap, removing it is harder. AAttoommss aanndd SSttrriinnggss SWI-Prolog has no limits on the sizes of atoms and strings. read/1 and its derivatives however normally limit the number of newlines in an atom or string to 5 to improve error detection and recovery. This can be switched off with style_check/1. The number of atoms is limited to 16777216 (16M) on 32-bit machines. On 64-bit machines this is virtually unlimited. See also section 9.6.2.1. MMeemmoorryy aarreeaass On 32-bit hardware, SWI-Prolog data is packed in a 32-bit word, which contains both type and value information. The size of the various memory areas is limited to 128 Mb for each of the areas, except for the program heap, which is not limited. On 64-bit hardware there are no meaningful limits. IInntteeggeerrss Integers are 64-bit on 32 as well as 64-bit machines. Integers up to the value of the max_tagged_integer prolog-flag are represented more efficiently on the stack. For clauses and records the difference is much smaller. FFllooaattss Floating point numbers are represented as C-native double precision floats, 64 bit IEEE on most machines. 22..1188..33 RReesseerrvveedd NNaammeess The boot compiler (see -b option) does not support the module system. As large parts of the system are written in Prolog itself we need some way to avoid name clashes with the user's predicates, database keys, etc. Like Edinburgh C-Prolog [Pereira, 1986] all predicates, database keys, etc. that should be hidden from the user start with a dollar ($) sign (see style_check/1). 22..1199 SSWWII--PPrroolloogg aanndd 6644--bbiitt mmaacchhiinneess SWI-Prolog support for 64-bit machines started with version 2.8 on DEC Alpha CPUs running Linux. Initially 64-bit hardware was developed to deal with the addressing demands of large databases, running primarily on expensive server hardware. Recently (2007) we see CPUs that support 64-bit addressing become commonplace, even in low-budget desktop hardware. Most todays 64-bit platforms are capable of running both 32-bit and 64-bit applications. This asks for some clarifications on the advantages and drawbacks of 64-bit addressing for (SWI-)Prolog. 22..1199..11 SSuuppppoorrtteedd ppllaattffoorrmmss On Unix systems, 64-bit addressing is configured using configure. Traditionally, both long and void* are 64-bits on these machines. Version 5.6.26 introduces support for 64-bit MS-Windows (Windows XP and Vista 64-bit editions) on amd64 (x64) hardware. Win64 uses long integers of only 32-bits. Version 5.6.26 introduces support for such platforms. 22..1199..22 CCoommppaarriinngg 3322-- aanndd 6644--bbiittss PPrroolloogg Most of Prolog's memory-usage consists of pointers. This indicates the primary drawback: Prolog memory usage almost doubles when using the 64 bit addressing model. Using more memory means copying more data between CPU and main memory, slowing down the system. What than are the advantages? First of all, SWI-Prolog's addressing of the Prolog stacks does not cover the whole address space due to the use of _t_y_p_e _t_a_g _b_i_t_s and _g_a_r_b_a_g_e _c_o_l_l_e_c_t_i_o_n _f_l_a_g_s. On 32-bit hardware the stacks are limited to 128MB each. This tends to be too low for demanding applications on modern hardware. On 64-bit hardware the limit is 232 times higher, exceeding the addressing capabilities of todays CPUs and operating systems. This implies Prolog can be started with stacks sizes that use the full capabilities of your hardware. Multi-threaded applications profit much more. SWI-Prolog threads claim the full stacksize limit in _v_i_r_t_u_a_l _a_d_d_r_e_s_s _s_p_a_c_e and each thread comes with its own set of stacks. This approach quickly exhaust virtual memory on 32-bit systems but poses no problems when using 64-bit addresses. The implications theoretical performance loss due to increased memory bandwidth implied by exchanging wider pointers depend on the design of the hardware. We only have data for the popular IA32 vs. AMD64 architectures. Here is appears that the loss is compensated for by a an instruction set that has been optimized for modern programming. In particular, the AMD64 has more registers and the relative addressing capabilities have been improved. Where we see a 10% performance degradation when placing the SWI-Prolog kernel in a Unix shared object, we cannot find a measurable difference on AMD64. Current SWI-Prolog (5.6.26) runs at practically the same speed on IA32 and AMD64. 22..1199..33 CChhoooossiinngg bbeettwweeeenn 3322-- aanndd 6644--bbiittss PPrroolloogg For those cases where we can choose between 32- and 64-bits, either because the hardware and OS support both or because we can still choose the hardware and OS, we give guidelines for this decision. First of all, if SWI-Prolog needs to be linked against 32- or 64-bit native libraries, there is no choice as it is not possible to link 32- and 64-bit code into a single executable. Only if all required libraries are available in both sizes and there is no clear reason to use either the different characteristics of Prolog become important. Prolog applications that require more than the 128MB stack limit provided in 32-bit addressing mode must use the 64-bit edition. Note however that the limits must be doubled to accommodate the same Prolog application. If the system is tight on physical memory, 32-bit Prolog has the clear advantage to use only slightly more than half of the memory of 64-bit Prolog. This argument applies as long as the application fits in the _v_i_r_t_u_a_l _a_d_d_r_e_s_s _s_p_a_c_e of the machine. The virtual address space of 32-bit hardware is 4GB, but in many cases the operating system provides less to user applications. Virtual memory usage of SWI-Prolog is roughly the program size (_h_e_a_p) plus the sum of the stack-limits. If there are multiple threads, each thread has its own stacks and the stack-limits must be summed over the running threads. The only standard SWI-Prolog library adding significantly to this calculation is the RDF database provided by the _s_e_m_w_e_b package. It uses approximately 80 bytes per triple on 32-bit hardware and 150 bytes on 64-bit hardware. Details depend on how many different resources and literals appear in the dataset as well as desired additional literal indexes. Summarizing, if applications are small enough to fit comfortably in virtual and physical memory simply take the model used by most of the applications on the OS. If applications require more than 128MB per stack, use the 64-bit edition. If applications approach the size of physical memory, fit in the 128MB stack limit and fit in virtual memory, the 32-bit version has clear advantages. For demanding applications on 64-bit hardware with more than about 6GB physical memory the 64-bit model is the model of choice. CChhaapptteerr 33.. IINNIITTIIAALLIISSIINNGG AANNDD MMAANNAAGGIINNGG AA PPRROOLLOOGG PPRROOJJEECCTT Prolog text-books give you an overview of the Prolog language. The manual tells you what predicates are provided in the system and what they do. This chapter wants to explain how to run a project. There is no ultimate `right' way to do this. Over the years we developed some practice in this area and SWI-Prolog's commands are there to support this practice. This chapter describes the conventions and supporting commands. The first two sections (section 3.1 and section 3.2 only require plain Prolog. The remainder discusses the use of the built-in graphical tools that require the XPCE graphical library installed on your system. 33..11 TThhee pprroojjeecctt ssoouurrccee--ffiilleess Organisation of source-files depends largely on the size of your project. If you are doing exercises for a Prolog course you'll normally use one file for each exercise. If you have a small project you'll work work with one directory holding a couple of files and some files to link it all together. Even bigger projects will be organised in sub-projects each using their own directory. 33..11..11 FFiillee NNaammeess aanndd LLooccaattiioonnss 33..11..11..11 FFiillee NNaammee EExxtteennssiioonnss The first consideration is what extension to use for the source-files. Tradition calls for .pl, but conflicts with Perl force the use of another extension on systems where extensions have global meaning, such as MS-Windows. On such systems .pro is the common alternative. All versions of SWI-Prolog load files with the extension .pl as well as with the registered alternative extension without explicitly specifying the extension. For portability reasons we propose the following convention: IIff tthheerree iiss nnoo ccoonnfflliicctt because you do not use a conflicting application or the system does not force a unique relation between extension and application, use .pl. WWiitthh aa ccoonnfflliicctt choose .pro and use this extension for the files you want to load through your file-manager. Use .pl for all other files for maximal portability. 33..11..11..22 PPrroojjeecctt DDiirreeccttoorriieess Large projects are generally composed of sub-projects, each using their own directory or directory-structure. If nobody else will ever touch your files and you use only one computer there is little to worry about, but this is rarely the case with a large project. To improve portability, SWI-Prolog uses the POSIX notation for filenames, which uses the forward slash (/) to separate directories. Just before hitting the file-system it uses prolog_to_os_filename/2 to convert the filename to the conventions used by the hosting operating system. It is _s_t_r_o_n_g_l_y advised to write paths using the /, especially on systems using the \ for this purpose (MS-Windows). Using \ violates the portability rules and requires you to _d_o_u_b_l_e the \ due to the Prolog quoted-atom escape rules. Portable code should use prolog_to_os_filename/2to convert computed paths into system-paths when constructing commands for shell/1 and friends. 33..11..11..33 SSuubb--pprroojjeeccttss uussiinngg sseeaarrcchh--ppaatthhss Thanks to Quintus, Prolog adapted an extensible mechanism for searching files using file_search_path/2. This mechanism allows for comfortable and readable specifications. Suppose you have extensive library packages on graph-algorithms, set-operations and GUI-primitives. These sub-projects are likely candidates for re-use in future projects. A good choice is to create a directory with sub-directories for each of these sub-projects. Next, there are three options. One is to add the sub-projects to the directory-hierarchy of the current project. Another is to use a completely dislocated directory and finally the sub-project can be added to the SWI-Prolog hierarchy. Using local installation, a typical file_search_path/2is: :- prolog_load_context(directory, Dir), asserta(user:file_search_path(myapp, Dir)). user:file_search_path(graph, myapp(graph)). user:file_search_path(ui, myapp(ui)). For using sub-projects in the SWI-Prolog hierarchy one should use the path-alias swi as basis. For a system-wide installation use an absolute-path. Extensive sub-projects with a small well-defined API should define a load-file using use_module/1 calls to import the various library-components and export the API. 33..11..22 PPrroojjeecctt SSppeecciiaall FFiilleess There are a number of tasks you typically carry out on your project, such as loading it, creating a saved-state, debugging it, etc. Good practice on large projects is to define small files that hold the commands to execute such a task, name this file after the task and give it a file-extension that makes starting easy (see section 3.1.1.1). The task _l_o_a_d is generally central to these tasks. Here is a tentative list. o load.pl Use this file to set up the environment (prolog flags and file search paths) and load the sources. Quite commonly this file also provides convenient predicates to parse command-line options and start the application. o run.pl Use this file to start the application. Normally it loads load.pl in silent-mode, and calls one of the starting predicates from load.pl. o save.pl Use this file to create a saved-state of the application by loading load.pl and call qsave_program/2to generate a saved-state with the proper options. o debug.pl Loads the program for debugging. In addition to loading load.pl this file defines rules for portray/1 to modify printing rules for complex terms and customisation rules for the debugger and editing environment. It may start some of these tools. 33..11..33 IInntteerrnnaattiioonnaall ssoouurrccee ffiilleess As discussed in section 2.17, SWI-Prolog supports international character handling. Its internal encoding is UNICODE. I/O streams convert to/from this internal format. This sections discusses the options for source-files not in US-ASCII. SWI-Prolog can read files in any of the encodings described in section 2.17. Two encodings are of particular interest. The text encoding deals with the current _l_o_c_a_l_e, the default used by this computer for representing text files. The encodings utf8, unicode_le and unicode_be are _U_N_I_C_O_D_E encodings: they can represent---in the same file---characters of virtually any known language. In addition, they do so unambiguously. If one wants to represent non US-ASCII text as Prolog terms in a source-file there are several options: o _U_s_e _e_s_c_a_p_e _s_e_q_u_e_n_c_e_s This approach describes NON-ASCII as sequences of the form \_o_c_t_a_l\. The numerical argument is interpreted as a UNICODE character. The resulting Prolog file is strict 7-bit US-ASCII, but if there are many NON-ASCII characters it becomes very unreadable. o _U_s_e _l_o_c_a_l _c_o_n_v_e_n_t_i_o_n_s Alternatively the file may be specified using local conventions, such as the EUC encoding for Japanese text. The disadvantage is portability. If the file is moved to another machine this machine must be using the same _l_o_c_a_l_e or the file is unreadable. There is no elegant if files from multiple locales must be united in one application using this technique. In other words, it is fine for local projects in countries with uniform locale conventions. o _U_s_i_n_g _U_T_F_-_8 _f_i_l_e_s The best way to specify source files with many NON-ASCII characters is definitely the use of UTF-8 encoding. Prolog can be notified two ways of this encoding, using a UTF-8 _B_O_M (see section 2.17.1.1) or using the directive :- encoding(utf8).. Many todays text editors, including PceEmacs, are capable of editing UTF-8 files. Projects that started using local conventions can be be re-coded using the Unix iconv tool or often using a commands offered by the editor. 33..22 UUssiinngg mmoodduulleess Modules have been debated fiercely in the Prolog world. Despite all counter-arguments we feel they are extremely useful because o _T_h_e_y _h_i_d_e _l_o_c_a_l _p_r_e_d_i_c_a_t_e_s This is the reason they have been invented in the first place. Hiding provides two features. They allow for short predicate names without worrying about conflicts. Given the flat name-space introduced by modules, they still require meaningful module names as well as meaningful names for exported predicates. o _T_h_e_y _d_o_c_u_m_e_n_t _t_h_e _i_n_t_e_r_f_a_c_e Possibly more important then avoiding name-conflicts is their role in documenting which part of the file is for public usage and which is private. When editing a module you may assume you can reorganise anything but the name and semantics of the exported predicates without worrying. o _T_h_e_y _h_e_l_p _t_h_e _e_d_i_t_o_r The PceEmacs built-in editor does on-the-fly cross-referencing of the current module, colouring predicates based on their origin and usage. Using modules, the editor can quickly find out what is provided by the imported modules by reading just the first term. This allows it to indicate real-time which predicates are not used or not defined. Using modules is generally easy. Only if you write meta-predicates (predicates reasoning about other predicates) that are exported from a module good understanding of resolution of terms to predicates inside a module is required. Here is a typical example from readutil. :- module(read_util, [ read_line_to_codes/2, % +Fd, -Codes read_line_to_codes/3, % +Fd, -Codes, ?Tail read_stream_to_codes/2, % +Fd, -Codes read_stream_to_codes/3, % +Fd, -Codes, ?Tail read_file_to_codes/3, % +File, -Codes, +Options read_file_to_terms/3 % +File, -Terms, +Options ]). 33..33 TThhee tteesstt--eeddiitt--rreellooaadd ccyyccllee SWI-Prolog does not enforce the use of a particular editor for writing down Prolog source code. Editors are complicated programs that must be mastered in detail for real productive programming and if you are familiar with a specific editor you should not be forced to change. You may specify your favourite editor using the prolog flag editor, the environment variable EDITOR or by defining rules for prolog_edit:edit_source/1 (see section 4.4). The use of a built-in editor, which is selected by setting the prolog-flag editor to pce_emacs, has advantages. The XPCE _e_d_i_t_o_r object around which the built-in PceEmacs is built can be opened as a Prolog stream allowing analysis of your source by the real Prolog system. 33..33..11 LLooccaattiinngg tthhiinnggss ttoo eeddiitt The central predicate for editing something is edit/1, an extensible front-end that searches for objects (files, predicates, modules as well as XPCE classes and methods) in the Prolog database. If multiple matches are found it provides a choice. Together with the built-in completion on atoms bound to the TAB key this provides a quick way to edit objects: ?- edit(country). Please select item to edit: 1 chat:country/10 '/staff/jan/lib/prolog/chat/countr.pl':16 2 chat:country/1 '/staff/jan/lib/prolog/chat/world0.pl':72 Your choice? 33..33..22 EEddiittiinngg aanndd iinnccrreemmeennttaall ccoommppiillaattiioonn One of the nice features of Prolog is that the code can be modified while the program is running. Using pure Prolog you can trace a program, find it is misbehaving, enter a _b_r_e_a_k _e_n_v_i_r_o_n_m_e_n_t, modify the source code, reload it and finally do _r_e_t_r_y on the misbehaving predicate and try again. This sequence is not uncommon for long-running programs. For faster programs one normally aborts after understanding the misbehaviour, edit the source, reload it and try again. One of the nice features of SWI-Prolog is the availability of make/0, a simple predicate that checks all loaded source files to see which ones you have modified. It then reloads these files, considering the module from which the file was loaded originally. This greatly simplifies the trace-edit-verify development cycle. After the tracer reveals there is something wrong with prove/3, you do: ?- edit(prove). Now edit the source, possibly switching to other files and making multiple changes. After finishing invoke make/0, either through the editor UI () Compile/Make (Control-C Control-M)) or on the top-level and watch the files being reloaded. ?- make. % show compiled into photo_gallery 0.03 sec, 3,360 bytes 33..44 UUssiinngg tthhee PPcceeEEmmaaccss bbuuiilltt--iinn eeddiittoorr 33..44..11 AAccttiivvaattiinngg PPcceeEEmmaaccss Initially edit/1 uses the editor specified in the EDITOR environment variable. There are two ways to force it to use the built-in editor. One is to set the prolog-flag editor to pce_emacs and the other is by starting the editor explicitly using the emacs/[0,1] predicates. 33..44..22 BBlluuffffiinngg tthhrroouugghh PPcceeEEmmaaccss PceEmacs closely mimics Richard Stallman's GNU-Emacs commands, adding features from modern window-based editors to make it more acceptable for beginners. At the basis, PceEmacs maps keyboard sequences to methods defined on the extended _e_d_i_t_o_r object. Some frequently used commands are, with their key-binding, presented in the menu-bar above each editor window. A complete overview of the bindings for the current _m_o_d_e is provided through ) Help/Show key bindings (Control-h Control-b). 33..44..22..11 EEddiitt mmooddeess Modes are the heart of (Pce)Emacs. Modes define dedicated editing support for a particular kind of (source-)text. For our purpose we want _P_r_o_l_o_g _m_o_d_e. Their are various ways to make PceEmacs use Prolog mode for a file. o _U_s_i_n_g _t_h_e _p_r_o_p_e_r _e_x_t_e_n_s_i_o_n If the file ends in .pl or the selected alternative (e.g. .pro) extension, Prolog mode is selected. o _U_s_i_n_g #!/path/to/pl If the file is a _P_r_o_l_o_g _S_c_r_i_p_t file, starting with the line #!/path/to/pl options -s, Prolog mode is selected regardless of the extension o _U_s_i_n_g -*- Prolog -*- If the above sequence appears in the first line of the file (inside a Prolog comment) Prolog mode is selected. o _E_x_p_l_i_c_i_t _s_e_l_e_c_t_i_o_n Finally, using ) File/Mode/Prolog (y)ou can switch to Prolog mode explicitly. 33..44..22..22 FFrreeqquueennttllyy uusseedd eeddiittoorr ccoommmmaannddss Below we list a few important commands and how to activate them. o _C_u_t_/_C_o_p_y_/_P_a_s_t_e These commands follow Unix/X11 traditions. You're best suited with a three-button mouse. After selecting using the left-mouse (double-click uses word-mode and triple line-mode), the selected text is _a_u_t_o_m_a_t_i_c_a_l_l_y copied to the clipboard (X11 primary selection on Unix). _C_u_t is achieved using the DEL key or by typing something else at the location. _P_a_s_t_e is achieved using the middle-mouse (or wheel) button. If you don't have a middle mouse-button, pressing the left- and right-button at the same time is interpreted as a middle-button click. If nothing helps there is the ) Edit/Paste menu-entry. Text is pasted at the caret-location. o _U_n_d_o Undo is bound to the GNU-Emacs Control-_ as well as the MS-Windows Control-Z sequence. o _A_b_o_r_t Multi-key sequences can be aborted at any stage using Control-G. o _F_i_n_d Find (Search) is started using Control-S (forward) or Control-R (backward). PceEmacs implements _i_n_c_r_e_m_e_n_t_a_l _s_e_a_r_c_h. This is difficult to use for novices, but very powerful once you get the clue. After one of the above start-keys the system indicates search mode in the status line. As you are typing the search-string, the system searches for it, extending the search with every character you type. It illustrates the current match using a green background. If the target cannot be found, PceEmacs warns you and no longer extends the search-string. During search some characters have special meaning. Typing anything but these characters commits the search, re-starting normal edit mode. Special commands are: Control-S Search for next forwards. Control-R Search for next backwards. Control-W Extend search to next word-boundary. Control-G Cancel search, go back to where it started. ESC Commit search, leaving caret at found location. Backspace Remove a character from the search string. o _D_y_n_a_m_i_c _A_b_b_r_e_v_i_a_t_i_o_n Also called _d_a_b_b_r_e_v is an important feature of Emacs clones to support programming. After typing the first few letters of an identifier you may hit Alt-/, causing PceEmacs to search backwards for identifiers that start the same and using it to complete the text you typed. A second Alt-/ searches further backwards. If there are no hits before the caret it starts searching forwards. With some practice, this system allows for very fast entering code with nice and readable identifiers (or other difficult long words). o _O_p_e_n _(_a _f_i_l_e_) Is called ) File/Find file (Control-x Control-f). By default the file is loaded into the current window. If you want to keep this window, Hit Alt-s or click the little icon at the bottom-left to make the window _s_t_i_c_k_y. o _S_p_l_i_t _v_i_e_w Sometimes you want to look at two places of the same file. To do this, use Control-x 2 to create a new window pointing to the same file. Do not worry, you can edit as well as move around in both. Control-x 1 kills all other windows running on the same file. These were the most commonly used commands. In section section 3.4.3 we discuss specific support for dealing with Prolog source code. 33..44..33 PPrroolloogg MMooddee In the previous section (section 3.4.2) we explained the basics of PceEmacs. Here we continue with Prolog specific functionality. Possibly the most interesting is _S_y_n_t_a_x _h_i_g_h_l_i_g_h_t_i_n_g. Unlike most editors where this is based on simple patterns, PceEmacs syntax highlighting is achieved by Prolog itself actually reading and interpreting the source as you type it. There are three moments at which PceEmacs checks (part of) the syntax. o _A_f_t_e_r _t_y_p_i_n_g _a . After typing a . that is not preceded by a _s_y_m_b_o_l character the system assumes you completed a clause, tries to find the start of this clause and verifies the syntax. If this process succeeds it colours the elements of the clause according to the rules given below. Colouring is done using information from the last full check on this file. If it fails, the syntax error is displayed in the status line and the clause is not coloured. o _A_f_t_e_r _t_h_e _c_o_m_m_a_n_d Control-c Control-s Acronym for CCcheck SSyntax it performs the same checks as above for the clause surrounding the caret. On a syntax error however, the caret is moved to the expected location of the error. o _A_f_t_e_r _p_a_u_s_i_n_g _f_o_r _t_w_o _s_e_c_o_n_d_s After a short pause (2 seconds), PceEmacs opens the edit-buffer and reads it as a whole, creating an index of defined, called, dynamic, imported and exported predicates. After completing this, it re-reads the file and colours all clauses and calls with valid syntax. o _A_f_t_e_r _t_y_p_i_n_g Control-l Control-l The Control-l commands re-centers the window (scrolls the window to make the caret the center of the window). Hitting this command twice starts the same process as above. TThhee ccoolloouurr sscchheemmaa itself is defined in emacs/prolog_colour. The colouring can be extended and modified using multifile predicates. Please check this source-file for details. In general, underlined objects have a popup (right-mouse button) associated for common commands such as viewing the documentation or source. BBoolldd text is used to indicate the definition of objects (typically predicates when using plain Prolog). Other colours follow intuitive conventions. See table 3.4.3. _____________________________________________________ |______________________Clauses_______________________| | Blue bold |Head of an exported predicate | | Red bold |Head of a predicate that is not called | |_Black_Bold_|Head_of_remaining_predicates___________| |______________Calls_in_the_clause-body______________| | Blue |Call to built-in or imported predicate | | Red |Call to not-defined predicate | |_Purple_____|Call_to_dynamic_predicate______________| |___________________Other_entities___________________| | Dark green |Comment | | Dark blue |Quoted atom or string | |_Brown______|Variable_______________________________| Table 3.1: Colour conventions LLaayyoouutt ssuuppppoorrtt Layout is not `just nice', it is _e_s_s_e_n_t_i_a_l for writing readable code. There is much debate on the proper layout of Prolog. PceEmacs, being a rather small project supports only one particular style for layout. Below are examples of typical constructs. head(arg1, arg2). head(arg1, arg2) :- !. head(Arg1, arg2) :- !, call1(Arg1). head(Arg1, arg2) :- ( if(Arg1) -> then ; else ). head(Arg1) :- ( a ; b ). head :- a(many, long, arguments(with, many, more), and([ a, long, list, with, a, | tail ])). PceEmacs uses the same conventions as GNU-Emacs. The TAB key indents the current line according to the syntax rules. Alt-q indents all lines of the current clause. It provides support for head, calls (indented 1 tab), if-then-else, disjunction and argument-lists broken across multiple lines as illustrated above. 33..44..33..11 FFiinnddiinngg yyoouurr wwaayy aarroouunndd The command Alt-. extracts name and arity from the caret location and jumps (after conformation or edit) to the definition of the predicate. It does so based on the source-location database of loaded predicates also used by edit/1. This makes locating predicates reliable if all sources are loaded and up-to-date (see make/0). In addition, references to files in use_module/[1,2], consult/1, etc. are red if the file cannot be found and underlined blue if the file can be loaded. A popup allows for opening the referenced file. 33..55 TThhee GGrraapphhiiccaall DDeebbuuggggeerr SWI-Prolog offers two debuggers. One is the traditional text-console based 4-port Prolog tracer and the other is a window-based source-level debugger. The window-based debugger requires XPCE installed. It operates based on the prolog_trace_interception/4 hook and other low-level functionality described in chapter 12. Window-based tracing provides much better overview due to the eminent relation to your source-code, a clear list of named variables and their bindings as well as a graphical overview of the call and choice-point stack. There are some drawbacks though. Using a textual trace on the console one can scroll back and examine the past, while the graphical debugger just presents a (much better) overview of the current state. 33..55..11 IInnvvookkiinngg tthhee wwiinnddooww--bbaasseedd ddeebbuuggggeerr Whether the text-based or window-based debugger is used is controlled using the predicates guitracer/0 and noguitracer/0. Entering debug mode is controlled using the normal predicates for this: trace/0 and spy/1. In addition, PceEmacs prolog mode provides the command ) Prolog/Break at (Control-c b) to insert a break-point at a specific location in the source-code. The graphical tracer is particulary useful for debugging threads. The tracer must be loaded from the main thread before it can be used from a background thread. gguuiittrraacceerr This predicate installs the above-mentioned hooks that redirect tracing to the window-based environment. No window appears. The debugger window appears as actual tracing is started through trace/0, by hitting a spy-point defined by spy/1 or a break-point defined using PceEmacs command ) Prolog/Break at (Control-c b). nnoogguuiittrraacceerr Disable the hooks installed by guitracer/0, reverting to normal text-console based tracing. ggttrraaccee Utility defined as guitracer,trace. ggddeebbuugg Utility defined as guitracer,debug. ggssppyy((_+_P_r_e_d_i_c_a_t_e)) Utility defined as guitracer,spy(Predicate). 33..66 TThhee PPrroolloogg NNaavviiggaattoorr Another tool is the _P_r_o_l_o_g _N_a_v_i_g_a_t_o_r. This tool can be started from PceEmacs using the command ) Browse/Prolog navigator, from the GUI debugger or using the programmatic IDE interface described in section 3.8. 33..77 CCrroossss rreeffeerreenncceerr A cross-referencers is a tool examining the caller-callee relation between predicates and using this information to explicate dependency relations between source files, find calls to non-existing predicates and predicates for which no callers can be found. Cross-referencing is useful during program development, reorganisation, cleanup, porting and other program maintenance tasks. The dynamic nature of Prolog makes the task non-trivial. Goals can be created dynamically call/1 after construction of a goal term. Abtract interpretation can find some of such calls, but the ultimately they can come from external communication, making it completely impossible to predict the callee. In other words, the cross-referencer has only partial understanding of the program and its results are necessarily incomplete. Still, it provides valuable information to the developer. SWI-Prolog's cross-referencer is split into two parts. The standard Prolog library prolog_xref is an extensible library for information gathering described in section 11.17 and the XPCE library pce_xref provides a graphical frontend for the cross-referencer described here. We demonstrate the tool on CHAT80, a natural language question and answer system by Fernando C.N. Pereira and David H.D. Warren. ggxxrreeff Run cross-referencer on all currently loaded files and present a graphical overview of the result. As the predicate operates on the currently loaded application it must be run after loading the application. The lleefftt wwiinnddooww (see figure ???? provides browsers for loaded files and predicates. To avoid long file paths the file hierarchy has three main branches. The first is the current directory holding the sources. The second is marked alias and below it are the file-search-path aliases (see file_search_path/2 and absolute_file_name/3). Here you find files loaded from the system as well as modules of the program loaded from other locations using file search path. All loaded files that fall outside these categories are below the last branch called /. File where the system found suspicious dependencies are marked with an exclamation mark. This also holds for directories holding such files. Clicking on a file opens a _F_i_l_e _i_n_f_o window in the right pane. The FFiillee iinnffoo window shows a file, its main properties, its undefined and not-called predicates and its import- and export relations to other files in the project. Both predicates and files can be opened by clicking on them. The number of callers in a file for a certain predicate is indicated with a blue underlined number. A left-click will open a list and allows to edit the calling predicate. The DDeeppeennddeenncciieess (see figure ????) window displays a graphical overview of dependencies between files. Using the background menu a complete graph of the project can be created. It is also possible to drag files onto the graph window and use the menu on the nodes to incrementally expand the graph. The underlined blue text indicates the number of predicates used in the destination file. Left-clicking opens a menu to open the definition or select one of the callers. MMoodduullee aanndd nnoonn--mmoodduullee ffiilleess The cross-referencer threads module and non-module project files differently. Module files have explicit import and export relations and the tool shows the usage and consistency of the relations. Using the menu-command Header the tool creates a consistent import list for the module that can be included in the file. The tool computes the dependency relations between the non-module files. If the user wishes to convert the project into a module-based one the Header command generates an appropriate module header and import list. Note that the cross-referencer may have missed dependencies and does not deal with meta-predicates defined in one module and called in another. Such problems must be resolved manually. SSeettttiinnggss The following settings can be controlled from the settings menu: WWaarrnn aauuttoollooaadd By default disabled. If enabled, modules that require predicates to be autoloaded are flagged with a warning and the file info window of a module shows the required autoload predicates. WWaarrnn nnoott ccaalllleedd If enabled (default), the file-overview shows an alert icon for files that have predicates that are not called. 33..88 AAcccceessssiinngg tthhee IIDDEE ffrroomm yyoouurr pprrooggrraamm Over the years a collection of IDE components have been developed, each with their own interface. In addition, some of these components require each other and loading IDE components must be on demand to avoid the IDE being part of a saved-state (see qsave_program/2). For this reason, access to the IDE will be concentrated on a single interface called prolog_ide/1: pprroolloogg__iiddee((_+_A_c_t_i_o_n)) This predicate ensures the IDE enabling XPCE component is loaded, creates the XPCE class _p_r_o_l_o_g___i_d_e and sends _A_c_t_i_o_n to its one and only instance \index{@prolog_ide}\objectname{prolog_ide}. _A_c_t_i_o_n is one of the following: ooppeenn__nnaavviiggaattoorr((_+_D_i_r_e_c_t_o_r_y)) Open the Prolog Navigator (see section 3.6) in the given _D_i_r_e_c_t_o_r_y. ooppeenn__ddeebbuugg__ssttaattuuss Open a window to edit spy- and trace-points. ooppeenn__qquueerryy__wwiinnddooww Opens a little window to run Prolog queries from a GUI component. tthhrreeaadd__mmoonniittoorr Open a graphical window indicating existing threads and their status. ddeebbuugg__mmoonniittoorr Open a graphical front-end for the debug library that provides an overview of the topics and catches messages. xxrreeff Open a graphical front-end for the cross-referencer that provides an overview of predicates and their callers. 33..99 SSuummmmaarryy ooff tthhee iiDDEE The SWI-Prolog development environment consists of a number of interrelated but not (yet) integrated tools. Here is a list of the most important features and tips. o _A_t_o_m _c_o_m_p_l_e_t_i_o_n The console completes a partial atom on the TAB key and shows alternatives on the command Alt-?. o _U_s_e edit/1 _t_o _f_i_n_d_i_n_g _l_o_c_a_t_i_o_n_s The command edit/1 takes the name of a file, module, predicate or other entity registered through extensions and starts the users preferred editor at the right location. o _S_e_l_e_c_t _e_d_i_t_o_r External editors are selected using the EDITOR environment variable, by setting the prolog flag editor or by defining the hook prolog_edit:edit_source/1. o _U_p_d_a_t_e _P_r_o_l_o_g _a_f_t_e_r _e_d_i_t_i_n_g Using make/0, all files you have edited are re-loaded. o _P_c_e_E_m_a_c_s Offers syntax-highlighting and checking based on real-time parsing of the editor's buffer, layout-support and navigation support. o _U_s_i_n_g _t_h_e _g_r_a_p_h_i_c_a_l _d_e_b_u_g_g_e_r The predicates guitracer/0 and noguitracer/0 switch between traditional text-based and window-based debugging. The tracer is activated using the trace/0, spy/1 or menu-items from PceEmacs or the PrologNavigator. o _T_h_e _P_r_o_l_o_g _N_a_v_i_g_a_t_o_r Shows the file-structure and structure inside the file. It allows for loading files, editing, setting spy-points, etc. CChhaapptteerr 44.. BBUUIILLTT--IINN PPRREEDDIICCAATTEESS 44..11 NNoottaattiioonn ooff PPrreeddiiccaattee DDeessccrriippttiioonnss We have tried to keep the predicate descriptions clear and concise. First the predicate name is printed in bold face, followed by the arguments in italics. Arguments are preceded by a `+', `-' or `?' sign. `+' indicates the argument is input to the predicate, `-' denotes output and `?' denotes `either input or output'. Constructs like `op/3' refer to the predicate `op' with arity `3'. Finally, arguments may have the `:' specifier, which implies the argument is module-sensitive. Normally the argument is a _c_a_l_l_a_b_l_e term referring to a predicate in a specific module. See section 5 for more information on module-handing. 44..22 CChhaarraacctteerr rreepprreesseennttaattiioonn In traditional (Edinburgh-) Prolog, characters are represented using _c_h_a_r_a_c_t_e_r_-_c_o_d_e_s. Character codes are integer indices into a specific character set. Traditionally the character set was 7-bits US-ASCII. 8-bit character sets have been allowed for a long time, providing support for national character sets, of which iso-latin-1 (ISO 8859-1) is applicable to many western languages. Text-files are supposed to represent a sequence of character-codes. ISO Prolog introduces three types, two of which are used for characters and one for accessing binary streams (see open/4). These types are: o _c_o_d_e A _c_h_a_r_a_c_t_e_r_-_c_o_d_e is an integer representing a single character. As files may use multi-byte encoding for supporting different character sets (utf-8 encoding for example), reading a code from a text-file is in general not the same as reading a byte. o _c_h_a_r Alternatively, characters may be represented as _o_n_e_-_c_h_a_r_a_c_t_e_r_- _a_t_o_m_s. This is a very natural representation, hiding encoding problems from the programmer as well as providing much easier debugging. o _b_y_t_e Bytes are used for accessing binary-streams. The current version of SWI-Prolog does not provide support for multi-byte character encoding. This implies for example that it is not capable of breaking a multi-byte encoded atom into characters. For SWI-Prolog, bytes and codes are the same and one-character-atoms are simple atoms containing one byte. To ease the pain of these multiple representations, SWI-Prolog's built-in predicates dealing with character-data work as flexible as possible: they accept data in any of these formats as long as the interpretation is unambiguous. In addition, for output arguments that are instantiated, the character is extracted before unification. This implies that the following two calls are identical, both testing whether the next input characters is an a. peek_code(Stream, a). peek_code(Stream, 97). These multiple-representations are handled by a large number of built-in predicates, all of which are ISO-compatible. For converting between code and character there is char_code/2. For breaking atoms and numbers into characters are are atom_chars/2, atom_codes/2, number_codes/2 and number_chars/2. For character I/O on streams there is get_char/[1,2], get_code/[1,2], get_byte/[1,2], peek_char/[1,2], peek_code/[1,2], peek_byte/[1,2], put_code/[1,2], put_char/[1,2] and put_byte/[1,2]. The prolog-flag double_quotes (see current_prolog_flag/2) controls how text between double-quotes is interpreted. 44..33 LLooaaddiinngg PPrroolloogg ssoouurrccee ffiilleess This section deals with loading Prolog source-files. A Prolog source file is a plain text file containing a Prolog program or part thereof. Prolog source files come in three flavours: AA ttrraaddiittiioonnaall Prolog source file contains a Prolog clauses and directives, but no _m_o_d_u_l_e_-_d_e_c_l_a_r_a_t_i_o_n. They are normally loaded using consult/1 or ensure_loaded/1. AA mmoodduullee Prolog source file starts with a module declaration. The subsequent Prolog code is loaded into the specified module and only the _p_u_b_l_i_c predicates are made available to the context loading the module. Module files are normally loaded using use_module/[1,2]. See chapter 5 for details. AAnn iinncclluuddee Prolog source file is loaded using the include/1 directive and normally contains only directives. Prolog source-files are located using absolute_file_name/3 with the following options: locate_prolog_file(Spec, Path) :- absolute_file_name(Spec, [ file_type(prolog), access(read) ], Path). The file_type(_p_r_o_l_o_g) option is used to determine the extension of the file using prolog_file_type/2. The default extension is .pl. _S_p_e_c allows for the _p_a_t_h_-_a_l_i_a_s construct defined by absolute_file_name/3. The most commonly used path-alias is library(_L_i_b_r_a_r_y_F_i_l_e). The example below loads the library file ordsets.pl (containing predicates for manipulating ordered sets). :- use_module(library(ordsets)). SWI-Prolog recognises grammar rules (DCG) as defined in [Clocksin & Melish, 1987]. The user may define additional compilation of the source file by defining the dynamic predicates term_expansion/2 and goal_expansion/2. Transformations by term_expansion/2 overrule the systems grammar rule transformations. It is not allowed to use assert/1, retract/1 or any other database predicate in term_expansion/2 other than for local computational purposes. Directives may be placed anywhere in a source file, invoking any predicate. They are executed when encountered. If the directive fails, a warning is printed. Directives are specified by :-/1 or ?-/1. There is no difference between the two. SWI-Prolog does not have a separate reconsult/1 predicate. Reconsulting is implied automatically by the fact that a file is consulted which is already loaded. llooaadd__ffiilleess((_+_F_i_l_e_s_, _+_O_p_t_i_o_n_s)) The predicate load_files/2 is the parent of all the other loading predicates except for include/1. It currently supports a subset of the options of Quintus load_files/2. _F_i_l_e_s is either a single source-file, or a list of source-files. The specification for a source-file is handed to absolute_file_name/2. See this predicate for the supported expansions. _O_p_t_i_o_n_s is a list of options using the format _O_p_t_i_o_n_N_a_m_e(_O_p_t_i_o_n_V_a_l_u_e) The following options are currently supported: aauuttoollooaadd((_B_o_o_l)) If true (default false), indicate this load is a _d_e_m_a_n_d load. This implies that, depending on the setting of the prolog-flag verbose_autoload the load-action is printed at level informational or silent. See also print_message/2 and current_prolog_flag/2. ddeerriivveedd__ffrroomm((_F_i_l_e)) Indicate that the loaded file is derived from _F_i_l_e. Used by make/0 to time-check and load the original file rather than the derived file. eennccooddiinngg((_E_n_c_o_d_i_n_g)) Specify the way characters are encoded in the file. Default is taken from the prolog flag encoding. See section 2.17.1 for details. eexxppaanndd((_B_o_o_l)) If true, run the filenames through expand_file_name/2 and load the returned files. Default is false, except for consult/1 which is intended for interactive use. Flexible location of files is defined by file_search_path/2. iiff((_C_o_n_d_i_t_i_o_n)) Load the file only if the specified condition is satisfied. The value true loads the file unconditionally, changed loads the file if it was not loaded before, or has been modified since it was loaded the last time, not_loaded loads the file if it was not loaded before. iimmppoorrttss((_L_i_s_t_O_r_A_l_l)) If all and the file is a module file, import all public predicates. Otherwise import only the named predicates. Each predicate is referred to as <_n_a_m_e>/<_a_r_i_t_y>. This option has no effect if the file is not a module file. mmuusstt__bbee__mmoodduullee((_B_o_o_l)) If true, raise an error if the file is not a module file. Used by use_module/[1,2]. qqccoommppiillee((_B_o_o_l)) If this call appears in a directive of a file that is compiled into Quick Load Format using qcompile/1 and this flag is true, the contents of the argument files are included in the .qlf file instead of the loading directive. ssiilleenntt((_B_o_o_l)) If true, load the file without printing a message. The specified value is the default for all files loaded as a result of loading the specified files. This option writes the prolog flag verbose_load with the negation of _B_o_o_l. ssttrreeaamm((_I_n_p_u_t)) This SWI-Prolog extension compiles the data from the stream _I_n_p_u_t. If this option is used, _F_i_l_e_s must be a single atom which is used to identify the source-location of the loaded clauses as well as remove all clauses if the data is re-consulted. This option is added to allow compiling from non-file locations such as databases, the web, the _u_s_e_r (see consult/1) or other servers. The load_files/2 predicate can be hooked to load other data or data from other objects than files. See prolog_load_file/2for a description and http_load for an example. ccoonnssuulltt((_+_F_i_l_e)) Read _F_i_l_e as a Prolog source file. _F_i_l_e may be a list of files, in which case all members are consulted in turn. _F_i_l_e may start with the Unix shell special sequences ~, <_u_s_e_r> and $<_v_a_r>. _F_i_l_e may also be library(Name), in which case the libraries are searched for a file with the specified name. See also library_directory/1 and file_search_path/2. consult/1 may be abbreviated by just typing a number of file names in a list. Examples: ?- consult(load). % consult load or load.pl ?- [library(quintus)]. % load Quintus compatibility library ?- [user]. The predicate consult/1 is equivalent to load_files(Files, []), except for handling the special file user, which reads clauses from the terminal. See also the stream(_I_n_p_u_t) option of load_files/2. eennssuurree__llooaaddeedd((_+_F_i_l_e)) If the file is not already loaded, this is equivalent to consult/1. Otherwise, if the file defines a module, import all public predicates. Finally, if the file is already loaded, is not a module file and the context module is not the global user module, ensure_loaded/1 will call consult/1. With the semantics, we hope to get as closely possible to the clear semantics without the presence of a module system. Applications using modules should consider using use_module/[1,2]. Equivalent to load_files(Files, [if(not_loaded)]). iinncclluuddee((_+_F_i_l_e)) Pretend the terms in _F_i_l_e are in the source-file in which :- include(File) appears. The include construct is only honoured if it appears as a directive in a source-file. Normally _F_i_l_e contains a sequence of directives. rreeqquuiirree((_+_L_i_s_t_O_f_N_a_m_e_A_n_d_A_r_i_t_y)) Declare that this file/module requires the specified predicates to be defined ``with their commonly accepted definition''. This predicate originates from the Prolog portability layer for XPCE. It is intended to provide a portable mechanism for specifying that this module requires the specified predicates. The implementation normally first verifies whether the predicate is already defined. If not, it will search the libraries and load the required library. SWI-Prolog, having autoloading, does nnoott load the library. Instead it creates a procedure header for the predicate if it does not exist. This will flag the predicate as `undefined'. See also check/0 and autoload/0. eennccooddiinngg((_+_E_n_c_o_d_i_n_g)) This directive can appear anywhere in a source file to define how characters are encoded in the remainder of the file. It can be used in files that are encoded with a superset of US-ASCII, currently UTF-8 and ISO Latin-1. See also section 2.17.1. mmaakkee Consult all source files that have been changed since they were consulted. It checks _a_l_l loaded source files: files loaded into a compiled state using pl -c ... and files loaded using consult or one of its derivatives. The predicate make/0 is called after edit/1, automatically reloading all modified files. It the user uses an external editor (in a separate window), make/0 is normally used to update the program after editing. In addition, make/0 updates the autoload indices (see section 2.13) and runs list_undefined/0 from the check library to report on undefined predicates. lliibbrraarryy__ddiirreeccttoorryy((_?_A_t_o_m)) Dynamic predicate used to specify library directories. Default ./lib, ~/lib/prolog and the system's library (in this order) are defined. The user may add library directories using assert/1, asserta/1 or remove system defaults using retract/1. ffiillee__sseeaarrcchh__ppaatthh((_+_A_l_i_a_s_, _?_P_a_t_h)) Dynamic predicate used to specify `path-aliases'. This feature is best described using an example. Given the definition file_search_path(demo, '/usr/lib/prolog/demo'). the file specification demo(myfile) will be expanded to /usr/lib/ prolog/demo/myfile. The second argument of file_search_path/2 may be another alias. Below is the initial definition of the file search path. This path implies swi(<_P_a_t_h>) refers to a file in the SWI-Prolog home directory. The alias foreign(<_P_a_t_h>) is intended for storing shared libraries (.so or .DLL files). See also load_foreign_library/[1,2]. user:file_search_path(library, X) :- library_directory(X). user:file_search_path(swi, Home) :- current_prolog_flag(home, Home). user:file_search_path(foreign, swi(ArchLib)) :- current_prolog_flag(arch, Arch), atom_concat('lib/', Arch, ArchLib). user:file_search_path(foreign, swi(lib)). The file_search_path/2expansion is used by all loading predicates as well as by absolute_file_name/[2,3]. The prolog-flag verbose_file_search can be set to true to help debugging Prolog's search for files. eexxppaanndd__ffiillee__sseeaarrcchh__ppaatthh((_+_S_p_e_c_, _-_P_a_t_h)) Unifies _P_a_t_h with all possible expansions of the file name specification _S_p_e_c. See also absolute_file_name/3. pprroolloogg__ffiillee__ttyyppee((_?_E_x_t_e_n_s_i_o_n_, _?_T_y_p_e)) This dynamic multifile predicate defined in module user determines the extensions considered by file_search_path/2. _E_x_t_e_n_s_i_o_n is the filename extension without the leading dot, _T_y_p_e denotes the type as used by the file_type(_T_y_p_e) option of file_search_path/2. Here is the initial definition of prolog_file_type/2: user:prolog_file_type(pl, prolog). user:prolog_file_type(Ext, prolog) :- current_prolog_flag(associate, Ext), Ext \== pl. user:prolog_file_type(qlf, qlf). user:prolog_file_type(Ext, executable) :- current_prolog_flag(shared_object_extension, Ext). Users may wish to change the extension used for Prolog source files to avoid conflicts (for example with perl) as well as to be compatible with some specific implementation. The preferred alternative extension is .pro. ssoouurrccee__ffiillee((_?_F_i_l_e)) True if _F_i_l_e is a loaded Prolog source file. _F_i_l_e is the absolute and canonical path to the source-file. ssoouurrccee__ffiillee((_?_P_r_e_d_, _?_F_i_l_e)) Is true if the predicate specified by _P_r_e_d was loaded from file _F_i_l_e, where _F_i_l_e is an absolute path name (see absolute_file_name/2). Can be used with any instantiation pattern, but the database only maintains the source file for each predicate. See also clause_property/2. pprroolloogg__llooaadd__ccoonntteexxtt((_?_K_e_y_, _?_V_a_l_u_e)) Determine loading context. The following keys are defined: ________________________________________________________________ |__KKeeyy______________________||DDeessccrriippttiioonn________________________________________________________________________|| || module |Module into which file is loaded | | source |File loaded. Returns the original Prolog| | |file when loading a .qlf file. Compatible to| | |SICStus Prolog. | | file |Currently equivalent to file. In future| | |versions it may report a different values for| | |files being loaded using include/1. | | stream |Stream identifier (see current_input/1) | | directory |Directory in which _F_i_l_e lives. | | term_position |Position of last term read. Term of the form| | |'$stream_position'(0,<_L_i_n_e>,0,0,0). See also| |_______________|stream_position_data/3.________________________| Quintus compatibility predicate. See also source_location/2. ssoouurrccee__llooccaattiioonn((_-_F_i_l_e_, _-_L_i_n_e)) If the last term has been read from a physical file (i.e., not from the file user or a string), unify _F_i_l_e with an absolute path to the file and _L_i_n_e with the line-number in the file. New code should use prolog_load_context/2. tteerrmm__eexxppaannssiioonn((_+_T_e_r_m_1_, _-_T_e_r_m_2)) Dynamic and multifile predicate, normally not defined. When defined by the user all terms read during consulting are given to this predicate. If the predicate succeeds Prolog will assert _T_e_r_m_2 in the database rather then the read term (_T_e_r_m_1). _T_e_r_m_2 may be a term of a the form `?- _G_o_a_l' or `:- _G_o_a_l'. _G_o_a_l is then treated as a directive. If _T_e_r_m_2 is a list all terms of the list are stored in the database or called (for directives). If _T_e_r_m_2 is of the form below, the system will assert _C_l_a_u_s_e and record the indicated source-location with it. '$source_location'(<_F_i_l_e>, <_L_i_n_e>):<_C_l_a_u_s_e> When compiling a module (see chapter 5 and the directive module/2), expand_term/2 will first try term_expansion/2 in the module being compiled to allow for term-expansion rules that are local to a module. If there is no local definition, or the local definition fails to translate the term, expand_term/2 will try term_expansion/2 in module user. For compatibility with SICStus and Quintus Prolog, this feature should not be used. See also expand_term/2, goal_expansion/2 and expand_goal/2. eexxppaanndd__tteerrmm((_+_T_e_r_m_1_, _-_T_e_r_m_2)) This predicate is normally called by the compiler to perform preprocessing. First it calls term_expansion/2. If this predicate fails it performs a grammar-rule translation. If this fails it returns the first argument. ggooaall__eexxppaannssiioonn((_+_G_o_a_l_1_, _-_G_o_a_l_2)) Like term_expansion/2, goal_expansion/2 provides for macro- expansion of Prolog source-code. Between expand_term/2 and the actual compilation, the body of clauses analysed and the goals are handed to expand_goal/2, which uses the goal_expansion/2 hook to do user-defined expansion. The predicate goal_expansion/2 is first called in the module that is being compiled, and then on the user module. If _G_o_a_l is of the form _M_o_d_u_l_e:_G_o_a_l where _M_o_d_u_l_e is instantiated, goal_expansion/2 is called on _G_o_a_l using rules from module _M_o_d_u_l_e followed by user. Only goals appearing in the body of clauses when reading a source-file are expanded using mechanism, and only if they appear literally in the clause, or as an argument to the meta-predicates not/1, call/1, once/1, ignore/1, findall/3, bagof/3, setof/3 or forall/2. A real predicate definition is required to deal with dynamically constructed calls. eexxppaanndd__ggooaall((_+_G_o_a_l_1_, _-_G_o_a_l_2)) This predicate is normally called by the compiler to perform preprocessing. First it calls goal_expansion/2. If this fails it returns the first argument. aatt__iinniittiiaalliizzaattiioonn((_+_G_o_a_l)) Register _G_o_a_l to be run when the system initialises. Initialisation takes place after reloading a .qlf (formerly .wic) file as well as after reloading a saved-state. The hooks are run in the order they were registered. A warning message is issued if _G_o_a_l fails, but execution continues. See also at_halt/1 aatt__hhaalltt((_+_G_o_a_l)) Register _G_o_a_l to be run from PL_cleanup(), which is called when the system halts. The hooks are run in the reverse order they were registered (FIFO). Success or failure executing a hook is ignored. If the hook raises an exception this is printed using print_message/2. An attempt to call halt/[0,1] from a hook is ignored. iinniittiiaalliizzaattiioonn((_+_G_o_a_l)) Call _G_o_a_l and register it using at_initialization/1. Directives that do other things than creating clauses, records, flags or setting predicate attributes should normally be written using this tag to ensure the initialisation is executed when a saved system starts. See also qsave_program/[1,2]. ccoommppiilliinngg True if the system is compiling source files with the -c option or qcompile/1 into an intermediate code file. Can be used to perform conditional code optimisations in term_expansion/2(see also the -O option) or to omit execution of directives during compilation. pprreepprroocceessssoorr((_-_O_l_d_, _+_N_e_w)) Read the input file via a Unix process that acts as preprocessor. A preprocessor is specified as an atom. The first occurrence of the string `%f' is replaced by the name of the file to be loaded. The resulting atom is called as a Unix command and the standard output of this command is loaded. To use the Unix C preprocessor one should define: ?- preprocessor(Old, '/lib/cpp -C -P %f'), consult(...). Old = none 44..33..11 LLooaaddiinngg ffiilleess,, aaccttiivvee ccooddee aanndd tthhrreeaaddss Traditionally, Prolog environments allow for reloading files holding currently active code. In particular, the following sequence is valid use of the development environment: o Trace a goal o Find unexpected behaviour of a predicate o Enter a _b_r_e_a_k using the bb command o Fix the sources and reload them using make/0 o Exit the break, _r_e_t_r_y using the rr command Goals running during the reload keep running on the old definition, while new goals use the reloaded definition, which is why the _r_e_t_r_y must be used _a_f_t_e_r the reload. This implies that clauses of predicates that are active during the reload cannot be reclaimed. Normally a small amount of dead clauses should not be an issue during development. Such clauses can be reclaimed with garbage_collect_clauses/0. ggaarrbbaaggee__ccoolllleecctt__ccllaauusseess leanup all _d_i_r_t_y predicates, where dirty predicates are defined to be predicates that have both old and new definitions due to reloading a source file while the predicate was active. Of course, predicates that are active using garbage_collect_clauses/0 cannot be reclaimed and remain _d_i_r_t_y. Predicate are -like atoms- shared resources and therefore all threads are suspended during the execution of this predicate. 44..33..11..11 TThhrreeaaddss aanndd rreellooaaddiinngg rruunnnniinngg ccooddee As of version 5.5.30, there is basic thread-safety for reloading source files while other threads are executing code defined in these source files. Reloading a file freezes all threads after marking the active predicates originating from the file being reloaded. The threads are resumed after the file has been loaded. In addition, after completing loading the outermost file the system runs garbage_collect_clauses/0. What does that mean? Unfortunately it does _n_o_t mean we can `hot-swap' modules. Consider the case where thread A is executing the recursive predicate P. We `fix' P and reload. The already running goals for P continue to run the old definition, but new recursive calls will use the new definition! Many similar cases can be constructed with dependent predicates. It provides some basic security for reloading files in multi-threaded applications during development. In the above scenarios the system does not crash uncontrolled, but behaves like any broken program: it may return the wrong bindings, wrong truth value or raise an exception. Future versions may have an `update now' facility. Such as facility can be implemented on top of the _l_o_g_i_c_a_l _u_p_d_a_t_e _v_i_e_w. It would allow threads to do a controlled update between processing independent jobs. 44..33..22 QQuuiicckk llooaadd ffiilleess SWI-Prolog supports compilation of individual or multiple Prolog source files into `Quick Load Files'. A `Quick Load Files' (.qlf file) stores the contents of the file in a precompiled format. These files load considerably faster than source files and are normally more compact. They are machine independent and may thus be loaded on any implementation of SWI-Prolog. Note however that clauses are stored as virtual machine instructions. Changes to the compiler will generally make old compiled files unusable. Quick Load Files are created using qcompile/1. They are loaded using consult/1 or one of the other file-loading predicates described in section 4.3. If consult is given the explicit .pl file, it will load the Prolog source. When given the .qlf file, it will load the file. When no extension is specified, it will load the .qlf file when present and the .pl file otherwise. qqccoommppiillee((_+_F_i_l_e)) Takes a single file specification like consult/1 (i.e., accepts constructs like library(LibFile) and, in addition to the normal compilation, creates a _Q_u_i_c_k _L_o_a_d _F_i_l_e from _F_i_l_e. The file-extension of this file is .qlf. The base name of the Quick Load File is the same as the input file. If the file contains `:- consult(+File)', `:- [+File]' or :- load_files(+File, [qcompile(true), ...]) statements, the re- ferred files are compiled into the same .qlf file. Other directives will be stored in the .qlf file and executed in the same fashion as when loading the .pl file. For term_expansion/2, the same rules as described in section 2.10 apply. Conditional execution or optimisation may test the predicate compiling/0. Source references (source_file/2) in the Quick Load File refer to the Prolog source file from which the compiled code originates. 44..44 LLiissttiinngg aanndd EEddiittoorr IInntteerrffaaccee SWI-Prolog offers an extensible interface which allows the user to edit objects of the program: predicates, modules, files, etc. The editor interface is implemented by edit/1 and consists of three parts: _l_o_c_a_t_i_n_g, _s_e_l_e_c_t_i_n_g and _s_t_a_r_t_i_n_g _t_h_e _e_d_i_t_o_r. Any of these parts may be extended or redefined by adding clauses to various multi-file (see multifile/1) predicates defined in the module prolog_edit. The built-in edit specifications for edit/1 (see prolog_edit:locate/3) are described below. ___________________________________________________________________ |__________________________________________FFuullllyy__ssppeecciiffiieedd__oobbjjeeccttss____________________________________________|| || <_M_o_d_u_l_e>:<_N_a_m_e>/<_A_r_i_t_y>R|efers a predicate | | module(<_M_o_d_u_l_e>) |Refers to a module | | file(<_P_a_t_h>) |Refers to a file | |_source_file(<_P_a_t_h>)___R|efers_to_a_loaded_source-file___________|_ |__________________________________________AAmmbbiigguuoouuss__ssppeecciiffiiccaattiioonnss__________________________________________|| || <_N_a_m_e>/<_A_r_i_t_y> R|efers this predicate in any module | | <_N_a_m_e> |Refers to (1) named predicate in any| | |module with any arity, (2) a (source)| |_______________________|file_or_(3)_a_module.____________________|_ eeddiitt((_+_S_p_e_c_i_f_i_c_a_t_i_o_n)) First exploits prolog_edit:locate/3 to translate _S_p_e_c_i_f_i_c_a_t_i_o_n into a list of _L_o_c_a_t_i_o_n_s. If there is more than one `hit', the user is asked to select from the locations found. Finally, prolog_edit:edit_source/1 is used to invoke the user's preferred editor. Typically, edit/1 can be handed the name of a predicate, module, basename of a file, XPCE class, XPCE method, etc. eeddiitt Edit the `default' file using edit/1. The default file is the file loaded with the command-line option -s or, in windows, the file loaded by double-clicking from the Windows shell. pprroolloogg__eeddiitt::llooccaattee((_+_S_p_e_c_, _-_F_u_l_l_S_p_e_c_, _-_L_o_c_a_t_i_o_n)) Where _S_p_e_c is the specification provided through edit/1. This multifile predicate is used to enumerate locations at with an object satisfying the given _S_p_e_c can be found. _F_u_l_l_S_p_e_c is unified with the complete specification for the object. This distinction is used to allow for ambiguous specifications. For example, if _S_p_e_c is an atom, which appears as the base-name of a loaded file and as the name of a predicate, _F_u_l_l_S_p_e_c will be bound to file(_P_a_t_h) or _N_a_m_e/_A_r_i_t_y. _L_o_c_a_t_i_o_n is a list of attributes of the location. Normally, this list will contain the term file(_F_i_l_e) and ---if available--- the term line(_L_i_n_e). pprroolloogg__eeddiitt::llooccaattee((_+_S_p_e_c_, _-_L_o_c_a_t_i_o_n)) Same as prolog_edit:locate/3, but only deals with fully-specified objects. pprroolloogg__eeddiitt::eeddiitt__ssoouurrccee((_+_L_o_c_a_t_i_o_n)) Start editor on _L_o_c_a_t_i_o_n. See prolog_edit:locate/3 for the format of a location term. This multi-file predicate is normally not defined. If it succeeds, edit/1 assumes the editor is started. If it fails, edit/1 uses its internal defaults, which are defined by the prolog-flag editor and/or the environment variable EDITOR. The following rules apply. If the prolog-flag editor is of the format $<_n_a_m_e>, the editor is determined by the environment variable <_n_a_m_e>. Else, if this flag is pce_emacs or built_in _a_n_d XPCE is loaded or can be loaded, the built-in Emacs clone is used. Else, if the environment EDITOR is set, this editor is used. Finally, vi is used as default on Unix systems and notepad on Windows. See the default user preferences file dotfiles/dotplrc for examples. pprroolloogg__eeddiitt::eeddiitt__ccoommmmaanndd((_+_E_d_i_t_o_r_, _-_C_o_m_m_a_n_d)) Determines how _E_d_i_t_o_r is to be invoked using shell/1. _E_d_i_t_o_r is the determined editor (see edit_source/1), without the full path specification, and without possible (exe) extension. _C_o_m_m_a_n_d is an atom describing the command. The pattern %f is replaced by the full file-name of the location, and %d by the line number. If the editor can deal with starting at a specified line, two clauses should be provided, one holding only the %f pattern, and one holding both patterns. The default contains definitions for vi, emacs, emacsclient, vim and notepad (latter without line-number version). Please contribute your specifications to jan@swi.psy.uva.nl. pprroolloogg__eeddiitt::llooaadd Normally not-defined multifile predicate. This predicate may be defined to provide loading hooks for user-extensions to the edit module. For example, XPCE provides the code below to load swi_edit, containing definitions to locate classes and methods as well as to bind this package to the PceEmacs built-in editor. :- multifile prolog_edit:load/0. prolog_edit:load :- ensure_loaded(library(swi_edit)). lliissttiinngg((_+_P_r_e_d)) List specified predicates (when an atom is given all predicates with this name will be listed). The listing is produced on the basis of the internal representation, thus losing user's layout and variable name information. See also portray_clause/1. lliissttiinngg List all predicates of the database using listing/1. ppoorrttrraayy__ccllaauussee((_+_C_l_a_u_s_e)) Pretty print a clause. A clause should be specified as a term `<_H_e_a_d> :- <_B_o_d_y>'. Facts are represented as `<_H_e_a_d> :- true' or simply <_H_e_a_d>. Variables in the clause are written as A, B, .... Singleton variables are written as _. See also portray_clause/2. ppoorrttrraayy__ccllaauussee((_+_S_t_r_e_a_m_, _+_C_l_a_u_s_e)) Pretty print a clause to _S_t_r_e_a_m. See portray_clause/1 for details. 44..55 VVeerriiffyy TTyyppee ooff aa TTeerrmm vvaarr((_+_T_e_r_m)) True if _T_e_r_m currently is a free variable. nnoonnvvaarr((_+_T_e_r_m)) True if _T_e_r_m currently is not a free variable. iinntteeggeerr((_+_T_e_r_m)) True if _T_e_r_m is bound to an integer. ffllooaatt((_+_T_e_r_m)) True if _T_e_r_m is bound to a floating point number. rraattiioonnaall((_+_T_e_r_m)) True if _T_e_r_m is bound to a rational number. Rational numbers include integers. rraattiioonnaall((_+_T_e_r_m_, _-_N_u_m_e_r_a_t_o_r_, _-_D_e_n_o_m_i_n_a_t_o_r)) True if _T_e_r_m is a rational number with given _N_u_m_e_r_a_t_o_r and _D_e_n_o_m_i_n_a_t_o_r. The _N_u_m_e_r_a_t_o_r and _D_e_n_o_m_i_n_a_t_o_r are in canonical form, which means _D_e_n_o_m_i_n_a_t_o_r is a positive integer and there are no common divisors between _N_u_m_e_r_a_t_o_r and _D_e_n_o_m_i_n_a_t_o_r. nnuummbbeerr((_+_T_e_r_m)) True if _T_e_r_m is bound to an integer or floating point number. aattoomm((_+_T_e_r_m)) True if _T_e_r_m is bound to an atom. ssttrriinngg((_+_T_e_r_m)) True if _T_e_r_m is bound to a string. Note that string here refers to the built-in atomic type string as described in section 4.23, Text in double quotes such as "hello" creates a _l_i_s_t of _c_h_a_r_a_c_t_e_r _c_o_d_e_s. We illustrate the issues in the example queries below. ?- write("hello"). [104, 101, 108, 108, 111] ?- string("hello"). No ?- is_list("hello"). Yes aattoommiicc((_+_T_e_r_m)) True if _T_e_r_m is bound to an atom, string, integer or floating point number. Note that string refers to the built-in type. See string/1. Strings in the classical Prolog sense are lists and therefore compound. ccoommppoouunndd((_+_T_e_r_m)) True if _T_e_r_m is bound to a compound term. See also functor/3 and =../2. ccaallllaabbllee((_+_T_e_r_m)) True if _T_e_r_m is bound to an atom or a compound term, so it can be handed without type-error to call/1, functor/3 and =../2. ggrroouunndd((_+_T_e_r_m)) True if _T_e_r_m holds no free variables. ccyycclliicc__tteerrmm((_+_T_e_r_m)) True if _T_e_r_m contains cycles, i.e. is an infinite term. See also acyclic_term/1 and section 2.16. aaccyycclliicc__tteerrmm((_+_T_e_r_m)) True if _T_e_r_m does not contain cycles, i.e. can be processed recursively in finite time. See also cyclic_term/1 and section 2.16. 44..66 CCoommppaarriissoonn aanndd UUnniiffiiccaattiioonn oorr TTeerrmmss 44..66..11 SSttaannddaarrdd OOrrddeerr ooff TTeerrmmss Comparison and unification of arbitrary terms. Terms are ordered in the so called ``standard order''. This order is defined as follows: 1. _V_a_r_i_a_b_l_e_s <_N_u_m_b_e_r_s <_A_t_o_m_s <_S_t_r_i_n_g_s <_C_o_m_o_u_n_d _T_e_r_m_s 2. Variables are sorted by address. Attaching attributes (see section 6.1) does not affect the ordering. 3. _A_t_o_m_s are compared alphabetically. 4. _S_t_r_i_n_g_s are compared alphabetically. 5. _N_u_m_b_e_r_s are compared by value. Integers and floats are treated identically. If the prolog_flag (see current_prolog_flag/2) iso is defined, all floating point numbers precede all integers. 6. _C_o_m_p_o_u_n_d terms are first checked on their arity, then on their functor-name (alphabetically) and finally recursively on their arguments, leftmost argument first. _+_T_e_r_m_1 == _+_T_e_r_m_2 True if _T_e_r_m_1 is equivalent to _T_e_r_m_2. A variable is only identical to a sharing variable. _+_T_e_r_m_1 \== _+_T_e_r_m_2 Equivalent to \+Term1 == Term2. _+_T_e_r_m_1 = _+_T_e_r_m_2 Unify _T_e_r_m_1 with _T_e_r_m_2. True if the unification succeeds. uunniiffyy__wwiitthh__ooccccuurrss__cchheecckk((_+_T_e_r_m_1_, _+_T_e_r_m_2)) As =/2, but using _s_o_u_n_d_-_u_n_i_f_i_c_a_t_i_o_n. That is, a variable only unifies to a term if this term does not contain the variable itself. To illustrate this, consider the two goals below: 1 ?- A = f(A). A = f(f(f(f(f(f(f(f(f(f(...)))))))))) 2 ?- unify_with_occurs_check(A, f(A)). No I.e. the first creates a _c_y_c_l_i_c_-_t_e_r_m, which is printed as an infinitely nested f/1 term (see the max_depth option of write_term/2). The second executes logically sound unification and thus fails. _+_T_e_r_m_1 \= _+_T_e_r_m_2 Equivalent to \+Term1 = Term2. _+_T_e_r_m_1 =@= _+_T_e_r_m_2 True if _T_e_r_m_1 is `structurally equal' to _T_e_r_m_2. Structural equivalence is weaker than equivalence (==/2), but stronger than unification (=/2). Two terms are structurally equal if their tree representation is identical and they have the same `pattern' of variables. Examples: a =@= A false A =@= B true x(A,A) =@= x(B,C) false x(A,A) =@= x(B,B) true x(A,B) =@= x(C,D) true The predicates =@=/2 and \=@=/2 are cycle-safe. Attributed variables are considered structurally equal iff their attributes are structurally equal. _+_T_e_r_m_1 \=@= _+_T_e_r_m_2 Equivalent to `\+Term1 =@= Term2'. _+_T_e_r_m_1 @< _+_T_e_r_m_2 True if _T_e_r_m_1 is before _T_e_r_m_2 in the standard order of terms. _+_T_e_r_m_1 @=< _+_T_e_r_m_2 True if both terms are equal (==/2) or _T_e_r_m_1 is before _T_e_r_m_2 in the standard order of terms. _+_T_e_r_m_1 @> _+_T_e_r_m_2 True if _T_e_r_m_1 is after _T_e_r_m_2 in the standard order of terms. _+_T_e_r_m_1 @>= _+_T_e_r_m_2 True if both terms are equal (==/2) or _T_e_r_m_1 is after _T_e_r_m_2 in the standard order of terms. ccoommppaarree((_?_O_r_d_e_r_, _+_T_e_r_m_1_, _+_T_e_r_m_2)) Determine or test the _O_r_d_e_r between two terms in the standard order of terms. _O_r_d_e_r is one of <, > or =, with the obvious meaning. ??==((_@_T_e_r_m_1_, _@_T_e_r_m_2)) Decide whether the equality of _T_e_r_m_1 and _T_e_r_m_2 can be compared safely, i.e. whether the result of Term1 == Term2 can change due to further instantiation of either term. It is defined as by ?=(A,B) :- (A==B ; A \= B), !. See also dif/2. uunniiffiiaabbllee((_@_X_, _@_Y_, _-_U_n_i_f_i_e_r)) If _X and _Y can unify, unify _U_n_i_f_i_e_r with a list of _V_a_r = _V_a_l_u_e, representing the bindings required to make _X and _Y equivalent. This predicate can handle cyclic terms. Attributed variables are handles as normal variables. Associated hooks are _n_o_t executed. 44..77 CCoonnttrrooll PPrreeddiiccaatteess The predicates of this section implement control structures. Normally the constructs in this section, except for repeat/0, are translated by the compiler. Please note that complex goals passed as arguments to meta-predicates such as findall/3 below cause the goal to be compiled to a temporary location before execution. It is faster to define a sub-predicate (i.e. one_character_atom/1 in the example below) and make a call to this simple predicate. one_character_atoms(As) :- findall(A, (current_atom(A), atom_length(A, 1)), As). ffaaiill Always fail. The predicate fail/0 is translated into a single virtual machine instruction. ttrruuee Always succeed. The predicate true/0 is translated into a single virtual machine instruction. rreeppeeaatt Always succeed, provide an infinite number of choice points. ! Cut. Discard choice points of parent frame and frames created after the parent frame. As of SWI-Prolog 3.3, the semantics of the cut are compliant with the ISO standard. This implies that the cut is transparent to ;/2, ->/2 and *->/2. Cuts appearing in the _c_o_n_d_i_t_i_o_n part of ->/2 and *->/2 as well as in \+/1 are local to the condition. t1 :- (a, !, fail ; b). % cuts a/0 and t1/0 t2 :- (a -> b, ! ; c). % cuts b/0 and t2/0 t3 :- call((a, !, fail ; b)). % cuts a/0 t4 :- \+(a, !, fail ; b). % cuts a/0 _+_G_o_a_l_1 , _+_G_o_a_l_2 Conjunction. True if both `Goal1' and `Goal2' can be proved. It is defined as (this definition does not lead to a loop as the second comma is handled by the compiler): Goal1, Goal2 :- Goal1, Goal2. _+_G_o_a_l_1 ; _+_G_o_a_l_2 The `or' predicate is defined as: Goal1 ; _Goal2 :- Goal1. _Goal1 ; Goal2 :- Goal2. _+_G_o_a_l_1 | _+_G_o_a_l_2 Equivalent to ;/2. Retained for compatibility only. New code should use ;/2. _+_C_o_n_d_i_t_i_o_n -> _+_A_c_t_i_o_n If-then and If-Then-Else. The ->/2 construct commits to the choices made at its left-hand side, destroying choice-points created inside the clause (by ;/2), or by goals called by this clause. Unlike !/0, the choice-point of the predicate as a whole (due to multiple clauses) is nnoott destroyed. The combination ;/2 and ->/2 acts as if defines by: If -> Then; _Else :- If, !, Then. If -> _Then; Else :- !, Else. If -> Then :- If, !, Then. Please note that (If -> Then) acts as (If -> Then ; ffaaiill), making the construct _f_a_i_l if the condition fails. This unusual semantics is part of the ISO and all de-facto Prolog standards. _+_C_o_n_d_i_t_i_o_n *-> _+_A_c_t_i_o_n _; _+_E_l_s_e This construct implements the so-called `soft-cut'. The control is defined as follows: If _C_o_n_d_i_t_i_o_n succeeds at least once, the semantics is the same as (_C_o_n_d_i_t_i_o_n, _A_c_t_i_o_n). If _C_o_n_d_i_t_i_o_n does not succeed, the semantics is that of (\+ _C_o_n_d_i_t_i_o_n, _E_l_s_e). In other words, If _C_o_n_d_i_t_i_o_n succeeds at least once, simply behave as the conjunction of _C_o_n_d_i_t_i_o_n and _A_c_t_i_o_n, otherwise execute _E_l_s_e. The construct _A *-> _B, i.e. without an _E_l_s_e branch, is translated as the normal conjunction _A, _B. \+ _+_G_o_a_l True if `Goal' cannot be proven (mnemonic: + refers to _p_r_o_v_a_b_l_e and the backslash (\) is normally used to indicate negation in Prolog). 44..88 MMeettaa--CCaallll PPrreeddiiccaatteess Meta-call predicates are used to call terms constructed at run time. The basic meta-call mechanism offered by SWI-Prolog is to use variables as a subclause (which should of course be bound to a valid goal at runtime). A meta-call is slower than a normal call as it involves actually searching the database at runtime for the predicate, while for normal calls this search is done at compile time. ccaallll((_+_G_o_a_l)) Invoke _G_o_a_l as a goal. Note that clauses may have variables as subclauses, which is identical to call/1. ccaallll((_+_G_o_a_l_, _+_E_x_t_r_a_A_r_g_1_, _._._.)) Append _E_x_t_r_a_A_r_g_1_, _E_x_t_r_a_A_r_g_2_, _._._. to the argument list of _G_o_a_l and call the result. For example, call(plus(1), 2, X) will call plus/3, binding _X to 3. The call/[2..] construct is handled by the compiler, which implies that redefinition as a predicate has no effect. The predicates call/[2-6] are defined as true predicates, so they can be handled by interpreted code. aappppllyy((_+_T_e_r_m_, _+_L_i_s_t)) Append the members of _L_i_s_t to the arguments of _T_e_r_m and call the resulting term. For example: apply(plus(1), [2, X]) will call plus(1, 2, X). apply/2 is incorporated in the virtual machine of SWI-Prolog. This implies that the overhead can be compared to the overhead of call/1. New code should use call/[2..] if the length of _L_i_s_t is fixed, which is more widely supported and faster because there is no need to build and examine the argument list. nnoott((_+_G_o_a_l)) True if _G_o_a_l cannot be proven. Retained for compatibility only. New code should use \+/1. oonnccee((_+_G_o_a_l)) Defined as: once(Goal) :- Goal, !. once/1 can in many cases be replaced with ->/2. The only difference is how the cut behaves (see !/0). The following two clauses are identical: 1) a :- once((b, c)), d. 2) a :- b, c -> d. iiggnnoorree((_+_G_o_a_l)) Calls _G_o_a_l as once/1, but succeeds, regardless of whether _G_o_a_l succeeded or not. Defined as: ignore(Goal) :- Goal, !. ignore(_). ccaallll__wwiitthh__ddeepptthh__lliimmiitt((_+_G_o_a_l_, _+_L_i_m_i_t_, _-_R_e_s_u_l_t)) If _G_o_a_l can be proven without recursion deeper than _L_i_m_i_t levels, call_with_depth_limit/3 succeeds, binding _R_e_s_u_l_t to the deepest recursion level used during the proof. Otherwise, _R_e_s_u_l_t is unified with depth_limit_exceeded if the limit was exceeded during the proof, or the entire predicate fails if _G_o_a_l fails without exceeding _L_i_m_i_t. The depth-limit is guarded by the internal machinery. This may differ from the depth computed based on a theoretical model. For example, true/0 is translated into an inlined virtual machine instruction. Also, repeat/0 is not implemented as below, but as a non-deterministic foreign predicate. repeat. repeat :- repeat. As a result, call_with_depth_limit/3may still loop infinitely on programs that should theoretically finish in finite time. This problem can be cured by using Prolog equivalents to such built-in predicates. This predicate may be used for theorem-provers to realise techniques like _i_t_e_r_a_t_i_v_e _d_e_e_p_e_n_i_n_g. It was implemented after discussion with Steve Moyle smoyle@ermine.ox.ac.uk. ccaallll__cclleeaannuupp((_:_G_o_a_l_, _+_C_a_t_c_h_e_r_, _:_C_l_e_a_n_u_p)) Calls _G_o_a_l. If _G_o_a_l is completely finished, either by deterministic success, failure, its choice-point being cut or raising an exception and _C_a_t_c_h_e_r unifies to the termination code (see below), _C_l_e_a_n_u_p is called. Success or failure of _C_l_e_a_n_u_p is ignored and possible choice-points it created are destroyed (as once/1). If cleanup throws an exception this is executed as normal. _C_a_t_c_h_e_r is unified with a term describing how the call has finished. If this unification fails, _C_l_e_a_n_u_p is _n_o_t called. eexxiitt _G_o_a_l succeeded without leaving any choice-points. ffaaiill _G_o_a_l failed. ! _G_o_a_l succeeded with choice-points and these are now discarded by the execution of a cut (or other pruning of the search tree such as if-then-else). eexxcceeppttiioonn((_E_x_c_e_p_t_i_o_n)) _G_o_a_l raised the given _E_x_c_e_p_t_i_o_n. Typical use of this predicate is cleanup of permanent data storage required to execute _G_o_a_l, close file-descriptors, etc. The example below provides a non-deterministic search for a term in a file, closing the stream as needed. term_in_file(Term, File) :- open(File, read, In), call_cleanup(term_in_stream(Term, In), _, close(In)). term_in_stream(Term, In) :- repeat, read(In, T), ( T == end_of_file -> !, fail ; T = Term ). Note that this predicate is impossible to implement in Prolog other then reading all terms into a list, close the file and call member/2 because without call_cleanup/3 there is no way to gain control if the choice-point left by repeat is killed by a cut. This predicate is a SWI-Prolog extension. See also call_cleanup/2 for compatibility to other Prolog implementations. ccaallll__cclleeaannuupp((_:_G_o_a_l_, _:_C_l_e_a_n_u_p)) This predicate is equivalent to call_cleanup(_G_o_a_l_, ___, _C_l_e_a_n_u_p), calling _C_l_e_a_n_u_p regardless of the reason for termination and without providing information. This predicate provides compatibility to a number of other Prolog implementations. 44..99 IISSOO ccoommpplliiaanntt EExxcceeppttiioonn hhaannddlliinngg SWI-Prolog defines the predicates catch/3 and throw/1 for ISO compliant raising and catching of exceptions. In the current implementation (4.0.6), most of the built-in predicates generate exceptions, but some obscure predicates merely print a message, start the debugger and fail, which was the normal behaviour before the introduction of exceptions. ccaattcchh((_:_G_o_a_l_, _+_C_a_t_c_h_e_r_, _:_R_e_c_o_v_e_r)) Behaves as call/1 if no exception is raised when executing _G_o_a_l. If a exception is raised using throw/1 while _G_o_a_l executes, and the _G_o_a_l is the innermost goal for which _C_a_t_c_h_e_r unifies with the argument of throw/1, all choice-points generated by _G_o_a_l are cut, the system backtracks to the start of catch/3 while preserving the thrown exception term and _R_e_c_o_v_e_r is called as in call/1. The overhead of calling a goal through catch/3 is very comparable to call/1. Recovery from an exception is much slower, especially if the exception-term is large due to the copying thereof. tthhrrooww((_+_E_x_c_e_p_t_i_o_n)) Raise an exception. The system looks for the innermost catch/3 ancestor for which _E_x_c_e_p_t_i_o_n unifies with the _C_a_t_c_h_e_r argument of the catch/3 call. See catch/3 for details. ISO demands throw/1 to make a copy of _E_x_c_e_p_t_i_o_n, walk up the stack to a catch/3 call, backtrack and try to unify the copy of _E_x_c_e_p_t_i_o_n with _C_a_t_c_h_e_r. SWI-Prolog delays making a copy of _E_x_c_e_p_t_i_o_n and backtracking until it actually found a matching catch/3 goal. The advantage is that we can start the debugger at the first possible location while preserving the entire exception context if there is no matching catch/3 goal. This approach can lead to different behaviour if _G_o_a_l and _C_a_t_c_h_e_r of catch/3 call share variables. We assume this to be highly unlikely and could not think of a scenario where this is useful. If an exception is raised in a callback from C (see chapter 9) and not caught in the same call-back, PL_next_solution() fails and the exception context can be retrieved using PL_exception(). 44..99..11 DDeebbuuggggiinngg aanndd eexxcceeppttiioonnss Before the introduction of exceptions in SWI-Prolog a runtime error was handled by printing an error message, after which the predicate failed. If the prolog_flag (see current_prolog_flag/2) debug_on_error was in effect (default), the tracer was switched on. The combination of the error message and trace information is generally sufficient to locate the error. With exception handling, things are different. A programmer may wish to trap an exception using catch/3 to avoid it reaching the user. If the exception is not handled by user-code, the interactive top-level will trap it to prevent termination. If we do not take special precautions, the context information associated with an unexpected exception (i.e., a programming error) is lost. Therefore, if an exception is raised, which is not caught using catch/3 and the top-level is running, the error will be printed, and the system will enter trace mode. If the system is in an non-interactive callback from foreign code and there is no catch/3 active in the current context, it cannot determine whether or not the exception will be caught by the external routine calling Prolog. It will then base its behaviour on the prolog_flag debug_on_error: o _c_u_r_r_e_n_t___p_r_o_l_o_g___f_l_a_g_(_d_e_b_u_g___o_n___e_r_r_o_r_, _f_a_l_s_e_) The exception does not trap the debugger and is returned to the foreign routine calling Prolog, where it can be accessed using PL_exception(). This is the default. o _c_u_r_r_e_n_t___p_r_o_l_o_g___f_l_a_g_(_d_e_b_u_g___o_n___e_r_r_o_r_, _t_r_u_e_) If the exception is not caught by Prolog in the current context, it will trap the tracer to help analysing the context of the error. While looking for the context in which an exception takes place, it is advised to switch on debug mode using the predicate debug/0. The hook prolog_exception_hook/4 can be used to add more debugging facilities to exceptions. An example is the library http/http_error, generating a full stack trace on errors in the HTTP server library. 44..99..22 TThhee eexxcceeppttiioonn tteerrmm Built-in predicates generates exceptions using a term error(_F_o_r_m_a_l_, _C_o_n_t_e_x_t). The first argument is the `formal' description of the error, specifying the class and generic defined context information. When applicable, the ISO error-term definition is used. The second part describes some additional context to help the programmer while debugging. In its most generic form this is a term of the form context(_N_a_m_e_/_A_r_i_t_y_, _M_e_s_s_a_g_e), where _N_a_m_e/_A_r_i_t_y describes the built-in predicate that raised the error, and _M_e_s_s_a_g_e provides an additional description of the error. Any part of this structure may be a variable if no information was present. 44..99..33 PPrriinnttiinngg mmeessssaaggeess The predicate print_message/2 may be used to print a message term in a human readable format. The other predicates from this section allow the user to refine and extend the message system. The most common usage of print_message/2 is to print error messages from exceptions. The code below prints errors encountered during the execution of _G_o_a_l, without further propagating the exception and without starting the debugger. ..., catch(Goal, E, ( print_message(error, E), fail )), ... Another common use is to defined message_hook/3 for printing messages that are normally _s_i_l_e_n_t, suppressing messages, redirecting messages or make something happen in addition to printing the message. pprriinntt__mmeessssaaggee((_+_K_i_n_d_, _+_T_e_r_m)) The predicate print_message/2 is used to print messages, notably from exceptions in a human-readable format. _K_i_n_d is one of informational, banner, warning, error, help or silent. A human-readable message is printed to the stream user_error. If the prolog flag (see current_prolog_flag/2) verbose is silent, messages with _K_i_n_d informational, or banner are treated as silent. See -q. This predicate first translates the _T_e_r_m into a list of `message lines' (see print_message_lines/3for details). Next it will call the hook message_hook/3to allow the user intercepting the message. If message_hook/3 fails it will print the message unless _K_i_n_d is silent. The print_message/2 predicate and its rules are in the file <_p_l_h_o_m_e>/boot/messages.pl, which may be inspected for more information on the error messages and related error terms. If you need to report errors from your own predicates, we advise you to stick to the existing error terms if you can; but should you need to invent new ones, you can define corresponding error messages by asserting clauses for prolog:message. You will need to declare the predicate as multifile. See also message_to_string/2. pprriinntt__mmeessssaaggee__lliinneess((_+_S_t_r_e_a_m_, _+_P_r_e_f_i_x_, _+_L_i_n_e_s)) Print a message (see print_message/2) that has been translated to a list of message elements. The elements of this list are: <_F_o_r_m_a_t>--<_A_r_g_s> Where _F_o_r_m_a_t is an atom and _A_r_g_s is a list of format argument. Handed to format/3. flush If this appears as the last element, _S_t_r_e_a_m is flushed (see flush_output/1) and no final newline is generated. at_same_line If this appears as first element, no prefix is printed for the first line and the line-position is not forced to 0 (see format/1, ~N). <_F_o_r_m_a_t> Handed to format/3 as format(Stream, Format, []). nnll A new line is started and if the message is not complete the _P_r_e_f_i_x is printed too. See also print_message/2 and message_hook/3. mmeessssaaggee__hhooookk((_+_T_e_r_m_, _+_K_i_n_d_, _+_L_i_n_e_s)) Hook predicate that may be define in the module user to intercept messages from print_message/2. _T_e_r_m and _K_i_n_d are the same as passed to print_message/2. _L_i_n_e_s is a list of format statements as described with print_message_lines/3. See also message_to_string/2. This predicate should be defined dynamic and multifile to allow other modules defining clauses for it too. mmeessssaaggee__ttoo__ssttrriinngg((_+_T_e_r_m_, _-_S_t_r_i_n_g)) Translates a message-term into a string object (see section 4.23. Primarily intended to write messages to Windows in XPCE (see section 1.5) or other GUI environments. 44..1100 HHaannddlliinngg ssiiggnnaallss As of version 3.1.0, SWI-Prolog is capable to handle software interrupts (signals) in Prolog as well as in foreign (C) code (see section 9.6.12). Signals are used to handle internal errors (execution of a non-existing CPU instruction, arithmetic domain errors, illegal memory access, resource overflow, etc.), as well as for dealing asynchronous inter-process communication. Signals are defined by the POSIX standard and part of all Unix machines. The MS-Windows Win32 provides a subset of the signal handling routines, lacking the vital functionality to raise a signal in another thread for achieving asynchronous inter-process (or inter-thread) communication (Unix kill() function). oonn__ssiiggnnaall((_+_S_i_g_n_a_l_, _-_O_l_d_, _:_N_e_w)) Determines the reaction on _S_i_g_n_a_l. _O_l_d is unified with the old behaviour, while the behaviour is switched to _N_e_w. As with similar environment-control predicates, the current value is retrieved using on_signal(Signal, Current, Current). The action description is an atom denoting the name of the predicate that will be called if _S_i_g_n_a_l arrives. on_signal/3 is a meta-predicate, which implies that <_M_o_d_u_l_e>:<_N_a_m_e> refers the <_N_a_m_e>/1 in the module <_M_o_d_u_l_e>. Two predicate-names have special meaning. throw implies Prolog will map the signal onto a Prolog exception as described in section 4.9. default resets the handler to the settings active before SWI-Prolog manipulated the handler. Signals bound to a foreign function through PL_signal() are reported using the term $foreign_function(_A_d_d_r_e_s_s). After receiving a signal mapped to throw, the exception raised has the structure error(signal(<_S_i_g_N_a_m_e>, <_S_i_g_N_u_m>), <_C_o_n_t_e_x_t>) One possible usage of this is, for example, to limit the time spent on proving a goal. This requires a little C-code for setting the alarm timer (see chapter 9): #include #include foreign_t pl_alarm(term_t time) { double t; if ( PL_get_float(time, &t) ) { alarm((long)(t+0.5)); PL_succeed; } PL_fail; } install_t install() { PL_register_foreign("alarm", 1, pl_alarm, 0); } Next, we can define the Prolog below. This will run _G_o_a_l just as once/1, throwing the exception error(_s_i_g_n_a_l_(_a_l_r_m_, ___)_, __) if a timeout occurs. :- load_foreign_library(alarm). :- on_signal(alrm, _, throw). :- module_transparent call_with_time_limit/2. call_with_time_limit(MaxTime, Goal) :- alarm(MaxTime), call_cleanup(Goal, _, alarm(0)), !. The signal names are defined by the POSIX standard as symbols of the form SIG_<_S_I_G_N_A_M_E>. The Prolog name for a signal is the lowercase version of <_S_I_G_N_A_M_E>. The predicate current_signal/3 may be used to map between names and signals. Initially, some signals are mapped to throw, while all other signals are default. The following signals throw an exception: ill, fpe, segv, pipe, alrm, bus, xcpu, xfsz and vtalrm. ccuurrrreenntt__ssiiggnnaall((_?_N_a_m_e_, _?_I_d_, _?_H_a_n_d_l_e_r)) Enumerate the currently defined signal handling. _N_a_m_e is the signal name, _I_d is the numerical identifier and _H_a_n_d_l_e_r is the currently defined handler (see on_signal/3). 44..1100..11 NNootteess oonn ssiiggnnaall hhaannddlliinngg Before deciding to deal with signals in your application, please consider the following: o _P_o_r_t_a_b_i_l_i_t_y On MS-Windows, the signal interface is severely limited. Different Unix brands support different sets of signals, and the relation between signal name and number may vary. o _S_a_f_e_t_y Signal handling is not completely safe in the current implementation, especially if throw is used in combination with external foreign code. The system will use the C longjmp() construct to direct control to the innermost PL_next_solution(), thus forcing an external procedure to be abandoned at an arbitrary moment. Most likely not all SWI-Prologs own foreign code is (yet) safe too. For the multi-threaded versions this is even worse: signals can easily violate thread synchronisation consistency. The C-interface described in section 9.6.12 provides the option PL_SIGSYNC for registering a signal handler that delays delivery of signals to a safe point. Unfortunately this may cause signals to be delayed for a long time if Prolog is executing foreign code. o _G_a_r_b_a_g_e _C_o_l_l_e_c_t_i_o_n The garbage collector will block all signals that are handled by Prolog. While handling a signal, the garbage-collector is disabled. o _T_i_m_e _o_f _d_e_l_i_v_e_r_y Normally delivery is immediate (or as defined by the operating system used). Signals are blocked when the garbage collector is active, and internally delayed if they occur within in a `critical section'. The critical sections are generally very short. 44..1111 TThhee ``bblloocckk'' ccoonnttrrooll--ssttrruuccttuurree The block/3 predicate and friends have been introduced before ISO compatible catch/3 exception handling for compatibility with some Prolog implementation. The only feature not covered by catch/3 and throw/1 is the possibility to execute global cuts. New code should use catch/3 and throw/1 to deal with exceptions. bblloocckk((_+_L_a_b_e_l_, _+_G_o_a_l_, _-_E_x_i_t_V_a_l_u_e)) Execute _G_o_a_l in a _b_l_o_c_k. _L_a_b_e_l is the name of the block. _L_a_b_e_l is normally an atom, but the system imposes no type constraints and may even be a variable. _E_x_i_t_V_a_l_u_e is normally unified to the second argument of an exit/2 call invoked by _G_o_a_l. eexxiitt((_+_L_a_b_e_l_, _+_V_a_l_u_e)) Calling exit/2 makes the innermost _b_l_o_c_k which _L_a_b_e_l unifies exit. The block's _E_x_i_t_V_a_l_u_e is unified with _V_a_l_u_e. If this unification fails the block fails. ffaaiill((_+_L_a_b_e_l)) Calling fail/1 makes the innermost _b_l_o_c_k which _L_a_b_e_l unifies fail immediately. Implemented as fail(Label) :- !(Label), fail. !((_+_L_a_b_e_l)) Cut all choice-points created since the entry of the innermost _b_l_o_c_k which _L_a_b_e_l unifies. 44..1122 DDCCGG GGrraammmmaarr rruulleess Grammar rules form a comfortable interface to _d_i_f_f_e_r_e_n_c_e_-_l_i_s_t_s. They are designed both to support writing parsers that build a parse-tree from a list as for generating a flat list from a term. Unfortunately, Definite Clause Grammar (DCG) handling is not part of the Prolog standard. Most Prolog engines implement DCG, but the details differ slightly. Grammar rules look like ordinary clauses using -->/2 for separating the head and body rather then :-/2. Expanding grammar rules is done by expand_term/2, which adds two additional argument to each term for representing the difference list. We will illustrate the behaviour by defining a rule-set for parsing an integer. integer(I) --> digit(D0), digits(D), { number_chars(I, [D0|D]) }. digits([D|T]) --> digit(D), !, digits(T). digits([]) --> []. digit(D) --> [D], { code_type(D, digit) }. The body of a grammar rule can contain three types of terms. A compound term interpreted as a reference to a grammar-rule. Code between {...} is interpreted as a reference to ordinary Prolog code and finally, a list is interpreted as a sequence of literals. The Prolog control-constructs (\+/1, ->/2, ;//2, ,/2 and !/0) can be used in grammar rules. Grammar rule-sets are called using the built-in predicates phrase/2 and phrase/3: pphhrraassee((_+_R_u_l_e_S_e_t_, _+_I_n_p_u_t_L_i_s_t)) Equivalent to phrase(RuleSet, InputList, []). pphhrraassee((_+_R_u_l_e_S_e_t_, _+_I_n_p_u_t_L_i_s_t_, _-_R_e_s_t)) Activate the rule-set with given name. `InputList' is the list of tokens to parse, `Rest' is unified with the remaining tokens if the sentence is parsed correctly. The example below calls the rule-set `integer' defined above. ?- phrase(integer(X), "42 times", Rest). X = 42 Rest = [32, 116, 105, 109, 101, 115] 44..1133 DDaattaabbaassee SWI-Prolog offers three different database mechanisms. The first one is the common assert/retract mechanism for manipulating the clause database. As facts and clauses asserted using assert/1 or one of its derivatives become part of the program these predicates compile the term given to them. retract/1 and retractall/1 have to unify a term and therefore have to decompile the program. For these reasons the assert/retract mechanism is expensive. On the other hand, once compiled, queries to the database are faster than querying the recorded database discussed below. See also dynamic/1. The second way of storing arbitrary terms in the database is using the ``recorded database''. In this database terms are associated with a _k_e_y. A key can be an atom, integer or term. In the last case only the functor and arity determine the key. Each key has a chain of terms associated with it. New terms can be added either at the head or at the tail of this chain. This mechanism is considerably faster than the assert/retract mechanism as terms are not compiled, but just copied into the heap. The third mechanism is a special purpose one. It associates an integer or atom with a key, which is an atom, integer or term. Each key can only have one atom or integer associated with it. It is faster than the mechanisms described above, but can only be used to store simple status information like counters, etc. aabboolliisshh((_:_P_r_e_d_i_c_a_t_e_I_n_d_i_c_a_t_o_r)) Removes all clauses of a predicate with functor _F_u_n_c_t_o_r and arity _A_r_i_t_y from the database. All predicate attributes (dynamic, multifile, index, etc.) are reset to their defaults. Abolishing an imported predicate only removes the import link; the predicate will keep its old definition in its definition module. According to the ISO standard, abolish/1 can only be applied to dynamic procedures. This is odd, as for dealing with dynamic procedures there is already retract/1 and retractall/1. The abolish/1 predicate has been introduced in DEC-10 Prolog precisely for dealing with static procedures. In SWI-Prolog, abolish/1 works on static procedures, unless the prolog flag iso is set to true. It is advised to use retractall/1 for erasing all clauses of a dynamic predicate. aabboolliisshh((_+_N_a_m_e_, _+_A_r_i_t_y)) Same as abolish(Name/Arity). The predicate abolish/2 conforms to the Edinburgh standard, while abolish/1 is ISO compliant. rreeddeeffiinnee__ssyysstteemm__pprreeddiiccaattee((_+_H_e_a_d)) This directive may be used both in module user and in normal modules to redefine any system predicate. If the system definition is redefined in module user, the new definition is the default definition for all sub-modules. Otherwise the redefinition is local to the module. The system definition remains in the module system. Redefining system predicate facilitates the definition of compatibility packages. Use in other context is discouraged. rreettrraacctt((_+_T_e_r_m)) When _T_e_r_m is an atom or a term it is unified with the first unifying fact or clause in the database. The fact or clause is removed from the database. rreettrraaccttaallll((_+_H_e_a_d)) All facts or clauses in the database for which the _h_e_a_d unifies with _H_e_a_d are removed. aasssseerrtt((_+_T_e_r_m)) Assert a fact or clause in the database. _T_e_r_m is asserted as the last fact or clause of the corresponding predicate. aasssseerrttaa((_+_T_e_r_m)) Equivalent to assert/1, but _T_e_r_m is asserted as first clause or fact of the predicate. aasssseerrttzz((_+_T_e_r_m)) Equivalent to assert/1. aasssseerrtt((_+_T_e_r_m_, _-_R_e_f_e_r_e_n_c_e)) Equivalent to assert/1, but _R_e_f_e_r_e_n_c_e is unified with a unique reference to the asserted clause. This key can later be used with clause/3 or erase/1. aasssseerrttaa((_+_T_e_r_m_, _-_R_e_f_e_r_e_n_c_e)) Equivalent to assert/2, but _T_e_r_m is asserted as first clause or fact of the predicate. aasssseerrttzz((_+_T_e_r_m_, _-_R_e_f_e_r_e_n_c_e)) Equivalent to assert/2. rreeccoorrddaa((_+_K_e_y_, _+_T_e_r_m_, _-_R_e_f_e_r_e_n_c_e)) Assert _T_e_r_m in the recorded database under key _K_e_y. _K_e_y is an integer, atom or term. _R_e_f_e_r_e_n_c_e is unified with a unique reference to the record (see erase/1). rreeccoorrddaa((_+_K_e_y_, _+_T_e_r_m)) Equivalent to recorda(Key, Value, _). rreeccoorrddzz((_+_K_e_y_, _+_T_e_r_m_, _-_R_e_f_e_r_e_n_c_e)) Equivalent to recorda/3, but puts the _T_e_r_m at the tail of the terms recorded under _K_e_y. rreeccoorrddzz((_+_K_e_y_, _+_T_e_r_m)) Equivalent to recordz(Key, Value, _). rreeccoorrddeedd((_+_K_e_y_, _-_V_a_l_u_e_, _-_R_e_f_e_r_e_n_c_e)) Unify _V_a_l_u_e with the first term recorded under _K_e_y which does unify. _R_e_f_e_r_e_n_c_e is unified with the memory location of the record. rreeccoorrddeedd((_+_K_e_y_, _-_V_a_l_u_e)) Equivalent to recorded(Key, Value, _). eerraassee((_+_R_e_f_e_r_e_n_c_e)) Erase a record or clause from the database. _R_e_f_e_r_e_n_c_e is an integer returned by recorda/3 or recorded/3, clause/3, assert/2, asserta/2 or assertz/2. Other integers might conflict with the internal consistency of the system. Erase can only be called once on a record or clause. A second call also might conflict with the internal consistency of the system. ffllaagg((_+_K_e_y_, _-_O_l_d_, _+_N_e_w)) _K_e_y is an atom, integer or term. As with the recorded database, if _K_e_y is a term, only the name and arity are used to locate the flag. Unify _O_l_d with the old value associated with _K_e_y. If the key is used for the first time _O_l_d is unified with the integer 0. Then store the value of _N_e_w, which should be an integer, float, atom or arithmetic expression, under _K_e_y. flag/3 is a fast mechanism for storing simple facts in the database. The flag database is shared between threads and updates are atomic, making it suitable for generating unique integer counters. 44..1133..11 UUppddaattee vviieeww Traditionally, Prolog systems used the _i_m_m_e_d_i_a_t_e _u_p_d_a_t_e _v_i_e_w: new clauses became visible to predicates backtracking over dynamic predicates immediately and retracted clauses became invisible immediately. Starting with SWI-Prolog 3.3.0 we adhere the _l_o_g_i_c_a_l _u_p_d_a_t_e _v_i_e_w, where backtrackable predicates that enter the definition of a predicate will not see any changes (either caused by assert/1 or retract/1) to the predicate. This view is the ISO standard, the most commonly used and the most `safe'. Logical updates are realised by keeping reference-counts on predicates and _g_e_n_e_r_a_t_i_o_n information on clauses. Each change to the database causes an increment of the generation of the database. Each goal is tagged with the generation in which it was started. Each clause is flagged with the generation it was created as well as the generation it was erased. Only clauses with `created' ...`erased' interval that encloses the generation of the current goal are considered visible. 44..1133..22 IInnddeexxiinngg ddaattaabbaasseess By default, SWI-Prolog, as most other implementations, indexes predicates on their first argument. SWI-Prolog allows indexing on other and multiple arguments using the declaration index/1. For advanced database indexing, it defines hash_term/2: hhaasshh__tteerrmm((_+_T_e_r_m_, _-_H_a_s_h_K_e_y)) If _T_e_r_m is a ground term (see ground/1), _H_a_s_h_K_e_y is unified with a positive integer value that may be used as a hash-key to the value. If _T_e_r_m is not ground, the predicate succeeds immediately, leaving _H_a_s_h_K_e_y an unbound variable. This predicate may be used to build hash-tables as well as to exploit argument-indexing to find complex terms more quickly. The hash-key does not rely on temporary information like addresses of atoms and may be assumed constant over different invocations and versions of SWI-Prolog. The hash_term/2 predicate is cycle-safe. 44..1144 DDeeccllaarriinngg pprreeddiiccaatteess pprrooppeerrttiieess This section describes directives which manipulate attributes of predicate definitions. The functors dynamic/1, multifile/1 and discontiguous/1 are operators of priority 1150 (see op/3), which implies the list of predicates they involve can just be a comma separated list: :- dynamic foo/0, baz/2. On SWI-Prolog all these directives are just predicates. This implies they can also be called by a program. Do not rely on this feature if you want to maintain portability to other Prolog implementations. ddyynnaammiicc _+_N_a_m_e_/_+_A_r_i_t_y_, _._._. Informs the interpreter that the definition of the predicate(s) may change during execution (using assert/1 and/or retract/1). In the multi-threaded version, the clauses of dynamic predicates are shared between the threads. The directive thread_local/1 provides an alternative where each threads has its own clause-list for the predicate. Dynamic predicates can be turned into static ones using compile_predicates/1. ccoommppiillee__pprreeddiiccaatteess((_:_L_i_s_t_O_f_N_a_m_e_A_r_i_t_y)) Compile a list of specified dynamic predicates (see dynamic/1 and assert/1) into normal static predicates. This call tells the Prolog environment the definition will not change anymore and further calls to assert/1 or retract/1 on the named predicates raise a permission error. This predicate is designed to deal with parts of the program that is generated at runtime but does not change during the remainder of the program execution. mmuullttiiffiillee _+_N_a_m_e_/_+_A_r_i_t_y_, _._._. Informs the system that the specified predicate(s) may be defined over more than one file. This stops consult/1 from redefining a predicate when a new definition is found. ddiissccoonnttiigguuoouuss _+_N_a_m_e_/_+_A_r_i_t_y_, _._._. Informs the system that the clauses of the specified predicate(s) might not be together in the source file. See also style_check/1. iinnddeexx((_+_H_e_a_d)) Index the clauses of the predicate with the same name and arity as _H_e_a_d on the specified arguments. _H_e_a_d is a term of which all arguments are either `1' (denoting `index this argument') or `0' (denoting `do not index this argument'). Indexing has no implications for the semantics of a predicate, only on its performance. If indexing is enabled on a predicate a special purpose algorithm is used to select candidate clauses based on the actual arguments of the goal. This algorithm checks whether indexed arguments might unify in the clause head. Only atoms, integers and compound terms are considered. Compound terms are indexed on the combination of their name and arity. Indexing is very useful for predicates with many clauses representing facts. Due to the representation technique used at most 4 arguments can be indexed. All indexed arguments should be in the first 32 arguments of the predicate. If more than 4 arguments are specified for indexing only the first 4 will be accepted. Arguments above 32 are ignored for indexing. Indexing as specified by this predicate uses a quick but linear scan. Without explicit specification the system uses an algorithm depending on the structure of the first argument and number of clauses, In particular, for predicates that can be indexed on the first argument and have many clauses, the system will use an automatically resizing hash-table to provide access time independent from the number of clauses. If---for example---one wants to represents sub-types using a fact list `sub_type(Sub, Super)' that should be used both to determine sub- and super types one should declare sub_type/2 as follows: :- index(sub_type(1, 1)). sub_type(horse, animal). ... ... Note that this type of indexing makes selecting clauses much faster but remains _l_i_n_e_a_r with respect to the number of clauses, while hashing as described with hash/1 provides constant access time. See also hash/1 and hash_term/2. hhaasshh((_+_H_e_a_d)) Index the given predicate by hashing on the first argument. This is done by default on any predicate with more than 5 clauses having a first argument that can be indexed and at most two that can not be indexed. On dynamic predicates the hash-table is resized as the number of clauses grows, providing roughly constant-time access regardless of the number of clauses predicates that can be indexed on the first argument. See also index/1, hash_term/2 and predicate_property/2. 44..1155 EExxaammiinniinngg tthhee pprrooggrraamm ccuurrrreenntt__aattoomm((_-_A_t_o_m)) Successively unifies _A_t_o_m with all atoms known to the system. Note that current_atom/1 always succeeds if _A_t_o_m is instantiated to an atom. ccuurrrreenntt__bblloobb((_?_B_l_o_b_, _?_T_y_p_e)) Examine the type or enumerate blobs of the given _T_y_p_e. Typed blobs are supported through the foreign language interface for storing arbitrary BLOBS (Binary Large Object) or handles to external entities. See section 9.6.6 for details. ccuurrrreenntt__ffuunnccttoorr((_?_N_a_m_e_, _?_A_r_i_t_y)) Successively unifies _N_a_m_e with the name and _A_r_i_t_y with the arity of functors known to the system. ccuurrrreenntt__ffllaagg((_-_F_l_a_g_K_e_y)) Successively unifies _F_l_a_g_K_e_y with all keys used for flags (see flag/3). ccuurrrreenntt__kkeeyy((_-_K_e_y)) Successively unifies _K_e_y with all keys used for records (see recorda/3, etc.). ccuurrrreenntt__pprreeddiiccaattee((_?_N_a_m_e_, _?_H_e_a_d)) Successively unifies _N_a_m_e with the name of predicates currently defined and _H_e_a_d with the most general term built from _N_a_m_e and the arity of the predicate. This predicate succeeds for all predicates defined in the specified module, imported to it, or in one of the modules from which the predicate will be imported if it is called. ccuurrrreenntt__pprreeddiiccaattee((_:_N_a_m_e_/_A_r_i_t_y)) ISO compliant implementation of current_predicate/2. Un- like current_predicate/2, the current implementation of current_predicate/1 does not consider predicates that can be autoloaded `current'. pprreeddiiccaattee__pprrooppeerrttyy((_:_H_e_a_d_, _?_P_r_o_p_e_r_t_y)) True if _H_e_a_d refers to a predicate that has property _P_r_o_p_e_r_t_y. Can be used to test whether a predicate has a certain property, obtain all properties known for _H_e_a_d, find all predicates having _p_r_o_p_e_r_t_y or even obtaining all information available about the current program. _P_r_o_p_e_r_t_y is one of: bbuuiilltt__iinn Is true if the predicate is locked as a built-in predicate. This implies it cannot be redefined in its definition module and it can normally not be seen in the tracer. ddyynnaammiicc Is true if assert/1 and retract/1 may be used to modify the predicate. This property is set using dynamic/1. eexxppoorrtteedd Is true if the predicate is in the public list of the context module. iimmppoorrtteedd__ffrroomm((_M_o_d_u_l_e)) Is true if the predicate is imported into the context module from module _M_o_d_u_l_e. ffiillee((_F_i_l_e_N_a_m_e)) Unify _F_i_l_e_N_a_m_e with the name of the source file in which the predicate is defined. See also source_file/2. ffoorreeiiggnn Is true if the predicate is defined in the C language. iinnddeexxeedd((_H_e_a_d)) Predicate is indexed (see index/1) according to _H_e_a_d. _H_e_a_d is a term whose name and arity are identical to the predicate. The arguments are unified with `1' for indexed arguments, `0' otherwise. iinntteerrpprreetteedd Is true if the predicate is defined in Prolog. We return true on this because, although the code is actually compiled, it is completely transparent, just like interpreted code. lliinnee__ccoouunntt((_L_i_n_e_N_u_m_b_e_r)) Unify _L_i_n_e_N_u_m_b_e_r with the line number of the first clause of the predicate. Fails if the predicate is not associated with a file. See also source_file/2. mmuullttiiffiillee Is true there may be multiple (or no) file providing clauses for the predicate. This property is set using multifile/1. nnooddeebbuugg Details of the predicate are not shown by the debugger. This is the default for built-in predicates. User predicates can be compiled this way using the Prolog flag generate_debug_info. nnoottrraaccee Do not show ports of this predicate in the debugger. nnuummbbeerr__ooff__ccllaauusseess((_C_l_a_u_s_e_C_o_u_n_t)) Unify _C_l_a_u_s_e_C_o_u_n_t to the number of clauses associated with the predicate. Fails for foreign predicates. tthhrreeaadd__llooccaall If true (only possible on the multi-threaded version) each thread has its own clauses for the predicate. This property is set using thread_local/1. ttrraannssppaarreenntt Is true if the predicate is declared transparent using the module_transparent/1 declaration. uunnddeeffiinneedd Is true if a procedure definition block for the predicate exists, but there are no clauses for it and it is not declared dynamic or multifile. This is true if the predicate occurs in the body of a loaded predicate, an attempt to call it has been made via one of the meta-call predicates or the predicate had a definition in the past. See the library package check for example usage. vvoollaattiillee If true, the clauses are not saved into a saved-state by qsave_program/[1,2]. This property is set using volatile/1. ddwwiimm__pprreeddiiccaattee((_+_T_e_r_m_, _-_D_w_i_m)) `Do What I Mean' (`dwim') support predicate. _T_e_r_m is a term, which name and arity are used as a predicate specification. _D_w_i_m is instantiated with the most general term built from _N_a_m_e and the arity of a defined predicate that matches the predicate specified by _T_e_r_m in the `Do What I Mean' sense. See dwim_match/2 for `Do What I Mean' string matching. Internal system predicates are not generated, unless style_check(+dollar)is active. Backtracking provides all alternative matches. ccllaauussee((_?_H_e_a_d_, _?_B_o_d_y)) True if _H_e_a_d can be unified with a clause head and _B_o_d_y with the corresponding clause body. Gives alternative clauses on backtracking. For facts _B_o_d_y is unified with the atom _t_r_u_e. Normally clause/2 is used to find clause definitions for a predicate, but it can also be used to find clause heads for some body template. ccllaauussee((_?_H_e_a_d_, _?_B_o_d_y_, _?_R_e_f_e_r_e_n_c_e)) Equivalent to clause/2, but unifies _R_e_f_e_r_e_n_c_e with a unique reference to the clause (see also assert/2, erase/1). If _R_e_f_e_r_e_n_c_e is instantiated to a reference the clause's head and body will be unified with _H_e_a_d and _B_o_d_y. nntthh__ccllaauussee((_?_P_r_e_d_, _?_I_n_d_e_x_, _?_R_e_f_e_r_e_n_c_e)) Provides access to the clauses of a predicate using their index number. Counting starts at 1. If _R_e_f_e_r_e_n_c_e is specified it unifies _P_r_e_d with the most general term with the same name/arity as the predicate and _I_n_d_e_x with the index-number of the clause. Otherwise the name and arity of _P_r_e_d are used to determine the predicate. If _I_n_d_e_x is provided _R_e_f_e_r_e_n_c_e will be unified with the clause reference. If _I_n_d_e_x is unbound, backtracking will yield both the indices and the references of all clauses of the predicate. The following example finds the 2nd clause of member/2: ?- nth_clause(member(_,_), 2, Ref), clause(Head, Body, Ref). Ref = 160088 Head = system : member(G575, [G578|G579]) Body = member(G575, G579) ccllaauussee__pprrooppeerrttyy((_+_C_l_a_u_s_e_R_e_f_, _-_P_r_o_p_e_r_t_y)) Queries properties of a clause. _C_l_a_u_s_e_R_e_f is a reference to a clause as produced by clause/3, nth_clause/3 or prolog_frame_attribute/3. _P_r_o_p_e_r_t_y is one of the following: ffiillee((_F_i_l_e_N_a_m_e)) Unify _F_i_l_e_N_a_m_e with the name of the source file in which the clause is defined. Fails if the clause is not associated to a file. lliinnee__ccoouunntt((_L_i_n_e_N_u_m_b_e_r)) Unify _L_i_n_e_N_u_m_b_e_r with the line number of the clause. Fails if the clause is not associated to a file. ffaacctt True if the clause has no body. eerraasseedd True if the clause has been erased, but not yet reclaimed because it is referenced. 44..1166 IInnppuutt aanndd oouuttppuutt SWI-Prolog provides two different packages for input and output. The native I/O system is based on the ISO standard predicates open/3, close/1 and friends. Being more widely portable and equipped with a clearer and more robust specification, new code is encouraged to use these predicates for manipulation of I/O streams. Section 4.16.2 describes tell/1, see/1 and friends, providing I/O in the spirit of the outdated Edinburgh standard. These predicates are layered on top of the ISO predicates. Both packages are fully integrated; the user may switch freely between them. 44..1166..11 IISSOO IInnppuutt aanndd OOuuttppuutt SSttrreeaammss The predicates described in this section provide ISO compliant I/O, where streams are explicitly created using the predicate open/3. The resulting stream identifier is then passed as a parameter to the reading and writing predicates to specify the source or destination of the data. This schema is not vulnerable to filename and stream ambiguities as well as changes to the working directory. New code is advised to use these predicates to manage input and output streams. ooppeenn((_+_S_r_c_D_e_s_t_, _+_M_o_d_e_, _-_S_t_r_e_a_m_, _+_O_p_t_i_o_n_s)) ISO compliant predicate to open a stream. _S_r_c_D_e_s is either an atom, specifying a file, or a term `pipe(Command)', like see/1 and tell/1. _M_o_d_e is one of read, write, append or update. Mode append opens the file for writing, positioning the file-pointer at the end. Mode update opens the file for writing, positioning the file-pointer at the beginning of the file without truncating the file. _S_t_r_e_a_m is either a variable, in which case it is bound to an integer identifying the stream, or an atom, in which case this atom will be the stream identifier. The _O_p_t_i_o_n_s list can contain the following options: ttyyppee((_T_y_p_e)) Using type text (default), Prolog will write a text-file in an operating-system compatible way. Using type binary the bytes will be read or written without any translation. See also the option encoding. aalliiaass((_A_t_o_m)) Gives the stream a name. Below is an example. Be careful with this option as stream-names are global. See also set_stream/2. ?- open(data, read, Fd, [alias(input)]). ..., read(input, Term), ... eennccooddiinngg((_E_n_c_o_d_i_n_g)) Define the encoding used for reading and writing text to this stream. The default encoding for type text is derived from the Prolog flag encoding. For binary streams the default encoding is octet. For details on encoding issues, see section 2.17.1. bboomm((_B_o_o_l)) Check for a BOM (_B_y_t_e _O_r_d_e_r _M_a_r_k_e_r) or write one. If omitted, the default is true for mode read and false for mode write. See also stream_property/2 and especially section 2.17.1.1 for a discussion on this feature. eeooff__aaccttiioonn((_A_c_t_i_o_n)) Defines what happens if the end of the input stream is reached. Action eof_code makes get0/1 and friends return -1 and read/1 and friends return the atom end_of_file. Repetitive reading keeps yielding the same result. Action error is like eof_code, but repetitive reading will raise an error. With action reset, Prolog will examine the file again and return more data if the file has grown. bbuuffffeerr((_B_u_f_f_e_r_i_n_g)) Defines output buffering. The atom full (default) defines full buffering, line buffering by line, and false implies the stream is fully unbuffered. Smaller buffering is useful if another process or the user is waiting for the output as it is being produced. See also flush_output/[0,1]. This option is not an ISO option. cclloossee__oonn__aabboorrtt((_B_o_o_l)) If true (default), the stream is closed on an abort (see abort/0). If false, the stream is not closed. If it is an output stream, it will be flushed however. Useful for logfiles and if the stream is associated to a process (using the pipe/1 construct). lloocckk((_L_o_c_k_i_n_g_M_o_d_e)) Try to obtain a lock on the open file. Default is none, which does not lock the file. The value read or shared means other processes may read the file, but not write it. The value write or exclusive means no other process may read or write the file. Locks are acquired through the POSIX function fcntl() using the command F_SETLKW, which makes a blocked call wait for the lock to be released. Please note that fcntl() locks are _a_d_v_i_s_o_r_y and therefore only other applications using the same advisory locks honour your lock. As there are many issues around locking in Unix, especially related to NFS (network file system), please study the fcntl() manual page before trusting your locks! The lock option is a SWI-Prolog extension. The option reposition is not supported in SWI-Prolog. All streams connected to a file may be repositioned. ooppeenn((_+_S_r_c_D_e_s_t_, _+_M_o_d_e_, _?_S_t_r_e_a_m)) Equivalent to open/4 with an empty option-list. ooppeenn__nnuullll__ssttrreeaamm((_?_S_t_r_e_a_m)) Open a stream that produces no output. All counting functions are enabled on such a stream. An attempt to read from a null-stream will immediately signal end-of-file. Similar to Unix /dev/null. _S_t_r_e_a_m can be an atom, giving the null-stream an alias name. cclloossee((_+_S_t_r_e_a_m)) Close the specified stream. If _S_t_r_e_a_m is not open an error message is displayed. If the closed stream is the current input or output stream the terminal is made the current input or output. cclloossee((_+_S_t_r_e_a_m_, _+_O_p_t_i_o_n_s)) Provides close(_S_t_r_e_a_m_, _[_f_o_r_c_e_(_t_r_u_e_)_]) as the only option. Called this way, any resource error (such as write-errors while flushing the output buffer) are ignored. ssttrreeaamm__pprrooppeerrttyy((_?_S_t_r_e_a_m_, _?_S_t_r_e_a_m_P_r_o_p_e_r_t_y)) ISO compatible predicate for querying status of open I/O streams. _S_t_r_e_a_m_P_r_o_p_e_r_t_y is one of: aalliiaass((_A_t_o_m)) If _A_t_o_m is bound, test of the stream has the specified alias. Otherwise unify _A_t_o_m with the first alias of the stream. bbuuffffeerr((_B_u_f_f_e_r_i_n_g)) SWI-Prolog extension to query the buffering mode of this stream. _B_u_f_f_e_r_i_n_g is one of full, line or false. See also open/4. bboomm((_B_o_o_l)) If present and true, a BOM (_B_y_t_e _O_r_d_e_r _M_a_r_k) was detected while opening the file for reading or a BOM was written while opening the stream. See section 2.17.1.1 for details. eennccooddiinngg((_E_n_c_o_d_i_n_g)) Query the encoding used for text. See section 2.17.1 for an overview of wide character and encoding issues in SWI-Prolog. eenndd__ooff__ssttrreeaamm((_E)) If _S_t_r_e_a_m is an input stream, unify _E with one of the atoms not, at or past. See also at_end_of_stream/[0,1]. eeooff__aaccttiioonn((_A)) Unify _A with one of eof_code, reset or error. See open/4 for details. ffiillee__nnaammee((_A_t_o_m)) If _S_t_r_e_a_m is associated to a file, unify _A_t_o_m to the name of this file. ffiillee__nnoo((_I_n_t_e_g_e_r)) If the stream is associated with a POSIX file-descriptor, unify _I_n_t_e_g_e_r with the descriptor number. SWI-Prolog extension used primarily for integration with foreign code. See also Sfileno() from SWI-Stream.h. iinnppuutt True if _S_t_r_e_a_m has mode read. mmooddee((_I_O_M_o_d_e)) Unify _I_O_M_o_d_e to the mode given to open/4 for opening the stream. Values are: read, write, append and the SWI-Prolog extension update. oouuttppuutt True if _S_t_r_e_a_m has mode write, append or update. ppoossiittiioonn((_T_e_r_m)) Unify _T_e_r_m with the current stream-position. A stream- position is an opaque term whose fields can be extracted using stream_position_data/3. See also set_stream_position/2. rreeppoossiittiioonn((_B_o_o_l)) Unify _B_o_o_l with _t_r_u_e if the position of the stream can be set (see seek/4). It is assumed the position can be set if the stream has a _s_e_e_k_-_f_u_n_c_t_i_o_n and is not based on a POSIX file-descriptor that is not associated to a regular file. rreepprreesseennttaattiioonn__eerrrroorrss((_M_o_d_e)) Determines behaviour of character output if the stream cannot represent a character. For example, an ISO Latin-1 stream cannot represent cyrillic characters. The behaviour is one of error (throw and I/O error exception), prolog (write \...\ escape code or xml (write &#...; XML character entity). The initial mode is prolog for the user streams and error for all other streams. See also section 2.17.1 and set_stream/2. ttyyppee((_T)) Unify _B_o_o_l with text or binary. ttttyy((_B_o_o_l)) This property is reported with _B_o_o_l equals true if the stream is associated with a terminal. See also set_stream/2. ccuurrrreenntt__ssttrreeaamm((_?_O_b_j_e_c_t_, _?_M_o_d_e_, _?_S_t_r_e_a_m)) The predicate current_stream/3 is used to access the status of a stream as well as to generate all open streams. _O_b_j_e_c_t is the name of the file opened if the stream refers to an open file, an integer file-descriptor if the stream encapsulates an operating-system stream or the atom [] if the stream refers to some other object. _M_o_d_e is one of read or write. iiss__ssttrreeaamm((_+_T_e_r_m)) True if _T_e_r_m is a stream name or valid stream handle. This predicate realises a safe test for the existence of a stream alias or handle. sseett__ssttrreeaamm__ppoossiittiioonn((_+_S_t_r_e_a_m_, _+_P_o_s)) Set the current position of _S_t_r_e_a_m to _P_o_s. _P_o_s is a term as returned by stream_property/2 using the position(_P_o_s) property. See also seek/4. ssttrreeaamm__ppoossiittiioonn__ddaattaa((_?_F_i_e_l_d_, _+_P_o_s_i_t_i_o_n_, _-_D_a_t_a)) Extracts information from the opaque stream position term as returned by stream_property/2 requesting the position(_P_o_s_i_t_i_o_n) property. _F_i_e_l_d is one of line_count, line_position, char_count or byte_count. See also line_count/2, line_position/2, character_count/2 and byte_count/2. sseeeekk((_+_S_t_r_e_a_m_, _+_O_f_f_s_e_t_, _+_M_e_t_h_o_d_, _-_N_e_w_L_o_c_a_t_i_o_n)) Reposition the current point of the given _S_t_r_e_a_m. _M_e_t_h_o_d is one of bof, current or eof, indicating positioning relative to the start, current point or end of the underlying object. _N_e_w_L_o_c_a_t_i_o_n is unified with the new offset, relative to the start of the stream. Positions are counted in `units'. A unit is 1 byte, except for text-files using 2-byte Unicode encoding (2 bytes) or _w_c_h_a_r encoding (sizeof(wchar_t)). The latter guarantees comfortable interaction with wide-character text-objects. Otherwise, the use of seek/4 on non-binary files (see open/4) is of limited use, especially when using multi-byte text-encodings (e.g. UTF-8) or multi-byte newline files (e.g. DOS/Windows). On text-files, SWI-Prolog offers reliable backup to an old position using stream_property/2 and set_stream_position/2. Skipping N character codes is achieved calling get_code/2 N times or using copy_stream_data/3, directing the output to a null-stream (see open_null_stream/1). If the seek modifies the current location, the line number and character position in the line are set to 0. If the stream cannot be repositioned, a reposition error is raised. The predicate seek/4 is compatible to Quintus Prolog, though the error conditions and signalling is ISO compliant. See also stream_property/2 and set_stream_position/2. sseett__ssttrreeaamm((_+_S_t_r_e_a_m_, _+_A_t_t_r_i_b_u_t_e)) Modify an attribute of an existing stream. _A_t_t_r_i_b_u_t_e specifies the stream property to set. See also stream_property/2 and open/4. aalliiaass((_A_l_i_a_s_N_a_m_e)) Set the alias of an already created stream. If _A_l_i_a_s_N_a_m_e is the name of one of the standard streams is used, this stream is rebound. Thus, set_stream(S, current_input)is the same as set_input/1 and by setting the alias of a stream to user_input, etc. all user terminal input is read from this stream. See also interactor/0. bbuuffffeerr((_B_u_f_f_e_r_i_n_g)) Set the buffering mode of an already created stream. Buffering is one of full, line or false. cclloossee__oonn__aabboorrtt((_B_o_o_l)) Determine whether or not the stream is closed by abort/0. By default streams are closed. eennccooddiinngg((_A_t_o_m)) Defines the mapping between bytes and character codes used for the stream. See section 2.17.1 for supported encodings. eeooff__aaccttiioonn((_A_c_t_i_o_n)) Set end-of-file handling to one of eof_code, reset or error. ttiimmeeoouutt((_S_e_c_o_n_d_s)) This option can be used to make streams generate an exception if it takes longer than _S_e_c_o_n_d_s before any new data arrives at the stream. The value _i_n_f_i_n_i_t_e (default) makes the stream block indefinitely. Like wait_for_input/3, this call only applies to streams that support the select() system call. For further information about timeout handling, see wait_for_input/3. The exception is of the form error(timeout_error_(_r_e_a_d_, _S_t_r_e_a_m_)_, __) rreeccoorrdd__ppoossiittiioonn((_B_o_o_l)) Do/do not record the line-count and line-position (see line_count/2 and line_position/2). rreepprreesseennttaattiioonn__eerrrroorrss((_M_o_d_e)) Change the behaviour when writing characters to the stream that cannot be represented by the encoding. See also stream_property/2 and section 2.17.1. ffiillee__nnaammee((_F_i_l_e_N_a_m_e)) Set the file name associated to this stream. This call can be used to set the file for error-locations if _S_t_r_e_a_m corresponds to _F_i_l_e_N_a_m_e and is not obtained by opening the file directly but, for example, through a network service. ttttyy((_B_o_o_l)) Modify whether Prolog thinks there is a terminal (i.e. human interaction) connected to this stream. On Unix systems the initial value comes from isatty(). On Windows, the initial user streams are supposed to be associated to a terminal. See also stream_property/2. sseett__pprroolloogg__IIOO((_+_I_n_, _+_O_u_t_, _+_E_r_r_o_r)) Prepare the given streams for interactive behaviour normally associated to the terminal. _I_n becomes the user_input and current_input of the calling thread. _O_u_t becomes user_output and current_output. If _E_r_r_o_r equals _O_u_t an unbuffered stream is associated to the same destination and linked to user_error. Otherwise _E_r_r_o_r is used for user_error. Output buffering for _O_u_t is set to line and buffering on _E_r_r_o_r is disabled. See also prolog/0 and set_stream/2. The _c_l_i_b package provides the library prolog_server creating a TCP/IP server for creating an interactive session to Prolog. 44..1166..22 EEddiinnbbuurrgghh--ssttyyllee II//OO The package for implicit input and output destination is (almost) compatible to Edinburgh DEC-10 and C-Prolog. The reading and writing predicates refer to resp. the _c_u_r_r_e_n_t input- and output stream. Initially these streams are connected to the terminal. The current output stream is changed using tell/1 or append/1. The current input stream is changed using see/1. The streams current value can be obtained using telling/1 for output- and seeing/1 for input streams. Source and destination are either a file, user, or a term `pipe(_C_o_m_m_a_n_d)'. The reserved stream name user refers to the terminal. In the predicate descriptions below we will call the source/destination argument `_S_r_c_D_e_s_t'. Below are some examples of source/destination specifications. ?- see(data). % Start reading from file `data'. ?- tell(user). % Start writing to the terminal. ?- tell(pipe(lpr)). % Start writing to the printer. Another example of using the pipe/1 construct is shown below. Note that the pipe/1 construct is not part of Prolog's standard I/O repertoire. getwd(Wd) :- seeing(Old), see(pipe(pwd)), collect_wd(String), seen, see(Old), atom_codes(Wd, String). collect_wd([C|R]) :- get0(C), C \== -1, !, collect_wd(R). collect_wd([]). CCoommppaattiibbiilliittyy nnootteess Unlike Edinburgh Prolog systems, telling/1 and seeing/1 do not return the filename of the current input/output, but the stream-identifier, to ensure the design pattern below works under all circumstances. ..., telling(Old), tell(x), ..., told, tell(Old), ..., The predicates tell/1 and see/1 first check for user, the pipe(_c_o_m_m_a_n_d) and a stream-handle. Otherwise, if the argument is an atom it is first compared to open streams associated to a file with _e_x_a_c_t_l_y the same name. If such a stream, created using tell/1 or see/1 exists, output (input) is switch to the open stream. Otherwise a file with the specified name is opened. The behaviour is compatible to Edinburgh Prolog. This is not without problems. Changing directory, non-file streams, multiple names referring to the same file easily lead to unexpected behaviour. New code, especially when managing multiple I/O channels should consider using the ISO I/O predicates defined in section 4.16.1. sseeee((_+_S_r_c_D_e_s_t)) Open _S_r_c_D_e_s_t for reading and make it the current input (see set_input/1). If _S_r_c_D_e_s_t is a stream-handle, just makes this stream the current input. See the introduction of section 4.16.2 for details. tteellll((_+_S_r_c_D_e_s_t)) Open _S_r_c_D_e_s_t for writing and make it the current output (see set_output/1). If _S_r_c_D_e_s_t is a stream-handle, just makes this stream the current output. See the introduction of section 4.16.2 for details. aappppeenndd((_+_F_i_l_e)) Similar to tell/1, but positions the file pointer at the end of _F_i_l_e rather than truncating an existing file. The pipe construct is not accepted by this predicate. sseeeeiinngg((_?_S_r_c_D_e_s_t)) Same as current_input/1, except that user is returned if the current input is the stream user_input to improve compatibility with traditional Edinburgh I/O. See the introduction of section 4.16.2 for details. tteelllliinngg((_?_S_r_c_D_e_s_t)) Same as current_output/1, except that user is returned if the current output is the stream user_output to improve compatibility with traditional Edinburgh I/O. See the introduction of section 4.16.2 for details. sseeeenn Close the current input stream. The new input stream becomes _u_s_e_r___i_n_p_u_t. ttoolldd Close the current output stream. The new output stream becomes _u_s_e_r___o_u_t_p_u_t. 44..1166..33 SSwwiittcchhiinngg BBeettwweeeenn EEddiinnbbuurrgghh aanndd IISSOO II//OO The predicates below can be used for switching between the implicit- and the explicit stream based I/O predicates. sseett__iinnppuutt((_+_S_t_r_e_a_m)) Set the current input stream to become _S_t_r_e_a_m. Thus, open(file, read, Stream), set_input(Stream) is equivalent to see(file). sseett__oouuttppuutt((_+_S_t_r_e_a_m)) Set the current output stream to become _S_t_r_e_a_m. See also with_output_to/2. ccuurrrreenntt__iinnppuutt((_-_S_t_r_e_a_m)) Get the current input stream. Useful to get access to the status predicates associated with streams. ccuurrrreenntt__oouuttppuutt((_-_S_t_r_e_a_m)) Get the current output stream. 44..1166..44 WWrriittee oonnttoo aattoommss,, ccooddee--lliissttss,, eettcc.. wwiitthh__oouuttppuutt__ttoo((_+_O_u_t_p_u_t_, _:_G_o_a_l)) Run _G_o_a_l as once/1, while characters written to the current output is sent to _O_u_t_p_u_t. The predicate is SWI-Prolog specific, inspired by various posts to the mailinglist. It provides a flexible replacement for predicates such as sformat/3, swritef/3, term_to_atom/2, atom_number/2 converting numbers to atoms, etc. The predicate format/3 accepts the same terms as output argument. Applications should generally avoid creating atoms by breaking and concatenating other atoms as the creation of large numbers of intermediate atoms generally leads to poor performance, even more so in multi-threaded applications. This predicate supports creating difference-lists from character data efficiently. The example below defines the DCG rule term//1 to insert a term in the output: term(Term, In, Tail) :- with_output_to(codes(In, Tail), write(Term)). ?- phrase(term(hello), X). X = [104, 101, 108, 108, 111] AA SSttrreeaamm hhaannddllee oorr aalliiaass Temporary switch current output to the given stream. Redirection using with_output_to/2 guarantees the original output is restored, also if _G_o_a_l fails or raises an exception. See also call_cleanup/2. aattoomm((_-_A_t_o_m)) Create an atom from the emitted characters. Please note the remark above. ssttrriinngg((_-_S_t_r_i_n_g)) Create a string-object as defined in section 4.23. ccooddeess((_-_C_o_d_e_s)) Create a list of character codes from the emitted characters, similar to atom_codes/2. ccooddeess((_-_C_o_d_e_s_, _-_T_a_i_l)) Create a list of character codes as a difference-list. cchhaarrss((_-_C_h_a_r_s)) Create a list of one-character-atoms codes from the emitted characters, similar to atom_chars/2. cchhaarrss((_-_C_h_a_r_s_, _-_T_a_i_l)) Create a list of one-character-atoms as a difference-list. 44..1177 SSttaattuuss ooff ssttrreeaammss wwaaiitt__ffoorr__iinnppuutt((_+_L_i_s_t_O_f_S_t_r_e_a_m_s_, _-_R_e_a_d_y_L_i_s_t_, _+_T_i_m_e_O_u_t)) Wait for input on one of the streams in _L_i_s_t_O_f_S_t_r_e_a_m_s and return a list of streams on which input is available in _R_e_a_d_y_L_i_s_t. wait_for_input/3 waits for at most _T_i_m_e_O_u_t seconds. _T_i_m_e_o_u_t may be specified as a floating point number to specify fractions of a second. If _T_i_m_e_o_u_t equals infinite, wait_for_input/3 waits indefinitely. This predicate can be used to implement timeout while reading and to handle input from multiple sources. The following example will wait for input from the user and an explicitly opened second terminal. On return, _I_n_p_u_t_s may hold user or _P_4 or both. ?- open('/dev/ttyp4', read, P4), wait_for_input([user, P4], Inputs, 0). This predicate relies on the select() call on most operating systems. On Unix this call is implemented for any stream referring to a file-handle, which implies all OS-based streams: sockets, terminals, pipes, etc. On non-Unix systems select() is generally only implemented for socket-based streams. See also socket from the clib package. Note that wait_for_input/3 returns streams that have data waiting. This does not mean you can, for example, call read/2 on the stream without blocking as the stream might hold an incomplete term. The predicate set_stream/2 using the option timeout(_S_e_c_o_n_d_s) can be used to make the stream generate an exception if no new data arrives for within the timeout. Suppose two processes communicate by exchanging Prolog terms. The following code makes the server immune for clients that write an incomplete term: ..., tcp_accept(Server, Socket, _Peer), tcp_open(Socket, In, Out), set_stream(In, timeout(10)), catch(read(In, Term), _, (close(Out), close(In), fail)), ..., bbyyttee__ccoouunntt((_+_S_t_r_e_a_m_, _-_C_o_u_n_t)) Byte-position in _S_t_r_e_a_m. For binary streams this is the same as character_count/2. For text files the number may be different due to multi-byte encodings or additional record separators (such as Control-M in Windows). cchhaarraacctteerr__ccoouunntt((_+_S_t_r_e_a_m_, _-_C_o_u_n_t)) Unify _C_o_u_n_t with the current character index. For input streams this is the number of characters read since the open, for output streams this is the number of characters written. Counting starts at 0. lliinnee__ccoouunntt((_+_S_t_r_e_a_m_, _-_C_o_u_n_t)) Unify _C_o_u_n_t with the number of lines read or written. Counting starts at 1. lliinnee__ppoossiittiioonn((_+_S_t_r_e_a_m_, _-_C_o_u_n_t)) Unify _C_o_u_n_t with the position on the current line. Note that this assumes the position is 0 after the open. Tabs are assumed to be defined on each 8-th character and backspaces are assumed to reduce the count by one, provided it is positive. ffiilleeeerrrroorrss((_-_O_l_d_, _+_N_e_w)) Define error behaviour on errors when opening a file for reading or writing. Valid values are the atoms on (default) and off. First _O_l_d is unified with the current value. Then the new value is set to _N_e_w. With the introduction of exception-handling, it is advised to use catch/3 to catch possibly file-errors and act accordingly. Note that if _f_i_l_e_e_r_r_o_r_s is off, _n_o exception is generated. 44..1188 PPrriimmiittiivvee cchhaarraacctteerr II//OO See section 4.2 for an overview of supported character representations. nnll Write a newline character to the current output stream. On Unix systems nl/0 is equivalent to put(10). nnll((_+_S_t_r_e_a_m)) Write a newline to _S_t_r_e_a_m. ppuutt((_+_C_h_a_r)) Write _C_h_a_r to the current output stream, _C_h_a_r is either an integer-expression evaluating to a character code or an atom of one character. Depreciated. New code should use put_char/1 or put_code/1. ppuutt((_+_S_t_r_e_a_m_, _+_C_h_a_r)) Write _C_h_a_r to _S_t_r_e_a_m. See put/1 for details. ppuutt__bbyyttee((_+_B_y_t_e)) Write a single byte to the output. _B_y_t_e must be an integer between 0 and 255. ppuutt__bbyyttee((_+_S_t_r_e_a_m_, _+_B_y_t_e)) Write a single byte to a stream. _B_y_t_e must be an integer between 0 and 255. ppuutt__cchhaarr((_+_C_h_a_r)) Write a character to the current output, obeying the encoding defined for the current output stream. Note that this may raise an exception if the encoding of _S_t_r_e_a_m cannot represent _C_h_a_r. ppuutt__cchhaarr((_+_S_t_r_e_a_m_, _+_C_h_a_r)) Write a character to _S_t_r_e_a_m, obeying the encoding defined for _S_t_r_e_a_m. Note that this may raise an exception if the encoding of _S_t_r_e_a_m cannot represent _C_h_a_r. ppuutt__ccooddee((_+_C_o_d_e)) Similar to put_char/1, but using a _c_h_a_r_a_c_t_e_r _c_o_d_e. _C_o_d_e is a non-negative integer. Note that this may raise an exception if the encoding of _S_t_r_e_a_m cannot represent _C_o_d_e. ppuutt__ccooddee((_+_S_t_r_e_a_m_, _+_C_o_d_e)) Same as put_code/1 but directing _C_o_d_e to _S_t_r_e_a_m. ttaabb((_+_A_m_o_u_n_t)) Writes _A_m_o_u_n_t spaces on the current output stream. _A_m_o_u_n_t should be an expression that evaluates to a positive integer (see section 4.26). ttaabb((_+_S_t_r_e_a_m_, _+_A_m_o_u_n_t)) Writes _A_m_o_u_n_t spaces to _S_t_r_e_a_m. fflluusshh__oouuttppuutt Flush pending output on current output stream. flush_output/0 is automatically generated by read/1 and derivatives if the current input stream is user and the cursor is not at the left margin. fflluusshh__oouuttppuutt((_+_S_t_r_e_a_m)) Flush output on the specified stream. The stream must be open for writing. ttttyyfflluusshh Flush pending output on stream _u_s_e_r. See also flush_output/[0,1]. ggeett__bbyyttee((_-_B_y_t_e)) Read the current input stream and unify the next byte with _B_y_t_e (an integer between 0 and 255. _B_y_t_e is unified with -1 on end of file. ggeett__bbyyttee((_+_S_t_r_e_a_m_, _-_B_y_t_e)) Read the next byte from _S_t_r_e_a_m, returning an integer between 0 and 255. ggeett__ccooddee((_-_C_o_d_e)) Read the current input stream and unify _C_o_d_e with the character code of the next character. _C_o_d_e is unified with -1 on end of file. See also get_char/1. ggeett__ccooddee((_+_S_t_r_e_a_m_, _-_C_o_d_e)) Read the next character-code from _S_t_r_e_a_m. ggeett__cchhaarr((_-_C_h_a_r)) Read the current input stream and unify _C_h_a_r with the next character as a one-character-atom. See also atom_chars/2. On end-of-file, _C_h_a_r is unified to the atom end_of_file. ggeett__cchhaarr((_+_S_t_r_e_a_m_, _-_C_h_a_r)) Unify _C_h_a_r with the next character from _S_t_r_e_a_m as a one-character-atom. See also get_char/2, get_byte/2 and get_code/2. ggeett00((_-_C_h_a_r)) Edinburgh version of the ISO get_code/1 predicate. Note that Edinburgh prolog didn't support wide characters and therefore technically speaking get0/1 should have been mapped to get_byte/1. The intention of get0/1 however is to read character codes. ggeett00((_+_S_t_r_e_a_m_, _-_C_h_a_r)) Edinburgh version of the ISO get_code/2 predicate. See also get0/1. ggeett((_-_C_h_a_r)) Read the current input stream and unify the next non-blank character with _C_h_a_r. _C_h_a_r is unified with -1 on end of file. ggeett((_+_S_t_r_e_a_m_, _-_C_h_a_r)) Read the next non-blank character from _S_t_r_e_a_m. ppeeeekk__bbyyttee((_-_B_y_t_e)) Reads the next input byte like get_byte/1, but does not remove it from the input stream. ppeeeekk__bbyyttee((_+_S_t_r_e_a_m_, _-_B_y_t_e)) Reads the next input byte like get_byte/2, but does not remove it from the stream. ppeeeekk__ccooddee((_-_C_o_d_e)) Reads the next input code like get_code/1, but does not remove it from the input stream. ppeeeekk__ccooddee((_+_S_t_r_e_a_m_, _-_C_o_d_e)) Reads the next input code like get_code/2, but does not remove it from the stream. ppeeeekk__cchhaarr((_-_C_h_a_r)) Reads the next input character like get_char/1, but does not remove it from the input stream. ppeeeekk__cchhaarr((_+_S_t_r_e_a_m_, _-_C_h_a_r)) Reads the next input character like get_char/2, but does not remove it from the stream. sskkiipp((_+_C_o_d_e)) Read the input until _C_h_a_r or the end of the file is encountered. A subsequent call to get_code/1 will read the first character after _C_o_d_e. sskkiipp((_+_S_t_r_e_a_m_, _+_C_o_d_e)) Skip input (as skip/1) on _S_t_r_e_a_m. ggeett__ssiinnggllee__cchhaarr((_-_C_o_d_e)) Get a single character from input stream `user' (regardless of the current input stream). Unlike get_code/1 this predicate does not wait for a return. The character is not echoed to the user's terminal. This predicate is meant for keyboard menu selection etc. If SWI-Prolog was started with the -tty option this predicate reads an entire line of input and returns the first non-blank character on this line, or the character code of the newline (10) if the entire line consisted of blank characters. aatt__eenndd__ooff__ssttrreeaamm Succeeds after the last character of the current input stream has been read. Also succeeds if there is no valid current input stream. aatt__eenndd__ooff__ssttrreeaamm((_+_S_t_r_e_a_m)) Succeeds after the last character of the named stream is read, or _S_t_r_e_a_m is not a valid input stream. The end-of-stream test is only available on buffered input stream (unbuffered input streams are rarely used, see open/4). ccooppyy__ssttrreeaamm__ddaattaa((_+_S_t_r_e_a_m_I_n_, _+_S_t_r_e_a_m_O_u_t_, _+_L_e_n)) Copy _L_e_n codes from stream _S_t_r_e_a_m_I_n to _S_t_r_e_a_m_O_u_t. Note that the copy is done using the semantics of get_code/2 and put_code/2, taking care of possibly recoding that needs take place between two text files. See section 2.17.1. ccooppyy__ssttrreeaamm__ddaattaa((_+_S_t_r_e_a_m_I_n_, _+_S_t_r_e_a_m_O_u_t)) Copy data all (remaining) data from stream _S_t_r_e_a_m_I_n to _S_t_r_e_a_m_O_u_t. rreeaadd__ppeennddiinngg__iinnppuutt((_+_S_t_r_e_a_m_I_n_, _-_C_o_d_e_s_, _?_T_a_i_l)) Read input pending in the input buffer of _S_t_r_e_a_m_I_n and return it in the difference list _C_o_d_e_s-_T_a_i_l. I.e. the available characters codes are used to create the list _C_o_d_e_s ending in the tail _T_a_i_l. This predicate is intended for efficient unbuffered copying and filtering of input coming from network connections or devices. The following code fragment realises efficient non-blocking copy of data from an input- to an output stream. The at_end_of_stream/1 call checks for end-of-stream and fills the input buffer. Note that the use of a get_code/2 and put_code/2 based loop requires a flush_output/1 call after _e_a_c_h put_code/2. The copy_stream_data/2 does not allow for inspection of the copied data and suffers from the same buffering issues. copy(In, Out) :- repeat, ( at_end_of_stream(In) -> ! ; read_pending_input(In, Chars, []), format(Out, '~s', [Chars]), flush_output(Out), fail ). 44..1199 TTeerrmm rreeaaddiinngg aanndd wwrriittiinngg This section describes the basic term reading and writing predicates. The predicates format/[1,2] and writef/2 provide formatted output. Writing to Prolog datastructures such as atoms or code-lists is supported by with_output_to/2and format/3. There are two ways to manipulate the output format. The predicate print/[1,2] may be programmed using portray/1. The format of floating point numbers may be manipulated using the prolog_flag (see current_prolog_flag/2) float_format. Reading is sensitive to the prolog_flag character_escapes, which controls the interpretation of the \ character in quoted atoms and strings. wwrriittee__tteerrmm((_+_T_e_r_m_, _+_O_p_t_i_o_n_s)) The predicate write_term/2 is the generic form of all Prolog term-write predicates. Valid options are: aattttrriibbuutteess((_A_t_o_m)) Define how attributed variables (see section 6.1) are written. The default is determined by the prolog flag write_attributes. Defined values are ignore (ignore the attribute), dots (write the attributes as {...}), write (simply hand the attributes recursively to write_term/2) and portray (hand the attributes to attr_portray_hook/2). bbaacckkqquuootteedd__ssttrriinngg((_B_o_o_l)) If true, write a string object (see section 4.23) as `...`. The default depends on the prolog flag with the same name. cchhaarraacctteerr__eessccaappeess((_B_o_o_l)) If true, and quoted(_t_r_u_e) is active, special characters in quoted atoms and strings are emitted as ISO escape-sequences. Default is taken from the reference module (see below). iiggnnoorree__ooppss((_B_o_o_l)) If true, the generic term-representation (<_f_u_n_c_t_o_r>(<_a_r_g_s> ...)) will be used for all terms, Otherwise (default), operators, list-notation and {}/1 will be written using their special syntax. mmaaxx__ddeepptthh((_I_n_t_e_g_e_r)) If the term is nested deeper than _I_n_t_e_g_e_r, print the remainder as eclipse (...). A 0 (zero) value (default) imposes no depth limit. This option also delimits the number of printed for a list. Example: ?- write_term(a(s(s(s(s(0)))), [a,b,c,d,e,f]), [max_depth(3)]). a(s(s(...)), [a, b|...]) Yes Used by the top-level and debugger to limit screen output. See also the prolog-flags toplevel_print_options and debugger_print_options. mmoodduullee((_M_o_d_u_l_e)) Define the reference module (default user). This defines the default value for the character_escapes option as well as the operator definitions to use. See also op/3. nnuummbbeerrvvaarrss((_B_o_o_l)) If true, terms of the format $VAR(N), where <_N> is a positive integer, will be written as a variable name. If _N is an atom it is written without quotes. This extension allows for writing variables with user-provided names. The default is false. See also numbervars/3. ppoorrttrraayy((_B_o_o_l)) If true, the hook portray/1 is called before printing a term that is not a variable. If portray/1 succeeds, the term is considered printed. See also print/1. The default is false. This option is an extension to the ISO write_term options. pprriioorriittyy((_I_n_t_e_g_e_r)) An integer between 0 and 1200 represeting the `context priority'. Default is 1200. Can be used to write partial terms appearing as the argument to an operator. For example: format('~w = ', [VarName]), write_term(Value, [quoted(true), priority(699)]) qquuootteedd((_B_o_o_l)) If true, atoms and functors that needs quotes will be quoted. The default is false. wwrriittee__tteerrmm((_+_S_t_r_e_a_m_, _+_T_e_r_m_, _+_O_p_t_i_o_n_s)) As write_term/2, but output is sent to _S_t_r_e_a_m rather than the current output. wwrriittee__ccaannoonniiccaall((_+_T_e_r_m)) Write _T_e_r_m on the current output stream using standard paren- thesised prefix notation (i.e., ignoring operator declarations). Atoms that need quotes are quoted. Terms written with this predicate can always be read back, regardless of current operator declarations. Equivalent to write_term/2 using the options ignore_ops, quoted and numbervars after numbervars/4 using the singletons option. Note that due to the use of numbervars/4, non-ground terms must be written using a _s_i_n_g_l_e write_canonical/1 call. This used to be the case anyhow, as garbage collection between multiple calls to one of the write predicates can change the _G<_N_N_N> identity of the variables. wwrriittee__ccaannoonniiccaall((_+_S_t_r_e_a_m_, _+_T_e_r_m)) Write _T_e_r_m in canonical form on _S_t_r_e_a_m. wwrriittee((_+_T_e_r_m)) Write _T_e_r_m to the current output, using brackets and operators where appropriate. See current_prolog_flag/2 for controlling floating point output format. wwrriittee((_+_S_t_r_e_a_m_, _+_T_e_r_m)) Write _T_e_r_m to _S_t_r_e_a_m. wwrriitteeqq((_+_T_e_r_m)) Write _T_e_r_m to the current output, using brackets and operators where appropriate. Atoms that need quotes are quoted. Terms written with this predicate can be read back with read/1 provided the currently active operator declarations are identical. wwrriitteeqq((_+_S_t_r_e_a_m_, _+_T_e_r_m)) Write _T_e_r_m to _S_t_r_e_a_m, inserting quotes. pprriinntt((_+_T_e_r_m)) Prints _T_e_r_m on the current output stream similar to write/1, but for each (sub)term of _T_e_r_m first the dynamic predicate portray/1 is called. If this predicate succeeds _p_r_i_n_t assumes the (sub)term has been written. This allows for user defined term writing. pprriinntt((_+_S_t_r_e_a_m_, _+_T_e_r_m)) Print _T_e_r_m to _S_t_r_e_a_m. ppoorrttrraayy((_+_T_e_r_m)) A dynamic predicate, which can be defined by the user to change the behaviour of print/1 on (sub)terms. For each subterm encountered that is not a variable print/1 first calls portray/1 using the term as argument. For lists only the list as a whole is given to portray/1. If portray succeeds print/1 assumes the term has been written. rreeaadd((_-_T_e_r_m)) Read the next Prolog term from the current input stream and unify it with _T_e_r_m. On a syntax error read/1 displays an error message, attempts to skip the erroneous term and fails. On reaching end-of-file _T_e_r_m is unified with the atom end_of_file. rreeaadd((_+_S_t_r_e_a_m_, _-_T_e_r_m)) Read _T_e_r_m from _S_t_r_e_a_m. rreeaadd__ccllaauussee((_-_T_e_r_m)) Equivalent to read/1, but warns the user for variables only occurring once in a term (singleton variables, see section 2.15.1.5) which do not start with an underscore if style_check(singleton) is active (default). Used to read Prolog source files (see consult/1). New code should use read_term/2 with the option singletons(warning). rreeaadd__ccllaauussee((_+_S_t_r_e_a_m_, _-_T_e_r_m)) Read a clause from _S_t_r_e_a_m. See read_clause/1. rreeaadd__tteerrmm((_-_T_e_r_m_, _+_O_p_t_i_o_n_s)) Read a term from the current input stream and unify the term with _T_e_r_m. The reading is controlled by options from the list of _O_p_t_i_o_n_s. If this list is empty, the behaviour is the same as for read/1. The options are upward compatible to Quintus Prolog. The argument order is according to the ISO standard. Syntax-errors are always reported using exception-handling (see catch/3). Options: bbaacckkqquuootteedd__ssttrriinngg((_B_o_o_l)) If true, read `...` to a string object (see section 4.23). The default depends on the prolog flag with the same name. cchhaarraacctteerr__eessccaappeess((_B_o_o_l)) Defines how to read \ escape-sequences in quoted atoms. See the prolog-flags character_escapes, current_prolog_flag/2. (SWI-Prolog). ccoommmmeennttss((_-_C_o_m_m_e_n_t_s)) Unify _C_o_m_m_e_n_t_s with a list of _P_o_s_i_t_i_o_n-_C_o_m_m_e_n_t, where _P_o_s_i_t_i_o_n is a stream-position object (see stream_position_data/3) indicating the start of a comment and _C_o_m_m_e_n_t is a string-object containing the text including delimiters of a comment. It returns all comments from where the read_term/2 call started upto the end of the term read. ddoouubbllee__qquuootteess((_B_o_o_l)) Defines how to read "..." strings. See the prolog-flags double_quotes, current_prolog_flag/2. (SWI-Prolog). mmoodduullee((_M_o_d_u_l_e)) Specify _M_o_d_u_l_e for operators, character_escapes flag and double_quotes flag. The value of the latter two is overruled if the corresponding read_term/3 option is provided. If no module is specified, the current `source-module' is used. (SWI-Prolog). ssiinngglleettoonnss((_V_a_r_s)) As variable_names, but only reports the variables occurring only once in the _T_e_r_m read. Variables starting with an underscore (`_') are not included in this list. (ISO). If _V_a_r_s is the constant warning, singleton variables are reported using print_message/2. ssyynnttaaxx__eerrrroorrss((_A_t_o_m)) If error (default), throw and exception on a syntax error. Other values are fail, which causes a message to be printed using print_message/2, after which the predicate fails, quiet which causes the predicate to fail silently and dec10 which causes syntax errors to be printed, after which read_term/[2,3] continues reading the next term. Using dec10, read_term/[2,3] never fails. (Quintus, SICStus). ssuubbtteerrmm__ppoossiittiioonnss((_T_e_r_m_P_o_s)) Describes the detailed layout of the term. The formats for the various types of terms if given below. All positions are character positions. If the input is related to a normal stream, these positions are relative to the start of the input, when reading from the terminal, they are relative to the start of the term. FFrroomm--TToo Used for primitive types (atoms, numbers, variables). ssttrriinngg__ppoossiittiioonn((_F_r_o_m_, _T_o)) Used to indicate the position of a string enclosed in double quotes ("). bbrraaccee__tteerrmm__ppoossiittiioonn((_F_r_o_m_, _T_o_, _A_r_g)) Term of the form {...}, as used in DCG rules. _A_r_g describes the argument. lliisstt__ppoossiittiioonn((_F_r_o_m_, _T_o_, _E_l_m_s_, _T_a_i_l)) A list. _E_l_m_s describes the positions of the elements. If the list specifies the tail as |<_T_a_i_l_T_e_r_m>, _T_a_i_l is unified with the term-position of the tail, otherwise with the atom none. tteerrmm__ppoossiittiioonn((_F_r_o_m_, _T_o_, _F_F_r_o_m_, _F_T_o_, _S_u_b_P_o_s)) Used for a compound term not matching one of the above. _F_F_r_o_m and _F_T_o describe the position of the functor. _S_u_b_P_o_s is a list, each element of which describes the term-position of the corresponding subterm. tteerrmm__ppoossiittiioonn((_P_o_s)) Unifies _P_o_s with the starting position of the term read. _P_o_s if of the same format as use by stream_property/2. vvaarriiaabblleess((_V_a_r_s)) Unify _V_a_r_s with a list of variables in the term. The variables appear in the order they have been read. See also term_variables/2. (ISO). vvaarriiaabbllee__nnaammeess((_V_a_r_s)) Unify _V_a_r_s with a list of `_N_a_m_e = _V_a_r', where _N_a_m_e is an atom describing the variable name and _V_a_r is a variable that shares with the corresponding variable in _T_e_r_m. (ISO). rreeaadd__tteerrmm((_+_S_t_r_e_a_m_, _-_T_e_r_m_, _+_O_p_t_i_o_n_s)) Read term with options from _S_t_r_e_a_m. See read_term/2. rreeaadd__hhiissttoorryy((_+_S_h_o_w_, _+_H_e_l_p_, _+_S_p_e_c_i_a_l_, _+_P_r_o_m_p_t_, _-_T_e_r_m_, _-_B_i_n_d_i_n_g_s)) Similar to read_term/2 using the option variable_names, but allows for history substitutions. read_history/6is used by the top level to read the user's actions. _S_h_o_w is the command the user should type to show the saved events. _H_e_l_p is the command to get an overview of the capabilities. _S_p_e_c_i_a_l is a list of commands that are not saved in the history. _P_r_o_m_p_t is the first prompt given. Continuation prompts for more lines are determined by prompt/2. A %w in the prompt is substituted by the event number. See section 2.7 for available substitutions. SWI-Prolog calls read_history/6 as follows: read_history(h, '!h', [trace], '%w ?- ', Goal, Bindings) pprroommpptt((_-_O_l_d_, _+_N_e_w)) Set prompt associated with read/1 and its derivatives. _O_l_d is first unified with the current prompt. On success the prompt will be set to _N_e_w if this is an atom. Otherwise an error message is displayed. A prompt is printed if one of the read predicates is called and the cursor is at the left margin. It is also printed whenever a newline is given and the term has not been terminated. Prompts are only printed when the current input stream is _u_s_e_r. pprroommpptt11((_+_P_r_o_m_p_t)) Sets the prompt for the next line to be read. Continuation lines will be read using the prompt defined by prompt/2. 44..2200 AAnnaallyyssiinngg aanndd CCoonnssttrruuccttiinngg TTeerrmmss ffuunnccttoorr((_?_T_e_r_m_, _?_F_u_n_c_t_o_r_, _?_A_r_i_t_y)) True if _T_e_r_m is a term with functor _F_u_n_c_t_o_r and arity _A_r_i_t_y. If _T_e_r_m is a variable it is unified with a new term holding only variables. functor/3 silently fails on instantiation faults If _T_e_r_m is an atom or number, _F_u_n_c_t_o_r will be unified with _T_e_r_m and arity will be unified with the integer 0 (zero). aarrgg((_?_A_r_g_, _+_T_e_r_m_, _?_V_a_l_u_e)) _T_e_r_m should be instantiated to a term, _A_r_g to an integer between 1 and the arity of _T_e_r_m. _V_a_l_u_e is unified with the _A_r_g-th argument of _T_e_r_m. _A_r_g may also be unbound. In this case _V_a_l_u_e will be unified with the successive arguments of the term. On successful unification, _A_r_g is unified with the argument number. Backtracking yields alternative solutions. The predicate arg/3 fails silently if _A_r_g= 0 or _A_r_g > _a_r_i_t_y and raises the exception domain_error(not_less_then_zero, Arg)if _A_r_g <0. _?_T_e_r_m =.. _?_L_i_s_t _L_i_s_t is a list which head is the functor of _T_e_r_m and the remaining arguments are the arguments of the term. Each of the arguments may be a variable, but not both. This predicate is called `Univ'. Examples: ?- foo(hello, X) =.. List. List = [foo, hello, X] ?- Term =.. [baz, foo(1)] Term = baz(foo(1)) nnuummbbeerrvvaarrss((_+_T_e_r_m_, _+_S_t_a_r_t_, _-_E_n_d)) Unify the free variables of _T_e_r_m with a term $VAR(_N), where _N is the number of the variable. Counting starts at _S_t_a_r_t. _E_n_d is unified with the number that should be given to the next variable. Example: ?- numbervars(foo(A, B, A), 0, End). A = '$VAR'(0) B = '$VAR'(1) End = 2 See also the numbervars option to write_term/3 and numbervars/4. nnuummbbeerrvvaarrss((_+_T_e_r_m_, _+_S_t_a_r_t_, _-_E_n_d_, _+_O_p_t_i_o_n_s)) As numbervars/3, but providing the following options: ffuunnccttoorr__nnaammee((_+_A_t_o_m)) Name of the functor to use instead of $VAR. aattttvvaarr((_+_A_c_t_i_o_n)) What to do if an attributed variable is encountered. Options are skip, which causes numbervars/3 to ignore the attributed variable, bind which causes it to thread it as a normal variable and assign the next '$VAR'(N) term to it or (default) error which raises the a type_error exception. ssiinngglleettoonnss((_+_B_o_o_l)) If true (default false), numbervars/4 does singleton detection. Singleton variables are unified with '$VAR'('_'), causing them to be printed as _ by write_term/2 using the numbervars option. This option is exploited by portray_clause/2 and write_canonical/2. tteerrmm__vvaarriiaabblleess((_+_T_e_r_m_, _-_L_i_s_t)) Unify _L_i_s_t with a list of variables, each sharing with a unique variable of _T_e_r_m. See also term_variables/3. For example: ?- term_variables(a(X, b(Y, X), Z), L). L = [G367, G366, G371] X = G367 Y = G366 Z = G371 tteerrmm__vvaarriiaabblleess((_+_T_e_r_m_, _-_L_i_s_t_, _?_T_a_i_l)) Difference list version of term_variables/2. I.e. _T_a_i_l is the tail of the variable-list _L_i_s_t. ccooppyy__tteerrmm((_+_I_n_, _-_O_u_t)) Create a version if _I_n with renamed (fresh) variables and unify it to _O_u_t. Attributed variables (see section 6.1) have their attributed copied. The implementation of copy_term/2 can deal with infinite trees (cyclic terms). As pure Prolog cannot distinguish a ground term from another ground term with exactly the same structure, ground sub-terms are _s_h_a_r_e_d between _I_n and _O_u_t. Sharing ground terms does affect setarg/3. SWI-Prolog provides duplicate_term/2 to create a true copy of a term. 44..2200..11 NNoonn--llooggiiccaall ooppeerraattiioonnss oonn tteerrmmss Prolog is not capable to _m_o_d_i_f_y instantiated parts of a term. Lacking that capability makes that language much safer, but unfortunately there are problems that suffer severely in terms of time and/or memory usage. Always try hard to avoid the use of these primitives, but they can be a good alternative to using dynamic predicates. See also section 6.3, discussing the use of global variables. sseettaarrgg((_+_A_r_g_, _+_T_e_r_m_, _+_V_a_l_u_e)) Extra-logical predicate. Assigns the _A_r_g-th argument of the compound term _T_e_r_m with the given _V_a_l_u_e. The assignment is undone if backtracking brings the state back into a position before the setarg/3 call. See also nb_setarg/3. This predicate may be used for destructive assignment to terms, using them as an extra-logical storage bin. Always try hard to avoid the use of setarg/3 as it is not supported by many Prolog systems and one has to be very careful about unexpected copying as well as unexpected not copying of terms. nnbb__sseettaarrgg((_+_A_r_g_, _+_T_e_r_m_, _+_V_a_l_u_e)) Assigns the _A_r_g-th argument of the compound term _T_e_r_m with the given _V_a_l_u_e as setarg/3, but on backtracking the assignment is _n_o_t reversed. If _T_e_r_m is not atomic, it is duplicated using duplicate_term/2. This predicate uses the same technique as nb_setval/2. We therefore refer to the description of nb_setval/2 for details on non-backtrackable assignment of terms. This predicate is compatible to GNU-Prolog setarg(_A_,_T_,_V_,_f_a_l_s_e), removing the type-restriction on _V_a_l_u_e. See also nb_linkarg/3. Below is an example for counting the number of solutions of a goal. Note that this implementation is thread-safe, reentrant and capable of handling exceptions. Realising these features with a traditional implementation based on assert/retract or flag/3 is much more complicated. :- module_transparent succeeds_n_times/2. succeeds_n_times(Goal, Times) :- Counter = counter(0), ( Goal, arg(1, Counter, N0), N is N0 + 1, nb_setarg(1, Counter, N), fail ; arg(1, Counter, Times) ). nnbb__lliinnkkaarrgg((_+_A_r_g_, _+_T_e_r_m_, _+_V_a_l_u_e)) As nb_setarg/3, but like nb_linkval/2 it does _n_o_t duplicate _V_a_l_u_e. Use with extreme care and consult the documentation of nb_linkval/2 before use. dduupplliiccaattee__tteerrmm((_+_I_n_, _-_O_u_t)) Version of copy_term/2 that also copies ground terms and therefore ensures destructive modification using setarg/3 does not affect the copy. See also nb_setval/2, nb_linkval/2, nb_setarg/3 and nb_linkarg/3. 44..2211 AAnnaallyyssiinngg aanndd CCoonnssttrruuccttiinngg AAttoommss These predicates convert between Prolog constants and lists of character codes. The predicates atom_codes/2, number_codes/2 and name/2 behave the same when converting from a constant to a list of character codes. When converting the other way around, atom_codes/2 will generate an atom, number_codes/2 will generate a number or exception and name/2 will return a number if possible and an atom otherwise. The ISO standard defines atom_chars/2 to describe the `broken-up' atom as a list of one-character atoms instead of a list of codes. Up-to version 3.2.x, SWI-Prolog's atom_chars/2 behaved, compatible to Quintus and SICStus Prolog, like atom_codes. As of 3.3.x SWI-Prolog atom_codes/2 and atom_chars/2are compliant to the ISO standard. To ease the pain of all variations in the Prolog community, all SWI-Prolog predicates behave as flexible as possible. This implies the `list-side' accepts either a code-list or a char-list and the `atom-side' accept all atomic types (atom, number and string). aattoomm__ccooddeess((_?_A_t_o_m_, _?_S_t_r_i_n_g)) Convert between an atom and a list of character codes. If _A_t_o_m is instantiated, if will be translated into a list of character codes and the result is unified with _S_t_r_i_n_g. If _A_t_o_m is unbound and _S_t_r_i_n_g is a list of character codes, it will _A_t_o_m will be unified with an atom constructed from this list. aattoomm__cchhaarrss((_?_A_t_o_m_, _?_C_h_a_r_L_i_s_t)) As atom_codes/2, but _C_h_a_r_L_i_s_t is a list of one-character atoms rather than a list of character codes. ?- atom_chars(hello, X). X = [h, e, l, l, o] cchhaarr__ccooddee((_?_A_t_o_m_, _?_C_o_d_e)) Convert between character and character code for a single character. nnuummbbeerr__cchhaarrss((_?_N_u_m_b_e_r_, _?_C_h_a_r_L_i_s_t)) Similar to atom_chars/2, but converts between a number and its representation as a list of one-character atoms. Fails with a representation_error if _N_u_m_b_e_r is unbound and _C_h_a_r_L_i_s_t does not describe a number. nnuummbbeerr__ccooddeess((_?_N_u_m_b_e_r_, _?_C_o_d_e_L_i_s_t)) As number_chars/2, but converts to a list of character codes rather than one-character atoms. In the mode -, +, both predicates behave identically to improve handling of non-ISO source. aattoomm__nnuummbbeerr((_?_A_t_o_m_, _?_N_u_m_b_e_r)) Realises the popular combination of atom_codes/2 and number_codes/2 to convert between atom and number (integer or float) in one predicate, avoiding the intermediate list. nnaammee((_?_A_t_o_m_O_r_I_n_t_, _?_S_t_r_i_n_g)) _S_t_r_i_n_g is a list of character codes representing the same text as _A_t_o_m. Each of the arguments may be a variable, but not both. When _S_t_r_i_n_g is bound to an character code list describing an integer and _A_t_o_m is a variable _A_t_o_m will be unified with the integer value described by _S_t_r_i_n_g (e.g. `name(N, "300"), 400 is N + 100' succeeds). tteerrmm__ttoo__aattoomm((_?_T_e_r_m_, _?_A_t_o_m)) True if _A_t_o_m describes a term that unifies with _T_e_r_m. When _A_t_o_m is instantiated _A_t_o_m is converted and then unified with _T_e_r_m. If _A_t_o_m has no valid syntax, a syntax_errorexception is raised. Otherwise _T_e_r_m is ``written'' on _A_t_o_m using write/1. aattoomm__ttoo__tteerrmm((_+_A_t_o_m_, _-_T_e_r_m_, _-_B_i_n_d_i_n_g_s)) Use _A_t_o_m as input to read_term/2 using the option variable_names and return the read term in _T_e_r_m and the variable bindings in _B_i_n_d_i_n_g_s. _B_i_n_d_i_n_g_s is a list of _N_a_m_e =_V_a_r couples, thus providing access to the actual variable names. See also read_term/2. If _A_t_o_m has no valid syntax, a syntax_error exception is raised. aattoomm__ccoonnccaatt((_?_A_t_o_m_1_, _?_A_t_o_m_2_, _?_A_t_o_m_3)) _A_t_o_m_3 forms the concatenation of _A_t_o_m_1 and _A_t_o_m_2. At least two of the arguments must be instantiated to atoms, integers or floating point numbers. For ISO compliance, the instantiation-pattern -, -, + is allowed too, non-deterministically splitting the 3-th argument into two parts (as append/3 does for lists). See also string_concat/3. ccoonnccaatt__aattoomm((_+_L_i_s_t_, _-_A_t_o_m)) _L_i_s_t is a list of atoms, integers or floating point numbers. Succeeds if _A_t_o_m can be unified with the concatenated elements of _L_i_s_t. If _L_i_s_t has exactly 2 elements it is equivalent to atom_concat/3, allowing for variables in the list. ccoonnccaatt__aattoomm((_?_L_i_s_t_, _+_S_e_p_a_r_a_t_o_r_, _?_A_t_o_m)) Creates an atom just like concat_atom/2, but inserts _S_e_p_a_r_a_t_o_r between each pair of atoms. For example: ?- concat_atom([gnu, gnat], ', ', A). A = 'gnu, gnat' This predicate can also be used to split atoms by instantiating _S_e_p_a_r_a_t_o_r and _A_t_o_m: ?- concat_atom(L, -, 'gnu-gnat'). L = [gnu, gnat] aattoomm__lleennggtthh((_+_A_t_o_m_, _-_L_e_n_g_t_h)) True if _A_t_o_m is an atom of _L_e_n_g_t_h characters long. This predicate also works for strings (see section 4.23). If the prolog flag iso is _n_o_t set, it also accepts integers and floats, expressing the number of characters output when given to write/1 as well as code-lists and character-lists, expressing the length of the list. aattoomm__pprreeffiixx((_+_A_t_o_m_, _+_P_r_e_f_i_x)) True if _A_t_o_m starts with the characters from _P_r_e_f_i_x. Its behaviour is equivalent to ?- sub_atom(Atom, 0, _, _, Prefix). Depreciated. ssuubb__aattoomm((_+_A_t_o_m_, _?_B_e_f_o_r_e_, _?_L_e_n_, _?_A_f_t_e_r_, _?_S_u_b)) ISO predicate for breaking atoms. It maintains the following relation: _S_u_b is a sub-atom of _A_t_o_m that starts at _B_e_f_o_r_e, has _L_e_n characters and _A_t_o_m contains _A_f_t_e_r characters after the match. ?- sub_atom(abc, 1, 1, A, S). A = 1, S = b The implementation minimises non-determinism and creation of atoms. This is a very flexible predicate that can do search, prefix- and suffix-matching, etc. 44..2222 CChhaarraacctteerr pprrooppeerrttiieess SWI-Prolog offers two comprehensive predicates for classifying characters and character-codes. These predicates are defined as built- in predicates to exploit the C-character classification's handling of _l_o_c_a_l_e (handling of local character-sets). These predicates are fast, logical and deterministic if applicable. In addition, there is the library ctype providing compatibility to some other Prolog systems. The predicates of this library are defined in terms of code_type/2. cchhaarr__ttyyppee((_?_C_h_a_r_, _?_T_y_p_e)) Tests or generates alternative _T_y_p_es or _C_h_a_rs. The character-types are inspired by the standard C primitives. aallnnuumm _C_h_a_r is a letter (upper- or lowercase) or digit. aallpphhaa _C_h_a_r is a letter (upper- or lowercase). ccssyymm _C_h_a_r is a letter (upper- or lowercase), digit or the underscore (_). These are valid C- and Prolog symbol characters. ccssyymmff _C_h_a_r is a letter (upper- or lowercase) or the underscore (_). These are valid first characters for C- and Prolog symbols aasscciiii _C_h_a_r is a 7-bits ASCII character (0..127). wwhhiittee _C_h_a_r is a space or tab. E.i. white space inside a line. ccnnttrrll _C_h_a_r is an ASCII control-character (0..31). ddiiggiitt _C_h_a_r is a digit. ddiiggiitt((_W_e_i_g_t_h)) _C_h_a_r is a digit with value _W_e_i_g_t_h. I.e. char_type(X, digit(6) yields _X = '6'. Useful for parsing numbers. xxddiiggiitt((_W_e_i_g_t_h)) _C_h_a_r is a hexa-decimal digit with value _W_e_i_g_t_h. I.e. char_type(a, xdigit(X) yields _X = '10'. Useful for parsing numbers. ggrraapphh _C_h_a_r produces a visible mark on a page when printed. Note that the space is not included! lloowweerr _C_h_a_r is a lower-case letter. lloowweerr((_U_p_p_e_r)) _C_h_a_r is a lower-case version of _U_p_p_e_r. Only true if _C_h_a_r is lowercase and _U_p_p_e_r uppercase. ttoo__lloowweerr((_U_p_p_e_r)) _C_h_a_r is a lower-case version of _U_p_p_e_r. For non-letters, or letter without case, _C_h_a_r and _L_o_w_e_r are the same. See also upcase_atom/2 and downcase_atom/2. uuppppeerr _C_h_a_r is an upper-case letter. uuppppeerr((_L_o_w_e_r)) _C_h_a_r is an upper-case version of _L_o_w_e_r. Only true if _C_h_a_r is uppercase and _L_o_w_e_r lowercase. ttoo__uuppppeerr((_L_o_w_e_r)) _C_h_a_r is an upper-case version of _L_o_w_e_r. For non-letters, or letter without case, _C_h_a_r and _L_o_w_e_r are the same. See also upcase_atom/2 and downcase_atom/2. ppuunncctt _C_h_a_r is a punctuation character. This is a graph character that is not a letter or digit. ssppaaccee _C_h_a_r is some form of layout character (tab, vertical-tab, newline, etc.). eenndd__ooff__ffiillee _C_h_a_r is -1. eenndd__ooff__lliinnee _C_h_a_r ends a line (ASCII: 10..13). nneewwlliinnee _C_h_a_r is a the newline character (10). ppeerriioodd _C_h_a_r counts as the end of a sentence (.,!,?). qquuoottee _C_h_a_r is a quote-character (", ', `). ppaarreenn((_C_l_o_s_e)) _C_h_a_r is an open-parenthesis and _C_l_o_s_e is the corresponding close-parenthesis. ccooddee__ttyyppee((_?_C_o_d_e_, _?_T_y_p_e)) As char_type/2, but uses character-codes rather than one-character atoms. Please note that both predicates are as flexible as possible. They handle either representation if the argument is instantiated and only will instantiate with an integer code or one-character atom depending of the version used. See also the prolog-flag double_quotes, atom_chars/2 and atom_codes/2. 44..2222..11 CCaassee ccoonnvveerrssiioonn There is nothing in the Prolog standard for converting case in textual data. The SWI-Prolog predicates code_type/2 and char_type/2 can be used to test and convert individual characters. We have started some additional support: ddoowwnnccaassee__aattoomm((_+_A_n_y_C_a_s_e_, _-_L_o_w_e_r_C_a_s_e)) Converts the characters of _A_n_y_C_a_s_e into lowercase as char_type/2 does (i.e. based on the defined _l_o_c_a_l_e if Prolog provides locale support on the hosting platform) and unifies the lowercase atom with _L_o_w_e_r_C_a_s_e. uuppccaassee__aattoomm((_+_A_n_y_C_a_s_e_, _-_U_p_p_e_r_C_a_s_e)) Converts, similar to downcase_atom/2, an atom to upper-case. 44..2222..22 LLaanngguuaaggee ssppeecciiffiicc ccoommppaarriissoonn This section deals with predicates for language specific string comparison operations. ccoollllaattiioonn__kkeeyy((_+_A_t_o_m_, _-_K_e_y)) Create a _K_e_y from _A_t_o_m for locale specific comparison. The key is defined such that if the key of atom A preceeds the key of atom B in the standard order of terms, A is alphabetically smaller than B using the sort order of the current locale. The predicate collation_key/2 is used by locale_sort/2 from library(sort). Please examine the implementation of locale_sort/2 as an example of using this call. The _K_e_y is an implementation defined and generally unreadable string. llooccaallee__ssoorrtt((_+_L_i_s_t_, _-_S_o_r_t_e_d)) Sort a list of atoms using the current locale. _L_i_s_t is a list of atoms or string objects (see section 4.23). _S_o_r_t_e_d is unified with a list containing all atoms of _L_i_s_t, sorted to the rules of the current locale. See also collation_key/2 and setlocale/3. 44..2233 RReepprreesseennttiinngg tteexxtt iinn ssttrriinnggss SWI-Prolog supports the data type _s_t_r_i_n_g. Strings are a time and space efficient mechanism to handle text in Prolog. Strings are stored as a byte array on the global (term) stack and thus destroyed on backtracking and reclaimed by the garbage collector. Strings were added to SWI-Prolog based on an early draft of the ISO standard, offering a mechanism to represent temporary character data efficiently. As SWI-Prolog strings can handle 0-bytes, they are frequently used through the foreign language interface (section 9) for storing arbitrary byte-sequences. Starting with version 3.3, SWI-Prolog offers garbage collection on the atom-space as well as representing 0-bytes in atoms. Although strings and atoms still have different features, new code should consider using atoms to avoid too many representations for text as well as for compatibility to other Prolog implementations. Below are some of the differences: o _c_r_e_a_t_i_o_n Creating strings is fast, as the data is simply copied to the global stack. Atoms are unique and therefore more expensive in terms of memory and time to create. On the other hand, if the same text has to be represented multiple times, atoms are more efficient. o _d_e_s_t_r_u_c_t_i_o_n Backtracking destroys strings at no cost. They are cheap to handle by the garbage collector, but it should be noted that extensive use of strings will cause many garbage collections. Atom garbage collection is generally faster. String objects by default have no lexical representation and thus can only be created using the predicates below or through the foreign language interface (See chapter 9. There are two ways to make read/1 read text into strings, both controlled through Prolog flags. One is by setting the double_quotes flag to string and the other is by setting the backquoted_string flag to true. In latter case, `Hello world` is read into a string and write_term/2 prints strings between back-quotes if quoted is true. This flag provides compatibility to LPA Prolog string handling. ssttrriinngg__ttoo__aattoomm((_?_S_t_r_i_n_g_, _?_A_t_o_m)) Logical conversion between a string and an atom. At least one of the two arguments must be instantiated. _A_t_o_m can also be an integer or floating point number. ssttrriinngg__ttoo__lliisstt((_?_S_t_r_i_n_g_, _?_L_i_s_t)) Logical conversion between a string and a list of character codes characters. At least one of the two arguments must be instantiated. ssttrriinngg__lleennggtthh((_+_S_t_r_i_n_g_, _-_L_e_n_g_t_h)) Unify _L_e_n_g_t_h with the number of characters in _S_t_r_i_n_g. This predicate is functionally equivalent to atom_length/2 and also accepts atoms, integers and floats as its first argument. ssttrriinngg__ccoonnccaatt((_?_S_t_r_i_n_g_1_, _?_S_t_r_i_n_g_2_, _?_S_t_r_i_n_g_3)) Similar to atom_concat/3, but the unbound argument will be unified with a string object rather than an atom. Also, if both _S_t_r_i_n_g_1 and _S_t_r_i_n_g_2 are unbound and _S_t_r_i_n_g_3 is bound to text, it breaks _S_t_r_i_n_g_3, unifying the start with _S_t_r_i_n_g_1 and the end with _S_t_r_i_n_g_2 as append does with lists. Note that this is not particularly fast on long strings as for each redo the system has to create two entirely new strings, while the list equivalent only creates a single new list-cell and moves some pointers around. ssuubb__ssttrriinngg((_+_S_t_r_i_n_g_, _?_S_t_a_r_t_, _?_L_e_n_g_t_h_, _?_A_f_t_e_r_, _?_S_u_b)) _S_u_b is a substring of _S_t_r_i_n_g starting at _S_t_a_r_t, with length _L_e_n_g_t_h and _S_t_r_i_n_g has _A_f_t_e_r characters left after the match. See also sub_atom/5. 44..2244 OOppeerraattoorrss Operators are defined to improve the readability of source-code. For example, without operators, to write 2*3+4*5 one would have to write +(*(2,3),*(4,5)). In Prolog, a number of operators have been predefined. All operators, except for the comma (,) can be redefined by the user. Some care has to be taken before defining new operators. Defining too many operators might make your source `natural' looking, but at the same time lead to hard to understand the limits of your syntax. To ease the pain, as of SWI-Prolog 3.3.0, operators are local to the module in which they are defined. Operators can be exported from modules using a term op(_P_r_e_c_e_d_e_n_c_e_, _T_y_p_e_, _N_a_m_e) in the export list as specified by module/2. This is an extension specific to SWI-Prolog and the advised mechanism of portability is not an important concern. The module-table of the module user acts as default table for all modules and can be modified explicitly from inside a module to achieve compatibility to other Prolog systems: :- module(prove, [ prove/1 ]). :- op(900, xfx, user:(=>)). Unlike what many users think, operators and quoted atoms have no relation: defining an atom as an operator does nnoott influence parsing characters into atoms and quoting an atom does nnoott stop it from acting as an operator. To stop an atom acting as an operator, enclose it in braces like this: (myop). oopp((_+_P_r_e_c_e_d_e_n_c_e_, _+_T_y_p_e_, _:_N_a_m_e)) Declare _N_a_m_e to be an operator of type _T_y_p_e with precedence _P_r_e_c_e_d_e_n_c_e. _N_a_m_e can also be a list of names, in which case all elements of the list are declared to be identical operators. _P_r_e_c_e_d_e_n_c_e is an integer between 0 and 1200. Precedence 0 removes the declaration. _T_y_p_e is one of: xf, yf, xfx, xfy, yfx, yfy, fy or fx. The `f' indicates the position of the functor, while x and y indicate the position of the arguments. `y' should be interpreted as ``on this position a term with precedence lower or equal to the precedence of the functor should occur''. For `x' the precedence of the argument must be strictly lower. The precedence of a term is 0, unless its principal functor is an operator, in which case the precedence is the precedence of this operator. A term enclosed in brackets (...) has precedence 0. The predefined operators are shown in table 4.1. Note that all operators can be redefined by the user. ______________________________________________________________ | 1200 |xfx |-->, :- | | 1200 | fx |:-, ?- | | 1150 | fx |dynamic, discontiguous, initialization, mod- | | | |ule_transparent, multifile, thread_local,| | | |volatile | | 1100 |xfy |;, | | | 1050 |xfy |->, op*-> | | 1000 |xfy |, | | 954 |xfy |\ | | 900 | fy |\+ | | 900 | fx |~ | | 700 |xfx |<, =, =.., =@=, =:=, =<, ==, =\=, >, >=, @<, | | | |@=<, @>, @>=, \=, \==, is | | 600 |xfy |: | | 500 | yfx |+, -, /\, \/, xor | | 500 | fx |+, -, ?, \ | | 400 | yfx |*, /, //, rdiv, <<, >>, mod, rem | | 200 |xfx |** | |__200_|xfy__|^______________________________________________|_ Table 4.1: System operators ccuurrrreenntt__oopp((_?_P_r_e_c_e_d_e_n_c_e_, _?_T_y_p_e_, _?_:_N_a_m_e)) True if _N_a_m_e is currently defined as an operator of type _T_y_p_e with precedence _P_r_e_c_e_d_e_n_c_e. See also op/3. 44..2255 CChhaarraacctteerr CCoonnvveerrssiioonn Although I wouldn't really know for what you would like to use these features, they are provided for ISO compliance. cchhaarr__ccoonnvveerrssiioonn((_+_C_h_a_r_I_n_, _+_C_h_a_r_O_u_t)) Define that term-input (see read_term/3) maps each character read as _C_h_a_r_I_n to the character _C_h_a_r_O_u_t. Character conversion is only executed if the prolog-flag char_conversion is set to true and not inside quoted atoms or strings. The initial table maps each character onto itself. See also current_char_conversion/2. ccuurrrreenntt__cchhaarr__ccoonnvveerrssiioonn((_?_C_h_a_r_I_n_, _?_C_h_a_r_O_u_t)) Queries the current character conversion-table. See char_conversion/2 for details. 44..2266 AArriitthhmmeettiicc Arithmetic can be divided into some special purpose integer predicates and a series of general predicates for integer, floating point and rational arithmetic as appropriate. The general arithmetic predicates all handle _e_x_p_r_e_s_s_i_o_n_s. An expression is either a simple number or a _f_u_n_c_t_i_o_n. The arguments of a function are expressions. The functions are described in section 4.26.2.3. 44..2266..11 SSppeecciiaall ppuurrppoossee iinntteeggeerr aarriitthhmmeettiicc The predicates in this section provide more logical operations between integers. They are not covered by the ISO standard, although they are `part of the community' and found as either library or built-in in many other Prolog systems. bbeettwweeeenn((_+_L_o_w_, _+_H_i_g_h_, _?_V_a_l_u_e)) _L_o_w and _H_i_g_h are integers, _H_i_g_h >=_L_o_w. If _V_a_l_u_e is an integer, _L_o_w=< _V_a_l_u_e=< _H_i_g_h. When _V_a_l_u_e is a variable it is successively bound to all integers between _L_o_w and _H_i_g_h. If _H_i_g_h is inf or infinite between/3 is true iff _V_a_l_u_e>= _L_o_w, a feature that is particularly interesting for generating integers from a certain value. ssuucccc((_?_I_n_t_1_, _?_I_n_t_2)) True if _I_n_t_2 = _I_n_t_1+ 1 and _I_n_t_1>=0. At least one of the arguments must be instantiated to a natural number. This predicate raises the domain-error not_less_than_zero if called with a negative integer. E.g. succ(_X_, _0) fails silently and succ(_X_, _-_1) raises a domain-error. pplluuss((_?_I_n_t_1_, _?_I_n_t_2_, _?_I_n_t_3)) True if _I_n_t_3 =_I_n_t_1 +_I_n_t_2. At least two of the three arguments must be instantiated to integers. 44..2266..22 GGeenneerraall ppuurrppoossee aarriitthhmmeettiicc The general arithmetic predicates are optionally compiled (see set_prolog_flag/2 and the -O command line option). Compiled arithmetic reduces global stack requirements and improves performance. Unfortunately compiled arithmetic cannot be traced, which is why it is optional. _+_E_x_p_r_1 > _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a larger number than _E_x_p_r_2. _+_E_x_p_r_1 < _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a smaller number than _E_x_p_r_2. _+_E_x_p_r_1 =< _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a smaller or equal number to _E_x_p_r_2. _+_E_x_p_r_1 >= _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a larger or equal number to _E_x_p_r_2. _+_E_x_p_r_1 =\= _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a number non-equal to _E_x_p_r_2. _+_E_x_p_r_1 =:= _+_E_x_p_r_2 True if expression _E_x_p_r_1 evaluates to a number equal to _E_x_p_r_2. _-_N_u_m_b_e_r iiss _+_E_x_p_r True if _N_u_m_b_e_r has successfully been unified with the number _E_x_p_r evaluates to. If _E_x_p_r evaluates to a float that can be represented using an integer (i.e, the value is integer and within the range that can be described by Prolog's integer representation), _E_x_p_r is unified with the integer value. Note that normally, is/2 should be used with unbound left operand. If equality is to be tested, =:=/2 should be used. For example: ?- 1 is sin(pi/2). Fails!. sin(pi/2) evaluates to the float 1.0, which does not unify with the integer 1. ?- 1 =:= sin(pi/2). Succeeds as expected. 44..2266..22..11 AArriitthhmmeettiicc ttyyppeess SWI-Prolog defines the following numeric types: o _i_n_t_e_g_e_r If SWI-Prolog is built using the _G_N_U _m_u_l_t_i_p_l_e _p_r_e_c_i_s_i_o_n _a_r_i_t_h_m_e_t_i_c _l_i_b_r_a_r_y (GMP), integer arithmetic is _u_n_b_o_u_n_d_e_d, which means that the size of integers is limited by available memory only. Without GMP, SWI-Prolog integers are 64-bits, regardless of the native integer size of the platform. The type of integer support can be detected using the Prolog flags bounded, min_integer and max_integer. As the use of GMP is default, most of the following descriptions assume unbounded integer arithmetic. Internally, SWI-Prolog has three integer representations. Small integers (defined by the Prolog flag max_tagged_integer) are encoded directly. Larger integers are represented as 64-bit value on the global stack. Integers that do not fit in 64-bit are represented as serialised GNU MPZ structures on the global stack. o _r_a_t_i_o_n_a_l _n_u_m_b_e_r Rational numbers (Q) are quotients of two integers. Rational arithmetic is only provided if GMP is used (see above). Rational numbers are currently not supported by a Prolog type. They are represented by the compound term rdiv(_N_,_M). Rational numbers that are returned from is/2 are _c_a_n_o_n_i_c_a_l, which means M is positive and N and M have no common divisors. Rational numbers are introduced in the computation using the rational/1, rationalize/1 or the rdiv/2 (rational division) function. Using the same functor for rational division and representing rational numbers allow for passing rational numbers between computations as well as to format/3 for printing. On the long term it is likely that rational numbers will become _a_t_o_m_i_c as well as subtype of _n_u_m_b_e_r. User code that creates or inspects the rdiv(_M_,_N) terms will not be portable to future versions. Rationals are created using one of the functions mentioned above and inspected using rational/3. o _f_l_o_a_t Floating point numbers are represented using the C-type double. On most today platforms these are 64-bit IEEE floating point numbers. Arithmetic functions that require integer arguments accept, in addition to integers, rational numbers with denominator `1' and floating point numbers that can be accurately converted to integers. If the required argument is a float the argument is converted to float. Note that conversion of integers to floating point numbers may raise an overflow exception. In all other cases, arguments are converted to the same type using the order below. integer ! rational number ! floating point number 44..2266..22..22 RRaattiioonnaall nnuummbbeerr eexxaammpplleess The use of rational numbers with unbounded integers allows for exact integer or _f_i_x_e_d _p_o_i_n_t arithmetic under the addition, subtraction, multiplication and division. To exploit rational arithmetic rdiv/2 should be used instead of `/' and floating point numbers must be converted to rational using rational/1. Omitting the rational/1 on floats will convert a rational operand to float and continue the arithmetic using floating point numbers. Here are some examples. A is 2 rdiv 6 A = 1 rdiv 3 A is 4 rdiv 3 + 1 A = 7 rdiv 3 A is 4 rdiv 3 + 1.5 A = 2.83333 A is 4 rdiv 3 + rational(1.5) A = 17 rdiv 6 Note that floats cannot represent all decimal numbers exactly. The function rational/1 creates an _e_x_a_c_t equivalent of the float, while rationalize/1 creates a rational number that is within the float rounding error from the original float. Please check the documentation of these functions for details and examples. Rational numbers can be printed as decimal numbers with arbitrary precision using the format/3 floating point conversion: ?- A is 4 rdiv 3 + rational(1.5), format('~50f~n', [A]). 2.83333333333333333333333333333333333333333333333333 A = 17 rdiv 6 44..2266..22..33 AArriitthhmmeettiicc FFuunnccttiioonnss Arithmetic functions are terms which are evaluated by the arithmetic predicates described in section 4.26.2. SWI-Prolog tries to hide the difference between integer arithmetic and floating point arithmetic from the Prolog user. Arithmetic is done as integer arithmetic as long as possible and converted to floating point arithmetic whenever one of the arguments or the combination of them requires it. If a function returns a floating point value which is whole it is automatically transformed into an integer. There are four types of arguments to functions: _E_x_p_r Arbitrary expression, returning either a floating point value or an integer. _I_n_t_E_x_p_r Arbitrary expression that must evaluate into an integer. _R_a_t_E_x_p_r Arbitrary expression that must evaluate into a rational number. _F_l_o_a_t_E_x_p_r Arbitrary expression that must evaluate into a floating point. For systems using bounded integer arithmetic (default is unbounded, see section 4.26.2.1 for details), integer operations that would cause overflow automatically convert to floating point arithmetic. - _+_E_x_p_r _R_e_s_u_l_t =-_E_x_p_r _+_E_x_p_r_1 + _+_E_x_p_r_2 _R_e_s_u_l_t =_E_x_p_r_1 +_E_x_p_r_2 _+_E_x_p_r_1 - _+_E_x_p_r_2 _R_e_s_u_l_t =_E_x_p_r_1 -_E_x_p_r_2 _+_E_x_p_r_1 * _+_E_x_p_r_2 _R_e_s_u_l_t =_E_x_p_r_1_*Expr2 _+_E_x_p_r_1 / _+_E_x_p_r_2 _R_e_s_u_l_t = _E_x_p_r_1=_E_x_p_r_2 The the flag iso is true, both arguments are converted to float and the return value is a float. Otherwise (default), if both arguments are integers the operation returns an integer if the division is exact. If at least one of the arguments is rational and the other argument is integer, the operation returns a rational number. In all other cases the return value is a float. See also ///2 and rdiv/2. _+_I_n_t_E_x_p_r_1 mmoodd _+_I_n_t_E_x_p_r_2 Modulo: _R_e_s_u_l_t = _I_n_t_E_x_p_r_1 - (_I_n_t_E_x_p_r_1 // _I_n_t_E_x_p_r_2) * _I_n_t_E_x_p_r_2 The function mod/2 is implemented using the C % operator. It's behaviour with negative values is illustrated in the table below. 2 = 17 mod 5 2 = 17 mod -5 -2 = -17 mod 5 -2 = -17 mod -5 _+_I_n_t_E_x_p_r_1 rreemm _+_I_n_t_E_x_p_r_2 Remainder of division: _R_e_s_u_l_t is float_fractional_part(_I_n_t_E_x_p_r_1/_I_n_t_E_x_p_r_2) _+_I_n_t_E_x_p_r_1 // _+_I_n_t_E_x_p_r_2 Integer division: _R_e_s_u_l_t is truncate(_E_x_p_r_1/_E_x_p_r_2) _+_R_a_t_E_x_p_r rrddiivv _+_R_a_t_E_x_p_r Rational number division. This function is only available if SWI-Prolog has been compiled with rational number support. See section 4.26.2.2 for details. aabbss((_+_E_x_p_r)) Evaluate _E_x_p_r and return the absolute value of it. ssiiggnn((_+_E_x_p_r)) Evaluate to -1 if _E_x_p_r <0, 1 if _E_x_p_r >0 and 0 if _E_x_p_r =0. mmaaxx((_+_E_x_p_r_1_, _+_E_x_p_r_2)) Evaluates to the largest of both _E_x_p_r_1 and _E_x_p_r_2. Both arguments are compared after converting to the same type, but the return value is in the original type. For example, max(2.5, 3) compares the two values after converting to float, but returns the integer 3. mmiinn((_+_E_x_p_r_1_, _+_E_x_p_r_2)) Evaluates to the smallest of both _E_x_p_r_1 and _E_x_p_r_2. See max/2 for a description of type-handling. .((_+_I_n_t_, _[_])) A list of one element evaluates to the element. This implies "a" evaluates to the character code of the letter `a' (97). This option is available for compatibility only. It will not work if `style_check(+string)' is active as "a" will then be transformed into a string object. The recommended way to specify the character code of the letter `a' is 0'a. rraannddoomm((_+_I_n_t_E_x_p_r)) Evaluates to a random integer _i for which 0=< i< _I_n_t_E_x_p_r. The seed of this random generator is determined by the system clock when SWI-Prolog was started. rroouunndd((_+_E_x_p_r)) Evaluates _E_x_p_r and rounds the result to the nearest integer. iinntteeggeerr((_+_E_x_p_r)) Same as round/1 (backward compatibility). ffllooaatt((_+_E_x_p_r)) Translate the result to a floating point number. Normally, Prolog will use integers whenever possible. When used around the 2nd argument of is/2, the result will be returned as a floating point number. In other contexts, the operation has no effect. rraattiioonnaall((_+_E_x_p_r)) Convert the _E_x_p_r to a rational number or integer. The function returns the input on integers and rational numbers. For floating point numbers, the returned rational number _e_x_a_c_t_l_y represents the float. As floats cannot exactly represent all decimal numbers the results may be surprising. In the examples below, doubles can represent 0.25 and the result is as expected, in contrast to the result of rational(_0_._1). The function rationalize/1 remedies this. See section 4.26.2.2 for more information on rational number support. ?- A is rational(0.25). A is 1 rdiv 4 ?- A is rational(0.1). A = 3602879701896397 rdiv 36028797018963968 rraattiioonnaalliizzee((_+_E_x_p_r)) Convert the _E_x_p_r to a rational number or integer. The function is similar to rational/1, but the result is only accurate within the rounding error of floating point numbers, generally producing a much smaller denominator. ?- A is rationalize(0.25). A = 1 rdiv 4 ?- A is rationalize(0.1). A = 1 rdiv 10 ffllooaatt__ffrraaccttiioonnaall__ppaarrtt((_+_E_x_p_r)) Fractional part of a floating-point number. Negative if _E_x_p_r is negative, rational if _E_x_p_r is rational and 0 if _E_x_p_r is integer. The following relation is always true: Xisfloatfractionalpart(X)+ floatintegerpart(X). ffllooaatt__iinntteeggeerr__ppaarrtt((_+_E_x_p_r)) Integer part of floating-point number. Negative if _E_x_p_r is negative, _E_x_p_r if _E_x_p_r is integer. ttrruunnccaattee((_+_E_x_p_r)) Truncate _E_x_p_r to an integer. If _E_x_p_r>= 0 this is the same as floor(_E_x_p_r). For _E_x_p_r< 0 this is the same as ceil(_E_x_p_r). E.i. truncate rounds towards zero. fflloooorr((_+_E_x_p_r)) Evaluates _E_x_p_r and returns the largest integer smaller or equal to the result of the evaluation. cceeiilliinngg((_+_E_x_p_r)) Evaluates _E_x_p_r and returns the smallest integer larger or equal to the result of the evaluation. cceeiill((_+_E_x_p_r)) Same as ceiling/1 (backward compatibility). _+_I_n_t_E_x_p_r >> _+_I_n_t_E_x_p_r Bitwise shift _I_n_t_E_x_p_r_1 by _I_n_t_E_x_p_r_2 bits to the right. The operation performs _a_r_i_t_h_m_e_t_i_c _s_h_i_f_t, which implies that the inserted most significant bits are copies of the original most significant bit. _+_I_n_t_E_x_p_r << _+_I_n_t_E_x_p_r Bitwise shift _I_n_t_E_x_p_r_1 by _I_n_t_E_x_p_r_2 bits to the left. _+_I_n_t_E_x_p_r \/ _+_I_n_t_E_x_p_r Bitwise `or' _I_n_t_E_x_p_r_1 and _I_n_t_E_x_p_r_2. _+_I_n_t_E_x_p_r /\ _+_I_n_t_E_x_p_r Bitwise `and' _I_n_t_E_x_p_r_1 and _I_n_t_E_x_p_r_2. _+_I_n_t_E_x_p_r xxoorr _+_I_n_t_E_x_p_r Bitwise `exclusive or' _I_n_t_E_x_p_r_1 and _I_n_t_E_x_p_r_2. \ _+_I_n_t_E_x_p_r Bitwise negation. The returned value is the one's complement of _I_n_t_E_x_p_r. ssqqrrtt((_+_E_x_p_r)) _R_e_s_u_l_t =square root of _E_x_p_r ssiinn((_+_E_x_p_r)) _R_e_s_u_l_t =sine of _E_x_p_r. _E_x_p_r is the angle in radians. ccooss((_+_E_x_p_r)) _R_e_s_u_l_t =cosine of _E_x_p_r. _E_x_p_r is the angle in radians. ttaann((_+_E_x_p_r)) _R_e_s_u_l_t =tangus of _E_x_p_r. _E_x_p_r is the angle in radians. aassiinn((_+_E_x_p_r)) _R_e_s_u_l_t =inverse sine of _E_x_p_r. _R_e_s_u_l_t is the angle in radians. aaccooss((_+_E_x_p_r)) _R_e_s_u_l_t =inverse cosine of _E_x_p_r. _R_e_s_u_l_t is the angle in radians. aattaann((_+_E_x_p_r)) _R_e_s_u_l_t =inverse tangus of _E_x_p_r. _R_e_s_u_l_t is the angle in radians. aattaann((_+_Y_E_x_p_r_, _+_X_E_x_p_r)) _R_e_s_u_l_t = inverse tangus of _Y_E_x_p_r / _X_E_x_p_r. _R_e_s_u_l_t is the angle in radians. The return value is in the range [-pi:::pi]. Used to convert between rectangular and polar coordinate system. lloogg((_+_E_x_p_r)) _R_e_s_u_l_t =natural logarithm of _E_x_p_r lloogg1100((_+_E_x_p_r)) _R_e_s_u_l_t =10 base logarithm of _E_x_p_r eexxpp((_+_E_x_p_r)) _R_e_s_u_l_t =e to the power _E_x_p_r _+_E_x_p_r_1 ** _+_E_x_p_r_2 _R_e_s_u_l_t = _E_x_p_r_1 to the power _E_x_p_r_2. With unbounded integers and integer values for _E_x_p_r_1 and a non-negative integer _E_x_p_r_2, the result is always integer. ppoowwmm((_+_I_n_t_E_x_p_r_B_a_s_e_, _+_I_n_t_E_x_p_r_E_x_p_, _+_I_n_t_E_x_p_r_M_o_d)) _R_e_s_u_l_t = (_I_n_t_E_x_p_r_B_a_s_e to the power _I_n_t_E_x_p_r_E_x_p) modulo _I_n_t_E_x_p_r_M_o_d. Only available when compiled with unbounded integer support. This formula is required for Diffie-Hellman key-exchange, a technique where two parties can establish a secret key over a public network. _+_E_x_p_r_1 ^ _+_E_x_p_r_2 Same as **/2. (backward compatibility). ppii Evaluates to the mathematical constant pi (3.141593). ee Evaluates to the mathematical constant e (2.718282). ccppuuttiimmee Evaluates to a floating point number expressing the cpu time (in seconds) used by Prolog up till now. See also statistics/2 and time/1. BBiittvveeccttoorr ffuunnccttiioonnss The functions below are not covered by the standard. The msb/1 function is compatible to hProlog. The others are private extensions that improve handling of ---unbounded--- integers as bit-vectors. mmssbb((_+_I_n_t_E_x_p_r)) Return the largest integer N such that (IntExpr >> N) /\ 1 =:= 1. This is the (zero-origin) index of the most significant 1 bit in the value of _I_n_t_E_x_p_r, which must evaluate to a positive integer. Errors for 0, negative integers, and non-integers. llssbb((_+_I_n_t_E_x_p_r)) Return the smallest integer N such that (IntExpr >> N) /\ 1 =:= 1. This is the (zero-origin) index of the least significant 1 bit in the value of IntExpr, which must evaluate to a positive integer. Errors for 0, negative integers, and non-integers. ppooppccoouunntt((_+_I_n_t_E_x_p_r)) Return the number of 1s in the binary representation of the non-negative integer _I_n_t_E_x_p_r. 44..2277 AAddddiinngg AArriitthhmmeettiicc FFuunnccttiioonnss Prolog predicates can be given the role of arithmetic function. The last argument is used to return the result, the arguments before the last are the inputs. Arithmetic functions are added using the predicate arithmetic_function/1, which takes the head as its argument. Arithmetic functions are module sensitive, that is they are only visible from the module in which the function is defined and declared. Global arithmetic functions should be defined and registered from module user. Global definitions can be overruled locally in modules. The built-in functions described above can be redefined as well. aarriitthhmmeettiicc__ffuunnccttiioonn((_+_H_e_a_d)) Register a Prolog predicate as an arithmetic function (see is/2, >/2 , etc.). The Prolog predicate should have one more argument than specified by _H_e_a_d, which it either a term _N_a_m_e_/_A_r_i_t_y, an atom or a complex term. This last argument is an unbound variable at call time and should be instantiated to an integer or floating point number. The other arguments are the parameters. This predicate is module sensitive and will declare the arithmetic function only for the context module, unless declared from module user. Example: 1 ?- [user]. :- arithmetic_function(mean/2). mean(A, B, C) :- C is (A+B)/2. user compiled, 0.07 sec, 440 bytes. Yes 2 ?- A is mean(4, 5). A = 4.500000 ccuurrrreenntt__aarriitthhmmeettiicc__ffuunnccttiioonn((_?_H_e_a_d)) Successively unifies all arithmetic functions that are visible from the context module with _H_e_a_d. 44..2288 BBuuiilltt--iinn lliisstt ooppeerraattiioonnss Most list operations are defined in the library lists described in section 11.1. Some that are implemented with more low-level primitives are built-in and described here. iiss__lliisstt((_+_T_e_r_m)) True if _T_e_r_m is bound to the empty list ([]) or a term with functor `.' and arity 2 and the second argument is a list. This predicate acts as if defined by the following definition: is_list(X) :- var(X), !, fail. is_list([]). is_list([_|T]) :- is_list(T). mmeemmbbeerrcchhkk((_?_E_l_e_m_, _+_L_i_s_t)) Equivalent to member/2, but leaves no choice point. lleennggtthh((_?_L_i_s_t_, _?_I_n_t)) True if _I_n_t represents the number of elements of list _L_i_s_t. Can be used to create a list holding only variables. ssoorrtt((_+_L_i_s_t_, _-_S_o_r_t_e_d)) True if _S_o_r_t_e_d can be unified with a list holding the elements of _L_i_s_t, sorted to the standard order of terms (see section 4.6). Duplicates are removed. The implementation is in C, using _n_a_t_u_r_a_l _m_e_r_g_e _s_o_r_t mmssoorrtt((_+_L_i_s_t_, _-_S_o_r_t_e_d)) Equivalent to sort/2, but does not remove duplicates. kkeeyyssoorrtt((_+_L_i_s_t_, _-_S_o_r_t_e_d)) List is a proper list whose elements are Key-Value, that is, terms whose principal functor is (-)/2, whose first argument is the sorting key, and whose second argument is the satellite data to be carried along with the key. keysort/2 sorts _L_i_s_t like msort/2, but only compares the keys. It is used to sort terms not on standard order, but on any criterion that can be expressed on a multi-dimensional scale. Sorting on more than one criterion can be done using terms as keys, putting the first criterion as argument 1, the second as argument 2, etc. The order of multiple elements that have the same _K_e_y is not changed. The implementation is in C, using _n_a_t_u_r_a_l _m_e_r_g_e _s_o_r_t. pprreeddssoorrtt((_+_P_r_e_d_, _+_L_i_s_t_, _-_S_o_r_t_e_d)) Sorts similar to sort/2, but determines the order of two terms by calling _P_r_e_d(-_D_e_l_t_a, +_E_1, +_E_2). This call must unify _D_e_l_t_a with one of <, > or =. If built-in predicate compare/3 is used, the result is the same as sort/2. See also keysort/2. mmeerrggee((_+_L_i_s_t_1_, _+_L_i_s_t_2_, _-_L_i_s_t_3)) _L_i_s_t_1 and _L_i_s_t_2 are lists, sorted to the standard order of terms (see section 4.6). _L_i_s_t_3 will be unified with an ordered list holding both the elements of _L_i_s_t_1 and _L_i_s_t_2. Duplicates are nnoott removed. mmeerrggee__sseett((_+_S_e_t_1_, _+_S_e_t_2_, _-_S_e_t_3)) _S_e_t_1 and _S_e_t_2 are lists without duplicates, sorted to the standard order of terms. _S_e_t_3 is unified with an ordered list without duplicates holding the union of the elements of _S_e_t_1 and _S_e_t_2. 44..2299 FFiinnddiinngg aallll SSoolluuttiioonnss ttoo aa GGooaall ffiinnddaallll((_+_T_e_m_p_l_a_t_e_, _+_G_o_a_l_, _-_B_a_g)) Creates a list of the instantiations _T_e_m_p_l_a_t_e gets successively on backtracking over _G_o_a_l and unifies the result with _B_a_g. Succeeds with an empty list if _G_o_a_l has no solutions. findall/3 is equivalent to bagof/3 with all free variables bound with the existential operator (^), except that bagof/3 fails when goal has no solutions. bbaaggooff((_+_T_e_m_p_l_a_t_e_, _+_G_o_a_l_, _-_B_a_g)) Unify _B_a_g with the alternatives of _T_e_m_p_l_a_t_e, if _G_o_a_l has free variables besides the one sharing with _T_e_m_p_l_a_t_e bagof will backtrack over the alternatives of these free variables, unifying _B_a_g with the corresponding alternatives of _T_e_m_p_l_a_t_e. The construct +Var^Goal tells bagof not to bind _V_a_r in _G_o_a_l. bagof/3 fails if _G_o_a_l has no solutions. The example below illustrates bagof/3 and the ^ operator. The variable bindings are printed together on one line to save paper. 2 ?- listing(foo). foo(a, b, c). foo(a, b, d). foo(b, c, e). foo(b, c, f). foo(c, c, g). Yes 3 ?- bagof(C, foo(A, B, C), Cs). A = a, B = b, C = G308, Cs = [c, d] ; A = b, B = c, C = G308, Cs = [e, f] ; A = c, B = c, C = G308, Cs = [g] ; No 4 ?- bagof(C, A^foo(A, B, C), Cs). A = G324, B = b, C = G326, Cs = [c, d] ; A = G324, B = c, C = G326, Cs = [e, f, g] ; No 5 ?- sseettooff((_+_T_e_m_p_l_a_t_e_, _+_G_o_a_l_, _-_S_e_t)) Equivalent to bagof/3, but sorts the result using sort/2 to get a sorted list of alternatives without duplicates. 44..3300 IInnvvookkiinngg PPrreeddiiccaatteess oonn aallll MMeemmbbeerrss ooff aa LLiisstt All the predicates in this section call a predicate on all members of a list or until the predicate called fails. The predicate is called via call/[2..], which implies common arguments can be put in front of the arguments obtained from the list(s). For example: ?- maplist(plus(1), [0, 1, 2], X). X = [1, 2, 3] we will phrase this as ``_P_r_e_d_i_c_a_t_e is applied on ...'' mmaapplliisstt((_+_P_r_e_d_, _+_L_i_s_t)) _P_r_e_d is applied successively on each element of _L_i_s_t until the end of the list or _P_r_e_d fails. In the latter case the maplist/2 fails. mmaapplliisstt((_+_P_r_e_d_, _?_L_i_s_t_1_, _?_L_i_s_t_2)) Apply _P_r_e_d on all successive pairs of elements from _L_i_s_t_1 and _L_i_s_t_2. Fails if _P_r_e_d can not be applied to a pair. See the example above. mmaapplliisstt((_+_P_r_e_d_, _?_L_i_s_t_1_, _?_L_i_s_t_2_, _?_L_i_s_t_3)) Apply _P_r_e_d on all successive triples of elements from _L_i_s_t_1, _L_i_s_t_2 and _L_i_s_t_3. Fails if _P_r_e_d can not be applied to a triple. See the example above. ssuubblliisstt((_+_P_r_e_d_, _+_L_i_s_t_1_, _?_L_i_s_t_2)) Unify _L_i_s_t_2 with a list of all elements of _L_i_s_t_1 to which _P_r_e_d applies. 44..3311 FFoorraallll ffoorraallll((_+_C_o_n_d_, _+_A_c_t_i_o_n)) For all alternative bindings of _C_o_n_d _A_c_t_i_o_n can be proven. The example verifies that all arithmetic statements in the list _L are correct. It does not say which is wrong if one proves wrong. ?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]), Result =:= Formula). 44..3322 FFoorrmmaatttteedd WWrriittee The current version of SWI-Prolog provides two formatted write predicates. The first is writef/[1,2], which is compatible with Edinburgh C-Prolog. The second is format/[1,2], which is compatible with Quintus Prolog. We hope the Prolog community will once define a standard formatted write predicate. If you want performance use format/[1,2] as this predicate is defined in C. Otherwise compatibility reasons might tell you which predicate to use. 44..3322..11 WWrriitteeff wwrriitteellnn((_+_T_e_r_m)) Equivalent to write(Term), nl. wwrriitteeff((_+_A_t_o_m)) Equivalent to writef(Atom, []). wwrriitteeff((_+_F_o_r_m_a_t_, _+_A_r_g_u_m_e_n_t_s)) Formatted write. _F_o_r_m_a_t is an atom whose characters will be printed. _F_o_r_m_a_t may contain certain special character sequences which specify certain formatting and substitution actions. _A_r_g_u_m_e_n_t_s then provides all the terms required to be output. Escape sequences to generate a single special character: __________________________________________________ | \n |Output a newline character (see also | | |nl/[0,1]) | | \l |Output a line separator (same as \n) | | \r |Output a carriage-return character | | |(ASCII 13) | | \t |Output the ASCII character TAB (9) | | \\ |The character \ is output | | \% |The character % is output | | \nnn |where <_n_n_n> is an integer (1-3 digits) | | |the character with character code <_n_n_n> | |______|is_output_(NB_:_<_n_n_n>_is_read_as_ddeecciimmaall)_| Note that \l, \nnn and \\ are interpreted differently when character-escapes are in effect. See section 2.15.1.2. Escape sequences to include arguments from _A_r_g_u_m_e_n_t_s. Each time a % escape sequence is found in _F_o_r_m_a_t the next argument from _A_r_g_u_m_e_n_t_s is formatted according to the specification. _________________________________________________%t | %w print/1 the next item (mnemonic: term) | | | %q |write/1the next item | | |writeq/1the next item | | %d |Write the term, ignoring operators. See| | |also write_term/2. Mnemonic: old| | %p |Edinburgh display/1. | | |print/1the next item (identical to %t) | | %n |Put the next item as a character (i.e.,| | |it is a character code) | | %r |Write the next item N times where N is| | |the second item (an integer) | | %s |Write the next item as a String (so it| | |must be a list of characters) | | %f |Perform a ttyflush/0 (no items used) | | %Nc |Write the next item Centered in N | | |columns. | | %Nl |Write the next item Left justified in N | | |columns. | | %Nr |Write the next item Right justified in N | | |columns. N is a decimal number with at| | |least one digit. The item must be an| |_____|atom,_integer,_float_or_string.__________|_ sswwrriitteeff((_-_S_t_r_i_n_g_, _+_F_o_r_m_a_t_, _+_A_r_g_u_m_e_n_t_s)) Equivalent to writef/2, but ``writes'' the result on _S_t_r_i_n_g instead of the current output stream. Example: ?- swritef(S, '%15L%w', ['Hello', 'World']). S = "Hello World" sswwrriitteeff((_-_S_t_r_i_n_g_, _+_F_o_r_m_a_t)) Equivalent to swritef(String, Format, []). 44..3322..22 FFoorrmmaatt ffoorrmmaatt((_+_F_o_r_m_a_t)) Defined as `format(Format) :- format(Format, []).' ffoorrmmaatt((_+_F_o_r_m_a_t_, _+_A_r_g_u_m_e_n_t_s)) _F_o_r_m_a_t is an atom, list of character codes, or a Prolog string. _A_r_g_u_m_e_n_t_s provides the arguments required by the format specification. If only one argument is required and this is not a list of character codes the argument need not be put in a list. Otherwise the arguments are put in a list. Special sequences start with the tilde (~), followed by an optional numeric argument, followed by a character describing the action to be undertaken. A numeric argument is either a sequence of digits, representing a positive decimal number, a sequence `<_c_h_a_r_a_c_t_e_r>, representing the character code value of the character (only useful for ~t) or a asterisk (*), in when the numeric argument is taken from the next argument of the argument list, which should be a positive integer. Numeric conversion (d, D, e, E, f, g and G) accept an arithmetic expression as argument. This is introduced to handle rational numbers transparently (see section 4.26.2.2. The floating point conversions allow for unlimited precision for printing rational numbers in decimal form. ~ Output the tilde itself. a Output the next argument, which must be an atom. This option is equivalent to ww, except for that it requires the argument to be an atom. c Interpret the next argument as an character code and add it to the output. This argument should be an integer in the range [0, ..., 255] (including 0 and 255). d Output next argument as a decimal number. It should be an integer. If a numeric argument is specified a dot is inserted _a_r_g_u_m_e_n_t positions from the right (useful for doing fixed point arithmetic with integers, such as handling amounts of money). D Same as dd, but makes large values easier to read by inserting a comma every three digits left to the dot or right. e Output next argument as a floating point number in exponential notation. The numeric argument specifies the precision. Default is 6 digits. Exact representation depends on the C library function printf(). This function is invoked with the format %.<_p_r_e_c_i_s_i_o_n>e. E Equivalent to ee, but outputs a capital E to indicate the exponent. f Floating point in non-exponential notation. See C library function printf(). g Floating point in ee or ff notation, whichever is shorter. G Floating point in EE or ff notation, whichever is shorter. i Ignore next argument of the argument list. Produces no output. k Give the next argument to (write_canonical/1). n Output a newline character. N Only output a newline if the last character output on this stream was not a newline. Not properly implemented yet. p Give the next argument to print/1. q Give the next argument to writeq/1. r Print integer in radix the numeric argument notation. Thus ~16r prints its argument hexadecimal. The argument should be in the range [2; :::;36]. Lower case letters are used for digits above 9. R Same as rr, but uses upper case letters for digits above 9. s Output text from a list of character codes or a string (see string/1 and section 4.23) from the next argument. @ Interpret the next argument as a goal and execute it. Output written to the current_output stream is inserted at this place. Goal is called in the module calling format/3. This option is not present in the original definition by Quintus, but supported by some other Prolog systems. t All remaining space between 2 tab stops is distributed equally over ~t statements between the tab stops. This space is padded with spaces by default. If an argument is supplied this is taken to be the character code of the character used for padding. This can be used to do left or right alignment, centering, distributing, etc. See also ~| and ~+ to set tab stops. A tab stop is assumed at the start of each line. | Set a tab stop on the current position. If an argument is supplied set a tab stop on the position of that argument. This will cause all ~t's to be distributed between the previous and this tab stop. + Set a tab stop relative to the current position. Further the same as ~|. w Give the next argument to write/1. W Give the next two argument to write_term/2. E.g. format(' W', [Term, [numbervars(true)]]). This option is SWI-Prolog specific. Example: simple_statistics :- % left to the user format('~tStatistics~t~72|~n~n'), format('Runtime: ~`.t ~2f~34| Inferences: ~`.t ~D~72|~n', [RunT, Inf]), .... Will output Statistics Runtime: .................. 3.45 Inferences: .......... 60,345 ffoorrmmaatt((_+_O_u_t_p_u_t_, _+_F_o_r_m_a_t_, _+_A_r_g_u_m_e_n_t_s)) As format/2, but write the output on the given _O_u_t_p_u_t. The de- facto standard only allows _O_u_t_p_u_t to be a stream. The SWI-Prolog implementation allows all valid arguments for with_output_to/2. For example: ?- format(atom(A), '~D', [1000000]). A = '1,000,000' 44..3322..33 PPrrooggrraammmmiinngg FFoorrmmaatt ffoorrmmaatt__pprreeddiiccaattee((_+_C_h_a_r_, _+_H_e_a_d)) If a sequence ~c (tilde, followed by some character) is found, the format derivatives will first check whether the user has defined a predicate to handle the format. If not, the built in formatting rules described above are used. _C_h_a_r is either an ascii value, or a one character atom, specifying the letter to be (re)defined. _H_e_a_d is a term, whose name and arity are used to determine the predicate to call for the redefined formatting character. The first argument to the predicate is the numeric argument of the format command, or the atom default if no argument is specified. The remaining arguments are filled from the argument list. The example below redefines ~n to produce _A_r_g times return followed by linefeed (so a (Grr.) DOS machine is happy with the output). :- format_predicate(n, dos_newline(_Arg)). dos_newline(default) :- !, dos_newline(1). dos_newline(N) :- ( N > 0 -> write('\r\n'), N2 is N - 1, dos_newline(N2) ; true ). ccuurrrreenntt__ffoorrmmaatt__pprreeddiiccaattee((_?_C_o_d_e_, _?_:_H_e_a_d)) Enumerates all user-defined format predicates. _C_o_d_e is the character code of the format character. _H_e_a_d is unified with a term with the same name and arity as the predicate. If the predicate does not reside in module user, _H_e_a_d is qualified with the definition module of the predicate. 44..3333 TTeerrmmiinnaall CCoonnttrrooll The following predicates form a simple access mechanism to the Unix termcap library to provide terminal independent I/O for screen terminals. These predicates are only available on Unix machines. The SWI-Prolog Windows consoles accepts the ANSI escape sequences. ttttyy__ggeett__ccaappaabbiilliittyy((_+_N_a_m_e_, _+_T_y_p_e_, _-_R_e_s_u_l_t)) Get the capability named _N_a_m_e from the termcap library. See termcap(5) for the capability names. _T_y_p_e specifies the type of the expected result, and is one of string, number or bool. String results are returned as an atom, number result as an integer and bool results as the atom on or off. If an option cannot be found this predicate fails silently. The results are only computed once. Successive queries on the same capability are fast. ttttyy__ggoottoo((_+_X_, _+_Y)) Goto position (_X, _Y) on the screen. Note that the predicates line_count/2 and line_position/2 will not have a well defined behaviour while using this predicate. ttttyy__ppuutt((_+_A_t_o_m_, _+_L_i_n_e_s)) Put an atom via the termcap library function tputs(). This function decodes padding information in the strings returned by tty_get_capability/3 and should be used to output these strings. _L_i_n_e_s is the number of lines affected by the operation, or 1 if not applicable (as in almost all cases). sseett__ttttyy((_-_O_l_d_S_t_r_e_a_m_, _+_N_e_w_S_t_r_e_a_m)) Set the output stream, used by tty_put/2 and tty_goto/2 to a specific stream. Default is user_output. ttttyy__ssiizzee((_-_R_o_w_s_, _-_C_o_l_u_m_n_s)) Determine the size of the terminal. Platforms: UUnniixx If the system provides _i_o_c_t_l calls for this, these are used and tty_size/2 properly reflects the actual size after a user resize of the window. As a fallback, the system uses tty_get_capability/3 using li and co capabilities. In this case the reported size reflects the size at the first call and is not updated after a user-initiated resize of the terminal. WWiinnddoowwss Getting the size of the terminal is provided for plwin.exe. The requested value reflects the current size. For the multi-threaded version the console that is associated with the user_input stream is used. 44..3344 OOppeerraattiinngg SSyysstteemm IInntteerraaccttiioonn sshheellll((_+_C_o_m_m_a_n_d_, _-_S_t_a_t_u_s)) Execute _C_o_m_m_a_n_d on the operating system. _C_o_m_m_a_n_d is given to the Bourne shell (/bin/sh). _S_t_a_t_u_s is unified with the exit status of the command. On _W_i_n_3_2 systems, shell/[1,2] executes the command using the CreateProcess() API and waits for the command to terminate. If the command ends with a & sign, the command is handed to the WinExec() API, which does not wait for the new task to terminate. See also win_exec/2 and win_shell/2. Please note that the CreateProcess() API does nnoott imply the Windows command interpreter (command.exe on Windows 95/98 and cmd.exe on Windows-NT) and therefore commands built-in to the command-interpreter can only be activated using the command interpreter. For example: 'command.exe /C copy file1.txt file2.txt' sshheellll((_+_C_o_m_m_a_n_d)) Equivalent to `shell(Command, 0)'. sshheellll Start an interactive Unix shell. Default is /bin/sh, the environment variable SHELL overrides this default. Not available for Win32 platforms. wwiinn__eexxeecc((_+_C_o_m_m_a_n_d_, _+_S_h_o_w)) Win32 systems only. Spawns a Windows task without waiting for its completion. _S_h_o_w is one of the Win32 SW_* constants written in lowercase without the SW_*: hide maximize minimize restore show showdefault showmaximized showminimized showminnoactive showna shownoactive shownormal. In addition, iconic is a synonym for minimize and normal for shownormal wwiinn__sshheellll((_+_O_p_e_r_a_t_i_o_n_, _+_F_i_l_e_, _+_S_h_o_w)) Win32 systems only. Opens the document _F_i_l_e using the windows shell-rules for doing so. _O_p_e_r_a_t_i_o_n is one of open, print or explore or another operation registered with the shell for the given document-type. On modern systems it is also possible to pass a URL as _F_i_l_e, opening the URL in Windows default browser. This call interfaces to the Win32 API ShellExecute(). The _S_h_o_w argument determines the initial state of the opened window (if any). See win_exec/2 for defined values. wwiinn__sshheellll((_+_O_p_e_r_a_t_i_o_n_, _+_F_i_l_e)) Same as win_shell(_O_p_e_r_a_t_i_o_n_, _F_i_l_e_, _n_o_r_m_a_l) wwiinn__rreeggiissttrryy__ggeett__vvaalluuee((_+_K_e_y_, _+_N_a_m_e_, _-_V_a_l_u_e)) Win32 systems only. Fetches the value of a Win32 registry key. _K_e_y is an atom formed as a path-name describing the desired registry key. _N_a_m_e is the desired attribute name of the key. _V_a_l_u_e is unified with the value. If the value is of type DWORD, the value is returned as an integer. If the value is a string it is returned as a Prolog atom. Other types are currently not supported. The default `root' is HKEY_CURRENT_USER. Other roots can be specified explicitly as HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE or HKEY_USERS. The example below fetches the extension to use for Prolog files (see README.TXT on the Windows version): ?- win_registry_get_value('HKEY_LOCAL_MACHINE/Software/SWI/Prolog', fileExtension, Ext). Ext = pl ggeetteennvv((_+_N_a_m_e_, _-_V_a_l_u_e)) Get environment variable. Fails silently if the variable does not exist. Please note that environment variable names are case-sensitive on Unix systems and case-insensitive on Windows. sseetteennvv((_+_N_a_m_e_, _+_V_a_l_u_e)) Set an environment variable. _N_a_m_e and _V_a_l_u_e must be instantiated to atoms or integers. The environment variable will be passed to shell/[0-2] and can be requested using getenv/2. They also influence expand_file_name/2. Environment variables are shared between threads. Depending on the underlying C library, setenv/2 and unsetenv/1 may not be thread-safe and may cause memory leaks. Only changing the environment once and before starting threads is safe in all versions of SWI-Prolog. uunnsseetteennvv((_+_N_a_m_e)) Remove an environment variable from the environment. Some systems lack the underlying unsetenv() library function. On these systems unsetenv/1 sets the variable to the empty string. sseettllooccaallee((_+_C_a_t_e_g_o_r_y_, _-_O_l_d_, _+_N_e_w)) Set/Query the _l_o_c_a_l_e setting which tells the C-library how to interpret text-files, write numbers, dates, etc. Category is one of all, collate, ctype, messages, monetary, numeric or time. For details, please consult the C-library locale documentation. See also section 2.17.1. Please note that the locale is shared between all threads and thread-safe usage of setlocale/3 is in general not possible. Do locale operations before starting threads or thoroughly study threading aspects of locale support in your environment before use in multi-threaded environments. Locale settings are used by format_time/3, collation_key/2 and locale_sort/2. uunniixx((_+_C_o_m_m_a_n_d)) This predicate comes from the Quintus compatibility library and provides a partial implementation thereof. It provides access to some operating system features and unlike the name suggests, is not operating system specific. Defined _C_o_m_m_a_n_d's are below. ssyysstteemm((_+_C_o_m_m_a_n_d)) Equivalent to calling shell/1. Use for compatibility only. sshheellll((_+_C_o_m_m_a_n_d)) Equivalent to calling shell/1. Use for compatibility only. sshheellll Equivalent to calling shell/0. Use for compatibility only. ccdd Equivalent to calling working_directory/2 to the expansion (see expand_file_name/2) of ~. For compatibility only. ccdd((_+_D_i_r_e_c_t_o_r_y)) Equivalent to calling working_directory/2. Use for compatibility only. aarrggvv((_-_A_r_g_v)) Unify _A_r_g_v with the list of command-line arguments provides to this Prolog run. Please note that Prolog system-arguments and application arguments are separated by --. Integer arguments are passed as Prolog integers, float arguments and Prolog floating point numbers and all other arguments as Prolog atoms. New applications should use the prolog-flag argv. See also prolog prolog-flag argv. A stand-alone program could use the following skeleton to handle command-line arguments. See also section 2.10.2.4. main :- current_prolog_flag(argv, Argv), append(_PrologArgs, [--|AppArgs], Argv), !, main(AppArgs). 44..3344..11 DDeeaalliinngg wwiitthh ttiimmee aanndd ddaattee Representing time in a computer system is surprisingly complicated. There are a large number of time representations in use and the correct choice depends on factors such as compactness, resolution and desired operations. Humans tend to think about time in hours, days, months, years or centuries. Physicists think about time in seconds. But, a month does not have a defined number of seconds. Even a day does not have a defined number of seconds as sometimes a leap-second is introduced to synchronise properly with our earth's rotation. At the same time, resolution demands range from better then pico-seconds to millions of years. Finally, civilizations have a wide range of calendars. Although there exist libraries dealing with most if this complexity, our desire to keep Prolog clean and lean stops us from fully supporting these. For human-oriented tasks, time can be broken into years, months, days, hours, minutes, seconds and a timezone. Physicists prefer to have time in an arithmetic type representing seconds or fraction thereof, so basic arithmetic deal with comparison and durations. An additional advantage of the physicists approach is that it requires much less space. For these reasons, SWI-Prolog uses an arithmetic type as its prime time representation. Many C libraries deal with time using fixed-point arithmetic, dealing with a large but finite time interval at constant resolution. In our opinion using a floating point number is a more natural choice as we can use a natural unit and the interface does not need to be changed if a higher resolution is required in the future. Our unit of choice is the second as it is the scientific unit. e have placed our origin at 1970-1-1T0:0:0Z for compatibility with the POSIX notion of time as well as with older time support provided by SWI-Prolog. Where older versions of SWI-Prolog relied on the POSIX conversion functions, the current implementation uses libtai to realise conversion between time-stamps and calendar dates for a period of 10 million years. 44..3344..11..11 TTiimmee aanndd ddaattee ddaattaa--ssttrruuccttuurreess We use the following time representations TTiimmeeSSttaammpp A TimeStamp is a floating point number expression the time in seconds since the Epoch at 1970-1-1. ddaattee((_Y_,_M_,_D_,_H_,_M_n_,_S_,_O_f_f_,_T_Z_,_D_S_T)) We call this term a _d_a_t_e_-_t_i_m_e structure. The first 5 fields are integers expressing the year, month (1..12), day (1..31), hour (0..23), Minute (0..59). The _S field holds the seconds as a floating point number between 0.0 and 60.0. _O_f_f is an integer representing the offset relative to UTC in seconds where positive values are west of Greenwhich. If converted from local time (see stamp_date_time/3, _T_Z holds the name of the local timezone. If the timezone is not known _T_Z is the atom -. _D_S_T is true if daylight saving time applies to the current time, false if daylight saving time is relevant but not effective and - if unknown or the timezone has no daylight saving time. ddaattee((_Y_,_M_._D)) Date using the same values as described above. Extracted using date_time_value/3. ttiimmee((_H_,_M_n_,_S)) Time using the same values as described above. Extracted using date_time_value/3. 44..3344..11..22 TTiimmee aanndd ddaattee pprreeddiiccaatteess ggeett__ttiimmee((_-_T_i_m_e_S_t_a_m_p)) Return the current time as a _T_i_m_e_S_t_a_m_p. The granularity is system dependent. See section 4.34.1.1. ssttaammpp__ddaattee__ttiimmee((_+_T_i_m_e_S_t_a_m_p_, _-_D_a_t_e_T_i_m_e_, _+_T_i_m_e_Z_o_n_e)) Convert a _T_i_m_e_Z_o_n_e to a _D_a_t_e_T_i_m_e in the given time zone. See section 4.34.1.1 for details on the data-types. _T_i_m_e_Z_o_n_e describes the timezone for the conversion. It is one of local to extract the local time, 'UTC' to extract at UTC time or an integer describing the seconds west of Greenwhich. ddaattee__ttiimmee__ssttaammpp((_+_D_a_t_e_T_i_m_e_, _-_T_i_m_e_S_t_a_m_p)) Compute the timestamp from a date/9 term. Values for month, day, hour, minute or second need not be normalized. This flexibility allows for easy computation of the time at any given number of these units from a given timestamp. Normalization can be achieved following this call with stamp_date_time/3. This example computes the date 200 days after 2006-7-14: ?- date_time_stamp(date(2006,7,214,0,0,0,0,-,-), Stamp), stamp_date_time(Stamp, D, 0), date_time_value(date, D, Date). Date = date(2007, 1, 30) ddaattee__ttiimmee__vvaalluuee((_?_K_e_y_, _+_D_a_t_e_T_i_m_e_, _?_V_a_l_u_e)) Extract values from a date/9 term. Provided keys are: ______________________________________________________________kkeeyyvvaalluuee ____________________________________________________________________________________________________________________________yearCalendar year as an integer month Calendar month as an integer 1..12 day Calendar day as an integer 1..31 hour Clock hour as an integer 0..23 minute Clock minute as an integer 0..59 second Clock second as a float 0.0..60.0 utc_offset Offset to UTC in seconds (positive is west) time_zone Name of timezone; fails if unknown daylight_saving Bool (true) if dst is effective date Term date(_Y_,_M_,_D) _time_____________Term_time(_H_,_M_,_S)____________________________ ffoorrmmaatt__ttiimmee((_+_O_u_t_, _+_F_o_r_m_a_t_, _+_S_t_a_m_p_O_r_D_a_t_e_T_i_m_e)) Modelled after POSIX strftime(), using GNU extensions. _O_u_t is a destination as specified with with_output_to/2. _F_o_r_m_a_t is an atom or string with the following conversions. Conversions start with a tilde (%) character. a The abbreviated weekday name according to the current locale. Use format_time/4 for POSIX locale. A The full weekday name according to the current locale. Use format_time/4 for POSIX locale. b The abbreviated month name according to the current locale. Use format_time/4 for POSIX locale. B The full month name according to the current locale. Use format_time/4 for POSIX locale. c The preferred date and time representation for the current locale. C The century number (year/100) as a 2-digit integer. d The day of the month as a decimal number (range 01 to 31). D Equivalent to %m/%d/%y. (Yecch for Americans only. Americans should note that in other countries %d/%m/%y is rather common. This means that in international context this format is ambigu ous and should not be used.) e Like %d, the day of the month as a decimal number, but a leading zero is replaced by a space. E Modifier. Not implemented. F Equivalent to %Y-%m-%d (the ISO 8601 date format). g Like %G, but without century, i.e., with a 2-digit year (00-99). G The ISO 8601 year with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V). This has the same format and value as %y, except that if the ISO week number belongs to the previous or next year, that year is used instead. V The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week. See also %U and %W. h Equivalent to %b. H The hour as a decimal number using a 24-hour clock (range 00 to 23). I The hour as a decimal number using a 12-hour clock (range 01 to 12). j The day of the year as a decimal number (range 001 to 366). k The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded by a blank. (See also %H.) l The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded by a blank. (See also %I.) m The month as a decimal number (range 01 to 12). M The minute as a decimal number (range 00 to 59). n A newline character. O Modifier. Not implemented. p Either `AM' or `PM' according to the given time value, or the corresponding strings for the current locale. Noon is treated as `pm' and midnight as `am'. P Like %p but in lowercase: `am' or `pm' or a corresponding string for the current locale. r The time in a.m. or p.m. notation. In the POSIX locale this is equivalent to `%I:%M:%S %p'. R The time in 24-hour notation (%H:%M). For a version including the seconds, see %T below. s The number of seconds since the Epoch, i.e., since 1970-01-01 00:00:00 UTC. S The second as a decimal number (range 00 to 60). (The range is up to 60 to allow for occasional leap seconds.) t A tab character. T The time in 24-hour notation (%H:%M:%S). u The day of the week as a decimal, range 1 to 7, Monday being 1. See also %w. U The week number of the current year as a decimal number, range 00 to 53, starting with the first Sunday as the first day of week 01. See also %V and %W. w The day of the week as a decimal, range 0 to 6, Sunday being 0. See also %u. W The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01. x The preferred date representation for the current locale without the time. X The preferred time representation for the current locale without the date. y The year as a decimal number without a century (range 00 to 99). Y The year as a decimal number including the century. z The time-zone as hour offset from GMT. Required to emit RFC822-conformant dates (using "%a, %d %b %Y %H:%M:%S %z"). Z The time zone or name or abbreviation. + The date and time in date(1) format. % A literal `%' character. ffoorrmmaatt__ttiimmee((_+_O_u_t_, _+_F_o_r_m_a_t_, _+_S_t_a_m_p_O_r_D_a_t_e_T_i_m_e_, _+_L_o_c_a_l_e)) Format time given a specified _L_o_c_a_l_e. This predicate is a work-around for lacking proper portable and thread-safe time and locale handling in current C libraries. In its current implementation the only value allowed for _L_o_c_a_l_e is posix, which currently only modifies the behaviour or the a, A, b and B format specifiers. The predicate is used to be able to emit POSIX locale week and month names for emitting standardised time-stamps such as RFC1123. ppaarrssee__ttiimmee((_+_T_e_x_t_, _-_S_t_a_m_p)) Parse a textual time representation, producing a time-stamp. Supported formats for _T_e_x_t are: __________________________________________ |__NNaammee__________||EExxaammppllee______________________________________________|| ||_RFC_1123_|Fri,_08_Dec_2006_15:29:44_GMT_| 44..3344..22 CCoonnttrroolllliinngg tthhee PLWIN.EXE ccoonnssoollee wwiinnddooww The Windows executable PLWIN.EXE console has a number of predicates to control the appearance of the console. Being totally non-portable, we do not advice using it for your own application, but use XPCE or another portable GUI platform instead. We give the predicates for reference here. wwiinnddooww__ttiittllee((_-_O_l_d_, _+_N_e_w)) Unify _O_l_d with the title displayed in the console and change the title to _N_e_w. wwiinn__wwiinnddooww__ppooss((_+_L_i_s_t_O_f_O_p_t_i_o_n_s)) Interface to the MS-Windows SetWindowPos() function, controlling size, position and stacking order of the window. _L_i_s_t_O_f_O_p_t_i_o_n_s is a list that may hold any number of the terms below. ssiizzee((_W_, _H)) Change the size of the window. _W and _H are expressed in character-units. ppoossiittiioonn((_X_, _Y)) Change the top-left corner of the window. The values are expressed in pixel units. zzoorrddeerr((_Z_O_r_d_e_r)) Change the location in the window stacking order. Values are bottom, top, topmost and notopmost. _T_o_p_m_o_s_t windows are displayed above all other windows. sshhooww((_B_o_o_l)) If true, show the window, if false hide the window. aaccttiivvaattee If present, activate the window. wwiinn__hhaass__mmeennuu True if win_insert_menu/2 and win_insert_menu_item/4are present. wwiinn__iinnsseerrtt__mmeennuu((_+_L_a_b_e_l_, _+_B_e_f_o_r_e)) Insert a new entry (pulldown) in the menu. If the menu already contains this entry, nothing is done. The _L_a_b_e_l is the label and using the Windows conventions, a letter prefixed with & is underlined and defines the associated accelerator key. _B_e_f_o_r_e is the label before which this one must be inserted. Using - adds the new entry at the end (right). For example, the call below adds a Application entry just before the Help menu. win_insert_menu('&Application', '&Help') wwiinn__iinnsseerrtt__mmeennuu__iitteemm((_+_P_u_l_l_d_o_w_n_, _+_L_a_b_e_l_, _+_B_e_f_o_r_e_, _:_G_o_a_l)) Add an item to the named _P_u_l_l_d_o_w_n menu. _L_a_b_e_l and _B_e_f_o_r_e are handled as in win_insert_menu/2, but the label - inserts a _s_e_p_a_r_a_t_o_r. _G_o_a_l is called if the user selects the item. 44..3355 FFiillee SSyysstteemm IInntteerraaccttiioonn aacccceessss__ffiillee((_+_F_i_l_e_, _+_M_o_d_e)) True if _F_i_l_e exists and can be accessed by this prolog process under mode _M_o_d_e. _M_o_d_e is one of the atoms read, write, append, exist, none or execute. _F_i_l_e may also be the name of a directory. Fails silently otherwise. access_file(File, none)simply succeeds without testing anything. If `Mode' is write or append, this predicate also succeeds if the file does not exist and the user has write-access to the directory of the specified location. eexxiissttss__ffiillee((_+_F_i_l_e)) True if _F_i_l_e exists and is a regular file. This does not imply the user has read and/or write permission for the file. ffiillee__ddiirreeccttoorryy__nnaammee((_+_F_i_l_e_, _-_D_i_r_e_c_t_o_r_y)) Extracts the directory-part of _F_i_l_e. The returned _D_i_r_e_c_t_o_r_y name does not end in /. There are two special cases. The directory-name of / is / itself and the directory-name if _F_i_l_e does not contain any / characters is .. ffiillee__bbaassee__nnaammee((_+_F_i_l_e_, _-_B_a_s_e_N_a_m_e)) Extracts the filename part from a path specification. If _F_i_l_e does not contain any directory separators, _F_i_l_e is returned. ssaammee__ffiillee((_+_F_i_l_e_1_, _+_F_i_l_e_2)) True if both filenames refer to the same physical file. That is, if _F_i_l_e_1 and _F_i_l_e_2 are the same string or both names exist and point to the same file (due to hard or symbolic links and/or relative vs. absolute paths). eexxiissttss__ddiirreeccttoorryy((_+_D_i_r_e_c_t_o_r_y)) True if _D_i_r_e_c_t_o_r_y exists and is a directory. This does not imply the user has read, search and or write permission for the directory. ddeelleettee__ffiillee((_+_F_i_l_e)) Remove _F_i_l_e from the file system. rreennaammee__ffiillee((_+_F_i_l_e_1_, _+_F_i_l_e_2)) Rename _F_i_l_e_1 into _F_i_l_e_2. Currently files cannot be moved across devices. ssiizzee__ffiillee((_+_F_i_l_e_, _-_S_i_z_e)) Unify _S_i_z_e with the size of _F_i_l_e in characters. ttiimmee__ffiillee((_+_F_i_l_e_, _-_T_i_m_e)) Unify the last modification time of _F_i_l_e with _T_i_m_e. _T_i_m_e is a floating point number expressing the seconds elapsed since Jan 1, 1970. See also convert_time/[2,8] and get_time/1. aabbssoolluuttee__ffiillee__nnaammee((_+_F_i_l_e_, _-_A_b_s_o_l_u_t_e)) Expand a local file-name into an absolute path. The absolute path is canonised: references to . and .. are deleted. This predicate ensures that expanding a file-name it returns the same absolute path regardless of how the file is addressed. SWI-Prolog uses absolute file names to register source files independent of the current working directory. See also absolute_file_name/3. See also absolute_file_name/3 and expand_file_name/2. aabbssoolluuttee__ffiillee__nnaammee((_+_S_p_e_c_, _+_O_p_t_i_o_n_s_, _-_A_b_s_o_l_u_t_e)) Converts the given file specification into an absolute path. _O_p_t_i_o_n is a list of options to guide the conversion: eexxtteennssiioonnss((_L_i_s_t_O_f_E_x_t_e_n_s_i_o_n_s)) List of file-extensions to try. Default is ''. For each extension, absolute_file_name/3 will first add the extension and then verify the conditions imposed by the other options. If the condition fails, the next extension of the list is tried. Extensions may be specified both as ..ext or plain ext. rreellaattiivvee__ttoo((_+_F_i_l_e_O_r_D_i_r)) Resolve the path relative to the given directory or directory the holding the given file. Without this option, paths are resolved relative to the working directory (see working_directory/2) or, if _S_p_e_c is atomic and absolute_file_name/[2,3] is executed in a directive, it uses the current source-file as reference. aacccceessss((_M_o_d_e)) Imposes the condition access_file(_F_i_l_e, _M_o_d_e). _M_o_d_e is on of read, write, append, exist or none. See also access_file/2. ffiillee__ttyyppee((_T_y_p_e)) Defines extensions. Current mapping: txt implies [''], prolog implies ['.pl', ''], executable implies ['.so', ''], qlf implies ['.qlf', ''] and directory implies ['']. The file-type source is an alias for prolog for compatibility to SICStus Prolog. See also prolog_file_type/2. ffiillee__eerrrroorrss((_f_a_i_l_/_e_r_r_o_r)) If error (default), throw and existence_error exception if the file cannot be found. If fail, stay silent. ssoolluuttiioonnss((_f_i_r_s_t_/_a_l_l)) If first (default), the predicates leaves no choice-point. Otherwise a choice-point will be left and backtracking may yield more solutions. eexxppaanndd((_t_r_u_e_/_f_a_l_s_e)) If true (default is false) and _S_p_e_c is atomic, call expand_file_name/2 followed by member/2 on _S_p_e_c before proceeding. This is a SWI-Prolog extension. The prolog-flag verbose_file_search can be set to true to help debugging Prolog's search for files. Compatibility considerations to common argument-order in ISO as well as SICStus absolute_file_name/3forced us to be flexible here. If the last argument is a list and the 2nd not, the arguments are swapped, making the call absolute_file_name(_+_S_p_e_c_, _-_P_a_t_h_, _+_O_p_t_i_o_n_s) valid as well. iiss__aabbssoolluuttee__ffiillee__nnaammee((_+_F_i_l_e)) True if _F_i_l_e specifies and absolute path-name. On Unix systems, this implies the path starts with a `/'. For Microsoft based systems this implies the path starts with <_l_e_t_t_e_r>:. This predicate is intended to provide platform-independent checking for absolute paths. See also absolute_file_name/2 and prolog_to_os_filename/2. ffiillee__nnaammee__eexxtteennssiioonn((_?_B_a_s_e_, _?_E_x_t_e_n_s_i_o_n_, _?_N_a_m_e)) This predicate is used to add, remove or test filename extensions. The main reason for its introduction is to deal with different filename properties in a portable manner. If the file system is case-insensitive, testing for an extension will be done case-insensitive too. _E_x_t_e_n_s_i_o_n may be specified with or without a leading dot (.). If an _E_x_t_e_n_s_i_o_n is generated, it will not have a leading dot. eexxppaanndd__ffiillee__nnaammee((_+_W_i_l_d_C_a_r_d_, _-_L_i_s_t)) Unify _L_i_s_t with a sorted list of files or directories matching _W_i_l_d_C_a_r_d. The normal Unix wildcard constructs `?', `*', `[...]' and `{...}' are recognised. The interpretation of `{...}' is interpreted slightly different from the C shell (csh(1)). The comma separated argument can be arbitrary patterns, including `{...}' patterns. The empty pattern is legal as well: `\{.pl,\}' matches either `.pl' or the empty string. If the pattern does contains wildcard characters, only existing files and directories are returned. Expanding a `pattern' without wildcard characters returns the argument, regardless on whether or not it exists. Before expanding wildcards, the construct $var is expanded to the value of the environment variable _v_a_r and a possible leading ~ character is expanded to the user's home directory.. pprroolloogg__ttoo__ooss__ffiilleennaammee((_?_P_r_o_l_o_g_P_a_t_h_, _?_O_s_P_a_t_h)) Converts between the internal Prolog pathname conventions and the operating-system pathname conventions. The internal conventions are Unix and this predicates is equivalent to =/2 (unify) on Unix systems. On DOS systems it will change the directory-separator, limit the filename length map dots, except for the last one, onto underscores. rreeaadd__lliinnkk((_+_F_i_l_e_, _-_L_i_n_k_, _-_T_a_r_g_e_t)) If _F_i_l_e points to a symbolic link, unify _L_i_n_k with the value of the link and _T_a_r_g_e_t to the file the link is pointing to. _T_a_r_g_e_t points to a file, directory or non-existing entry in the file system, but never to a link. Fails if _F_i_l_e is not a link. Fails always on systems that do not support symbolic links. ttmmpp__ffiillee((_+_B_a_s_e_, _-_T_m_p_N_a_m_e)) Create a name for a temporary file. _B_a_s_e is an identifier for the category of file. The _T_m_p_N_a_m_e is guaranteed to be unique. If the system halts, it will automatically remove all created temporary files. mmaakkee__ddiirreeccttoorryy((_+_D_i_r_e_c_t_o_r_y)) Create a new directory (folder) on the filesystem. Raises an exception on failure. On Unix systems, the directory is created with default permissions (defined by the process _u_m_a_s_k setting). ddeelleettee__ddiirreeccttoorryy((_+_D_i_r_e_c_t_o_r_y)) Delete directory (folder) from the filesystem. Raises an exception on failure. Please note that in general it will not be possible to delete a non-empty directory. wwoorrkkiinngg__ddiirreeccttoorryy((_-_O_l_d_, _+_N_e_w)) Unify _O_l_d with an absolute path to the current working directory and change working directory to _N_e_w. Use the pattern working_directory(_C_W_D_, _C_W_D) to get the current directory. See also absolute_file_name/2 and chdir/1. Note that the working directory is shared between all threads. cchhddiirr((_+_P_a_t_h)) Compatibility predicate. New code should use working_directory/2. 44..3366 UUsseerr TToopp--lleevveell MMaanniippuullaattiioonn bbrreeaakk Recursively start a new Prolog top level. This Prolog top level has its own stacks, but shares the heap with all break environments and the top level. Debugging is switched off on entering a break and restored on leaving one. The break environment is terminated by typing the system's end-of-file character (control-D). If the -t toplevel command line option is given this goal is started instead of entering the default interactive top level (prolog/0). aabboorrtt Abort the Prolog execution and restart the top level. If the -t toplevel command line options is given this goal is started instead of entering the default interactive top level. There are two implementations of abort/0. The default one uses the exception mechanism (see throw/1), throwing the exception $aborted. The other one uses the C-construct longjmp() to discard the entire environment and rebuild a new one. Using exceptions allows for proper recovery of predicates exploiting exceptions. Rebuilding the environment is safer if the Prolog stacks are corrupt. Therefore the system will use the rebuild-strategy if the abort was generated by an internal consistency check and the exception mechanism otherwise. Prolog can be forced to use the rebuild-strategy setting the prolog flag abort_with_exception to false. hhaalltt Terminate Prolog execution. Open files are closed and if the command line option -tty is not active the terminal status (see Unix stty(1)) is restored. Hooks may be registered both in Prolog and in foreign code. Prolog hooks are registered using at_halt/1. halt/0 is equivalent to halt(0). hhaalltt((_+_S_t_a_t_u_s)) Terminate Prolog execution with given status. Status is an integer. See also halt/0. pprroolloogg This goal starts the default interactive top level. Queries are read from the stream user_input. See also the history prolog_flag (current_prolog_flag/2). The prolog/0 predicate is terminated (succeeds) by typing the end-of-file character (On most systems control-D). The following two hooks allow for expanding queries and handling the result of a query. These hooks are used by the top-level variable expansion mechanism described in section 2.8. eexxppaanndd__qquueerryy((_+_Q_u_e_r_y_, _-_E_x_p_a_n_d_e_d_, _+_B_i_n_d_i_n_g_s_, _-_E_x_p_a_n_d_e_d_B_i_n_d_i_n_g_s)) Hook in module user, normally not defined. _Q_u_e_r_y and _B_i_n_d_i_n_g_s represents the query read from the user and the names of the free variables as obtained using read_term/3. If this predicate succeeds, it should bind _E_x_p_a_n_d_e_d and _E_x_p_a_n_d_e_d_B_i_n_d_i_n_g_s to the query and bindings to be executed by the top-level. This predicate is used by the top-level (prolog/0). See also expand_answer/2 and term_expansion/2. eexxppaanndd__aannsswweerr((_+_B_i_n_d_i_n_g_s_, _-_E_x_p_a_n_d_e_d_B_i_n_d_i_n_g_s)) Hook in module user, normally not defined. Expand the result of a successfully executed top-level query. _B_i_n_d_i_n_g_s is the query <_N_a_m_e>= <_V_a_l_u_e>binding list from the query. _E_x_p_a_n_d_e_d_B_i_n_d_i_n_g_s must be unified with the bindings the top-level should print. 44..3377 CCrreeaattiinngg aa PPrroottooccooll ooff tthhee UUsseerr IInntteerraaccttiioonn SWI-Prolog offers the possibility to log the interaction with the user on a file. All Prolog interaction, including warnings and tracer output, are written on the protocol file. pprroottooccooll((_+_F_i_l_e)) Start protocolling on file _F_i_l_e. If there is already a protocol file open then close it first. If _F_i_l_e exists it is truncated. pprroottooccoollaa((_+_F_i_l_e)) Equivalent to protocol/1, but does not truncate the _F_i_l_e if it exists. nnoopprroottooccooll Stop making a protocol of the user interaction. Pending output is flushed on the file. pprroottooccoolllliinngg((_-_F_i_l_e)) True if a protocol was started with protocol/1 or protocola/1 and unifies _F_i_l_e with the current protocol output file. 44..3388 DDeebbuuggggiinngg aanndd TTrraacciinngg PPrrooggrraammss This section is a reference to the debugger interaction predicates. A more use-oriented overview of the debugger is in section 2.9. If you have installed XPCE, you can use the graphical front-end of the tracer. This front-end is installed using the predicate guitracer/0. ttrraaccee Start the tracer. trace/0 itself cannot be seen in the tracer. Note that the Prolog top-level treats trace/0 special; it means `trace the next goal'. ttrraacciinngg True if the tracer is currently switched on. tracing/0 itself can not be seen in the tracer. nnoottrraaccee Stop the tracer. notrace/0 itself cannot be seen in the tracer. gguuiittrraacceerr Installs hooks (see prolog_trace_interception/4) into the system that redirects tracing information to a GUI front-end providing structured access to variable-bindings, graphical overview of the stack and highlighting of relevant source-code. nnoogguuiittrraacceerr Reverts back to the textual tracer. ttrraaccee((_+_P_r_e_d)) Equivalent to trace(Pred, +all). ttrraaccee((_+_P_r_e_d_, _+_P_o_r_t_s)) Put a trace-point on all predicates satisfying the predicate specification _P_r_e_d. _P_o_r_t_s is a list of port names (call, redo, exit, fail). The atom all refers to all ports. If the port is preceded by a - sign the trace-point is cleared for the port. If it is preceded by a + the trace-point is set. The predicate trace/2 activates debug mode (see debug/0). Each time a port (of the 4-port model) is passed that has a trace-point set the goal is printed as with trace/0. Unlike trace/0 however, the execution is continued without asking for further information. Examples: ?- trace(hello). Trace all ports of hello with any arity in any module. ?- trace(foo/2, +fail). Trace failures of foo/2 in any module. ?- trace(bar/1, -all). Stop tracing bar/1. The predicate debugging/0 shows all currently defined trace-points. nnoottrraaccee((_+_G_o_a_l)) Call _G_o_a_l, but suspend the debugger while _G_o_a_l is executing. The current implementation cuts the choice-points of _G_o_a_l after successful completion. See once/1. Later implementations may have the same semantics as call/1. ddeebbuugg Start debugger. In debug mode, Prolog stops at spy- and trace-points, disables tail-recursion optimisation and aggressive destruction of choice-points to make debugging information accessible. Implemented by the Prolog flag debug. nnooddeebbuugg Stop debugger. Implemented by the prolog flag debug. See also debug/0. ddeebbuuggggiinngg Print debug status and spy points on current output stream. See also the prolog flag debug. ssppyy((_+_P_r_e_d)) Put a spy point on all predicates meeting the predicate specification _P_r_e_d. See section 4.4. nnoossppyy((_+_P_r_e_d)) Remove spy point from all predicates meeting the predicate specification _P_r_e_d. nnoossppyyaallll Remove all spy points from the entire program. lleeaasshh((_?_P_o_r_t_s)) Set/query leashing (ports which allow for user interaction). _P_o_r_t_s is one of _+_N_a_m_e, _-_N_a_m_e, _?_N_a_m_e or a list of these. _+_N_a_m_e enables leashing on that port, _-_N_a_m_e disables it and _?_N_a_m_e succeeds or fails according to the current setting. Recognised ports are: call, redo, exit, fail and unify. The special shorthand all refers to all ports, full refers to all ports except for the unify port (default). half refers to the call, redo and fail port. vviissiibbllee((_+_P_o_r_t_s)) Set the ports shown by the debugger. See leash/1 for a description of the port specification. Default is full. uunnkknnoowwnn((_-_O_l_d_, _+_N_e_w)) Edinburgh-prolog compatibility predicate, interfacing to the ISO prolog flag unknown. Values are trace (meaning error) and fail. If the unknown flag is set to warning, unknown/2 reports the value as trace. ssttyyllee__cchheecckk((_+_S_p_e_c)) Set style checking options. _S_p_e_c is either +<_o_p_t_i_o_n>, -<_o_p_t_i_o_n>, ?(<_o_p_t_i_o_n>) or a list of such options. +<_o_p_t_i_o_n> sets a style checking option, -<_o_p_t_i_o_n> clears it and ?(<_o_p_t_i_o_n>) succeeds or fails according to the current setting. consult/1 and derivatives resets the style checking options to their value before loading the file. If---for example---a file containing long atoms should be loaded the user can start the file with: :- style_check(-atom). Currently available options are: ____________________________________________________________________ |_Name__________|Default_|Description_______________________________||singletonon| || | read_clause/1 (used by consult/1) warns | || | on variables only appearing once in a | || | term (clause) which have a name not | || ||atom | on |starting with an underscore. || || | | |read/1 and derivatives will produce an | | | |error message on quoted atoms or strings | | | |longer than 5 lines. | | dollar | off |Accept dollar as a lower case character, | | | |thus avoiding the need for quoting atoms | | | |with dollar signs. System maintenance | | | |use only. | | discontiguous | on |Warn if the clauses for a predicate are | | | |not together in the same source file. | | string | off |Backward compatibility. See | | | |the prolog-flag double_quotes | | | |(current_prolog_flag/2). | | charset | off |Warn on atoms and variables holding non- | | | |ASCII characters that are not quoted. | |_______________|________|See_also_section_2.15.1.1.________________| 44..3399 OObbttaaiinniinngg RRuunnttiimmee SSttaattiissttiiccss ssttaattiissttiiccss((_+_K_e_y_, _-_V_a_l_u_e)) Unify system statistics determined by _K_e_y with _V_a_l_u_e. The possible keys are given in the table 4.2. The last part of the table contains keys for compatibility to other Prolog implementations (Quintus) for improved portability. Note that the ISO standard does not define methods to collect system statistics. _________________________________________________________________________ | agc |Number of atom garbage-collections performed | | agc_gained N|umber of atoms removed | | agc_time T|ime spent in atom garbage-collections | | cputime |(User) cpu time since Prolog was started in| | |seconds | | inferences |Total number of passes via the call and redo| | |ports since Prolog was started. | | heap |Estimated total size of the heap (see| | |section 2.18.1.1) | | heapused |Bytes heap in use by Prolog. | | heaplimit |Maximum size of the heap (see sec-| | |tion 2.18.1.1) | | local |Allocated size of the local stack in bytes. | | localused |Number of bytes in use on the local stack. | | locallimit |Size to which the local stack is allowed to| | |grow | | global |Allocated size of the global stack in bytes. | | globalused |Number of bytes in use on the global stack. | | globallimit |Size to which the global stack is allowed to| | |grow | | trail |Allocated size of the trail stack in bytes. | | trailused |Number of bytes in use on the trail stack. | | traillimit |Size to which the trail stack is allowed to| | |grow | | atoms |Total number of defined atoms. | | functors |Total number of defined name/arity pairs. | | predicates |Total number of predicate definitions. | | modules |Total number of module definitions. | | codes |Total amount of byte codes in all clauses. | | threads |MT-version: number of active threads | | threads_created M|T-version: number of created threads | | thread_cputime M|T-version: seconds CPU time used by finished| | t|hreads. Supported on Windows-NT and later,| | L|inux and possibly a few more. Verify it| |________________________g|ives_plausible_results_before_using.__________| |___________________________Compatibility_keys___________________________ | | runtime |[ CPU time, CPU time since last ]| | |(milliseconds) | | system_time [|System CPU time, System CPU time since last | | ]|(milliseconds) | | real_time [|Wall time, Wall time since last ] (seconds | | s|ince 1970) | | memory |[ Total unshared data, free memory ] (Uses| | |getrusage() if available, otherwise incomplete| | |own statistics. | | stacks |[ global use, local use ] | | program |[ heap, 0 ] | | global_stack [|global use, global free ] | | local_stack [|local use, local free ] | | trail |[ trail use, 0 ] | | garbage_collection [|number of GC, bytes gained, time spent ] | | stack_shifts [|global shifts, local shifts, time spent ] | | (|fails if no shifter in this version) | | atoms |[ number, memory use, 0 ] | | atom_garbage_collection[|number of AGC, bytes gained, time spent ] | |_core___________________|Same_as_memory_________________________________| Table 4.2: Keys for statistics/2 ssttaattiissttiiccss Display a table of system statistics on the current output stream. ttiimmee((_+_G_o_a_l)) Execute _G_o_a_l just like once/1 (i.e., leaving no choice points), but print used time, number of logical inferences and the average number of _l_i_p_s (logical inferences per second). Note that SWI-Prolog counts the actual executed number of inferences rather than the number of passes through the call- and redo ports of the theoretical 4-port model. 44..4400 EExxeeccuuttiioonn pprrooffiilliinngg This section describes the hierarchical execution profiler introduced in SWI-Prolog 5.1.10. This profiler is based on ideas from gprof described in [Graham _e_t _a_l_., 1982]. The profiler consists of two parts: the information-gathering is built into the kernel, and a presentation component which is defined in the statistics library. The latter can be hooked, which is used by the XPCE module swi/pce_profile to provide an interactive graphical representation of results. 44..4400..11 PPrrooffiilliinngg pprreeddiiccaatteess Currently, the interface is kept compatible with the old profiler. As experience grows, it is likely that the old interface is replaced with one that better reflects the new capabilities. Feel free to examine the internal interfaces and report useful application thereof. pprrooffiillee((_:_G_o_a_l)) Execute _G_o_a_l just like time/1, collecting profiling statistics and call show_profile(_p_l_a_i_n_, _2_5). With XPCE installed this opens a graphical interface to the collected profiling data. pprrooffiillee((_:_G_o_a_l_, _+_S_t_y_l_e_, _+_N_u_m_b_e_r)) Execute _G_o_a_l just like time/1. Collect profiling statistics and show the top _N_u_m_b_e_r procedures on the current output stream (see show_profile/1) using _S_t_y_l_e. The results are kept in the database until reset_profiler/0or profile/3 is called and can be displayed again with show_profile/1. The profile/1 predicate is a backward compatibility interface to profile/1. The other predicates in this section are low-level predicates for special cases. sshhooww__pprrooffiillee((_+_S_t_y_l_e_, _+_N_u_m_b_e_r)) Show the collected results of the profiler. It shows the top _N_u_m_b_e_r predicates according the percentage cpu-time used. If _S_t_y_l_e is plain the time spent in the predicates itself is displayed. If _S_t_y_l_e is cumulative the time spent in its siblings (callees) is added to the predicate. This predicate first calls prolog:show_profile_hook/2. If XPCE is loaded this hook is used to activate a GUI interface to visualise the profile results. sshhooww__pprrooffiillee((_+_N_u_m_b_e_r)) Compatibility. Same as show_profile(_p_l_a_i_n_, _N_u_m_b_e_r). pprrooffiilleerr((_-_O_l_d_, _+_N_e_w)) Query or change the status of the profiler. The status is a boolean (true or false) stating whether or not the profiler is collecting data. It can be used to enable or disable profiling certain parts of the program. rreesseett__pprrooffiilleerr Switches the profiler to false and clears all collected statistics. nnoopprrooffiillee((_+_N_a_m_e_/_+_A_r_i_t_y_, _._._.)) Declares the predicate _N_a_m_e/_A_r_i_t_y to be invisible to the profiler. The time spend in the named predicate is added to the caller and the callees are linked directly to the caller. This is particularly useful for simple meta-predicates such as call/1, ignore/1, catch/3, etc. 44..4400..22 VViissuuaalliizziinngg pprrooffiilliinngg ddaattaa Browsing the annotated call-tree as described in section 4.40.3 itself is not very attractive. Therefore, the results are combined per predicate, collecting all _c_a_l_l_e_r_s and and _c_a_l_l_e_e_s as well as the propagation of time and activations in both directions. Figure ???? illustrates this. The central yellowish line is the `current' predicate with counts for time spent in the predicate (`Self'), time spent in its children (`Siblings'), activations through the call and redo ports. Above that are the _c_a_l_l_e_r_s. Here, the two time fields indicate how much time is spent serving each of the callers. The columns sum to the time in the yellowish line. The caller <_r_e_c_u_r_s_i_v_e> are the number of recursive calls. Below the yellowish lines are the callees, with the time spent in the callee itself for serving the current predicate and the time spent in the callees of the callee ('Siblings'), so the whole time-block adds up to the `Siblings' field of the current predicate. The `Access' fields show how many times the current predicate accesses each of the callees. The predicates have a menu that allows changing the view of the detail window to the given caller or callee, showing the documentation (if it is a built-in) and/or jumping to the source. The statistics shown in the report-field of figure ???? show the following information: o _s_a_m_p_l_e_s Number of times the call-tree was sampled for collecting time statistics. On most hardware the resolution of SIGPROF is 1/100 second. This number must be sufficiently large to get reliable timing figures. The Time menu allows viewing time as samples, relative time or absolute time. o _s_e_c Total user CPU time with the profiler active. o _p_r_e_d_i_c_a_t_e_s Total count of predicates that have been called at least one time during the profile. o _n_o_d_e_s Number of nodes in the call-tree. o _d_i_s_t_o_r_t_i_o_n How much of the time is spend building the call-tree as a percentage of the total execution time. Timing samples while the profiler is building the call-tree are not added to the call-tree. 44..4400..33 IInnffoorrmmaattiioonn ggaatthheerriinngg While the program executes under the profiler, the system builds a _d_y_n_a_m_i_c call-tree. It does this using three hooks from the kernel: one that starts a new goal (_p_r_o_f_C_a_l_l), one the tells the system which goal is resumed after an _e_x_i_t (_p_r_o_f_E_x_i_t) and one that tells the system which goal is resumed after a _f_a_i_l (i.e. which goal is used to _r_e_t_r_y (_p_r_o_f_R_e_d_o)). The profCall() function finds or creates the subnode for the argument predicate below the current node, increments the call-count of this link and returns the sub-node which is recorded in the Prolog stack-frame. Choice-points are marked with the current profiling node. profExit() and profRedo() pass the profiling node where execution resumes. Just using the above algorithm would create a much too big tree due to recursion. For this reason the system performs detection of recursion. In the simplest case, recursive procedures increment the `recursive' count on the current node. Mutual recursion however is not easily detected. For example, call/1 can call a predicate that uses call/1 itself. This can be viewed as a recursive invocation, but this is generally not desirable. Recursion is currently assumed if the same predicate _w_i_t_h _t_h_e _s_a_m_e _p_a_r_e_n_t appears higher in the call-graph. Early experience with a some arbitrary non-trivial programs are promising. The last part of the profiler collects statistics on the CPU-time used in each node. On systems providing setitimer() with SIGPROF, it `ticks' the current node of the call-tree each time the timer fires. On Windows a MM-timer in a separate thread checks 100 times per second how much time is spent in the profiled thread and adds this to the current node. See section 4.40.3.1 for details. 44..4400..33..11 PPrrooffiilliinngg iinn tthhee WWiinnddoowwss IImmpplleemmeennttaattiioonn Profiling in the Windows version is similar but as profiling is a statistical process it is good to be aware of the implementation for proper interpretation of the results. Windows does not provide timers that fire asynchronously, frequent and proportional to the CPU time used by the process. Windows does provide multi-media timers that can run at high frequency. Such timers however run in a separate thread of execution and they are fired on the wall-clock rather than the amount of CPU time used. The profiler installs such a timer running, for saving CPU time, rather inaccurately at about 100 Hz. Each time it is fired, it determines the milliseconds CPU time used by Prolog since the last time it was fired. If this value is non-zero, active predicates are incremented with this value. 44..4411 MMeemmoorryy MMaannaaggeemmeenntt Note: limit_stack/2 and trim_stacks/0 have no effect on machines that do not offer dynamic stack expansion. On these machines these predicates simply succeed to improve portability. ggaarrbbaaggee__ccoolllleecctt Invoke the global- and trail stack garbage collector. Normally the garbage collector is invoked automatically if necessary. Explicit invocation might be useful to reduce the need for garbage collections in time critical segments of the code. After the garbage collection trim_stacks/0 is invoked to release the collected memory resources. ggaarrbbaaggee__ccoolllleecctt__aattoommss Reclaim unused atoms. Normally invoked after agc_margin (a prolog flag) atoms have been created. On multi-threaded versions the actual collection is delayed until there there are no threads performing normal garbage collection. In this case garbage_collect_atoms/0 returns immediately. Note this implies there is no guarantee it will _e_v_e_r happen as there may always be threads performing garbage collection. lliimmiitt__ssttaacckk((_+_K_e_y_, _+_K_b_y_t_e_s)) Limit one of the stack areas to the specified value. _K_e_y is one of local, global or trail. The limit is an integer, expressing the desired stack limit in K bytes. If the desired limit is smaller than the currently used value, the limit is set to the nearest legal value above the currently used value. If the desired value is larger than the maximum, the maximum is taken. Finally, if the desired value is either 0 or the atom unlimited the limit is set to its maximum. The maximum and initial limit is determined by the command line options -L, -G and -T. ttrriimm__ssttaacckkss Release stack memory resources that are not in use at this moment, returning them to the operating system. Trim stack is a relatively cheap call. It can be used to release memory resources in a backtracking loop, where the iterations require typically seconds of execution time and very different, potentially large, amounts of stack space. Such a loop should be written as follows: loop :- generator, trim_stacks, potentially_expensive_operation, stop_condition, !. The prolog top level loop is written this way, reclaiming memory resources after every user query. ssttaacckk__ppaarraammeetteerr((_+_S_t_a_c_k_, _+_K_e_y_, _-_O_l_d_, _+_N_e_w)) Query/set a parameter for the runtime stacks. _S_t_a_c_k is one of local, global, trail or argument. The table below describes the _K_e_y/_V_a_l_u_e pairs. Old is first unified with the current value. ____________________________________________________________ | limit |Maximum size of the stack in bytes | |_min_free_|Minimum_free_space_at_entry_of_foreign_predicate_| This predicate is currently only available on versions that use the stack-shifter to enlarge the runtime stacks when necessary. It's definition is subject to change. 44..4422 WWiinnddoowwss DDDDEE iinntteerrffaaccee The predicates in this section deal with MS-Windows `Dynamic Data Exchange' or DDE protocol. A Windows DDE conversation is a form of interprocess communication based on sending reserved window-events between the communicating processes. See also section 9.4 for loading Windows DLL's into SWI-Prolog. 44..4422..11 DDDDEE cclliieenntt iinntteerrffaaccee The DDE client interface allows Prolog to talk to DDE server programs. We will demonstrate the use of the DDE interface using the Windows PROGMAN (Program Manager) application: 1 ?- open_dde_conversation(progman, progman, C). C = 0 2 ?- dde_request(0, groups, X) --> Unifies X with description of groups 3 ?- dde_execute(0, '[CreateGroup("DDE Demo")]'). Yes 4 ?- close_dde_conversation(0). Yes For details on interacting with progman, use the SDK online manual section on the Shell DDE interface. See also the Prolog library(progman), which may be used to write simple Windows setup scripts in Prolog. ooppeenn__ddddee__ccoonnvveerrssaattiioonn((_+_S_e_r_v_i_c_e_, _+_T_o_p_i_c_, _-_H_a_n_d_l_e)) Open a conversation with a server supporting the given service name and topic (atoms). If successful, _H_a_n_d_l_e may be used to send transactions to the server. If no willing server is found this predicate fails silently. cclloossee__ddddee__ccoonnvveerrssaattiioonn((_+_H_a_n_d_l_e)) Close the conversation associated with _H_a_n_d_l_e. All opened conversations should be closed when they're no longer needed, although the system will close any that remain open on process termination. ddddee__rreeqquueesstt((_+_H_a_n_d_l_e_, _+_I_t_e_m_, _-_V_a_l_u_e)) Request a value from the server. _I_t_e_m is an atom that identifies the requested data, and _V_a_l_u_e will be a string (CF_TEXT data in DDE parlance) representing that data, if the request is successful. If unsuccessful, _V_a_l_u_e will be unified with a term of form error(<_R_e_a_s_o_n>), identifying the problem. This call uses SWI-Prolog string objects to return the value rather then atoms to reduce the load on the atom-space. See section 4.23 for a discussion on this data type. ddddee__eexxeeccuuttee((_+_H_a_n_d_l_e_, _+_C_o_m_m_a_n_d)) Request the DDE server to execute the given command-string. Succeeds if the command could be executed and fails with error message otherwise. ddddee__ppookkee((_+_H_a_n_d_l_e_, _+_I_t_e_m_, _+_C_o_m_m_a_n_d)) Issue a POKE command to the server on the specified _I_t_e_m. Command is passed as data of type CF_TEXT. 44..4422..22 DDDDEE sseerrvveerr mmooddee The (autoload) library(dde) defines primitives to realise simple DDE server applications in SWI-Prolog. These features are provided as of version 2.0.6 and should be regarded prototypes. The C-part of the DDE server can handle some more primitives, so if you need features not provided by this interface, please study library(dde). ddddee__rreeggiisstteerr__sseerrvviiccee((_+_T_e_m_p_l_a_t_e_, _+_G_o_a_l)) Register a server to handle DDE request or DDE execute requests from other applications. To register a service for a DDE request, _T_e_m_p_l_a_t_e is of the form: +Service(+Topic, +Item, +Value) _S_e_r_v_i_c_e is the name of the DDE service provided (like progman in the client example above). _T_o_p_i_c is either an atom, indicating _G_o_a_l only handles requests on this topic or a variable that also appears in _G_o_a_l. _I_t_e_m and _V_a_l_u_e are variables that also appear in _G_o_a_l. _I_t_e_m represents the request data as a Prolog atom. The example below registers the Prolog current_prolog_flag/2 predicate to be accessible from other applications. The request may be given from the same Prolog as well as from another application. ?- dde_register_service(prolog(current_prolog_flag, F, V), current_prolog_flag(F, V)). ?- open_dde_conversation(prolog, current_prolog_flag, Handle), dde_request(Handle, home, Home), close_dde_conversation(Handle). Home = '/usr/local/lib/pl-2.0.6/' Handling DDE execute requests is very similar. In this case the template is of the form: +Service(+Topic, +Item) Passing a _V_a_l_u_e argument is not needed as execute requests either succeed or fail. If _G_o_a_l fails, a `not processed' is passed back to the caller of the DDE request. ddddee__uunnrreeggiisstteerr__sseerrvviiccee((_+_S_e_r_v_i_c_e)) Stop responding to _S_e_r_v_i_c_e. If Prolog is halted, it will automatically call this on all open services. ddddee__ccuurrrreenntt__sseerrvviiccee((_-_S_e_r_v_i_c_e_, _-_T_o_p_i_c)) Find currently registered services and the topics served on them. ddddee__ccuurrrreenntt__ccoonnnneeccttiioonn((_-_S_e_r_v_i_c_e_, _-_T_o_p_i_c)) Find currently open conversations. 44..4433 MMiisscceellllaanneeoouuss ddwwiimm__mmaattcchh((_+_A_t_o_m_1_, _+_A_t_o_m_2)) True if _A_t_o_m_1 matches _A_t_o_m_2 in `Do What I Mean' sense. Both _A_t_o_m_1 and _A_t_o_m_2 may also be integers or floats. The two atoms match if: o They are identical o They differ by one character (spy spu) o One character is inserted/deleted (debug deug) o Two characters are transposed (trace tarce) o `Sub-words' are glued differently (existsfile existsFile exists_file) o Two adjacent sub words are transposed (existsFile fileExists) ddwwiimm__mmaattcchh((_+_A_t_o_m_1_, _+_A_t_o_m_2_, _-_D_i_f_f_e_r_e_n_c_e)) Equivalent to dwim_match/2, but unifies _D_i_f_f_e_r_e_n_c_e with an atom identifying the the difference between _A_t_o_m_1 and _A_t_o_m_2. The return values are (in the same order as above): equal, mismatched_char, inserted_char, transposed_char, separated and transposed_word. wwiillddccaarrdd__mmaattcchh((_+_P_a_t_t_e_r_n_, _+_S_t_r_i_n_g)) True if _S_t_r_i_n_g matches the wildcard pattern _P_a_t_t_e_r_n. _P_a_t_t_e_r_n is very similar the the Unix csh pattern matcher. The patterns are given below: ? Matches one arbitrary character. * Matches any number of arbitrary characters. [...] Matches one of the characters specified between the brackets. <_c_h_a_r_1>-<_c_h_a_r_2>indicates a range. {...} Matches any of the patterns of the comma separated list between the braces. Example: ?- wildcard_match('[a-z]*.{pro,pl}[%~]', 'a_hello.pl%'). Yes sslleeeepp((_+_T_i_m_e)) Suspend execution _T_i_m_e seconds. _T_i_m_e is either a floating point number or an integer. Granularity is dependent on the system's timer granularity. A negative time causes the timer to return immediately. On most non-realtime operating systems we can only ensure execution is suspended for aatt lleeaasstt _T_i_m_e seconds. On Unix systems the sleep/1 predicate is realised ---in order of preference--- by nanosleep(), usleep(), select() if the time is below 1 minute or sleep(). On Windows systems Sleep() is used. CChhaapptteerr 55.. UUSSIINNGG MMOODDUULLEESS 55..11 WWhhyy UUssiinngg MMoodduulleess?? In traditional Prolog systems the predicate space was flat. This approach is not very suitable for the development of large applications, certainly not if these applications are developed by more than one programmer. In many cases, the definition of a Prolog predicate requires sub-predicates that are intended only to complete the definition of the main predicate. With a flat and global predicate space these support predicates will be visible from the entire program. For this reason, it is desirable that each source module has its own predicate space. A module consists of a declaration for its name, its _p_u_b_l_i_c _p_r_e_d_i_c_a_t_e_s and the predicates themselves. This approach allow the programmer to use short (local) names for support predicates without worrying about name conflicts with the support predicates of other modules. The module declaration also makes explicit which predicates are meant for public usage and which for private purposes. Finally, using the module information, cross reference programs can indicate possible problems much better. 55..22 NNaammee--bbaasseedd vveerrssuuss PPrreeddiiccaattee--bbaasseedd MMoodduulleess Two approaches to realize a module system are commonly used in Prolog and other languages. The first one is the _n_a_m_e _b_a_s_e_d module system. In these systems, each atom read is tagged (normally prefixed) with the module name, with the exception of those atoms that are defined _p_u_b_l_i_c. In the second approach, each module actually implements its own predicate space. A critical problem with using modules in Prolog is introduced by the meta-predicates that transform between Prolog data and Prolog predicates. Consider the case where we write: :- module(extend, [add_extension/3]). add_extension(Extension, Plain, Extended) :- maplist(extend_atom(Extension), Plain, Extended). extend_atom(Extension, Plain, Extended) :- atom_concat(Plain, Extension, Extended). In this case we would like maplist to call extend_atom/3 in the module extend. A name based module system will do this correctly. It will tag the atom extend_atom with the module and maplist will use this to construct the tagged term extend_atom/3. A name based module however, will not only tag the atoms that will eventually be used to refer to a predicate, but aallll atoms that are not declared public. So, with a name based module system also data is local to the module. This introduces another serious problem: :- module(action, [action/3]). action(Object, sleep, Arg) :- .... action(Object, awake, Arg) :- .... :- module(process, [awake_process/2]). awake_process(Process, Arg) :- action(Process, awake, Arg). This code uses a simple object-oriented implementation technique were atoms are used as method selectors. Using a name based module system, this code will not work, unless we declare the selectors public atoms in all modules that use them. Predicate based module systems do not require particular precautions for handling this case. It appears we have to choose either to have local data, or to have trouble with meta-predicates. Probably it is best to choose for the predicate based approach as novice users will not often write generic meta-predicates that have to be used across multiple modules, but are likely to write programs that pass data around across modules. Experienced Prolog programmers should be able to deal with the complexities of meta-predicates in a predicate based module system. 55..33 DDeeffiinniinngg aa MMoodduullee Modules normally are created by loading a _m_o_d_u_l_e _f_i_l_e. A module file is a file holding a module/2 directive as its first term. The module/2 directive declares the name and the public (i.e., externally visible) predicates of the module. The rest of the file is loaded into the module. Below is an example of a module file, defining reverse/2. :- module(reverse, [reverse/2]). reverse(List1, List2) :- rev(List1, [], List2). rev([], List, List). rev([Head|List1], List2, List3) :- rev(List1, [Head|List2], List3). 55..44 IImmppoorrttiinngg PPrreeddiiccaatteess iinnttoo aa MMoodduullee As explained before, in the predicate based approach adapted by SWI-Prolog, each module has its own predicate space. In SWI-Prolog, a module initially is completely empty. Predicates can be added to a module by loading a module file as demonstrated in the previous section, using assert or by _i_m_p_o_r_t_i_n_g them from another module. Two mechanisms for importing predicates explicitly from another module exist. The use_module/[1,2] predicates load a module file and import (part of the) public predicates of the file. The import/1 predicate imports any predicate from any module. uussee__mmoodduullee((_+_F_i_l_e)) Load the file(s) specified with _F_i_l_e just like ensure_loaded/1. The files should all be module files. All exported predicates from the loaded files are imported into the context module. This predicate is equivalent to ensure_loaded/1, except that it raises an error if _F_i_l_e is not a module file. uussee__mmoodduullee((_+_F_i_l_e_, _+_I_m_p_o_r_t_L_i_s_t)) Load the file specified with _F_i_l_e (only one file is accepted). _F_i_l_e should be a module file. _I_m_p_o_r_t_L_i_s_t is a list of name/arity pairs specifying the predicates that should be imported from the loaded module. If a predicate is specified that is not exported from the loaded module a warning will be printed. The predicate will nevertheless be imported to simplify debugging. iimmppoorrtt((_+_H_e_a_d)) Import predicate _H_e_a_d into the current context module. _H_e_a_d should specify the source module using the <_m_o_d_u_l_e>:<_t_e_r_m>construct. Note that predicates are normally imported using one of the directives use_module/[1,2]. import/1 is meant for handling imports into dynamically created modules. It would be rather inconvenient to have to import each predicate referred to by the module, including the system predicates. For this reason each module is assigned a _d_e_f_a_u_l_t _m_o_d_u_l_e. All predicates in the default module are available without extra declarations. Their definition however can be overruled in the local module. This schedule is implemented by the exception handling mechanism of SWI-Prolog: if an undefined predicate exception is raised for a predicate in some module, the exception handler first tries to import the predicate from one of the module's _i_m_p_o_r_t _m_o_d_u_l_e_s. On success, normal execution is resumed. 55..44..11 RReesseerrvveedd MMoodduulleess SWI-Prolog contains two special modules. The first one is the module system. This module contains all built-in predicates described in this manual. Module system has no default module assigned to it. The second special module is the module user. This module forms the initial working space of the user. Initially it is empty. The import module of module user is system, making all built-in predicate definitions available as defaults. Built-in predicates thus can be overruled by defining them in module user before they are used. All other modules import from the module user. This implies they can use all predicates imported into user without explicitly importing them. 55..55 UUssiinngg tthhee MMoodduullee SSyysstteemm The current structure of the module system has been designed with some specific organisations for large programs in mind. Many large programs define a basic library layer on top of which the actual program itself is defined. The module user, acting as the default module for all other modules of the program can be used to distribute these definitions over all program module without introducing the need to import this common layer each time explicitly. It can also be used to redefine built-in predicates if this is required to maintain compatibility to some other Prolog implementation. Typically, the loadfile of a large application looks like this: :- use_module(compatibility). % load XYZ prolog compatibility :- use_module( % load generic parts [ error % errors and warnings , goodies % general goodies (library extensions) , debug % application specific debugging , virtual_machine % virtual machine of application , ... % more generic stuff ]). :- ensure_loaded( [ ... % the application itself ]). The `use_module' declarations will import the public predicates from the generic modules into the user module. The `ensure_loaded' directive loads the modules that constitute the actual application. It is assumed these modules import predicates from each other using use_module/[1,2] as far as necessary. In combination with the object-oriented schema described below it is possible to define a neat modular architecture. The generic code defines general utilities and the message passing predicates (invoke/3 in the example below). The application modules define classes that communicate using the message passing predicates. 55..55..11 OObbjjeecctt OOrriieenntteedd PPrrooggrraammmmiinngg Another typical way to use the module system is for defining classes within an object oriented paradigm. The class structure and the methods of a class can be defined in a module and the explicit module-boundary overruling describes in section 5.6.2 can by used by the message passing code to invoke the behaviour. An outline of this mechanism is given below. % Define class point :- module(point, []). % class point, no exports % name type, default access % value variable(x, integer, 0, both). variable(y, integer, 0, both). % method name predicate name arguments behaviour(mirror, mirror, []). mirror(P) :- fetch(P, x, X), fetch(P, y, Y), store(P, y, X), store(P, x, Y). The predicates fetch/3 and store/3 are predicates that change instance variables of instances. The figure below indicates how message passing can easily be implemented: % invoke(+Instance, +Selector, ?ArgumentList) % send a message to an instance invoke(I, S, Args) :- class_of_instance(I, Class), Class:behaviour(S, P, ArgCheck), !, convert_arguments(ArgCheck, Args, ConvArgs), Goal =.. [P|ConvArgs], Class:Goal. The construct <_M_o_d_u_l_e>:<_G_o_a_l> explicitly calls _G_o_a_l in module _M_o_d_u_l_e. It is discussed in more detail in section 5.6. 55..66 MMeettaa--PPrreeddiiccaatteess iinn MMoodduulleess As indicated in the introduction, the problem with a predicate based module system lies in the difficulty to find the correct predicate from a Prolog term. The predicate `solution(Solution)' can exist in more than one module, but `assert(solution(4))' in some module is supposed to refer to the correct version of solution/1. Various approaches are possible to solve this problem. One is to add an extra argument to all predicates (e.g. `assert(Module, Term)'). Another is to tag the term somehow to indicate which module is desired (e.g. `assert(Module:Term)'). Both approaches are not very attractive as they make the user responsible for choosing the correct module, inviting unclear programming by asserting in other modules. The predicate assert/1 is supposed to assert in the module it is called from and should do so without being told explicitly. For this reason, the notion _c_o_n_t_e_x_t _m_o_d_u_l_e has been introduced. 55..66..11 DDeeffiinniittiioonn aanndd CCoonntteexxtt MMoodduullee Each predicate of the program is assigned a module, called its _d_e_f_i_n_i_t_i_o_n _m_o_d_u_l_e. The definition module of a predicate is always the module in which the predicate was originally defined. Each active goal in the Prolog system has a _c_o_n_t_e_x_t _m_o_d_u_l_e assigned to it. The context module is used to find predicates from a Prolog term. By default, this module is the definition module of the predicate running the goal. For meta-predicates however, this is the context module of the goal that invoked them. We call this _m_o_d_u_l_e___t_r_a_n_s_p_a_r_e_n_t in SWI-Prolog. In the `using maplist' example above, the predicate maplist/3 is declared module_transparent. This implies the context module remains extend, the context module of add_extension/3. This way maplist/3 can decide to call extend_atom in module extend rather than in its own definition module. All built-in predicates that refer to predicates via a Prolog term are declared module_transparent. Below is the code defining maplist. :- module(maplist, maplist/3). :- module_transparent maplist/3. % maplist(+Goal, +List1, ?List2) % True if Goal can successfully be applied to all succes- sive pairs % of elements of List1 and List2. maplist(_, [], []). maplist(Goal, [Elem1|Tail1], [Elem2|Tail2]) :- apply(Goal, [Elem1, Elem2]), maplist(Goal, Tail1, Tail2). 55..66..22 OOvveerrrruulliinngg MMoodduullee BBoouunnddaarriieess The mechanism above is sufficient to create an acceptable module system. There are however cases in which we would like to be able to overrule this schema and explicitly call a predicate in some module or assert explicitly in some module. The first is useful to invoke goals in some module from the user's top-level or to implement a object-oriented system (see above). The latter is useful to create and modify _d_y_n_a_m_i_c _m_o_d_u_l_e_s (see section 5.7). For this purpose, the reserved term :/2 has been introduced. All built-in predicates that transform a term into a predicate reference will check whether this term is of the form `<_M_o_d_u_l_e>:<_T_e_r_m>'. If so, the predicate is searched for in _M_o_d_u_l_e instead of the goal's context module. The : operator may be nested, in which case the inner-most module is used. The special calling construct <_M_o_d_u_l_e>:<_G_o_a_l>pretends _G_o_a_l is called from _M_o_d_u_l_e instead of the context module. Examples: ?- assert(world:done). % asserts done/0 into module world ?- world:assert(done). % the same ?- world:done. % calls done/0 in module world 55..77 DDyynnaammiicc MMoodduulleess So far, we discussed modules that were created by loading a module-file. These modules have been introduced on facilitate the development of large applications. The modules are fully defined at load-time of the application and normally will not change during execution. Having the notion of a set of predicates as a self-contained world can be attractive for other purposes as well. For example, assume an application that can reason about multiple worlds. It is attractive to store the data of a particular world in a module, so we extract information from a world simply by invoking goals in this world. Dynamic modules can easily be created. Any built-in predicate that tries to locate a predicate in a specific module will create this module as a side-effect if it did not yet exist. Example: ?- assert(world_a:consistent), world_a:unknown(_, fail). These calls create a module called `world_a' and make the call `world_a:consistent' succeed. Undefined predicates will not start the tracer or autoloader for this module (see unknown/2). Import and export from dynamically created world is arranged via the predicates import/1 and export/1: ?- world_b:export(solve(_,_)). % exports solve/2 from world_b ?- world_c:import(world_b:solve(_,_)). % and import it to world_c 55..88 MMoodduullee HHaannddlliinngg PPrreeddiiccaatteess This section gives the predicate definitions for the remaining built-in predicates that handle modules. ::-- mmoodduullee((_+_M_o_d_u_l_e_, _+_P_u_b_l_i_c_L_i_s_t)) This directive can only be used as the first term of a source file. It declares the file to be a _m_o_d_u_l_e _f_i_l_e, defining _M_o_d_u_l_e and exporting the predicates of _P_u_b_l_i_c_L_i_s_t. _P_u_b_l_i_c_L_i_s_t is a list of predicate indicators (name/arity pairs) or operator declarations using the format op(_P_r_e_c_e_d_e_n_c_e_, _T_y_p_e_, _N_a_m_e). Operators defined in the export list are available inside the module as well as to modules importing this module. See also section 4.24. mmoodduullee__ttrraannssppaarreenntt _+_P_r_e_d_s _P_r_e_d_s is a comma separated list of name/arity pairs (like dynamic/1). Each goal associated with a transparent declared predicate will inherit the _c_o_n_t_e_x_t _m_o_d_u_l_e from its parent goal. mmeettaa__pprreeddiiccaattee _+_H_e_a_d_s This predicate is defined in quintus and provides a partial emulation of the Quintus predicate. See section 5.9.1 for details. ccuurrrreenntt__mmoodduullee((_-_M_o_d_u_l_e)) Generates all currently known modules. ccuurrrreenntt__mmoodduullee((_?_M_o_d_u_l_e_, _?_F_i_l_e)) Is true if _F_i_l_e is the file from which _M_o_d_u_l_e was loaded. _F_i_l_e is the internal canonical filename. See also source_file/[1,2]. ccoonntteexxtt__mmoodduullee((_-_M_o_d_u_l_e)) Unify _M_o_d_u_l_e with the context module of the current goal. context_module/1 itself is transparent. ssttrriipp__mmoodduullee((_+_T_e_r_m_, _-_M_o_d_u_l_e_, _-_P_l_a_i_n)) Used in module transparent or meta-predicates to extract the referenced module and plain term. If _T_e_r_m is a module-qualified term, i.e. of the format _M_o_d_u_l_e:_P_l_a_i_n, _M_o_d_u_l_e and _P_l_a_i_n are unified to these values. Otherwise _P_l_a_i_n is unified to _T_e_r_m and _M_o_d_u_l_e to the context module. eexxppoorrtt((_+_H_e_a_d)) Add a predicate to the public list of the context module. This implies the predicate will be imported into another module if this module is imported with use_module/[1,2]. Note that predicates are normally exported using the directive module/2. export/1 is meant to handle export from dynamically created modules. eexxppoorrtt__lliisstt((_+_M_o_d_u_l_e_, _?_E_x_p_o_r_t_s)) Unifies _E_x_p_o_r_t_s with a list of terms. Each term has the name and arity of a public predicate of _M_o_d_u_l_e. The order of the terms in _E_x_p_o_r_t_s is not defined. See also predicate_property/2. iimmppoorrtt__mmoodduullee((_+_M_o_d_u_l_e_, _-_I_m_p_o_r_t)) True if _I_m_p_o_r_t is defined as an import module for _M_o_d_u_l_e. All normal modules only import from user, which imports from system. The predicates add_import_module/3and delete_import_module/2 can be used to manipulate the import list. aadddd__iimmppoorrtt__mmoodduullee((_+_M_o_d_u_l_e_, _+_I_m_p_o_r_t_, _+_S_t_a_r_t_O_r_E_n_d)) If _I_m_p_o_r_t is not already an import module for _M_o_d_u_l_e, add it to this list at the start or end depending on _S_t_a_r_t_O_r_E_n_d. See also import_module/2 and delete_import_module/2. ddeelleettee__iimmppoorrtt__mmoodduullee((_+_M_o_d_u_l_e_, _+_I_m_p_o_r_t)) Delete _I_m_p_o_r_t from the list of import modules for _M_o_d_u_l_e. Fails silently if _I_m_p_o_r_t is not in the list. ddeeffaauulltt__mmoodduullee((_+_M_o_d_u_l_e_, _-_D_e_f_a_u_l_t)) Successively unifies _D_e_f_a_u_l_t with the module names from which a call in _M_o_d_u_l_e attempts to use the definition. For the module user, this will generate user and system. For any other module, this will generate the module itself, followed by user and system. Backward compatibility. New code should use import_module/2. mmoodduullee((_+_M_o_d_u_l_e)) The call module(Module) may be used to switch the default working module for the interactive top-level (see prolog/0). This may be used to when debugging a module. The example below lists the clauses of file_of_label/2 in the module tex. 1 ?- module(tex). Yes tex: 2 ?- listing(file_of_label/2). ... 55..99 CCoommppaattiibbiilliittyy ooff tthhee MMoodduullee SSyysstteemm The principles behind the module system of SWI-Prolog differ in a number of aspects from the Quintus Prolog module system. o The SWI-Prolog module system allows the user to redefine system predicates. o All predicates that are available in the system and user modules are visible in all other modules as well. o Quintus has the `meta_predicate/1' declaration were SWI-Prolog has the module_transparent/1 declaration. o Operator declarations are local to a module and may be exported. The meta_predicate/1 declaration causes the compiler to tag arguments that pass module sensitive information with the module using the :/2 operator. This approach has some disadvantages: o Changing a meta_predicate declaration implies all predicates ccaalllliinngg the predicate need to be reloaded. This can cause serious consistency problems. o It does not help for dynamically defined predicates calling module sensitive predicates. o It slows down the compiler (at least in the SWI-Prolog architecture). o At least within the SWI-Prolog architecture the run-time overhead is larger than the overhead introduced by the transparent mechanism. Unfortunately the transparent predicate approach also has some disadvantages. If a predicate A passes module sensitive information to a predicate B, passing the same information to a module sensitive system predicate both A and B should be declared transparent. Using the Quintus approach only A needs to be treated special (i.e., declared with meta_predicate/1). A second problem arises if the body of a transparent predicate uses module sensitive predicates for which it wants to refer to its own module. Suppose we want to define findall/3 using assert/1 and retract/1. The example in figure 5.1 gives the solution. :- module(findall, [findall/3]). :- dynamic solution/1. :- module_transparent findall/3, store/2. findall(Var, Goal, Bag) :- assert(findall:solution('$mark')), store(Var, Goal), collect(Bag). store(Var, Goal) :- Goal, % refers to context module of % caller of findall/3 assert(findall:solution(Var)), fail. store(_, _). collect(Bag) :- ..., Figure 5.1: findall/3 using modules 55..99..11 EEmmuullaattiinngg mmeettaa__pprreeddiiccaattee The Quintus meta_predicate/1 directive can in many cases be replaced by the transparent declaration. Below is the definition of meta_predicate/1 as available from quintus. :- op(1150, fx, (meta_predicate)). meta_predicate((Head, More)) :- !, meta_predicate1(Head), meta_predicate(More). meta_predicate(Head) :- meta_predicate1(Head). meta_predicate1(Head) :- Head =.. [Name|Arguments], member(Arg, Arguments), module_expansion_argument(Arg), !, functor(Head, Name, Arity), module_transparent(Name/Arity). meta_predicate1(_). % just a mode declaration module_expansion_argument(:). module_expansion_argument(N) :- integer(N). The discussion above about the problems with the transparent mechanism show the two cases in which this simple transformation does not work. CChhaapptteerr 66.. SSPPEECCIIAALL VVAARRIIAABBLLEESS AANNDD CCOORROOUUTTIINNIINNGG This chapter deals with extensions primarily designed to support constraint logic programming (CLP). 66..11 AAttttrriibbuutteedd vvaarriiaabblleess _A_t_t_r_i_b_u_t_e_d _v_a_r_i_a_b_l_e_s provide a technique for extending the Prolog unification algorithm [Holzbaur, 1990] by hooking the binding of attributed variables. There is little consensus in the Prolog community on the exact definition and interface to attributed variables. The SWI-Prolog interface is identical to the one realised by Bart Demoen for hProlog [Demoen, 2002]. Binding an attributed variable schedules a goal to be executed at the first possible opportunity. In the current implementation the hooks are executed immediately after a successful unification of the clause-head or successful completion of a foreign language (built-in) predicate. Each attribute is associated to a module and the hook (attr_unify_hook/2) is executed in this module. The example below realises a very simple and incomplete finite domain reasoner. :- module(domain, [ domain/2 % Var, ?Domain ]). :- use_module(library(ordsets)). domain(X, Dom) :- var(Dom), !, get_attr(X, domain, Dom). domain(X, List) :- list_to_ordset(List, Domain), put_attr(Y, domain, Domain), X = Y. % An attributed variable with attribute value Domain has been % assigned the value Y attr_unify_hook(Domain, Y) :- ( get_attr(Y, domain, Dom2) -> ordset_intersection(Domain, Dom2, NewDomain), ( NewDomain == [] -> fail ; NewDomain = [Value] -> Y = Value ; put_attr(Y, domain, NewDomain) ) ; var(Y) -> put_attr( Y, domain, Domain ) ; ordset_memberchk(Y, Domain) ). Before explaining the code we give some example queries: ?- domain(X, [a,b]), X = c no ?- domain(X, [a,b]), domain(X, [a,c]). X = a ?- domain(X, [a,b,c]), domain(X, [a,c]). X = _G492att(domain, [a, c], []) The predicate domain/2 fetches (first clause) or assigns (second clause) the variable a _d_o_m_a_i_n, a set of values it can be unified with. In the second clause first associates the domain with a fresh variable and then unifies X to this variable to deal with the possibility that X already has a domain. The predicate attr_unify_hook/2is a hook called after a variable with a domain is assigned a value. In the simple case where the variable is bound to a concrete value we simply check whether this value is in the domain. Otherwise we take the intersection of the domains and either fail if the intersection is empty (first example), simply assign the value if there is only one value in the intersection (second example) or assign the intersection as the new domain of the variable (third example). aattttvvaarr((_@_T_e_r_m)) Succeeds if _T_e_r_m is an attributed variable. Note that var/1 also succeeds on attributed variables. Attributed variables are created with put_attr/3. ppuutt__aattttrr((_+_V_a_r_, _+_M_o_d_u_l_e_, _+_V_a_l_u_e)) If _V_a_r is a variable or attributed variable, set the value for the attribute named _M_o_d_u_l_e to _V_a_l_u_e. If an attribute with this name is already associated with _V_a_r, the old value is replaced. Backtracking will restore the old value (i.e. an attribute is a mutable term. See also setarg/3). This predicate raises a type error if _V_a_r is not a variable or _M_o_d_u_l_e is not an atom. ggeett__aattttrr((_+_V_a_r_, _+_M_o_d_u_l_e_, _-_V_a_l_u_e)) Request the current _v_a_l_u_e for the attribute named _M_o_d_u_l_e. If _V_a_r is not an attributed variable or the named attribute is not associated to _V_a_r this predicate fails silently. If _M_o_d_u_l_e is not an atom, a type error is raised. ddeell__aattttrr((_+_V_a_r_, _+_M_o_d_u_l_e)) Delete the named attribute. If _V_a_r loses its last attribute it is transformed back into a traditional Prolog variable. If _M_o_d_u_l_e is not an atom, a type error is raised. In all other cases this predicate succeeds regardless whether or not the named attribute is present. aattttrr__uunniiffyy__hhooookk((_+_A_t_t_V_a_l_u_e_, _+_V_a_r_V_a_l_u_e)) Hook that must be defined in the module an attributed variable refers to. Is is called _a_f_t_e_r the attributed variable has been unified with a non-var term, possibly another attributed variable. _A_t_t_V_a_l_u_e is the attribute that was associated to the variable in this module and _V_a_r_V_a_l_u_e is the new value of the variable. Normally this predicate fails to veto binding the variable to _V_a_r_V_a_l_u_e, forcing backtracking to undo the binding. If _V_a_r_V_a_l_u_e is another attributed variable the hook often combines the two attribute and associates the combined attribute with _V_a_r_V_a_l_u_e using put_attr/3. aattttrr__ppoorrttrraayy__hhooookk((_+_A_t_t_V_a_l_u_e_, _+_V_a_r)) Called by write_term/2and friends for each attribute if the option attributes(_p_o_r_t_r_a_y) is in effect. If the hook succeeds the attribute is considered printed. Otherwise Module = ... is printed to indicate the existence of a variable. 66..11..11 SSppeecciiaall ppuurrppoossee pprreeddiiccaatteess ffoorr aattttrriibbuutteess Normal user code should deal with put_attr/3, get_attr/3 and del_attr/2. The routines in this section fetch or set the entire attribute list of a variables. Use of these predicates is anticipated to be restricted to printing and other special purpose operations. ggeett__aattttrrss((_+_V_a_r_, _-_A_t_t_r_i_b_u_t_e_s)) Get all attributes of _V_a_r. _A_t_t_r_i_b_u_t_e_s is a term of the form att(_M_o_d_u_l_e_, _V_a_l_u_e_, _M_o_r_e_A_t_t_r_i_b_u_t_e_s), where _M_o_r_e_A_t_t_r_i_b_u_t_e_s is [] for the last attribute. ppuutt__aattttrrss((_+_V_a_r_, _-_A_t_t_r_i_b_u_t_e_s)) Set all attributes of _V_a_r. See get_attrs/2 for a description of _A_t_t_r_i_b_u_t_e_s. ccooppyy__tteerrmm__nnaatt((_+_T_e_r_m_, _-_C_o_p_y)) As copy_term/2. Attributes however, are _n_o_t copied but replaced by fresh variables. 66..22 CCoorroouuttiinniinngg Coroutining deals with having Prolog goals scheduled for execution as soon as some conditions is fulfilled. In Prolog the most commonly used conditions is the instantiation (binding) of a variable. Scheduling a goal to execute immediately after a variable is bound allows may be used to avoid instantiation errors for some built-in predicates (e.g. arithmetic), do work _l_a_z_y, prevent the binding of a variable to a particular value, etc. Using freeze/2 for example we can define a variable can only be assigned an even number: ?- freeze(X, X mod 2 =:= 0), X = 3 No ffrreeeezzee((_+_V_a_r_, _:_G_o_a_l)) Delay the execution of _G_o_a_l until _V_a_r is bound (i.e. is not a variable or attributed variable). If _V_a_r is bound on entry freeze/2 is equivalent to call/1. The freeze/2 predicate is realised using an attributed variable associated with the module freeze, so get_attr(Var, freeze, AttVal) can be used to find out whether and which goals are delayed on _V_a_r. ffrroozzeenn((_@_V_a_r_, _-_G_o_a_l)) Unify _G_o_a_l with the goal or conjunction of goals delayed on _V_a_r. If no goals are frozen on _V_a_r, _G_o_a_l is unified to true. wwhheenn((_@_C_o_n_d_i_t_i_o_n_, _:_G_o_a_l)) Execute _G_o_a_l when _C_o_n_d_i_t_i_o_n becomes true. _C_o_n_d_i_t_i_o_n is one of ?=(_X_, _Y), nonvar(_X), ground(_X), ,(_C_o_n_d_1_, _C_o_n_d_2) or ;(_C_o_n_d_1_, _C_o_n_d_2). See also freeze/2 and dif/2. The implementation can deal with cyclic terms. The when/2 predicate is realised using attributed variable associated with the module when. It is defined in the autoload library when. ddiiff((_@_A_, _@_B)) The dif/2 predicate provides a constraint stating that _A and _B are different terms. If _A and _B can never unify dif/2 succeeds deterministically. If _A and _B are identical it fails immediately and finally, if _A and _B can unify, goals are delayed that prevent _A and _B to become equal. The dif/2 predicate behaves as if defined by dif(X, Y) :- when(?=(X, Y), X \== Y). See also ?=/2. The implementation can deal with cyclic terms. The dif/2 predicate is realised using attributed variable associated with the module dif. It is defined in the autoload library dif. 66..33 GGlloobbaall vvaarriiaabblleess Global variables are associations between names (atoms) and terms. They differ in various ways from storing information using assert/1 or recorda/3. o The value lives on the Prolog (global) stack. This implies that lookup time is independent from the size of the term. This is particularly interesting for large data structures such as parsed XML documents or the CHR global constraint store. o They support both global assignment using nb_setval/2 and backtrackable assignment using b_setval/2. o Only one value (which can be an arbitrary complex Prolog term) can be associated to a variable at a time. o Their value cannot be shared among threads. Each thread has its own namespace and values for global variables. o Currently global variables are scoped globally. We may consider module scoping in future versions. Both b_setval/2 and nb_setval/2 implicitly create a variable if the referenced name does not already refer to a variable. Global variables may be initialised from directives to make them available during the program lifetime, but some considerations are necessary for saved-states and threads. Saved-states to not store global variables, which implies they have to be declared with initialization/1 to recreate them after loading the saved state. Each thread has its own set of global variables, starting with an empty set. Using thread_initialization/1 to define a global variable it will be defined, restored after reloading a saved state and created in all threads that are created _a_f_t_e_r the registration. Finally, global variables can be initialised using the exception hook called exception/3. The latter technique is by CHR (see chapter 7. bb__sseettvvaall((_+_N_a_m_e_, _+_V_a_l_u_e)) Associate the term _V_a_l_u_e with the atom _N_a_m_e or replaces the currently associated value with _V_a_l_u_e. If _N_a_m_e does not refer to an existing global variable a variable with initial value [] is created (the empty list). On backtracking the assignment is reversed. bb__ggeettvvaall((_+_N_a_m_e_, _-_V_a_l_u_e)) Get the value associated with the global variable _N_a_m_e and unify it with _V_a_l_u_e. Note that this unification may further instantiate the value of the global variable. If this is undesirable the normal precautions (double negation or copy_term/2) must be taken. The b_getval/2 predicate generates errors if _N_a_m_e is not an atom or the requested variable does not exist. nnbb__sseettvvaall((_+_N_a_m_e_, _+_V_a_l_u_e)) Associates a copy of _V_a_l_u_e created with duplicate_term/2 with the atom _N_a_m_e. Note that this can be used to set an initial value other than [] prior to backtrackable assignment. nnbb__ggeettvvaall((_+_N_a_m_e_, _-_V_a_l_u_e)) The nb_getval/2 predicate is a synonym for b_getval/2, introduced for compatibility and symmetry. As most scenarios will use a particular global variable either using non-backtracable or backtrackable assignment, using nb_getval/2can be used to document that the variable is used non-backtracable. nnbb__lliinnkkvvaall((_+_N_a_m_e_, _+_V_a_l_u_e)) Associates the term _V_a_l_u_e with the atom _N_a_m_e without copying it. This is a fast special-purpose variation of nb_setval/2 intended for expert users only because the semantics on backtracking to a point before creating the link are poorly defined for compound terms. The principal term is always left untouched, but backtracking behaviour on arguments is undone if the original assignment was _t_r_a_i_l_e_d and left alone otherwise, which implies that the history that created the term affects the behaviour on backtracking. Please consider the following example: demo_nb_linkval :- T = nice(N), ( N = world, nb_linkval(myvar, T), fail ; nb_getval(myvar, V), writeln(V) ). nnbb__ccuurrrreenntt((_?_N_a_m_e_, _?_V_a_l_u_e)) Enumerate all defined variables with their value. The order of enumeration is undefined. nnbb__ddeelleettee((_+_N_a_m_e)) Delete the named global variable. 66..33..11 CCoommppaattiibbiilliittyy ooff SSWWII--PPrroolloogg GGlloobbaall VVaarriiaabblleess Global variables have been introduced by various Prolog implementations recently. The implementation of them in SWI-Prolog is based on hProlog by Bart Demoen. In discussion with Bart it was decided that the semantics if hProlog nb_setval/2, which is equivalent to nb_linkval/2 is not acceptable for normal Prolog users as the behaviour is influenced by how built-in predicates constructing terms (read/1, =../2, etc.) are implemented. GNU-Prolog provides a rich set of global variables, including arrays. Arrays can be implemented easily in SWI-Prolog using functor/3 and setarg/3 due to the unrestricted arity of compound terms. CChhaapptteerr 77.. CCHHRR:: CCOONNSSTTRRAAIINNTT HHAANNDDLLIINNGG RRUULLEESS This chapter is written by Tom Schrijvers, K.U. Leuven, and adjustments by Jan Wielemaker. The CHR system of SWI-Prolog is the _K_._U_._L_e_u_v_e_n _C_H_R _s_y_s_t_e_m. The runtime environment is written by Christian Holzbaur and Tom Schrijvers while the compiler is written by Tom Schrijvers. Both are integrated with SWI-Prolog and licensed under compatible conditions with permission from the authors. The main reference for the K.U.Leuven CHR system is: o T. Schrijvers, and B. Demoen, _T_h_e _K_._U_._L_e_u_v_e_n _C_H_R _S_y_s_t_e_m_: _I_m_p_l_e_m_e_n_t_a_t_i_o_n _a_n_d _A_p_p_l_i_c_a_t_i_o_n, First Workshop on Constraint Handling Rules: Selected Contributions (Fr"uhwirth, T. and Meister, M., eds.), pp. 1--5, 2004. On the K.U.Leuven CHR website (http://www.cs.kuleuven.be/~toms/CHR/) you can find more related papers, references and example programs. 77..11 IInnttrroodduuccttiioonn Constraint Handling Rules (CHR) is a committed-choice rule-based language embedded in Prolog. It is designed for writing constraint solvers and is particularly useful for providing application-specific constraints. It has been used in many kinds of applications, like scheduling, model checking, abduction, type checking among many others. CHR has previously been implemented in other Prolog systems (SICStus, Eclipse, Yap), Haskell and Java. This CHR system is based on the compilation scheme and runtime environment of CHR in SICStus. In this documentation we restrict ourselves to giving a short overview of CHR in general and mainly focus on elements specific to this implementation. For a more thorough review of CHR we refer the reader to [Fr"uhwirth, 1998]. More background on CHR can be found at [Fr"uhwirth,]. In section 7.2 we present the syntax of CHR in Prolog and explain informally its operational semantics. Next, section 7.3 deals with practical issues of writing and compiling Prolog programs containing CHR. Section 7.4 explains the currently primitive CHR debugging facilities. Section 7.4.3 provides a few useful predicates to inspect the constraint store and section 7.5 illustrates CHR with two example programs. In section 7.6 some compatibility issues with older versions of this system and SICStus' CHR system. Finally, section 7.7 concludes with a few practical guidelines for using CHR. 77..22 SSyynnttaaxx aanndd SSeemmaannttiiccss 77..22..11 SSyynnttaaxx The syntax of CHR rules is the following: rules --> rule, rules. rules --> []. rule --> name, actual_rule, pragma, [atom('.')]. name --> atom, [atom('@')]. name --> []. actual_rule --> simplification_rule. actual_rule --> propagation_rule. actual_rule --> simpagation_rule. simplification_rule --> head, [atom('<=>')], guard, body. propagation_rule --> head, [atom('==>')], guard, body. simpagation_rule --> head, [atom('\')], head, [atom('<=>')], guard, body. head --> constraints. constraints --> constraint, constraint_id. constraints --> constraint, constraint_id, [atom(',')], constraints. constraint --> compound_term. constraint_id --> []. constraint_id --> [atom('#')], variable. constraint_id --> [atom('#')], [atom('passive')] . guard --> []. guard --> goal, [atom('|')]. body --> goal. pragma --> []. pragma --> [atom('pragma')], actual_pragmas. actual_pragmas --> actual_pragma. actual_pragmas --> actual_pragma, [atom(',')], actual_pragmas. actual_pragma --> [atom('passive(')], variable, [atom(')')]. Note that the guard of a rule may not contain any goal that binds a variable in the head of the rule with a non-variable or with another variable in the head of the rule. It may however bind variables that do not appear in the head of the rule, e.g. an auxiliary variable introduced in the guard. 77..22..22 SSeemmaannttiiccss In this subsection the operational semantics of CHR in Prolog are presented informally. They do not differ essentially from other CHR systems. When a constraint is called, it is considered an active constraint and the system will try to apply the rules to it. Rules are tried and executed sequentially in the order they are written. A rule is conceptually tried for an active constraint in the following way. The active constraint is matched with a constraint in the head of the rule. If more constraints appear in the head they are looked for among the suspended constraints, which are called passive constraints in this context. If the necessary passive constraints can be found and all match with the head of the rule and the guard of the rule succeeds, then the rule is committed and the body of the rule executed. If not all the necessary passive constraint can be found, the matching fails or the guard fails, then the body is not executed and the process of trying and executing simply continues with the following rules. If for a rule, there are multiple constraints in the head, the active constraint will try the rule sequentially multiple times, each time trying to match with another constraint. This process ends either when the active constraint disappears, i.e. it is removed by some rule, or after the last rule has been processed. In the latter case the active constraint becomes suspended. A suspended constraint is eligible as a passive constraint for an active constraint. The other way it may interact again with the rules, is when a variable appearing in the constraint becomes bound to either a non-variable or another variable involved in one or more constraints. In that case the constraint is triggered, i.e. it becomes an active constraint and all the rules are tried. RRuullee TTyyppeess There are three different kinds of rules, each with their specific semantics: o _s_i_m_p_l_i_f_i_c_a_t_i_o_n The simplification rule removes the constraints in its head and calls its body. o _p_r_o_p_a_g_a_t_i_o_n The propagation rule calls its body exactly once for the constraints in its head. o _s_i_m_p_a_g_a_t_i_o_n The simpagation rule removes the constraints in its head after the \ and then calls its body. It is an optimization of simplification rules of the form: constraints1;constraints2<=> constraints1;body Namely, in the simpagation form: constraints1\constraints2<=> body The constraints1constraints are not called in the body. RRuullee NNaammeess Naming a rule is optional and has no semantical meaning. It only functions as documentation for the programmer. PPrraaggmmaass The semantics of the pragmas are: ppaassssiivvee((_I_d_e_n_t_i_f_i_e_r)) The constraint in the head of a rule _I_d_e_n_t_i_f_i_e_r can only match a passive constraint in that rule. There is an abbreviated syntax for this pragma. Instead of: ..., c # Id, ... <=> ... pragma passive(Id) you can also write ..., c # passive, ... <=> ... Additional pragmas may be released in the future. ::-- cchhrr__ooppttiioonn((_+_O_p_t_i_o_n_, _+_V_a_l_u_e)) It is possible to specify options that apply to all the CHR rules in the module. Options are specified with the chr_option/2 declaration: :- chr_option(Option,Value). and may appear in the file anywhere after the first constraints declaration. Available options are: cchheecckk__gguuaarrdd__bbiinnddiinnggss This option controls whether guards should be checked for (illegal) variable bindings or not. Possible values for this option are on, to enable the checks, and off, to disable the checks. If this option is on, any guard fails when it binds a variable that appears in the head of the rule. When the option is off (default), the behavior of a binding in the guard is undefined. ooppttiimmiizzee This option controls the degree of optimization. Possible values are full, to enable all available optimizations, and off (default), to disable all optimizations. The default is derived from the SWI-Prolog flag optimise, where true is mapped to full. Therefore the command-line option -O provides full CHR optimization. If optimization is enabled, debugging must be disabled. ddeebbuugg This options enables or disables the possibility to debug the CHR code. Possible values are on (default) and off. See section 7.4 for more details on debugging. The default is derived from the prolog flag generate_debug_info, which is true by default. See -nodebug. If debugging is enabled, optimization must be disabled. 77..33 CCHHRR iinn SSWWII--PPrroolloogg PPrrooggrraammss 77..33..11 EEmmbbeeddddiinngg iinn PPrroolloogg PPrrooggrraammss The CHR constraints defined in a .pl file are associated with a module. The default module is user. One should never load different .pl files with the same CHR module name. 77..33..22 CCoonnssttrraaiinntt ddeeccllaarraattiioonn ::-- cchhrr__ccoonnssttrraaiinntt((_+_S_p_e_c_i_f_i_e_r)) Every constraint used in CHR rules has to be declared with a chr_constraint/1 declaration by the _c_o_n_s_t_r_a_i_n_t _s_p_e_c_i_f_i_e_r. For convenience multiple constraints may be declared at once with the same chr_constraint/1 declaration followed by a comma-separated list of constraint specifiers. A constraint specifier is, in its compact form, F/A where F and A are respectively the functor name and arity of the constraint, e.g.: :- chr_constraint foo/1. :- chr_constraint bar/2, baz/3. In its extended form, a constraint specifier is c(A1,...,An) where c is the constraint's functor, n its arity and the Aiare argument specifiers. An argument specifier is a mode, optionally followed by a type. E.g. :- chr_constraint get_value(+,?). :- chr_constraint domain(?int, +list(int)), alldifferent(?list(int)). MMooddeess A mode is one of: - The corresponding argument of every occurrence of the constraint is always unbound. + The corresponding argument of every occurrence of the constraint is always ground. ? The corresponding argument of every occurrence of the constraint can have any instantiation, which may change over time. This is the default value. TTyyppeess A type can be a user-defined type or one of the built-in types. A type comprises a (possibly infinite) set of values. The type declaration for a constraint argument means that for every instance of that constraint the corresponding argument is only ever bound to values in that set. It does not state that the argument necessarily has to be bound to a value. The built-in types are: iinntt The corresponding argument of every occurrence of the constraint is an integer number. ddeennssee__iinntt The corresponding argument of every occurrence of the constraint is an integer that can be used as an array index. Note that if this argument takes values in [0; n], the array takes O(n) space. ffllooaatt ...a floating point number. nnuummbbeerr ...a number. nnaattuurraall ...a positive integer. aannyy The corresponding argument of every occurrence of the constraint can have any type. This is the default value. ::-- cchhrr__ttyyppee((_+_T_y_p_e_D_e_c_l_a_r_a_t_i_o_n)) User-defined types are algebraic data types, similar to those in Haskell or the discriminated unions in Mercury. An algebraic data type is defined using chr_type/1: :- chr_type type ---> body. If the type term is a functor of arity zero (i.e. one having zero arguments), it names a monomorphic type. Otherwise, it names a polymorphic type; the arguments of the functor must be distinct type variables. The body term is defined as a sequence of constructor definitions separated by semi-colons. Each constructor definition must be a functor whose arguments (if any) are types. Discriminated union definitions must be transparent: all type variables occurring in the body must also occur in the type. Here are some examples of algebraic data type definitions: :- chr_type color ---> red ; blue ; yellow ; green. :- chr_type tree ---> empty ; leaf(int) ; branch(tree, tree). :- chr_type list(T) ---> [] ; [T | list(T)]. :- chr_type pair(T1, T2) ---> (T1 - T2). Each algebraic data type definition introduces a distinct type. Two algebraic data types that have the same bodies are considered to be distinct types (name equivalence). Constructors may be overloaded among different types: there may be any number of constructors with a given name and arity, so long as they all have different types. Aliases can be defined using ==. For example, if your program uses lists of lists of integers, you can define an alias as follows: :- chr_type lli == list(list(int)). TTyyppee CChheecckkiinngg Currently two complementary forms of type checking are performed: 1. Static type checking is always performed by the compiler. It is limited to CHR rule heads and CHR constraint calls in rule bodies. Two kinds of type error are detected. The first is where a variable has to belong to two types. For example, in the program: :-chr_type foo ---> foo. :-chr_type bar ---> bar. :-chr_constraint abc(?foo). :-chr_constraint def(?bar). foobar @ abc(X) <=> def(X). the variable X has to be of both type foo and bar. This is reported by the type clash error: CHR compiler ERROR: `--> Type clash for variable _G5398 in rule foobar: expected type foo in body goal def(_G5398, _G5448) expected type bar in head def(_G5448, _G5398) The second kind of error is where a functor is used that does not belong to the declared type. For example in: :-chr_type foo ---> foo. :-chr_type bar ---> bar. :-chr_constraint abc(?foo). foo @ abc(bar) <=> true. in the head of the rule bar appears where something of type foo is expected. This is reported as: CHR compiler ERROR: `--> Invalid functor in head abc(bar) of rule foo: found `bar', expected type `foo'! No runtime overhead is incurred in static type checking. 2. Dynamic type checking checks at runtime, during program execution, whether the arguments of CHR constraints respect their declared types. The when/2 co-routining library is used to delay dynamic type checks until variables are instantiated. The kind of error detected by dynamic type checking is where a functor is used that does not belong to the declared type. E.g. for the program: :-chr_type foo ---> foo. :-chr_constraint abc(?foo). we get the following error in an erroneous query: ?- abc(bar). ERROR: Type error: `foo' expected, found `bar' (CHR Run- time Type Error) Dynamic type checking is weaker than static type checking in the sense that it only checks the particular program execution at hand rather than all possible executions. It is stronger in the sense that it tracks types throughout the whole program. Note that it is enabled only in debug mode, as it incurs some (minor) runtime overhead. 77..33..33 CCoommppiillaattiioonn The SWI-Prolog CHR compiler exploits term_expansion/2 rules to translate the constraint handling rules to plain Prolog. These rules are loaded from the library chr. They are activated if the compiled file has the .chr extension or after finding a declaration of the format below. :- chr_constraint ... It is advised to define CHR rules in a module file, where the module declaration is immediately followed by including the library(chr) library as exemplified below: :- module(zebra, [ zebra/0 ]). :- use_module(library(chr)). :- chr_constraint ... Using this style CHR rules can be defined in ordinary Prolog .pl files and the operator definitions required by CHR do not leak into modules where they might cause conflicts. 77..44 DDeebbuuggggiinngg The CHR debugging facilities are currently rather limited. Only tracing is currently available. To use the CHR debugging facilities for a CHR file it must be compiled for debugging. Generating debug info is controlled by the CHR option debug, whose default is derived from the SWI-Prolog flag generate_debug_info. Therefore debug info is provided unless the -nodebug is used. 77..44..11 PPoorrttss For CHR constraints the four standard ports are defined: ccaallll A new constraint is called and becomes active. eexxiitt An active constraint exits: it has either been inserted in the store after trying all rules or has been removed from the constraint store. ffaaiill An active constraint fails. rreeddoo An active constraint starts looking for an alternative solution. In addition to the above ports, CHR constraints have five additional ports: wwaakkee A suspended constraint is woken and becomes active. iinnsseerrtt An active constraint has tried all rules and is suspended in the constraint store. rreemmoovvee An active or passive constraint is removed from the constraint store. ttrryy An active constraints tries a rule with possibly some passive constraints. The try port is entered just before committing to the rule. aappppllyy An active constraints commits to a rule with possibly some passive constraints. The apply port is entered just after committing to the rule. 77..44..22 TTrraacciinngg Tracing is enabled with the chr_trace/0 predicate and disabled with the chr_notrace/0 predicate. When enabled the tracer will step through the call, exit, fail, wake and apply ports, accepting debug commands, and simply write out the other ports. The following debug commands are currently supported: CHR debug options: creep c creep s skip g ancestors n nodebug b break a abort f fail ? help h help Their meaning is: ccrreeeepp Step to the next port. sskkiipp Skip to exit port of this call or wake port. aanncceessttoorrss Print list of ancestor call and wake ports. nnooddeebbuugg Disable the tracer. bbrreeaakk Enter a recursive Prolog top-level. See break/0. aabboorrtt Exit to the top-level. See abort/0. ffaaiill Insert failure in execution. hheellpp Print the above available debug options. 77..44..33 CCHHRR DDeebbuuggggiinngg PPrreeddiiccaatteess The chr module contains several predicates that allow inspecting and printing the content of the constraint store. cchhrr__ttrraaccee Activate the CHR tracer. By default the CHR tracer is activated and deactivated automatically by the Prolog predicates trace/0 and notrace/0. cchhrr__nnoottrraaccee De-activate the CHR tracer. By default the CHR tracer is activated and deactivated automatically by the Prolog predicates trace/0 and notrace/0. cchhrr__lleeaasshh((_+_S_p_e_c)) Define the set of CHR ports on which the CHR tracer asks for user intervention (i.e. stops). _S_p_e_c is either a list of ports as defined in section 7.4.1 or a predefined `alias'. Defined aliases are: full to stop at all ports, none or off to never stop, and default to stop at the call, exit, fail, wake and apply ports. See also leash/1. cchhrr__sshhooww__ssttoorree((_+_M_o_d)) Prints all suspended constraints of module _M_o_d to the standard output. This predicate is automatically called by the SWI-Prolog top-level at the end of each query for every CHR module currently loaded. The prolog-flag chr_toplevel_show_store controls whether the top-level shows the constraint stores. The value true enables it. Any other value disables it. 77..55 EExxaammpplleess Here are two example constraint solvers written in CHR. o The program below defines a solver with one constraint, leq/2/, which is a less-than-or-equal constraint, also known as a partial order constraint. :- module(leq,[leq/2]). :- use_module(library(chr)). :- chr_constraint leq/2. reflexivity @ leq(X,X) <=> true. antisymmetry @ leq(X,Y), leq(Y,X) <=> X = Y. idempotence @ leq(X,Y) \ leq(X,Y) <=> true. transitivity @ leq(X,Y), leq(Y,Z) ==> leq(X,Z). When the above program is saved in a file and loaded in SWI-Prolog, you can call the leq/2 constraints in a query, e.g.: ?- leq(X,Y), leq(Y,Z). leq(_G23837, _G23841) leq(_G23838, _G23841) leq(_G23837, _G23838) X = _G23837{leq = ...} Y = _G23838{leq = ...} Z = _G23841{leq = ...} Yes When the query succeeds, the SWI-Prolog top-level prints the content of the CHR constraint store and displays the bindings generate during the query. Some of the query variables may have been bound to attributed variables, as you see in the above example. o The program below implements a simple finite domain constraint solver. :- module(dom,[dom/2]). :- use_module(library(chr)). :- chr_constraint dom(?int,+list(int)). :- chr_type list(T) ---> [] ; [T|list(T)]. dom(X,[]) <=> fail. dom(X,[Y]) <=> X = Y. dom(X,L) <=> nonvar(X) | memberchk(X,L). dom(X,L1), dom(X,L2) <=> intersection(L1,L2,L3), dom(X,L3). When the above program is saved in a file and loaded in SWI-Prolog, you can call the dom/2 constraints in a query, e.g.: ?- dom(A,[1,2,3]), dom(A,[3,4,5]). A = 3 Yes 77..66 BBaacckkwwaarrddss CCoommppaattiibbiilliittyy 77..66..11 TThhee OOlldd SSIICCSSttuuss CCHHRR iimmpplleemmeennaattiioonn There are small differences between the current K.U.Leuven CHR system in SWI-Prolog, older versions of the same system and SICStus' CHR system. The current system maps old syntactic elements onto new ones and ignores a number of no longer required elements. However, for each a _d_e_p_r_e_c_a_t_e_d warning is issued. You are strongly urged to replace or remove deprecated features. Besides differences in available options and pragmas, the following differences should be noted: o _T_h_e constraints/1 _d_e_c_l_a_r_a_t_i_o_n This declaration is deprecated. It has been replaced with the chr_constraint/1 declaration. o _T_h_e option/2 _d_e_c_l_a_r_a_t_i_o_n This declaration is deprecated. It has been replaced with the chr_option/2 declaration. o _T_h_e handler/1 _d_e_c_l_a_r_a_t_i_o_n In SICStus every CHR module requires a handler/1 declaration declaring a unique handler name. This declaration is valid syntax in SWI-Prolog, but will have no effect. A warning will be given during compilation. o _T_h_e rules/1 _d_e_c_l_a_r_a_t_i_o_n In SICStus, for every CHR module it is possible to only enable a subset of the available rules through the rules/1 declaration. The declaration is valid syntax in SWI-Prolog, but has no effect. A warning is given during compilation. o _G_u_a_r_d _b_i_n_d_i_n_g_s The check_guard_bindings option only turns invalid calls to unification into failure. In SICStus this option does more: it intercepts instantiation errors from Prolog built-ins such as is/2 and turns them into failure. In SWI-Prolog, we do not go this far, as we like to separate concerns more. The CHR compiler is aware of the CHR code, the Prolog system and programmer should be aware of the appropriate meaning of the Prolog goals used in guards and bodies of CHR rules. 77..66..22 TThhee OOlldd EECCLLiiPPSSee CCHHRR iimmpplleemmeennaattiioonn The old ECLiPSe CHR implementations features a label_with/1 construct for labeling variables in CHR constraints. This feature has long since been abandoned. However, a simple transformation is all that is required to port the functionality. label_with Constraint1 if Condition1. ... label_with ConstraintN if ConditionN. Constraint1 :- Body1. ... ConstraintN :- BodyN. is transformed into :- chr_constraint my_labeling/0. my_labeling \ Constraint1 <=> Condition1 | Body1. ... my_labeling \ ConstraintN <=> ConditionN | BodyN. my_labeling <=> true. Be sure to put this code after all other rules in your program! With my_labeling/0 (or another predicate name of your choosing) the labeling is initiated, rather than ECLiPSe's chr_labeling/0. 77..77 PPrrooggrraammmmiinngg TTiippss aanndd TTrriicckkss In this section we cover several guidelines on how to use CHR to write constraint solvers and how to do so efficiently. o _C_h_e_c_k _g_u_a_r_d _b_i_n_d_i_n_g_s _y_o_u_r_s_e_l_f It is considered bad practice to write guards that bind variables of the head and to rely on the system to detect this at runtime. It is inefficient and obscures the working of the program. o _S_e_t _s_e_m_a_n_t_i_c_s The CHR system allows the presence of identical constraints, i.e. multiple constraints with the same functor, arity and arguments. For most constraint solvers, this is not desirable: it affects efficiency and possibly termination. Hence appropriate simpagation rules should be added of the form: constraint\constraint <=>true o _M_u_l_t_i_-_h_e_a_d_e_d _r_u_l_e_s Multi-headed rules are executed more efficiently when the constraints share one or more variables. o _M_o_d_e _a_n_d _t_y_p_e _d_e_c_l_a_r_a_t_i_o_n_s Provide mode and type declarations to get more efficient program execution. Make sure to disable debug (-nodebug) and enable optimization (-O). o _C_o_m_p_i_l_e _o_n_c_e_, _r_u_n _m_a_n_y _t_i_m_e_s Does consulting your CHR program take a long time in SWI-Prolog? Probably it takes the CHR compiler a long time to compile the CHR rules into Prolog code. When you disable optimizations the CHR compiler will be a lot quicker, but you may loose performance. Alternatively, you can just use SWI-Prolog's qcompile/1 to generate a .qlf file once from your .pl file. This .qlf contains the generated code of the CHR compiler (be it in a binary format). When you consult the .qlf file, the CHR compiler is not invoked and consultation is much faster. 77..88 CCoommppiilleerr EErrrroorrss aanndd WWaarrnniinnggss In this section we summarize the most important error and warning messages of the CHR compiler. 77..88..11 CCHHRR CCoommppiilleerr EErrrroorrss TTyyppee ccllaasshh for variable ... in rule ... This error indicates an inconsistency between declared types; a variable should belong to two types. See static type checking. IInnvvaalliidd ffuunnccttoorr in head ... of rule ... This error indicates an inconsistency between a declared type and the use of a functor in a rule. See static type checking. CCyycclliicc aalliiaass definition: ... == ... You have defined a type alias in terms of itself, either directly or indirectly. AAmmbbiigguuoouuss ttyyppee aalliiaasseess You have defined two overlapping type aliases. MMuullttiippllee ddeeffiinniittiioonnss for type You have defined the same type multiple times. NNoonn--ggrroouunndd ttyyppee in constraint definition: ... You have declared a non-ground type for a constraint argument. CCoouulldd nnoott ffiinndd ttyyppee ddeeffiinniittiioonn for ... You have used an undefined type in a type declaration. IIlllleeggaall mmooddee//ttyyppee ddeeccllaarraattiioonn You have used invalid syntax in a constraint declaration. CCoonnssttrraaiinntt mmuullttiippllyy ddeeffiinneedd There is more than one declaration for the same constraint. UUnnddeeccllaarreedd ccoonnssttrraaiinntt ... in head of ... You have used an undeclared constraint in the head of a rule. This often indicates a misspelled constrained name or wrong number of arguments. IInnvvaalliidd pprraaggmmaa ... in ... Pragma should not be a variable. You have used a variable as a pragma in a rule. This is not allowed. IInnvvaalliidd iiddeennttiiffiieerr ... in pragma passive in ... You have used an identifier in a passive pragma that does not correspond to an identifier in the head of the rule. Likely the identifier name is misspelled. UUnnkknnoowwnn pprraaggmmaa ... in ... You have used an unknown pragma in a rule. Likely the pragma is misspelled or not supported. SSoommeetthhiinngg uunneexxppeecctteedd happened in the CHR compiler You have most likely bumped into a bug in the CHR compiler. Please contact Tom Schrijvers to notify him of this error. CChhaapptteerr 88.. MMUULLTTII--TTHHRREEAADDEEDD AAPPPPLLIICCAATTIIOONNSS SWI-Prolog multithreading is based on standard C-language multithread- ing support. It is not like _P_a_r_L_o_g or other parallel implementations of the Prolog language. Prolog threads have their own stacks and only share the Prolog _h_e_a_p: predicates, records, flags and other global non-backtrackable data. SWI-Prolog thread support is designed with the following goals in mind. o _M_u_l_t_i_-_t_h_r_e_a_d_e_d _s_e_r_v_e_r _a_p_p_l_i_c_a_t_i_o_n_s Todays computing services often focus on (internet) server applications. Such applications often have need for communication between services and/or fast non-blocking service to multiple concurrent clients. The shared heap provides fast communication and thread creation is relatively cheap. o _I_n_t_e_r_a_c_t_i_v_e _a_p_p_l_i_c_a_t_i_o_n_s Interactive applications often need to perform extensive computation. If such computations are executed in a new thread, the main thread can process events and allow the user to cancel the ongoing computation. User interfaces can also use multiple threads, each thread dealing with input from a distinct group of windows. See also section 8.7. o _N_a_t_u_r_a_l _i_n_t_e_g_r_a_t_i_o_n _w_i_t_h _f_o_r_e_i_g_n _c_o_d_e Each Prolog thread runs in a native thread of the operating system, automatically making them cooperate with _M_T_-_s_a_f_e foreign-code. In addition, any foreign thread can create its own Prolog engine for dealing with calling Prolog from C-code. SWI-Prolog multi-threading is based on the POSIX thread standard [Butenhof, 1997] used on most popular systems except for MS-Windows. On Windows it uses the pthread-win32 emulation of POSIX threads mixed with the Windows native API for smoother and faster operation. 88..11 CCrreeaattiinngg aanndd ddeessttrrooyyiinngg PPrroolloogg tthhrreeaaddss tthhrreeaadd__ccrreeaattee((_:_G_o_a_l_, _-_I_d_, _+_O_p_t_i_o_n_s)) Create a new Prolog thread (and underlying C-thread) and start it by executing _G_o_a_l. If the thread is created successfully, the thread-identifier of the created thread is unified to _I_d. _O_p_t_i_o_n_s is a list of options. The currently defined options are below. Stack size options can also take the value inf or infinite, which is mapped to the maximum stack size supported by the platform. llooccaall((_K_-_B_y_t_e_s)) Set the limit to which the local stack of this thread may grow. If omitted, the limit of the calling thread is used. See also the -L command-line option. gglloobbaall((_K_-_B_y_t_e_s)) Set the limit to which the global stack of this thread may grow. If omitted, the limit of the calling thread is used. See also the -G command-line option. ttrraaiill((_K_-_B_y_t_e_s)) Set the limit to which the trail stack of this thread may grow. If omitted, the limit of the calling thread is used. See also the -T command-line option. aarrgguummeenntt((_K_-_B_y_t_e_s)) Set the limit to which the argument stack of this thread may grow. If omitted, the limit of the calling thread is used. See also the -A command-line option. ssttaacckk((_K_-_B_y_t_e_s)) Set the limit to which the system stack of this thread may grow. The default, minimum and maximum values are system-dependant. aalliiaass((_A_l_i_a_s_N_a_m_e)) Associate an `alias-name' with the thread. This named may be used to refer to the thread and remains valid until the thread is joined (see thread_join/2). ddeettaacchheedd((_B_o_o_l)) If false (default), the thread can be waited for using thread_join/2. thread_join/2 must be called on this thread to reclaim the all resources associated to the thread. If true, the system will reclaim all associated resources automatically after the thread finishes. Please note that thread identifiers are freed for reuse after a detached thread finishes or a normal thread has been joined. See also thread_join/2 and thread_detach/1. If a detached thread dies due to failure or exception of the initial goal the thread prints a message using print_message/2. If such termination is considered normal the code must be wrapped using ignore/1 and/or catch/3 to ensure successful completion. The _G_o_a_l argument is _c_o_p_i_e_d to the new Prolog engine. This implies further instantiation of this term in either thread does not have consequences for the other thread: Prolog threads do not share data from their stacks. tthhrreeaadd__sseellff((_-_I_d)) Get the Prolog thread identifier of the running thread. If the thread has an alias, the alias-name is returned. tthhrreeaadd__jjooiinn((_+_I_d_, _-_S_t_a_t_u_s)) Wait for the termination of thread with given _I_d. Then unify the result-status of the thread with _S_t_a_t_u_s. After this call, _I_d becomes invalid and all resources associated with the thread are reclaimed. Note that threads with the attribute detached(_t_r_u_e) cannot be joined. See also current_thread/2. A thread that has been completed without thread_join/2 being called on it is partly reclaimed: the Prolog stacks are released and the C-thread is destroyed. A small data-structure representing the exit-status of the thread is retained until thread_join/2 is called on the thread. Defined values for _S_t_a_t_u_s are: ttrruuee The goal has been proven successfully. ffaallssee The goal has failed. eexxcceeppttiioonn((_T_e_r_m)) The thread is terminated on an exception. See print_message/2 to turn system exceptions into readable messages. eexxiitteedd((_T_e_r_m)) The thread is terminated on thread_exit/1 using the argument _T_e_r_m. tthhrreeaadd__ddeettaacchh((_+_I_d)) Switch thread into detached-state (see detached(_B_o_o_l) option at thread_create/3) at runtime. _I_d is the identifier of the thread placed in detached state. This may be the result of PL_thread_self/1. One of the possible applications is to simplify debugging. Threads that are created as _d_e_t_a_c_h_e_d leave no traces if they crash. For not-detached threads the status can be inspected using current_thread/2. Threads nobody is waiting for may be created normally and detach themselves just before completion. This way they leave no traces on normal completion and their reason for failure can be inspected. tthhrreeaadd__eexxiitt((_+_T_e_r_m)) Terminates the thread immediately, leaving exited(_T_e_r_m) as result-state for thread_join/2. If the thread has the attribute detached(_t_r_u_e) it terminates, but its exit status cannot be retrieved using thread_join/2 making the value of _T_e_r_m irrelevant. The Prolog stacks and C-thread are reclaimed. tthhrreeaadd__iinniittiiaalliizzaattiioonn((_:_G_o_a_l)) Run _G_o_a_l when thread is started. This predicate must be compared with initialization/1, but is intended for initialization operations of the runtime stacks, such as setting global variables as described in section 6.3. _G_o_a_l is run on four occasions: at the call to this predicate, after loading a saved state, on starting a new thread and on creating a Prolog engine through the C interface. On loading a saved state, _G_o_a_l is executed _a_f_t_e_r running the initialization/1 hooks. tthhrreeaadd__aatt__eexxiitt((_:_G_o_a_l)) Run _G_o_a_l just before releasing the thread resources. This is to be compared to at_halt/1, but only for the current thread. These hooks are ran regardless of why the execution of the thread has been completed. As these hooks are run, the return-code is already available through current_thread/2 using the result of thread_self/1 as thread-identifier. tthhrreeaadd__sseettccoonnccuurrrreennccyy((_-_O_l_d_, _+_N_e_w)) Determine the concurrency of the process, which is defined as the maximum number of concurrently active threads. `Active' here means they are using CPU time. This option is provided if the thread-implementation provides pthread_setconcurrency(). Solaris is a typical example of this family. On other systems this predicate unifies _O_l_d to 0 (zero) and succeeds silently. 88..22 MMoonniittoorriinngg tthhrreeaaddss Normal multi-threaded applications should not need these the predicates from this section because almost any usage of these predicates is unsafe. For example checking the existence of a thread before signalling it is of no use as it may vanish between the two calls. Catching exceptions using catch/3 is the only safe way to deal with thread-existence errors. These predicates are provided for diagnosis and monitoring tasks. See also section 8.5, describing more high-level primitives. ccuurrrreenntt__tthhrreeaadd((_?_I_d_, _?_S_t_a_t_u_s)) Enumerates identifiers and status of all currently known threads. Calling current_thread/2 does not influence any thread. See also thread_join/2. For threads that have an alias-name, this name is returned in _I_d instead of the numerical thread identifier. _S_t_a_t_u_s is one of: rruunnnniinngg The thread is running. This is the initial status of a thread. Please note that threads waiting for something are considered running too. ffaallssee The _G_o_a_l of the thread has been completed and failed. ttrruuee The _G_o_a_l of the thread has been completed and succeeded. eexxiitteedd((_T_e_r_m)) The _G_o_a_l of the thread has been terminated using thread_exit/1 with _T_e_r_m as argument. If the underlying native thread has exited (using pthread_exit()) _T_e_r_m is unbound. eexxcceeppttiioonn((_T_e_r_m)) The _G_o_a_l of the thread has been terminated due to an uncaught exception (see throw/1 and catch/3). tthhrreeaadd__ssttaattiissttiiccss((_+_I_d_, _+_K_e_y_, _-_V_a_l_u_e)) Obtains statistical information on thread _I_d as statistics/2 does in single-threaded applications. This call returns all keys of statistics/2, although only information statistics about the stacks and CPU time yield different values for each thread. mmuutteexx__ssttaattiissttiiccss Print usage statistics on internal mutexes and mutexes associated with dynamic predicates. For each mutex two numbers are printed: the number of times the mutex was acquired and the number of _c_o_l_l_i_s_i_o_n_s: the number times the calling thread has to wait for the mutex. The collision-count is not available on Windows as this would break portability to Windows-95/98/ME or significantly harm performance. Generally collision count is close to zero on single-CPU hardware. 88..22..11 LLiinnuuxx:: lliinnuuxxtthhrreeaaddss vvss.. NNPPTTLL Linux has introduces POSIX threads (pthread) using an implementation called _l_i_n_u_x_t_h_r_e_a_d_s, where each thread was `almost' a process. This approach has various disadvantages, such as poor performance and non-compliance with several aspects of POSIX. However, there is one advantage. Where pthread does not provide a way to get statistics per thread, we could get this info from the process-oriented times() function. Since the 2.6.x kernels, Linux by default now uses the _N_P_T_L implementation which is POSIX compliant. Unfortunately, getting per-thread CPU statistics involves reading /proc and is therefore too slow for some applications. SWI-Prolog is setup to run with the default thread model. Unfortunately there is no way to modify this at runtime, but there is a way to select the old thread model on modern machines at _l_i_n_k _t_i_m_e. This is achieved using the environment variable LD_ASSUME_KERNEL which must be set to a pre-nptl kernel version for linking the main executable. The value 2.4.21 is appropriate. When building from source, this flag can be set during the build process. When using a binary distribution one could create a minimal C program and relink the system using the plld utility. 88..33 TThhrreeaadd ccoommmmuunniiccaattiioonn 88..33..11 MMeessssaaggee qquueeuueess Prolog threads can exchange data using dynamic predicates, database records, and other globally shared data. These provide no suitable means to wait for data or a condition as they can only be checked in an expensive polling loop. _M_e_s_s_a_g_e _q_u_e_u_e_s provide a means for threads to wait for data or conditions without using the CPU. Each thread has a message-queue attached to it that is identified by the thread. Additional queues are created using message_queue_create/1. tthhrreeaadd__sseenndd__mmeessssaaggee((_+_Q_u_e_u_e_O_r_T_h_r_e_a_d_I_d_, _+_T_e_r_m)) Place _T_e_r_m in the given queue or default queue of the indicated thread (which can even be the message queue of itself (see thread_self/1). Any term can be placed in a message queue, but note that the term is copied to the receiving thread and variable-bindings are thus lost. This call returns immediately. If more than one thread is waiting for messages on the given queue and at least one of these is waiting with a partially instantiated _T_e_r_m, the waiting threads are _a_l_l sent a wake-up signal, starting a rush for the available messages in the queue. This behaviour can seriously harm performance with many threads waiting on the same queue as all-but-the-winner perform a useless scan of the queue. If there is only one waiting thread or all waiting threads wait with an unbound variable an arbitrary thread is restarted to scan the queue. tthhrreeaadd__ggeett__mmeessssaaggee((_?_T_e_r_m)) Examines the thread message-queue and if necessary blocks execution until a term that unifies to _T_e_r_m arrives in the queue. After a term from the queue has been unified unified to _T_e_r_m, the term is deleted from the queue and this predicate returns. Please note that not-unifying messages remain in the queue. After the following has been executed, thread 1 has the term b(_g_n_u) in its queue and continues execution using _A is gnat. thread_get_message(a(A)), thread_send_message(Thread_1, b(gnu)), thread_send_message(Thread_1, a(gnat)), See also thread_peek_message/1. tthhrreeaadd__ppeeeekk__mmeessssaaggee((_?_T_e_r_m)) Examines the thread message-queue and compares the queued terms with _T_e_r_m until one unifies or the end of the queue has been reached. In the first case the call succeeds (possibly instantiating _T_e_r_m. If no term from the queue unifies this call fails. mmeessssaaggee__qquueeuuee__ccrreeaattee((_?_Q_u_e_u_e)) If _Q_u_e_u_e is an atom, create a named queue. To avoid ambiguity of thread_send_message/2, the name of a queue may not be in use as a thread-name. If _Q_u_e_u_e is unbound an anonymous queue is created and _Q_u_e_u_e is unified to its identifier. mmeessssaaggee__qquueeuuee__ddeessttrrooyy((_+_Q_u_e_u_e)) Destroy a message queue created with message_queue_create/1. It is _n_o_t allows to destroy the queue of a thread. Neither is it allowed to destroy a queue other threads are waiting for or, for anonymous message queues, may try to wait for later. tthhrreeaadd__ggeett__mmeessssaaggee((_+_Q_u_e_u_e_, _?_T_e_r_m)) As thread_get_message/1, operating on a given queue. It is allowed (but not advised) to get messages from the queue of other threads. tthhrreeaadd__ppeeeekk__mmeessssaaggee((_+_Q_u_e_u_e_, _?_T_e_r_m)) As thread_peek_message/1, operating on a given queue. It is allowed to peek into another thread's message queue, an operation that can be used to check whether a thread has swallowed a message sent to it. mmeessssaaggee__qquueeuuee__ssiizzee((_+_Q_u_e_u_e_, _-_S_i_z_e)) Unify _S_i_z_e with the number of terms waiting in _Q_u_e_u_e. Note that due to concurrent access the returned value may be outdated before it is returned. It can be used for debugging purposes as well as work distribution purposes. Explicit message queues are designed with the _w_o_r_k_e_r_-_p_o_o_l model in mind, where multiple threads wait on a single queue and pick up the first goal to execute. Below is a simple implementation where the workers execute arbitrary Prolog goals. Note that this example provides no means to tell when all work is done. This must be realised using additional synchronisation. % create_workers(+Id, +N) % % Create a pool with given Id and number of workers. create_workers(Id, N) :- message_queue_create(Id), forall(between(1, N, _), thread_create(do_work(Id), _, [])). do_work(Id) :- repeat, thread_get_message(Id, Goal), ( catch(Goal, E, print_message(error, E)) -> true ; print_message(error, goal_failed(Goal, worker(Id))) ), fail. % work(+Id, +Goal) % % Post work to be done by the pool work(Id, Goal) :- thread_send_message(Id, Goal). 88..33..22 SSiiggnnaalllliinngg tthhrreeaaddss These predicates provide a mechanism to make another thread execute some goal as an _i_n_t_e_r_r_u_p_t. Signalling threads is safe as these interrupts are only checked at safe points in the virtual machine. Nevertheless, signalling in multi-threaded environments should be handled with care as the receiving thread may hold a _m_u_t_e_x (see with_mutex). Signalling probably only makes sense to start debugging threads and to cancel no-longer-needed threads with throw/1, where the receiving thread should be designed carefully do handle exceptions at any point. tthhrreeaadd__ssiiggnnaall((_+_T_h_r_e_a_d_I_d_, _:_G_o_a_l)) Make thread _T_h_r_e_a_d_I_d execute _G_o_a_l at the first opportunity. In the current implementation, this implies at the first pass through the _C_a_l_l_-_p_o_r_t. The predicate thread_signal/2 itself places _G_o_a_l into the signalled-thread's signal queue and returns immediately. Signals (interrupts) do not cooperate well with the world of multi-threading, mainly because the status of mutexes cannot be guaranteed easily. At the call-port, the Prolog virtual machine holds no locks and therefore the asynchronous execution is safe. _G_o_a_l can be any valid Prolog goal, including throw/1 to make the receiving thread generate an exception and trace/0 to start tracing the receiving thread. In the Windows version, the receiving thread immediately executes the signal if it reaches a Windows GetMessage() call, which generally happens of the thread is waiting for (user-)input. 88..33..33 TThhrreeaaddss aanndd ddyynnaammiicc pprreeddiiccaatteess Besides queues (section 8.3.1) threads can share and exchange data using dynamic predicates. The multi-threaded version knows about two types of dynamic predicates. By default, a predicate declared _d_y_n_a_m_i_c (see dynamic/1) is shared by all threads. Each thread may assert, retract and run the dynamic predicate. Synchronisation inside Prolog guarantees the consistency of the predicate. Updates are _l_o_g_i_c_a_l: visible clauses are not affected by assert/retract after a query started on the predicate. In many cases primitive from section 8.4 should be used to ensure application invariants on the predicate are maintained. Besides shared predicates, dynamic predicates can be declared with the thread_local/1 directive. Such predicates share their attributes, but the clause-list is different in each thread. tthhrreeaadd__llooccaall _+_F_u_n_c_t_o_r_/_+_A_r_i_t_y_, _._._. This directive is related to the dynamic/1 directive. It tells the system that the predicate may be modified using assert/1, retract/1, etc. during execution of the program. Unlike normal shared dynamic data however each thread has its own clause-list for the predicate. As a thread starts, this clause list is empty. If there are still clauses as the thread terminates these are automatically reclaimed by the system (see also volatile/1). The thread_local property implies the properties dynamic and volatile. Thread-local dynamic predicates are intended for maintaining thread-specific state or intermediate results of a computation. It is not recommended to put clauses for a thread-local predicate into a file as in the example below as the clause is only visible from the thread that loaded the source-file. All other threads start with an empty clause-list. :- thread_local foo/1. foo(gnat). DDIISSCCLLAAIIMMEERR Whether or not this declaration is appropriate in the sense of the proper mechanism to reach the goal is still debated. If you have strong feeling in favour or against, please share them in the SWI-Prolog mailing list. 88..44 TThhrreeaadd ssyynncchhrroonniissaattiioonn All internal Prolog operations are thread-safe. This implies two Prolog threads can operate on the same dynamic predicate without corrupting the consistency of the predicate. This section deals with user-level _m_u_t_e_x_e_s (called _m_o_n_i_t_o_r_s in ADA or _c_r_i_t_i_c_a_l_-_s_e_c_t_i_o_n_s by Microsoft). A mutex is a MMUUTTual EEXXclusive device, which implies at most one thread can _h_o_l_d a mutex. Mutexes are used to realise related updates to the Prolog database. With `related', we refer to the situation where a `transaction' implies two or more changes to the Prolog database. For example, we have a predicate address/2, representing the address of a person and we want to change the address by retracting the old and asserting the new address. Between these two operations the database is invalid: this person has either no address or two addresses, depending on the assert/retract order. Here is how to realise a correct update: :- initialization mutex_create(addressbook). change_address(Id, Address) :- mutex_lock(addressbook), retractall(address(Id, _)), asserta(address(Id, Address)), mutex_unlock(addressbook). mmuutteexx__ccrreeaattee((_?_M_u_t_e_x_I_d)) Create a mutex. if _M_u_t_e_x_I_d is an atom, a _n_a_m_e_d mutex is created. If it is a variable, an anonymous mutex reference is returned. There is no limit to the number of mutexes that can be created. mmuutteexx__ddeessttrrooyy((_+_M_u_t_e_x_I_d)) Destroy a mutex. After this call, _M_u_t_e_x_I_d becomes invalid and further references yield an existence_error exception. wwiitthh__mmuutteexx((_+_M_u_t_e_x_I_d_, _:_G_o_a_l)) Execute _G_o_a_l while holding _M_u_t_e_x_I_d. If _G_o_a_l leaves choice-points, these are destroyed (as in once/1). The mutex is unlocked regardless of whether _G_o_a_l succeeds, fails or raises an exception. An exception thrown by _G_o_a_l is re-thrown after the mutex has been successfully unlocked. See also mutex_create/1 and call_cleanup/3. Although described in the thread-section, this predicate is also available in the single-threaded version, where it behaves simply as once/1. mmuutteexx__lloocckk((_+_M_u_t_e_x_I_d)) Lock the mutex. Prolog mutexes are _r_e_c_u_r_s_i_v_e mutexes: they can be locked multiple times by the same thread. Only after unlocking it as many times as it is locked, the mutex becomes available for locking by other threads. If another thread has locked the mutex the calling thread is suspended until to mutex is unlocked. If _M_u_t_e_x_I_d is an atom, and there is no current mutex with that name, the mutex is created automatically using mutex_create/1. This implies named mutexes need not be declared explicitly. Please note that locking and unlocking mutexes should be paired carefully. Especially make sure to unlock mutexes even if the protected code fails or raises an exception. For most common cases use with_mutex/2, which provides a safer way for handling Prolog-level mutexes. The predicate call_cleanup/[2-3]is another way to guarantee that the mutex is unlocked while retaining non-determinism. mmuutteexx__ttrryylloocckk((_+_M_u_t_e_x_I_d)) As mutex_lock/1, but if the mutex is held by another thread, this predicates fails immediately. mmuutteexx__uunnlloocckk((_+_M_u_t_e_x_I_d)) Unlock the mutex. This can only be called if the mutex is held by the calling thread. If this is not the case, a permission_error exception is raised. mmuutteexx__uunnlloocckk__aallll Unlock all mutexes held by the current thread. This call is especially useful to handle thread-termination using abort/0 or exceptions. See also thread_signal/2. ccuurrrreenntt__mmuutteexx((_?_M_u_t_e_x_I_d_, _?_T_h_r_e_a_d_I_d_, _?_C_o_u_n_t)) Enumerates all existing mutexes. If the mutex is held by some thread, _T_h_r_e_a_d_I_d is unified with the identifier of the holding thread and _C_o_u_n_t with the recursive count of the mutex. Otherwise, _T_h_r_e_a_d_I_d is [] and _C_o_u_n_t is 0. 88..55 TThhrreeaadd--ssuuppppoorrtt lliibbrraarryy((tthhrreeaadduuttiill)) This library defines a couple of useful predicates for demonstrating and debugging multi-threaded applications. This library is certainly not complete. tthhrreeaaddss Lists all current threads and their status. jjooiinn__tthhrreeaaddss Join all terminated threads. For normal applications, dealing with terminated threads must be part of the application logic, either detaching the thread before termination or making sure it will be joined. The predicate join_threads/0 is intended for interactive sessions to reclaim resources from threads that died unexpectedly during development. iinntteerraaccttoorr Create a new console and run the Prolog top-level in this new console. See also attach_console/0. In the Windows version a new interactor can also be created from the Run/New thread menu. 88..55..11 DDeebbuuggggiinngg tthhrreeaaddss Support for debugging threads is still very limited. Debug and trace mode are flags that are local to each thread. Individual threads can be debugged either using the graphical debugger described in section 3.5 (see tspy/1 and friends) or by attaching a console to the thread and running the traditional command-line debugger (see attach_console/0). When using the graphical debugger, the debugger must be _l_o_a_d_e_d from the main thread (for example using guitracer) before gtrace/0 can be called from a thread. aattttaacchh__ccoonnssoollee If the current thread has no console attached yet, attach one and redirect the user streams (input, output, and error) to the new console window. On Unix systems the console is an xterm application. On Windows systems this requires the GUI version plwin.exe rather than the console based plcon.exe. This predicate has a couple of useful applications. One is to separate (debugging) I/O of different threads. Another is to start debugging a thread that is running in the background. If thread 10 is running, the following sequence starts the tracer on this thread: ?- thread_signal(10, (attach_console, trace)). ttddeebbuugg((_+_T_h_r_e_a_d_I_d)) Prepare _T_h_r_e_a_d_I_d for debugging using the graphical tracer. This implies installing the tracer hooks in the thread and switching the thread to debug-mode using debug/0. The call is injected into the thread using thread_signal/2. We refer to the documentation of this predicate for asynchronous interaction with threads. New threads created inherit their debug-mode from the thread that created them. ttddeebbuugg Call tdebug/1 in all running threads. ttnnooddeebbuugg((_+_T_h_r_e_a_d_I_d)) Disable debugging thread _T_h_r_e_a_d_I_d. ttnnooddeebbuugg Disable debugging in all threads. ttssppyy((_:_S_p_e_c_, _+_T_h_r_e_a_d_I_d)) Set a spy-point as spy/1 and enable the thread for debugging using tdebug/1. Note that a spy-point is a global flag on a predicate that is visible from all threads. Spy points are honoured in all threads that are in debug-mode and ignored in threads that are in nodebug mode. ttssppyy((_:_S_p_e_c)) Set a spy-point as spy/1 and enable debugging in all threads using tdebug/0. Note that removing spy-points can be done using nospy/1. Disabling spy-points in a specific thread is achieved by tnodebug/1. 88..55..22 PPrrooffiilliinngg tthhrreeaaddss In the current implementation, at most one thread can be profiled at any moment. Any thread can call profile/1 to profile the execution of some part of its code. The predicate tprofile/1 allows for profiling the execution of another thread until the user stops collecting profile data. ttpprrooffiillee((_+_T_h_r_e_a_d_I_d)) Start collecting profile data in _T_h_r_e_a_d_I_d and ask the user to hit <_r_e_t_u_r_n> to stop the profiler. See section 4.40 for details on the execution profiler. 88..66 MMuullttii--tthhrreeaaddeedd mmiixxeedd CC aanndd PPrroolloogg aapppplliiccaattiioonnss All foreign-code linked to the multi-threading version of SWI-Prolog should be thread-safe (_r_e_e_n_t_r_a_n_t) or guarded in Prolog using with_mutex/2 from simultaneous access from multiple Prolog threads. If you want to write mixed multi-threaded C and Prolog application you should first familiarise yourself with writing multi-threaded applications in C (C++). If you are using SWI-Prolog as an embedded engine in a multi-threaded application you can access the Prolog engine from multiple threads by creating an _e_n_g_i_n_e in each thread from which you call Prolog. Without creating an engine, a thread can only use functions that do _n_o_t use the term_t type (for example PL_new_atom()). The system supports two models. Section 8.6.1 describes the original one-to-one mapping. In this schema a native thread attaches a Prolog thread if it needs to call Prolog and detaches is when finished, as opposed to the model from section 8.6.2 where threads temporary use a Prolog engine. PPlleeaassee nnoottee tthhaatt tthhee iinntteerrffaaccee bbeellooww wwiillll oonnllyy wwoorrkk iiff tthhrreeaaddiinngg iinn yyoouurr aapppplliiccaattiioonn iiss bbaasseedd oonn tthhee ssaammee tthhrreeaadd--lliibbrraarryy aass uusseedd ttoo ccoommppiillee SSWWII--PPrroolloogg.. 88..66..11 AA PPrroolloogg tthhrreeaadd ffoorr eeaacchh nnaattiivvee tthhrreeaadd ((oonnee--ttoo--oonnee)) In the one-to-one model, the thread that called PL_initialise() has a Prolog engine attached. If another C-thread in the system wishes to call Prolog it must first attach an engine using PL_thread_attach_engine() and call PL_thread_destroy_engine() after all Prolog work is finished. This model is especially suitable with long running threads that need to do Prolog work regularly. See section 8.6.2 for the alternative many-to-many model. int PPLL__tthhrreeaadd__sseellff() Returns the integer Prolog identifier of the engine or -1 if the calling thread has no Prolog engine. This function is also provided in the single-threaded version of SWI-Prolog, where it returns -2. int PPLL__tthhrreeaadd__aattttaacchh__eennggiinnee(_c_o_n_s_t _P_L___t_h_r_e_a_d___a_t_t_r___t _*_a_t_t_r) Creates a new Prolog engine in the calling thread. If the calling thread already has an engine the reference count of the engine is incremented. The _a_t_t_r argument can be NULL to create a thread with default attributes. Otherwise it is a pointer to a structure with the definition below. For any field with value `0', the default is used. The cancel field may be filled with a pointer to a function that is called when PL_cleanup() terminates the running Prolog engines. If this function is not present or returns FALSE pthread_cancel() is used. typedef struct { unsigned long local_size; /* Stack sizes (K-bytes) */ unsigned long global_size; unsigned long trail_size; unsigned long argument_size; char * alias; /* alias name */ int (*cancel)(int thread); } PL_thread_attr_t; The structure may be destroyed after PL_thread_attach_engine() has returned. On success it returns the Prolog identifier for the thread (as returned by PL_thread_self()). If an error occurs, -1 is returned. If this Prolog is not compiled for multi-threading, -2 is returned. int PPLL__tthhrreeaadd__ddeessttrrooyy__eennggiinnee() Destroy the Prolog engine in the calling thread. Only takes effect if PL_thread_destroy_engine() is called as many times as PL_thread_attach_engine() in this thread. Returns TRUE on success and FALSE if the calling thread has no engine or this Prolog does not support threads. Please note that construction and destruction of engines are relatively expensive operations. Only destroy an engine if performance is not critical and memory is a critical resource. int PPLL__tthhrreeaadd__aatt__eexxiitt(_v_o_i_d _(_*_f_u_n_c_t_i_o_n_)_(_v_o_i_d _*_)_, _v_o_i_d _*_c_l_o_s_u_r_e_, _i_n_t _g_l_o_b_a_l) Register a handle to be called as the Prolog engine is destroyed. The handler function is called with one void * argument holding _c_l_o_s_u_r_e. If _g_l_o_b_a_l is TRUE, the handler is installed _f_o_r _a_l_l _t_h_r_e_a_d_s. Globally installed handlers are executed after the thread-local handlers. If the handler is installed local for the current thread only (_g_l_o_b_a_l == FALSE) it is stored in the same FIFO queue as used by thread_at_exit/1. 88..66..22 PPoooolliinngg PPrroolloogg eennggiinneess ((mmaannyy--ttoo--mmaannyy)) In this model Prolog engines live as entities that are independent from threads. If a thread needs to call Prolog it takes one of the engines from the pool and returns the engine when done. This model is suitable in the following identified cases: o _C_o_m_p_a_t_i_b_i_l_i_t_y _w_i_t_h _t_h_e _s_i_n_g_l_e_-_t_h_r_e_a_d_e_d _v_e_r_s_i_o_n In the single-threaded version, foreign threads must serialise access the the one and only thread engine. Functions from this section allow sharing one engine among multiple threads. o _M_a_n_y _n_a_t_i_v_e _t_h_r_e_a_d_s _w_i_t_h _i_n_f_r_e_q_u_e_n_t _P_r_o_l_o_g _w_o_r_k Prolog threads are expensive in terms of memory and time to create and destroy them. Systems that use a large number of threads that only infrequently need to call Prolog are better take an engine from a pool and return it there. o _P_r_o_l_o_g _s_t_a_t_u_s _m_u_s_t _b_e _h_a_n_d_e_d _t_o _a_n_o_t_h_e_r _t_h_r_e_a_d This situation has been identified by Uwe Lesta when creating a .NET interface for SWI-Prolog. .NET distributes work for active internet connection over a pool of threads. If a Prolog engine contains state for a connection, it must be possible to detach the engine from a thread and re-attach it to another thread handling the same connection. PL_engine_t PPLL__ccrreeaattee__eennggiinnee(_P_L___t_h_r_e_a_d___a_t_t_r___t _*_a_t_t_r_i_b_u_t_e_s) Create a new Prolog engine. _a_t_t_r_i_b_u_t_e_s is described with PL_thread_attach_engine(). Any thread can make this call after PL_initialise() returned success. The returned engine is not attached to any thread and lives until PL_destroy_engine() is used on the returned handle. In the single-threaded version this call always returns NULL, indicating failure. int PPLL__ddeessttrrooyy__eennggiinnee(_P_L___e_n_g_i_n_e___t _e) Destroy the given engine. Destroying an engine is only allowed if the engine is not attached to any thread or attached to the calling thread. On success this function returns TRUE, on failure the return value is FALSE. int PPLL__sseett__eennggiinnee(_P_L___e_n_g_i_n_e___t _e_n_g_i_n_e_, _P_L___e_n_g_i_n_e___t _*_o_l_d) Make the calling thread ready to use _e_n_g_i_n_e. If _o_l_d is non-NULL the current engine associated with the calling thread is stored at the given location. If _e_n_g_i_n_e equals PL_ENGINE_MAIN the initial engine is attached to the calling thread. If _e_n_g_i_n_e is PL_ENGINE_CURRENT the engine is not changed. This can be used to query the current engine. This call returns PL_ENGINE_SET if the engine was switched successfully, PL_ENGINE_INVAL if _e_n_g_i_n_e is not a valid engine handle and PL_ENGINE_INUSE if the engine is currently in use by another thread. Engines can be changed at any time. For example, it is allowed to select an engine to initiate a Prolog goal, detach it and at a later moment execute the goal from another thread. Note however that the term_t, qid_t and fid_t types are interpreted relative to the engine for which they are created. Behaviour when passing one of these types from one engine to another is undefined. In the single-threaded version this call only succeeds if _e_n_g_i_n_e refers to the main engine. 88..66..22..11 EEnnggiinneess iinn ssiinnggllee--tthhrreeaaddeedd SSWWII--PPrroolloogg In theory it is possible to port the API of section 8.6.2 to the single-threaded version of SWI-Prolog. This allows C-programs to control multiple Prolog engines concurrently. This has not yet been realised. 88..77 MMuullttiitthhrreeaaddiinngg aanndd tthhee XXPPCCEE ggrraapphhiiccss ssyysstteemm GUI applications written in XPCE can benefit from the multi-threaded version of XPCE/SWI-Prolog if they need to do expensive computations that block to UI in the single-threaded version. Due to various technical problems on both Windows and Unix/X11 threading is best exploited by handing long computations to their own thread. The XPCE message passing system is guarded with a single _m_u_t_e_x, which synchronises both access from Prolog and activation through the GUI. In MS-Windows, GUI events are processed by the thread that created the window in which the event occurred, whereas in Unix/X11 they are processed by the thread that dispatches messages. Some tentative work is underway to improve the integration between XPCE and multi-threaded SWI-Prolog. There are two sets of support predicates. The first model assumes that XPCE is running in the main thread and background threads are used for computation. In the second model, XPCE event dispatching runs in the background, while the foreground thread is used for Prolog. XXPPCCEE iinn tthhee ffoorreeggrroouunndd Using XPCE in the foreground simplifies debugging of the UI and generally provides the most comfortable development environment. The GUI creates new threads using thread_create/3 and, after work in the thread is completed, the sub-thread signals the main thread of the the completion using in_pce_thread/1. iinn__ppccee__tthhrreeaadd((_:_G_o_a_l)) Assuming XPCE is running in the foreground thread, this call gives background threads the opportunity to make calls to the XPCE thread. A call to in_pce_thread/1 succeeds immediately, copying _G_o_a_l to the XPCE thread. _G_o_a_l is added to the XPCE event-queue and executed synchronous to normal user events like typing and clicking. XXPPCCEE iinn tthhee bbaacckkggrroouunndd In this model a thread for running XPCE is created using pce_dispatch/1 and actions are sent to this thread using pce_call/1. ppccee__ddiissppaattcchh((_+_O_p_t_i_o_n_s)) Create a Prolog thread with the alias-name pce for XPCE event-handling. In the X11 version this call creates a thread that executes the X11 event-dispatch loop. In MS-Windows it creates a thread that executes a windows event-dispatch loop. The XPCE event-handling thread has the alias pce. _O_p_t_i_o_n_s specifies the thread-attributes as thread_create/3. ppccee__ccaallll((_:_G_o_a_l)) Post _G_o_a_l to the pce thread, executing it synchronous with the thread's event-loop. The pce_call/1 predicate returns immediately without waiting. Note that _G_o_a_l is _c_o_p_i_e_d to the pce thread. For further information about XPCE in threaded applications, please visit http://gollem.science.uva.nl/twiki/pl/bin/view/Development/MultiThreadsXPCE CChhaapptteerr 99.. FFOORREEIIGGNN LLAANNGGUUAAGGEE IINNTTEERRFFAACCEE SWI-Prolog offers a powerful interface to C [Kernighan & Ritchie, 1978]. The main design objectives of the foreign language interface are flexibility and performance. A foreign predicate is a C-function that has the same number of arguments as the predicate represented. C-functions are provided to analyse the passed terms, convert them to basic C-types as well as to instantiate arguments using unification. Non-deterministic foreign predicates are supported, providing the foreign function with a handle to control backtracking. C can call Prolog predicates, providing both an query interface and an interface to extract multiple solutions from an non-deterministic Prolog predicate. There is no limit to the nesting of Prolog calling C, calling Prolog, etc. It is also possible to write the `main' in C and use Prolog as an embedded logical engine. 99..11 OOvveerrvviieeww ooff tthhee IInntteerrffaaccee A special include file called SWI-Prolog.h should be included with each C-source file that is to be loaded via the foreign interface. The installation process installs this file in the directory include in the SWI-Prolog home directory (?- current_prolog_flag(home, Home).). This C-header file defines various data types, macros and functions that can be used to communicate with SWI-Prolog. Functions and macros can be divided into the following categories: o Analysing Prolog terms o Constructing new terms o Unifying terms o Returning control information to Prolog o Registering foreign predicates with Prolog o Calling Prolog from C o Recorded database interactions o Global actions on Prolog (halt, break, abort, etc.) 99..22 LLiinnkkiinngg FFoorreeiiggnn MMoodduulleess Foreign modules may be linked to Prolog in two ways. Using _s_t_a_t_i_c _l_i_n_k_i_n_g, the extensions, a (short) file defining main() which attaches the extensions calls Prolog and the SWI-Prolog kernel distributed as a C-library are linked together to form a new executable. Using _d_y_n_a_m_i_c _l_i_n_k_i_n_g, the extensions are linked to a shared library (.so file on most Unix systems) or dynamic-link library (.DLL file on Microsoft platforms) and loaded into the the running Prolog process.. 99..22..11 WWhhaatt lliinnkkiinngg iiss pprroovviiddeedd?? The _s_t_a_t_i_c _l_i_n_k_i_n_g schema can be used on all versions of SWI-Prolog. Whether or not dynamic linking is supported can be deduced from the prolog-flag open_shared_object (see current_prolog_flag/2). If this prolog-flag yields true, open_shared_object/2 and related predicates are defined. See section 9.4 for a suitable high-level interface to these predicates. 99..22..22 WWhhaatt kkiinndd ooff llooaaddiinngg sshhoouulldd II bbee uussiinngg?? All described approaches have their advantages and disadvantages. Static linking is portable and allows for debugging on all platforms. It is relatively cumbersome and the libraries you need to pass to the linker may vary from system to system, though the utility program plld described in section 9.7 often hides these problems from the user. Loading shared objects (DLL files on Windows) provides sharing and protection and is generally the best choice. If a saved-state is created using qsave_program/[1,2], an initialization/1 directive may be used to load the appropriate library at startup. Note that the definition of the foreign predicates is the same, regardless of the linking type used. 99..33 DDyynnaammiicc LLiinnkkiinngg ooff sshhaarreedd lliibbrraarriieess The interface defined in this section allows the user to load shared libraries (.so files on most Unix systems, .dll files on Windows). This interface is portable to Windows as well as to Unix machines providing dlopen(2) (Solaris, Linux, FreeBSD, Irix and many more) or shl_open(2) (HP/UX). It is advised to use the predicates from section 9.4 in your application. ooppeenn__sshhaarreedd__oobbjjeecctt((_+_F_i_l_e_, _-_H_a_n_d_l_e)) _F_i_l_e is the name of a shared object file (called dynamic load library in MS-Windows). This file is attached to the current process and _H_a_n_d_l_e is unified with a handle to the library. Equivalent to open_shared_object(File, [], Handle). See also load_foreign_library/[1,2]. On errors, an exception shared_object(_A_c_t_i_o_n_, _M_e_s_s_a_g_e) is raised. _M_e_s_s_a_g_e is the return value from dlerror(). ooppeenn__sshhaarreedd__oobbjjeecctt((_+_F_i_l_e_, _-_H_a_n_d_l_e_, _+_O_p_t_i_o_n_s)) As open_shared_object/2, but allows for additional flags to be passed. _O_p_t_i_o_n_s is a list of atoms. now implies the symbols are resolved immediately rather than lazy (default). global implies symbols of the loaded object are visible while loading other shared objects (by default they are local). Note that these flags may not be supported by your operating system. Check the documentation of dlopen() or equivalent on your operating system. Unsupported flags are silently ignored. cclloossee__sshhaarreedd__oobbjjeecctt((_+_H_a_n_d_l_e)) Detach the shared object identified by _H_a_n_d_l_e. ccaallll__sshhaarreedd__oobbjjeecctt__ffuunnccttiioonn((_+_H_a_n_d_l_e_, _+_F_u_n_c_t_i_o_n)) Call the named function in the loaded shared library. The function is called without arguments and the return-value is ignored. Normally this function installs foreign language predicates using calls to PL_register_foreign(). 99..44 UUssiinngg tthhee lliibbrraarryy sshhlliibb ffoorr .DLL aanndd .so ffiilleess This section discusses the functionality of the (autoload) library shlib.pl, providing an interface to shared libraries. This library can only be used if the prolog-flag open_shared_object is enabled. llooaadd__ffoorreeiiggnn__lliibbrraarryy((_+_L_i_b_, _+_E_n_t_r_y)) Search for the given foreign library and link it to the current SWI-Prolog instance. The library may be specified with or without the extension. First, absolute_file_name/3 is used to locate the file. If this succeeds, the full path is passed to the low-level function to open the library. Otherwise, the plain library name is passed, exploiting the operating-system defined search mechanism for the shared library. The file_search_path/2 alias mechanism defines the alias foreign, which refers to the directories <_p_l_h_o_m_e>/lib/<_a_r_c_h>and <_p_l_h_o_m_e>/lib, in this order. If the library can be loaded, the function called _E_n_t_r_y will be called without arguments. The return value of the function is ignored. The _E_n_t_r_y function will normally call PL_register_foreign() to declare functions in the library as foreign predicates. llooaadd__ffoorreeiiggnn__lliibbrraarryy((_+_L_i_b)) Equivalent to load_foreign_library/2. For the entry-point, this function first identifies the `base-name' of the library, which is defined to be the file-name with path nor extension. It will then try the entry-point install-<_b_a_s_e>. On failure it will try to function install(). Otherwise no install function will be called. uunnllooaadd__ffoorreeiiggnn__lliibbrraarryy((_+_L_i_b)) If the foreign library defines the function uninstall_<_b_a_s_e>() or uninstall(), this function will be called without arguments and its return value is ignored. Next, abolish/2 is used to remove all known foreign predicates defined in the library. Finally the library itself is detached from the process. ccuurrrreenntt__ffoorreeiiggnn__lliibbrraarryy((_-_L_i_b_, _-_P_r_e_d_i_c_a_t_e_s)) Query the currently loaded foreign libraries and their predicates. _P_r_e_d_i_c_a_t_e_s is a list with elements of the form _M_o_d_u_l_e_:_H_e_a_d, indicating the predicates installed with PL_register_foreign() when the entry-point of the library was called. Figure 9.1 connects a Windows message-box using a foreign function. This example was tested using Windows NT and Microsoft Visual C++ 2.0. #include #include static foreign_t pl_say_hello(term_t to) { char *a; if ( PL_get_atom_chars(to, &a) ) { MessageBox(NULL, a, "DLL test", MB_OK|MB_TASKMODAL); PL_succeed; } PL_fail; } install_t install() { PL_register_foreign("say_hello", 1, pl_say_hello, 0); } Figure 9.1: MessageBox() example in Windows NT 99..44..11 SSttaattiicc LLiinnkkiinngg Below is an outline of the files structure required for statically linking SWI-Prolog with foreign extensions. \ldots/pl refers to the SWI-Prolog home directory (see current_prolog_flag/2). <_a_r_c_h> refers to the architecture identifier that may be obtained using current_prolog_flag/2. .../pl/runtime/<_a_r_c_h>/libpl.a SWI-Library .../pl/include/SWI-Prolog.h Include file .../pl/include/SWI-Stream.h Stream I/O include file .../pl/include/SWI-Exports Export declarations (AIX only) .../pl/include/stub.c Extension stub The definition of the foreign predicates is the same as for dynamic linking. Unlike with dynamic linking however, there is no initialisation function. Instead, the file \ldots/pl/include/stub.c may be copied to your project and modified to define the foreign extensions. Below is stub.c, modified to link the lowercase example described later in this chapter: #include #include extern foreign_t pl_lowercase(term, term); PL_extension predicates[] = { /*{ "name", arity, function, PL_FA_ },*/ { "lowercase", 2 pl_lowercase, 0 }, { NULL, 0, NULL, 0 } /* terminating line */ }; int main(int argc, char **argv) { PL_register_extensions(predicates); if ( !PL_initialise(argc, argv) ) PL_halt(1); PL_install_readline(); /* delete if not required */ PL_halt(PL_toplevel() ? 0 : 1); } Now, a new executable may be created by compiling this file and linking it to libpl.a from the runtime directory and the libraries required by both the extensions and the SWI-Prolog kernel. This may be done by hand, or using the plld utility described in secrefplld. If the linking is performed `by hand', the command-line option -dump-runtime-variables (see section 2.4) can be used to obtain the required paths, libraries and linking options to link the new executable. 99..55 IInntteerrffaaccee DDaattaa ttyyppeess 99..55..11 TTyyppee term_t:: aa rreeffeerreennccee ttoo aa PPrroolloogg tteerrmm The principal data-type is term_t. Type term_t is what Quintus calls QP_term_ref. This name indicates better what the type represents: it is a _h_a_n_d_l_e for a term rather than the term itself. Terms can only be represented and manipulated using this type, as this is the only safe way to ensure the Prolog kernel is aware of all terms referenced by foreign code and thus allows the kernel to perform garbage-collection and/or stack-shifts while foreign code is active, for example during a callback from C. A term reference is a C unsigned long, representing the offset of a variable on the Prolog environment-stack. A foreign function is passed term references for the predicate-arguments, one for each argument. If references for intermediate results are needed, such references may be created using PL_new_term_ref() or PL_new_term_refs(). These references normally live till the foreign function returns control back to Prolog. Their scope can be explicitly limited using PL_open_foreign_frame() and PL_close_foreign_frame()/PL_discard_foreign_frame(). A term_t always refers to a valid Prolog term (variable, atom, integer, float or compound term). A term lives either until backtracking takes us back to a point before the term was created, the garbage collector has collected the term or the term was created after a PL_open_foreign_frame() and PL_discard_foreign_frame() has been called. The foreign-interface functions can either _r_e_a_d, _u_n_i_f_y or _w_r_i_t_e to term-references. In the this document we use the following notation for arguments of type term_t: term_t +t Accessed in read-mode. The `+' indicates the argument is `input'. term_t -t Accessed in write-mode. term_t ?t Accessed in unify-mode. Term references are obtained in any of the following ways. o _P_a_s_s_e_d _a_s _a_r_g_u_m_e_n_t The C-functions implementing foreign predicates are passed their arguments as term-references. These references may be read or unified. Writing to these variables causes undefined behaviour. o _C_r_e_a_t_e_d _b_y _P_L___n_e_w___t_e_r_m___r_e_f_(_) A term created by PL_new_term_ref() is normally used to build temporary terms or be written by one of the interface functions. For example, PL_get_arg() writes a reference to the term-argument in its last argument. o _C_r_e_a_t_e_d _b_y _P_L___n_e_w___t_e_r_m___r_e_f_s_(_i_n_t _n_) This function returns a set of term refs with the same characteristics as PL_new_term_ref(). See PL_open_query(). o _C_r_e_a_t_e_d _b_y _P_L___c_o_p_y___t_e_r_m___r_e_f_(_t_e_r_m___t _t_) Creates a new term-reference to the same term as the argument. The term may be written to. See figure 9.3. Term-references can safely be copied to other C-variables of type term_t, but all copies will always refer to the same term. term_t PPLL__nneeww__tteerrmm__rreeff() Return a fresh reference to a term. The reference is allocated on the _l_o_c_a_l stack. Allocating a term-reference may trigger a stack-shift on machines that cannot use sparse-memory management for allocation the Prolog stacks. The returned reference describes a variable. term_t PPLL__nneeww__tteerrmm__rreeffss(_i_n_t _n) Return _n new term references. The first term-reference is returned. The others are _t +1, _t +2, etc. There are two reasons for using this function. PL_open_query() expects the arguments as a set of consecutive term references and _v_e_r_y time-critical code requiring a number of term-references can be written as: pl_mypredicate(term_t a0, term_t a1) { term_t t0 = PL_new_term_refs(2); term_t t1 = t0+1; ... } term_t PPLL__ccooppyy__tteerrmm__rreeff(_t_e_r_m___t _f_r_o_m) Create a new term reference and make it point initially to the same term as _f_r_o_m. This function is commonly used to copy a predicate argument to a term reference that may be written. void PPLL__rreesseett__tteerrmm__rreeffss(_t_e_r_m___t _a_f_t_e_r) Destroy all term references that have been created after _a_f_t_e_r, including _a_f_t_e_r itself. Any reference to the invalidated term references after this call results in undefined behaviour. Note that returning from the foreign context to Prolog will reclaim all references used in the foreign context. This call is only necessary if references are created inside a loop that never exits back to Prolog. See also PL_open_foreign_frame(), PL_close_foreign_frame() and PL_discard_foreign_frame(). 99..55..11..11 IInntteerraaccttiioonn wwiitthh tthhee ggaarrbbaaggee ccoolllleeccttoorr aanndd ssttaacckk--sshhiifftteerr Prolog implements two mechanisms for avoiding stack overflow: garbage collection and stack expansion. On machines that allow for it, Prolog will use virtual memory management to detect stack overflow and expand the runtime stacks. On other machines Prolog will reallocate the stacks and update all pointers to them. To do so, Prolog needs to know which data is referenced by C-code. As all Prolog data known by C is referenced through term references (term_t), Prolog has all information necessary to perform its memory management without special precautions from the C-programmer. 99..55..22 OOtthheerr ffoorreeiiggnn iinntteerrffaaccee ttyyppeess aattoomm__tt An atom in Prologs internal representation. Atoms are pointers to an opaque structure. They are a unique representation for represented text, which implies that atom A represents the same text as atom B if-and-only-if A and B are the same pointer. Atoms are the central representation for textual constants in Prolog The transformation of C a character string to an atom implies a hash-table lookup. If the same atom is needed often, it is advised to store its reference in a global variable to avoid repeated lookup. ffuunnccttoorr__tt A functor is the internal representation of a name/arity pair. They are used to find the name and arity of a compound term as well as to construct new compound terms. Like atoms they live for the whole Prolog session and are unique. pprreeddiiccaattee__tt Handle to a Prolog predicate. Predicate handles live forever (although they can loose their definition). qqiidd__tt Query Identifier. Used by PL_open_query()/PL_next_solution()/PL_close_query() to handle back- tracking from C. ffiidd__tt Frame Identifier. Used by PL_open_foreign_frame()/PL_close_foreign_frame(). mmoodduullee__tt A module is a unique handle to a Prolog module. Modules are used only to call predicates in a specific module. ffoorreeiiggnn__tt Return type for a C-function implementing a Prolog predicate. ccoonnttrrooll__tt Passed as additional argument to non-deterministic foreign functions. See PL_retry*() and PL_foreign_context*(). iinnssttaallll__tt Type for the install() and uninstall() functions of shared or dynamic link libraries. See secrefshlib. iinntt6644__tt Actually part of the C99 standard rather than Prolog. As of version 5.5.6, Prolog integers are 64-bit on all hardware. The C99 type int64_t is defined in the stdint.h standard header and provides platform independent 64-bit integers. Portable code accessing Prolog should use this type to exchange integer values. Please note that PL_get_long() can return FALSE on Prolog integers outside the long domain. Robust code should not assume any of the integer fetching functions to succeed if the Prolog term is know to be an integer. 99..66 TThhee FFoorreeiiggnn IInncclluuddee FFiillee 99..66..11 AArrgguummeenntt PPaassssiinngg aanndd CCoonnttrrooll If Prolog encounters a foreign predicate at run time it will call a function specified in the predicate definition of the foreign predicate. The arguments 1;:::; <_a_r_i_t_y>pass the Prolog arguments to the goal as Prolog terms. Foreign functions should be declared of type foreign_t. Deterministic foreign functions have two alternatives to return control back to Prolog: _(_r_e_t_u_r_n_) _f_o_r_e_i_g_n___t PPLL__ssuucccceeeedd(()) Succeed deterministically. PL_succeed is defined as return TRUE. _(_r_e_t_u_r_n_) _f_o_r_e_i_g_n___t PPLL__ffaaiill(()) Fail and start Prolog backtracking. PL_fail is defined as return FALSE. 99..66..11..11 NNoonn--ddeetteerrmmiinniissttiicc FFoorreeiiggnn PPrreeddiiccaatteess By default foreign predicates are deterministic. Using the PL_FA_NONDETERMINISTIC attribute (see PL_register_foreign()) it is possible to register a predicate as a non-deterministic predicate. Writing non-deterministic foreign predicates is slightly more complicated as the foreign function needs context information for generating the next solution. Note that the same foreign function should be prepared to be simultaneously active in more than one goal. Suppose the natural_number_below_n/2 is a non-deterministic foreign predicate, backtracking over all natural numbers lower than the first argument. Now consider the following predicate: quotient_below_n(Q, N) :- natural_number_below_n(N, N1), natural_number_below_n(N, N2), Q =:= N1 / N2, !. In this predicate the function natural_number_below_n/2 simultaneously generates solutions for both its invocations. Non-deterministic foreign functions should be prepared to handle three different calls from Prolog: o _I_n_i_t_i_a_l _c_a_l_l _(PL_FIRST_CALL_) Prolog has just created a frame for the foreign function and asks it to produce the first answer. o _R_e_d_o _c_a_l_l _(PL_REDO_) The previous invocation of the foreign function associated with the current goal indicated it was possible to backtrack. The foreign function should produce the next solution. o _T_e_r_m_i_n_a_t_e _c_a_l_l _(PL_CUTTED_) The choice point left by the foreign function has been destroyed by a cut. The foreign function is given the opportunity to clean the environment. Both the context information and the type of call is provided by an argument of type control_t appended to the argument list for deterministic foreign functions. The macro PL_foreign_control() extracts the type of call from the control argument. The foreign function can pass a context handle using the PL_retry*() macros and extract the handle from the extra argument using the PL_foreign_context*() macro. _(_r_e_t_u_r_n_) _f_o_r_e_i_g_n___t PPLL__rreettrryy((_l_o_n_g)) The foreign function succeeds while leaving a choice point. On backtracking over this goal the foreign function will be called again, but the control argument now indicates it is a `Redo' call and the macro PL_foreign_context() returns the handle passed via PL_retry(). This handle is a 30 bits signed value (two bits are used for status indication). Defined as return _PL_retry(n). See also PL_succeed(). _(_r_e_t_u_r_n_) _f_o_r_e_i_g_n___t PPLL__rreettrryy__aaddddrreessss((_v_o_i_d _*)) As PL_retry(), but ensures an address as returned by malloc() is correctly recovered by PL_foreign_context_address(). Defined as return _PL_retry_address(n). See also PL_succeed(). _i_n_t PPLL__ffoorreeiiggnn__ccoonnttrrooll((_c_o_n_t_r_o_l___t)) Extracts the type of call from the control argument. The return values are described above. Note that the function should be prepared to handle the PL_CUTTED case and should be aware that the other arguments are not valid in this case. _l_o_n_g PPLL__ffoorreeiiggnn__ccoonntteexxtt((_c_o_n_t_r_o_l___t)) Extracts the context from the context argument. In the call type is PL_FIRST_CALL the context value is 0L. Otherwise it is the value returned by the last PL_retry() associated with this goal (both if the call type is PL_REDO as PL_CUTTED). _v_o_i_d _* PPLL__ffoorreeiiggnn__ccoonntteexxtt__aaddddrreessss((_c_o_n_t_r_o_l___t)) Extracts an address as passed in by PL_retry_address(). Note: If a non-deterministic foreign function returns using PL_succeed or PL_fail, Prolog assumes the foreign function has cleaned its environment. NNoo call with control argument PL_CUTTED will follow. The code of figure 9.2 shows a skeleton for a non-deterministic foreign predicate definition. typedef struct /* define a context structure */ { ... } context; foreign_t my_function(term_t a0, term_t a1, control_t handle) { struct context * ctxt; switch( PL_foreign_control(handle) ) { case PL_FIRST_CALL: ctxt = malloc(sizeof(struct context)); ... PL_retry_address(ctxt); case PL_REDO: ctxt = PL_foreign_context_address(handle); ... PL_retry_address(ctxt); case PL_CUTTED: ctxt = PL_foreign_context_address(handle); ... free(ctxt); PL_succeed; } } Figure 9.2: Skeleton for non-deterministic foreign functions 99..66..22 AAttoommss aanndd ffuunnccttoorrss The following functions provide for communication using atoms and functors. atom_t PPLL__nneeww__aattoomm(_c_o_n_s_t _c_h_a_r _*) Return an atom handle for the given C-string. This function always succeeds. The returned handle is valid as long as the atom is referenced (see section 9.6.2.1). const char* PPLL__aattoomm__cchhaarrss(_a_t_o_m___t _a_t_o_m) Return a C-string for the text represented by the given atom. The returned text will not be changed by Prolog. It is not allowed to modify the contents, not even `temporary' as the string may reside in read-only memory. The returned string becomes invalid if the atom is garbage-collected (see section 9.6.2.1). Foreign functions that require the text from an atom passed in a term_t normally use PL_get_atom_chars() or PL_get_atom_nchars(). functor_t PPLL__nneeww__ffuunnccttoorr(_a_t_o_m___t _n_a_m_e_, _i_n_t _a_r_i_t_y) Returns a _f_u_n_c_t_o_r _i_d_e_n_t_i_f_i_e_r, a handle for the name/arity pair. The returned handle is valid for the entire Prolog session. atom_t PPLL__ffuunnccttoorr__nnaammee(_f_u_n_c_t_o_r___t _f) Return an atom representing the name of the given functor. int PPLL__ffuunnccttoorr__aarriittyy(_f_u_n_c_t_o_r___t _f) Return the arity of the given functor. 99..66..22..11 AAttoommss aanndd aattoomm--ggaarrbbaaggee ccoolllleeccttiioonn With the introduction of atom-garbage collection in version 3.3.0, atoms no longer live as long as the process. Instead, their lifetime is guaranteed only as long as they are referenced. In the single-threaded version, atom garbage collections are only invoked at the _c_a_l_l_-_p_o_r_t. In the multi-threaded version (see section 8, they appear asynchronously, except for the invoking thread. For dealing with atom garbage collection, two additional functions are provided: void PPLL__rreeggiisstteerr__aattoomm(_a_t_o_m___t _a_t_o_m) Increment the reference count of the atom by one. PL_new_atom() performs this automatically, returning an atom with a reference count of at least one. void PPLL__uunnrreeggiisstteerr__aattoomm(_a_t_o_m___t _a_t_o_m) Decrement the reference count of the atom. If the reference-count drops below zero, an assertion error is raised. Please note that the following two calls are different with respect to atom garbage collection: PL_unify_atom_chars(t, "text"); PL_unify_atom(t, PL_new_atom("text")); The latter increments the reference count of the atom text, which effectively ensures the atom will never be collected. It is advised to use the *_chars() or *_nchars() functions whenever applicable. 99..66..33 AAnnaallyyssiinngg TTeerrmmss vviiaa tthhee FFoorreeiiggnn IInntteerrffaaccee Each argument of a foreign function (except for the control argument) is of type term_t, an opaque handle to a Prolog term. Three groups of functions are available for the analysis of terms. The first just validates the type, like the Prolog predicates var/1, atom/1, etc and are called PL_is_*(). The second group attempts to translate the argument into a C primitive type. These predicates take a term_t and a pointer to the appropriate C-type and return TRUE or FALSE depending on successful or unsuccessful translation. If the translation fails, the pointed-to data is never modified. 99..66..33..11 TTeessttiinngg tthhee ttyyppee ooff aa tteerrmm int PPLL__tteerrmm__ttyyppee(_t_e_r_m___t) Obtain the type of a term, which should be a term returned by one of the other interface predicates or passed as an argument. The function returns the type of the Prolog term. The type identifiers are listed below. Note that the extraction functions PL_ge_t*() also validate the type and thus the two sections below are equivalent. if ( PL_is_atom(t) ) { char *s; PL_get_atom_chars(t, &s); ...; } or char *s; if ( PL_get_atom_chars(t, &s) ) { ...; } ___________________________________________________________________ | PL_VARIABLE |An unbound variable. The value of term| | |as such is a unique identifier for the| | |variable. | | PL_ATOM |A Prolog atom. | | PL_STRING |A Prolog string. | | PL_INTEGER |A Prolog integer. | | PL_FLOAT |A Prolog floating point number. | | PL_TERM |A compound term. Note that a list is a| |________________________|compound_term_./2._______________________| The functions PL_is_<_t_y_p_e> are an alternative to PL_term_type(). The test PL_is_variable(term) is equivalent to PL_term_type(term) == PL_VARIABLE, but the first is considerably faster. On the other hand, using a switch over PL_term_type() is faster and more readable then using an if-then-else using the functions below. All these functions return either TRUE or FALSE. int PPLL__iiss__vvaarriiaabbllee(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a variable. int PPLL__iiss__ggrroouunndd(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a ground term. See also ground/1. This function is cycle-safe. int PPLL__iiss__aattoomm(_t_e_r_m___t) Returns non-zero if _t_e_r_m is an atom. int PPLL__iiss__ssttrriinngg(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a string. int PPLL__iiss__iinntteeggeerr(_t_e_r_m___t) Returns non-zero if _t_e_r_m is an integer. int PPLL__iiss__ffllooaatt(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a float. int PPLL__iiss__ccoommppoouunndd(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a compound term. int PPLL__iiss__ffuunnccttoorr(_t_e_r_m___t_, _f_u_n_c_t_o_r___t) Returns non-zero if _t_e_r_m is compound and its functor is _f_u_n_c_t_o_r. This test is equivalent to PL_get_functor(), followed by testing the functor, but easier to write and faster. int PPLL__iiss__lliisstt(_t_e_r_m___t) Returns non-zero if _t_e_r_m is a compound term with functor ./2 or the atom []. int PPLL__iiss__aattoommiicc(_t_e_r_m___t) Returns non-zero if _t_e_r_m is atomic (not variable or compound). int PPLL__iiss__nnuummbbeerr(_t_e_r_m___t) Returns non-zero if _t_e_r_m is an integer or float. 99..66..33..22 RReeaaddiinngg ddaattaa ffrroomm aa tteerrmm The functions PL_get_*() read information from a Prolog term. Most of them take two arguments. The first is the input term and the second is a pointer to the output value or a term-reference. int PPLL__ggeett__aattoomm(_t_e_r_m___t _+_t_, _a_t_o_m___t _*_a) If _t is an atom, store the unique atom identifier over _a. See also PL_atom_chars() and PL_new_atom(). If there is no need to access the data (characters) of an atom, it is advised to manipulate atoms using their handle. As the atom is referenced by _t, it will live at least as long as _t does. If longer live-time is required, the atom should be locked using PL_register_atom(). int PPLL__ggeett__aattoomm__cchhaarrss(_t_e_r_m___t _+_t_, _c_h_a_r _*_*_s) If _t is an atom, store a pointer to a 0-terminated C-string in _s. It is explicitly nnoott allowed to modify the contents of this string. Some built-in atoms may have the string allocated in read-only memory, so `temporary manipulation' can cause an error. int PPLL__ggeett__ssttrriinngg__cchhaarrss(_t_e_r_m___t _+_t_, _c_h_a_r _*_*_s_, _i_n_t _*_l_e_n) If _t is a string object, store a pointer to a 0-terminated C-string in _s and the length of the string in _l_e_n. Note that this pointer is invalidated by backtracking, garbage-collection and stack-shifts, so generally the only save operations are to pass it immediately to a C-function that doesn't involve Prolog. int PPLL__ggeett__cchhaarrss(_t_e_r_m___t _+_t_, _c_h_a_r _*_*_s_, _u_n_s_i_g_n_e_d _f_l_a_g_s) Convert the argument term _t to a 0-terminated C-string. _f_l_a_g_s is a bitwise disjunction from two groups of constants. The first specifies which term-types should converted and the second how the argument is stored. Below is a specification of these constants. BUF_RING implies, if the data is not static (as from an atom), the data is copied to the next buffer from a ring of 16 buffers. This is a convenient way of converting multiple arguments passed to a foreign predicate to C-strings. If BUF_MALLOC is used, the data must be freed using PL_free() when not needed any longer. With the introduction of wide-characters (see section 2.17.1), not all atoms can be converted into a char*. This function fails if _t is of the wrong type, but also if the text cannot be represented. See the REP_* flags below for details. ___________________________________________________________________ | CVT_ATOM |Convert if term is an atom | | CVT_STRING |Convert if term is a string | | CVT_LIST |Convert if term is a list of integers| | |between 1 and 255 | | CVT_INTEGER |Convert if term is an integer (using %d) | | CVT_FLOAT |Convert if term is a float (using %f) | | CVT_NUMBER |Convert if term is a integer or float | | CVT_ATOMIC |Convert if term is atomic | | CVT_VARIABLE |Convert variable to print-name | | CVT_WRITE |Convert any term that is not converted| | |by any of the other flags using write/1.| | |If no BUF_* is provided, BUF_RING is| | |implied. | | CVT_ALL |Convert if term is any of the above,| |________________________|except_for_CVT_VARIABLE_and_CVT_WRITE____| | CVT_EXCEPTION |If conversion fails due to a type error,| | |raise a Prolog type error exception in| |________________________|addition_to_failure______________________| | BUF_DISCARDABLE |Data must copied immediately | | BUF_RING |Data is stored in a ring of buffers | | BUF_MALLOC |Data is copied to a new buffer returned| | |by PL_malloc(3). When no longer needed| |________________________|the_user_must_call_PL_free()_on_the_data.|_ | REP_ISO_LATIN_1 |(0, default). Text is in ISO Latin-1| | |encoding and the call fails if text| | |cannot be represented. | | REP_UTF8 |Convert the text to a UTF-8 string.| | |This works for all text. | | REP_MB |Convert to default locale-defined 8-bit| | |string. Success depends on the locale.| | |Conversion is done using the wcrtomb()| |________________________|C-library_function.______________________| int PPLL__ggeett__lliisstt__cchhaarrss(_+_t_e_r_m___t _l_, _c_h_a_r _*_*_s_, _u_n_s_i_g_n_e_d _f_l_a_g_s) Same as PL_get_chars(l, s, CVT_LIST|flags), provided _f_l_a_g_s contains no of the CVT_* flags. int PPLL__ggeett__iinntteeggeerr(_+_t_e_r_m___t _t_, _i_n_t _*_i) If _t is a Prolog integer, assign its value over _i. On 32-bit machines, this is the same as PL_get_long(), but avoids a warning from the compiler. See also PL_get_long(). int PPLL__ggeett__lloonngg(_t_e_r_m___t _+_t_, _l_o_n_g _*_i) If _t is a Prolog integer that can be represented as a long, assign its value over _i. If _t is an integer that cannot be represented by a C long, this function returns FALSE. If _t is a floating point number that can be represented as a long, this function succeeds as well. See also PL_get_int64() int PPLL__ggeett__iinntt6644(_t_e_r_m___t _+_t_, _i_n_t_6_4___t _*_i) If _t is a Prolog integer or float that can be represented as a int64_t, assign its value over _i. Currently all Prolog integers can be represented using this type, but this might change if SWI-Prolog introduces unbounded integers. int PPLL__ggeett__bbooooll(_t_e_r_m___t _+_t_, _i_n_t _*_v_a_l) If _t has the value true or false, set _v_a_l to the C constant TRUE or FALSE and return success. otherwise return failure. int PPLL__ggeett__ppooiinntteerr(_t_e_r_m___t _+_t_, _v_o_i_d _*_*_p_t_r) In the current system, pointers are represented by Prolog integers, but need some manipulation to make sure they do not get truncated due to the limited Prolog integer range. PL_put_pointer()/PL_get_pointer() guarantees pointers in the range of malloc() are handled without truncating. int PPLL__ggeett__ffllooaatt(_t_e_r_m___t _+_t_, _d_o_u_b_l_e _*_f) If _t is a float or integer, its value is assigned over _f. int PPLL__ggeett__ffuunnccttoorr(_t_e_r_m___t _+_t_, _f_u_n_c_t_o_r___t _*_f) If _t is compound or an atom, the Prolog representation of the name-arity pair will be assigned over _f. See also PL_get_name_arity() and PL_is_functor(). int PPLL__ggeett__nnaammee__aarriittyy(_t_e_r_m___t _+_t_, _a_t_o_m___t _*_n_a_m_e_, _i_n_t _*_a_r_i_t_y) If _t is compound or an atom, the functor-name will be assigned over _n_a_m_e and the arity over _a_r_i_t_y. See also PL_get_functor() and PL_is_functor(). int PPLL__ggeett__mmoodduullee(_t_e_r_m___t _+_t_, _m_o_d_u_l_e___t _*_m_o_d_u_l_e) If _t is an atom, the system will lookup or create the corresponding module and assign an opaque pointer to it over _m_o_d_u_l_e,. int PPLL__ggeett__aarrgg(_i_n_t _i_n_d_e_x_, _t_e_r_m___t _+_t_, _t_e_r_m___t _-_a) If _t is compound and index is between 1 and arity (including), assign _a with a term-reference to the argument. int _PPLL__ggeett__aarrgg(_i_n_t _i_n_d_e_x_, _t_e_r_m___t _+_t_, _t_e_r_m___t _-_a) Same as PL_get_arg(), but no checking is performed, nor whether _t is actually a term, nor whether _i_n_d_e_x is a valid argument-index. 99..66..33..33 EExxcchhaannggiinngg tteexxtt uussiinngg lleennggtthh aanndd ssttrriinngg All internal text-representation of SWI-Prolog is represented using char * plus length and allow for _0_-_b_y_t_e_s in them. The foreign library supports this by implementing a *_nchars() function for each applicable *_chars() function. Below we briefly present the signatures of these functions. For full documentation consult the *_chars() function. int PPLL__ggeett__aattoomm__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _*_l_e_n_, _c_h_a_r _*_*_s) See PL_get_atom_chars(). int PPLL__ggeett__lliisstt__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _*_l_e_n_, _c_h_a_r _*_*_s) See PL_get_list_chars(). int PPLL__ggeett__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _*_l_e_n_, _c_h_a_r _*_*_s_, _u_n_s_i_g_n_e_d _i_n_t _f_l_a_g_s) See PL_get_chars(). int PPLL__ppuutt__aattoomm__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_put_atom_chars(). int PPLL__ppuutt__ssttrriinngg__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_put_string_chars(). int PPLL__ppuutt__lliisstt__nnccooddeess(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_put_list_codes(). int PPLL__ppuutt__lliisstt__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_put_list_chars(). int PPLL__uunniiffyy__aattoomm__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_unify_atom_chars(). int PPLL__uunniiffyy__ssttrriinngg__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_unify_string_chars(). int PPLL__uunniiffyy__lliisstt__nnccooddeess(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_unify_codes(). int PPLL__uunniiffyy__lliisstt__nncchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) See PL_unify_list_chars(). In addition, the following functions are available for creating and inspecting atoms: atom_t PPLL__nneeww__aattoomm__nncchhaarrss(_s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_s) Create a new atom as PL_new_atom(), but from length and characters. const char * PPLL__aattoomm__nncchhaarrss(_a_t_o_m___t _a_, _s_i_z_e___t _*_l_e_n) Extract text and length of an atom. 99..66..33..44 WWiiddee cchhaarraacctteerr vveerrssiioonnss Support for exchange of wide character strings is still under considerations. The functions dealing with 8-bit character strings return failure when operating on a wide character atom or Prolog string object. The functions below can extract and unify bith 8-bit and wide atoms and string objects. Wide character strings are represented as C arrays of objects of the type pl_wchar_t, which is guaranteed to be the same as wchar_t on platforms supporting this type. For example, on MS-Windows, this represents 16-bit UCS2 characters, while using the GNU C library (glibc) this represents 32-bit UCS4 characters. atom_t PPLL__nneeww__aattoomm__wwcchhaarrss(_i_n_t _l_e_n_, _c_o_n_s_t _p_l___w_c_h_a_r___t _*_s) Create atom from wide-character string as PL_new_atom_nchars() does for ISO-Latin-1 strings. It _s only contains ISO-Latin-1 characters a normal byte-array atom is created. pl_wchar_t* PPLL__aattoomm__wwcchhaarrss(_a_t_o_m___t _a_t_o_m_, _i_n_t _*_l_e_n) Extract characters from a wide-character atom. Fails (returns NULL) if _a_t_o_m is not a wide-character atom. This is the wide-character version of PL_atom_nchars(). Note that only one of these functions succeeds on a particular atom. Especially, after creating an atom with PL_new_atom_wchars(), extracting the text using PL_atom_wchars() will fail of the atom only contains ISO-Latin-1 characters. int PPLL__ggeett__wwcchhaarrss(_t_e_r_m___t _t_, _s_i_z_e___t _*_l_e_n_, _p_l___w_c_h_a_r___t _*_*_s_, _u_n_s_i_g_n_e_d _f_l_a_g_s) Wide-character version of PL_get_chars(). The _f_l_a_g_s argument is the same as for PL_get_chars(). int PPLL__uunniiffyy__wwcchhaarrss(_t_e_r_m___t _t_, _i_n_t _t_y_p_e_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _p_l___w_c_h_a_r___t _*_s) Unify _t with a textual representation of the C wide character array _s. The _a_r_gtype argument defines the Prolog representation and is one of PL_ATOM, PL_STRING, PL_CODE_LIST or PL_CHAR_LIST. int PPLL__uunniiffyy__wwcchhaarrss__ddiiffff(_t_e_r_m___t _+_t_, _t_e_r_m___t _-_t_a_i_l_, _i_n_t _t_y_p_e_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _p_l___w_c_h_a_r___t _*_s) Difference list version of PL_unify_wchars(), only support- ing the types PL_CODE_LIST and PL_CHAR_LIST. It serves two purposes. It allows for returning very long lists from data read from a stream without the need for a resizing buffer in C and the use of difference lists is often practical for further processing in Prolog. Examples can be found in packages/clib/readutil.c from the source distribution. 99..66..33..55 RReeaaddiinngg aa lliisstt The functions from this section are intended to read a Prolog list from C. Suppose we expect a list of atoms, the following code will print the atoms, each on a line: foreign_t pl_write_atoms(term_t l) { term_t head = PL_new_term_ref(); /* variable for the elements */ term_t list = PL_copy_term_ref(l); /* copy as we need to write */ while( PL_get_list(list, head, list) ) { char *s; if ( PL_get_atom_chars(head, &s) ) Sprintf("%s\n", s); else PL_fail; } return PL_get_nil(list); /* test end for [] */ } int PPLL__ggeett__lliisstt(_t_e_r_m___t _+_l_, _t_e_r_m___t _-_h_, _t_e_r_m___t _-_t) If _l is a list and not [] assign a term-reference to the head to _h and to the tail to _t. int PPLL__ggeett__hheeaadd(_t_e_r_m___t _+_l_, _t_e_r_m___t _-_h) If _l is a list and not [] assign a term-reference to the head to _h. int PPLL__ggeett__ttaaiill(_t_e_r_m___t _+_l_, _t_e_r_m___t _-_t) If _l is a list and not [] assign a term-reference to the tail to _t. int PPLL__ggeett__nniill(_t_e_r_m___t _+_l) Succeeds if represents the atom []. 99..66..33..66 AAnn eexxaammppllee:: ddeeffiinniinngg write/1 iinn CC Figure 9.3 shows a simplified definition of write/1 to illustrate the described functions. This simplified version does not deal with operators. It is called display/1, because it mimics closely the behaviour of this Edinburgh predicate. foreign_t pl_display(term_t t) { functor_t functor; int arity, len, n; char *s; switch( PL_term_type(t) ) { case PL_VARIABLE: case PL_ATOM: case PL_INTEGER: case PL_FLOAT: PL_get_chars(t, &s, CVT_ALL); Sprintf("%s", s); break; case PL_STRING: PL_get_string_chars(t, &s, &len); Sprintf("\"%s\"", s); break; case PL_TERM: { term_t a = PL_new_term_ref(); PL_get_name_arity(t, &name, &arity); Sprintf("%s(", PL_atom_chars(name)); for(n=1; n<=arity; n++) { PL_get_arg(n, t, a); if ( n > 1 ) Sprintf(", "); pl_display(a); } Sprintf(")"); break; default: PL_fail; /* should not happen */ } PL_succeed; } Figure 9.3: A Foreign definition of display/1 99..66..44 CCoonnssttrruuccttiinngg TTeerrmmss Terms can be constructed using functions from the PL_put_*() and PL_cons_*() families. This approach builds the term `inside-out', starting at the leaves and subsequently creating compound terms. Alternatively, terms may be created `top-down', first creating a compound holding only variables and subsequently unifying the arguments. This section discusses functions for the first approach. This approach is generally used for creating arguments for PL_call() and PL_open_query. void PPLL__ppuutt__vvaarriiaabbllee(_t_e_r_m___t _-_t) Put a fresh variable in the term. The new variable lives on the global stack. Note that the initial variable lives on the local stack and is lost after a write to the term-references. After using this function, the variable will continue to live. void PPLL__ppuutt__aattoomm(_t_e_r_m___t _-_t_, _a_t_o_m___t _a) Put an atom in the term reference from a handle. See also PL_new_atom() and PL_atom_chars(). void PPLL__ppuutt__aattoomm__cchhaarrss(_t_e_r_m___t _-_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Put an atom in the term-reference constructed from the 0-terminated string. The string itself will never be references by Prolog after this function. void PPLL__ppuutt__ssttrriinngg__cchhaarrss(_t_e_r_m___t _-_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Put a zero-terminated string in the term-reference. The data will be copied. See also PL_put_string_nchars(). void PPLL__ppuutt__ssttrriinngg__nncchhaarrss(_t_e_r_m___t _-_t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Put a string, represented by a length/start pointer pair in the term-reference. The data will be copied. This interface can deal with 0-bytes in the string. See also section 9.6.19. void PPLL__ppuutt__lliisstt__cchhaarrss(_t_e_r_m___t _-_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Put a list of ASCII values in the term-reference. void PPLL__ppuutt__iinntteeggeerr(_t_e_r_m___t _-_t_, _l_o_n_g _i) Put a Prolog integer in the term reference. void PPLL__ppuutt__iinntt6644(_t_e_r_m___t _-_t_, _i_n_t_6_4___t _i) Put a Prolog integer in the term reference. void PPLL__ppuutt__ppooiinntteerr(_t_e_r_m___t _-_t_, _v_o_i_d _*_p_t_r) Put a Prolog integer in the term-reference. Provided ptr is in the `malloc()-area', PL_get_pointer() will get the pointer back. void PPLL__ppuutt__ffllooaatt(_t_e_r_m___t _-_t_, _d_o_u_b_l_e _f) Put a floating-point value in the term-reference. void PPLL__ppuutt__ffuunnccttoorr(_t_e_r_m___t _-_t_, _f_u_n_c_t_o_r___t _f_u_n_c_t_o_r) Create a new compound term from _f_u_n_c_t_o_r and bind _t to this term. All arguments of the term will be variables. To create a term with instantiated arguments, either instantiate the arguments using the PL_unify_*() functions or use PL_cons_functor(). void PPLL__ppuutt__lliisstt(_t_e_r_m___t _-_l) Same as PL_put_functor(l, PL_new_functor(PL_new_atom("."), 2)). void PPLL__ppuutt__nniill(_t_e_r_m___t _-_l) Same as PL_put_atom_chars("[]"). void PPLL__ppuutt__tteerrmm(_t_e_r_m___t _-_t_1_, _t_e_r_m___t _+_t_2) Make _t_1 point to the same term as _t_2. void PPLL__ccoonnss__ffuunnccttoorr(_t_e_r_m___t _-_h_, _f_u_n_c_t_o_r___t _f_, _._._.) Create a term, whose arguments are filled from variable argument list holding the same number of term_t objects as the arity of the functor. To create the term animal(gnu, 50), use: { term_t a1 = PL_new_term_ref(); term_t a2 = PL_new_term_ref(); term_t t = PL_new_term_ref(); functor_t animal2; /* animal2 is a constant that may be bound to a global variable and re-used */ animal2 = PL_new_functor(PL_new_atom("animal"), 2); PL_put_atom_chars(a1, "gnu"); PL_put_integer(a2, 50); PL_cons_functor(t, animal2, a1, a2); } After this sequence, the term-references _a_1 and _a_2 may be used for other purposes. void PPLL__ccoonnss__ffuunnccttoorr__vv(_t_e_r_m___t _-_h_, _f_u_n_c_t_o_r___t _f_, _t_e_r_m___t _a_0) Creates a compound term like PL_cons_functor(), but _a_0 is an array of term references as returned by PL_new_term_refs(). The length of this array should match the number of arguments required by the functor. void PPLL__ccoonnss__lliisstt(_t_e_r_m___t _-_l_, _t_e_r_m___t _+_h_, _t_e_r_m___t _+_t) Create a list (cons-) cell in _l from the head and tail. The code below creates a list of atoms from a char **. The list is built tail-to-head. The PL_unify_*() functions can be used to build a list head-to-tail. void put_list(term_t l, int n, char **words) { term_t a = PL_new_term_ref(); PL_put_nil(l); while( --n >= 0 ) { PL_put_atom_chars(a, words[n]); PL_cons_list(l, a, l); } } Note that _l can be redefined within a PL_cons_list call as shown here because operationally its old value is consumed before its new value is set. 99..66..55 UUnniiffyyiinngg ddaattaa The functions of this sections _u_n_i_f_y terms with other terms or translated C-data structures. Except for PL_unify(), the functions of this section are specific to SWI-Prolog. They have been introduced to make translation of old code easier, but also because they provide for a faster mechanism for returning data to Prolog that requires less term-references. Consider the case where we want a foreign function to return the host name of the machine Prolog is running on. Using the PL_get_*() and PL_put_*() functions, the code becomes: foreign_t pl_hostname(term_t name) { char buf[100]; if ( gethostname(buf, sizeof(buf)) ) { term_t tmp = PL_new_term_ref(); PL_put_atom_chars(tmp, buf); return PL_unify(name, tmp); } PL_fail; } Using PL_unify_atom_chars(), this becomes: foreign_t pl_hostname(term_t name) { char buf[100]; if ( gethostname(buf, sizeof(buf)) ) return PL_unify_atom_chars(name, buf); PL_fail; } int PPLL__uunniiffyy(_t_e_r_m___t _?_t_1_, _t_e_r_m___t _?_t_2) Unify two Prolog terms and return non-zero on success. int PPLL__uunniiffyy__aattoomm(_t_e_r_m___t _?_t_, _a_t_o_m___t _a) Unify _t with the atom _a and return non-zero on success. int PPLL__uunniiffyy__cchhaarrss(_t_e_r_m___t _?_t_, _i_n_t _f_l_a_g_s_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) New function do deal with unification of char* with various encodings to a Prolog representation. The _f_l_a_g_s argument is a bitwise _o_r specifying the Prolog target type and the encoding of _c_h_a_r_s. Prolog types is one of PL_ATOM, PL_STRING, PL_CODE_LIST or PL_CHAR_LIST. Representations is one of REP_ISO_LATIN_T, REP_UTF8 or REP_MB. See PL_get_chars() for a definition of the representation types. If _l_e_n is -1, _c_h_a_r_s is assumed to be null-terminated. int PPLL__uunniiffyy__aattoomm__cchhaarrss(_t_e_r_m___t _?_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Unify _t with an atom created from _c_h_a_r_s and return non-zero on success. int PPLL__uunniiffyy__lliisstt__cchhaarrss(_t_e_r_m___t _?_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Unify _t with a list of ASCII characters constructed from _c_h_a_r_s. void PPLL__uunniiffyy__ssttrriinngg__cchhaarrss(_t_e_r_m___t _?_t_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Unify _t with a Prolog string object created from the zero- terminated string _c_h_a_r_s. The data will be copied. See also PL_unify_string_nchars(). void PPLL__uunniiffyy__ssttrriinngg__nncchhaarrss(_t_e_r_m___t _?_t_, _s_i_z_e___t _l_e_n_, _c_o_n_s_t _c_h_a_r _*_c_h_a_r_s) Unify _t with a Prolog string object created from the string created from the _l_e_n/_c_h_a_r_s pair. The data will be copied. This interface can deal with 0-bytes in the string. See also section 9.6.19. int PPLL__uunniiffyy__iinntteeggeerr(_t_e_r_m___t _?_t_, _l_o_n_g _n) Unify _t with a Prolog integer from _n. int PPLL__uunniiffyy__iinntt6644(_t_e_r_m___t _?_t_, _i_n_t_6_4___t _n) Unify _t with a Prolog integer from _n. int PPLL__uunniiffyy__ffllooaatt(_t_e_r_m___t _?_t_, _d_o_u_b_l_e _f) Unify _t with a Prolog float from _f. int PPLL__uunniiffyy__ppooiinntteerr(_t_e_r_m___t _?_t_, _v_o_i_d _*_p_t_r) Unify _t with a Prolog integer describing the pointer. See also PL_put_pointer() and PL_get_pointer(). int PPLL__uunniiffyy__ffuunnccttoorr(_t_e_r_m___t _?_t_, _f_u_n_c_t_o_r___t _f) If _t is a compound term with the given functor, just succeed. If it is unbound, create a term and bind the variable, else fails. Not that this function does not create a term if the argument is already instantiated. int PPLL__uunniiffyy__lliisstt(_t_e_r_m___t _?_l_, _t_e_r_m___t _-_h_, _t_e_r_m___t _-_t) Unify _l with a list-cell (./2). If successful, write a reference to the head of the list to _h and a reference to the tail of the list in _t. This reference may be used for subsequent calls to this function. Suppose we want to return a list of atoms from a char **. We could use the example described by PL_put_list(), followed by a call to PL_unify(), or we can use the code below. If the predicate argument is unbound, the difference is minimal (the code based on PL_put_list() is probably slightly faster). If the argument is bound, the code below may fail before reaching the end of the word-list, but even if the unification succeeds, this code avoids a duplicate (garbage) list and a deep unification. foreign_t pl_get_environ(term_t env) { term_t l = PL_copy_term_ref(env); term_t a = PL_new_term_ref(); extern char **environ; char **e; for(e = environ; *e; e++) { if ( !PL_unify_list(l, a, l) || !PL_unify_atom_chars(a, *e) ) PL_fail; } return PL_unify_nil(l); } int PPLL__uunniiffyy__nniill(_t_e_r_m___t _?_l) Unify _l with the atom []. int PPLL__uunniiffyy__aarrgg(_i_n_t _i_n_d_e_x_, _t_e_r_m___t _?_t_, _t_e_r_m___t _?_a) Unifies the _i_n_d_e_x_-_t_h argument (1-based) of _t with _a. int PPLL__uunniiffyy__tteerrmm(_t_e_r_m___t _?_t_, _._._.) Unify _t with a (normally) compound term. The remaining arguments is a sequence of a type identifier, followed by the required arguments. This predicate is an extension to the Quintus and SICStus foreign interface from which the SWI-Prolog foreign interface has been derived, but has proved to be a powerful and comfortable way to create compound terms from C. Due to the vararg packing/unpacking and the required type-switching this interface is slightly slower than using the primitives. Please note that some bad C-compilers have fairly low limits on the number of arguments that may be passed to a function. Special attention is required when passing numbers. C `promotes' any integral smaller than int to int. I.e. the types char, short and int are all passed as int. In addition, on most 32-bit platforms int and long are the same. Up-to version 4.0.5, only PL_INTEGER could be specified which was taken from the stack as long. Such code fails when passing small integral types on machines where int is smaller than long. It is advised to use PL_SHORT, PL_INT or PL_LONG as appropriate. Similar, C compilers promote float to double and therefore PL_FLOAT and PL_DOUBLE are synonyms. The type identifiers are: PL_VARIABLE nnoonnee No op. Used in arguments of PL_FUNCTOR. PL_BOOL iinntt Unify the argument with true or false. PL_ATOM aattoomm__tt Unify the argument with an atom, as in PL_unify_atom(). PL_CHARS ccoonnsstt cchhaarr ** Unify the argument with an atom, constructed from the C char *, as in PL_unify_atom_chars(). PL_NCHARS ssiizzee__tt,, ccoonnsstt cchhaarr ** Unify the argument with an atom, constructed from length and char* as in PL_unify_atom_nchars(). PL_UTF8_CHARS ccoonnsstt cchhaarr ** Create an atom from a UTF-8 string. PL_UTF8_STRING ccoonnsstt cchhaarr ** Create a packed string object from a UTF-8 string. PL_MBCHARS ccoonnsstt cchhaarr ** Create an atom from a multi-byte string in the current locale. PL_MBCODES ccoonnsstt cchhaarr ** Create a list of character codes from a multi-byte string in the current locale. PL_MBSTRING ccoonnsstt cchhaarr ** Create a packed string object from a multi-byte string in the current locale. PL_NWCHARS ssiizzee__tt,, ccoonnsstt wwcchhaarr__tt ** Create an atom from a length and a wide character pointer. PL_NWCODES ssiizzee__tt,, ccoonnsstt wwcchhaarr__tt ** Create an list of character codes from a length and a wide character pointer. PL_NWSTRING ssiizzee__tt,, ccoonnsstt wwcchhaarr__tt ** Create a packed string object from a length and a wide character pointer. PL_SHORT sshhoorrtt Unify the argument with an integer, as in PL_unify_integer(). As short is promoted to int, PL_SHORT is a synonym for PL_INT. PL_INT iinntt Unify the argument with an integer, as in PL_unify_integer(). PL_LONG lloonngg Unify the argument with an integer, as in PL_unify_integer(). PL_INTEGER lloonngg Unify the argument with an integer, as in PL_unify_integer(). PL_DOUBLE ddoouubbllee Unify the argument with a float, as in PL_unify_float(). Note that, as the argument is passed using the C vararg conventions, a float must be casted to a double explicitly. PL_FLOAT ddoouubbllee Unify the argument with a float, as in PL_unify_float(). PL_POINTER vvooiidd ** Unify the argument with a pointer, as in PL_unify_pointer(). PL_STRING ccoonnsstt cchhaarr ** Unify the argument with a string object, as in PL_unify_string_chars(). PL_TERM tteerrmm__tt Unify a subterm. Note this may the return value of a PL_new_term_ref() call to get access to a variable. PL_FUNCTOR ffuunnccttoorr__tt,, ...... Unify the argument with a compound term. This specification should be followed by exactly as many specifications as the number of arguments of the compound term. PL_FUNCTOR_CHARS ccoonnsstt cchhaarr **nnaammee,, iinntt aarriittyy,, ...... Create a functor from the given name and arity and then behave as PL_FUNCTOR. PL_LIST iinntt lleennggtthh,, ...... Create a list of the indicated length. The following arguments contain the elements of the list. For example, to unify an argument with the term language(dutch), the following skeleton may be used: static functor_t FUNCTOR_language1; static void init_constants() { FUNCTOR_language1 = PL_new_functor(PL_new_atom("language"), 1); } foreign_t pl_get_lang(term_t r) { return PL_unify_term(r, PL_FUNCTOR, FUNCTOR_language1, PL_CHARS, "dutch"); } install_t install() { PL_register_foreign("get_lang", 1, pl_get_lang, 0); init_constants(); } int PPLL__cchhaarrss__ttoo__tteerrmm(_c_o_n_s_t _c_h_a_r _*_c_h_a_r_s_, _t_e_r_m___t _-_t) Parse the string _c_h_a_r_s and put the resulting Prolog term into _t. _c_h_a_r_s may or may not be closed using a Prolog full-stop (i.e., a dot followed by a blank). Returns FALSE if a syntax error was encountered and TRUE after successful completion. In addition to returning FALSE, the exception-term is returned in _t on a syntax error. See also term_to_atom/2. The following example build a goal-term from a string and calls it. int call_chars(const char *goal) { fid_t fid = PL_open_foreign_frame(); term_t g = PL_new_term_ref(); BOOL rval; if ( PL_chars_to_term(goal, g) ) rval = PL_call(goal, NULL); else rval = FALSE; PL_discard_foreign_frame(fid); return rval; } ... call_chars("consult(load)"); ... char * PPLL__qquuoottee(_i_n_t _c_h_r_, _c_o_n_s_t _c_h_a_r _*_s_t_r_i_n_g) Return a quoted version of _s_t_r_i_n_g. If _c_h_r is '\'', the result is a quoted atom. If _c_h_r is '"', the result is a string. The result string is stored in the same ring of buffers as described with the BUF_RING argument of PL_get_chars(); In the current implementation, the string is surrounded by _c_h_r and any occurrence of _c_h_r is doubled. In the future the behaviour will depend on the character_escape prolog-flag. See current_prolog_flag/2. 99..66..66 BBLLOOBBSS:: UUssiinngg aattoommss ttoo ssttoorree aarrbbiittrraarryy bbiinnaarryy ddaattaa SWI-Prolog atoms as well as strings can represent arbitrary binary data of arbitrary length. This facility is attractive for storing foreign data such as images in an atom. An atom is a unique handle to this data and the atom garbage collector is able to destroy atoms that are no longer referenced by the Prolog engine. This property of atoms makes them attractive as a handle to foreign resources, such as Java atoms, Microsoft's COM objects, etc., providing safe combined garbage collection. To exploit these features safely and in an organised manner the SWI-Prolog foreign interface allows for creating `atoms' with additional type information. The type is represented by a structure holding C function pointers that tell Prolog how to handle releasing the atom, writing it, sorting it, etc. Two atoms created with different types can represent the same sequence of bytes. Atoms are first ordered on the rank number of the type and then on the result of the compare() function. Rank numbers are assigned when the type is registered. 99..66..66..11 DDeeffiinniinngg aa BBLLOOBB ttyyppee The type PL_blob_t represents a structure with the layout displayed above. The structure contains additional fields at the ...for internal bookkeeping as well as future extension. typedef struct PL_blob_t { unsigned long magic; /* PL_BLOB_MAGIC */ unsigned long flags; /* Bitwise or of PL_BLOB_* */ char * name; /* name of the type */ int (*release)(atom_t a); int (*compare)(atom_t a, atom_t b); int (*write)(IOSTREAM *s, atom_t a, int flags); ... } PL_blob_t; For each type exactly one such structure should be allocated. Its first field must be initialised to PL_BLOB_MAGIC. The _f_l_a_g_s is a bitwise or of the following constants: PPLL__BBLLOOBB__TTEEXXTT If specified the blob is assumed to contain text and is considered a normal Prolog atom. PPLL__BBLLOOBB__UUNNIIQQUUEE If specified the system ensures that the blob-handle is a unique reference for a blob with the given type, length and content. If this flag is not specified each lookup creates a new blob. PPLL__BBLLOOBB__NNOOCCOOPPYY By default the content of the blob is copied. Using this flag the blob references the external data directly. The user must ensure the provided pointer is valid as long as the atom lives. If PL_BLOB_UNIQUE is also specified uniqueness is determined by comparing the pointer rather than the data pointed at. The _n_a_m_e field represents the type name as available to Prolog. See also current_blob/2. The other field are function pointers that must be initialised to proper functions or NULL to get the default behaviour of built-in atoms. Below are the defined member functions: void aaccqquuiirree(_a_t_o_m___t _a) Called if a new blob of this type is created through PL_put_blob() or PL_unify_blob(). This callback may be used together with the release hook to deal with reference counted external objects. int rreelleeaassee(_a_t_o_m___t _a) The blob (atom) _a is about to be released. This function can retrieve the data of the blob using PL_blob_data(). If it returns FALSE the atom garbage collector will _n_o_t reclaim the atom. int ccoommppaarree(_a_t_o_m___t _a_, _a_t_o_m___t _b) Compare the blobs _a and _b, both of which are of the type associated to this blob-type. Return values are, as memcmp(), <0 if _a is less then _b, = 0 if both are equal and >0 otherwise. int wwrriittee(_I_O_S_T_R_E_A_M _*_s_, _a_t_o_m___t _a_, _i_n_t _f_l_a_g_s) Write the content of the blob _a to the stream _s and respecting the _f_l_a_g_s. The _f_l_a_g_s are a bitwise or of zero or more of the PL_WRT_* flags defined in SWI-Prolog.h. This prototype is available if the undocumented SWI-Stream.h is included _b_e_f_o_r_e SWI-Prolog.h. If this function is not provided, write/1 emits the content of the blob for blobs of type PL_BLOB_TEXT or a string of the format <#_h_e_x _d_a_t_a> for binary blobs. If a blob type is registered from a loadable object (shared object or DLL) the blob-type must be deregistered before the object may be released. int PPLL__uunnrreeggiisstteerr__bblloobb__ttyyppee(_P_L___b_l_o_b___t _*_t_y_p_e) Unlink the blob type from the registered type and transform the type of possible living blobs to unregistered, avoiding further reference to the type structure, functions referred by it as well as the data. This function returns TRUE if no blobs of this type existed and FALSE otherwise. PL_unregister_blob_type() is intended for the uninstall() hook of foreign modules, avoiding further references to the module. 99..66..66..22 AAcccceessssiinngg bblloobbss The blob access functions are similar to the atom accessing functions. Blobs being atoms, the atom functions operate on blobs and visa versa. For clarity and possible future compatibility issues however it is not advised to rely on this. int PPLL__iiss__bblloobb(_t_e_r_m___t _t_, _P_L___b_l_o_b___t _*_*_t_y_p_e) Succeeds if _t refers to a blob, in which case _t_y_p_e is filled with the type of the blob. int PPLL__uunniiffyy__bblloobb(_t_e_r_m___t _t_, _v_o_i_d _*_b_l_o_b_, _s_i_z_e___t _l_e_n_, _P_L___b_l_o_b___t _*_t_y_p_e) Unify _t to a new blob constructed from the given data and associated to the given type. See also PL_unify_atom_nchars(). int PPLL__ppuutt__bblloobb(_t_e_r_m___t _t_, _v_o_i_d _*_b_l_o_b_, _s_i_z_e___t _l_e_n_, _P_L___b_l_o_b___t _*_t_y_p_e) Store the described blob in _t. The return value indicates whether a new blob was allocated (FALSE) or the blob is a reference to an existing blob (TRUE). Reporting new/existing can be used to deal with external objects having their own reference counts. If the return is TRUE this reference count must be incremented and it must be decremented on blob destruction callback. See also PL_put_atom_nchars(). int PPLL__ggeett__bblloobb(_t_e_r_m___t _t_, _v_o_i_d _*_*_b_l_o_b_, _s_i_z_e___t _*_l_e_n_, _P_L___b_l_o_b___t _*_*_t_y_p_e) If _t holds a blob or atom get the data and type and return TRUE. Otherwise return FALSE. Each result pointer may be NULL, in which case the requested information is ignored. void * PPLL__bblloobb__ddaattaa(_a_t_o_m___t _a_, _s_i_z_e___t _*_l_e_n_, _P_L___b_l_o_b___t _*_*_t_y_p_e) Get the data and type associated to a blob. This function is mainly used from the callback functions described in section 9.6.6.1. 99..66..77 EExxcchhaannggiinngg GGMMPP nnuummbbeerrss If SWI-Prolog is linked with the GNU Multiple Precision Arithmetic Library (GMP, used by default), the foreign interface provides functions for exchanging numeric values to GMP types. To access these functions the header must be included _b_e_f_o_r_e . Here is an example exploiting the function mpz_nextprime(): #include #include static foreign_t next_prime(term_t n, term_t prime) { mpz_t mpz; int rc; mpz_init(mpz); if ( PL_get_mpz(n, mpz) ) { mpz_nextprime(mpz, mpz); rc = PL_unify_mpz(prime, mpz); } else rc = FALSE; mpz_clear(mpz); return rc; } install_t install() { PL_register_foreign("next_prime", 2, next_prime, 0); } int PPLL__ggeett__mmppzz(_t_e_r_m___t _t_, _m_p_z___t _m_p_z) If _t represents an integer _m_p_z is filled with the value and the function returns TRUE. Otherwise _m_p_z is untouched and the function returns FALSE. Note that _m_p_z must have been initialised before calling this function and must be cleared using mpz_clear() to reclaim any storage associated with it. int PPLL__ggeett__mmppqq(_t_e_r_m___t _t_, _m_p_q___t _m_p_q) If _t is an integer or rational number (term rdiv/2) _m_p_q is filled with the _n_o_r_m_a_l_i_s_e rational number and the function returns TRUE. Otherwise _m_p_q is untouched and the function returns FALSE. Note that _m_p_q must have been initialised before calling this function and must be cleared using mpq_clear() to reclaim any storage associated with it. int PPLL__uunniiffyy__mmppzz(_t_e_r_m___t _t_, _m_p_z___t _m_p_z) Unify _t with the integer value represented by _m_p_z and return _T_R_U_E on success. The _m_p_z argument is not changed. int PPLL__uunniiffyy__mmppqq(_t_e_r_m___t _t_, _m_p_q___t _m_p_q) Unify _t with a rational number represented by _m_p_q and return _T_R_U_E on success. Note that _t is unified with an integer if the denominator is 1. The _m_p_q argument is not changed. 99..66..88 CCaalllliinngg PPrroolloogg ffrroomm CC The Prolog engine can be called from C. There are two interfaces for this. For the first, a term is created that could be used as an argument to call/1 and next PL_call() is used to call Prolog. This system is simple, but does not allow to inspect the different answers to a non-deterministic goal and is relatively slow as the runtime system needs to find the predicate. The other interface is based on PL_open_query(), PL_next_solution() and PL_cut_query() or PL_close_query(). This mechanism is more powerful, but also more complicated to use. 99..66..88..11 PPrreeddiiccaattee rreeffeerreenncceess This section discusses the functions used to communicate about predicates. Though a Prolog predicate may defined or not, redefined, etc., a Prolog predicate has a handle that is not destroyed, nor moved. This handle is known by the type predicate_t. predicate_t PPLL__pprreedd(_f_u_n_c_t_o_r___t _f_, _m_o_d_u_l_e___t _m) Return a handle to a predicate for the specified name/arity in the given module. This function always succeeds, creating a handle for an undefined predicate if no handle was available. If the module argument _m is NULL, the current context module is used. predicate_t PPLL__pprreeddiiccaattee(_c_o_n_s_t _c_h_a_r _*_n_a_m_e_, _i_n_t _a_r_i_t_y_, _c_o_n_s_t _c_h_a_r_* _m_o_d_u_l_e) Same a PL_pred(), but provides a more convenient interface to the C-programmer. void PPLL__pprreeddiiccaattee__iinnffoo(_p_r_e_d_i_c_a_t_e___t _p_, _a_t_o_m___t _*_n_, _i_n_t _*_a_, _m_o_d_u_l_e___t _*_m) Return information on the predicate _p. The name is stored over _n, the arity over _a, while _m receives the definition module. Note that the latter need not be the same as specified with PL_predicate(). If the predicate is imported into the module given to PL_predicate(), this function will return the module where the predicate is defined. 99..66..88..22 IInniittiiaattiinngg aa qquueerryy ffrroomm CC This section discusses the functions for creating and manipulating queries from C. Note that a foreign context can have at most one active query. This implies it is allowed to make strictly nested calls between C and Prolog (Prolog calls C, calls Prolog, calls C, etc., but it is nnoott allowed to open multiple queries and start generating solutions for each of them by calling PL_next_solution(). Be sure to call PL_cut_query() or PL_close_query() on any query you opened before opening the next or returning control back to Prolog. qid_t PPLL__ooppeenn__qquueerryy(_m_o_d_u_l_e___t _c_t_x_, _i_n_t _f_l_a_g_s_, _p_r_e_d_i_c_a_t_e___t _p_, _t_e_r_m___t _+_t_0) Opens a query and returns an identifier for it. This function always succeeds, regardless whether the predicate is defined or not. _c_t_x is the _c_o_n_t_e_x_t _m_o_d_u_l_e of the goal. When NULL, the context module of the calling context will be used, or user if there is no calling context (as may happen in embedded systems). Note that the context module only matters for _m_o_d_u_l_e___t_r_a_n_s_p_a_r_e_n_t predicates. See context_module/1 and module_transparent/1. The _p argument specifies the predicate, and should be the result of a call to PL_pred() or PL_predicate(). Note that it is allowed to store this handle as global data and reuse it for future queries. The term-reference _t_0 is the first of a vector of term-references as returned by PL_new_term_refs(n). The _f_l_a_g_s arguments provides some additional options concerning debugging and exception handling. It is a bitwise or of the following values: PL_Q_NORMAL Normal operation. The debugger inherits its settings from the environment. If an exception occurs that is not handled in Prolog, a message is printed and the tracer is started to debug the error. PL_Q_NODEBUG Switch off the debugger while executing the goal. This option is used by many calls to hook-predicates to avoid tracing the hooks. An example is print/1 calling portray/1 from foreign code. PL_Q_CATCH_EXCEPTION If an exception is raised while executing the goal, do not report it, but make it available for PL_exception(). PL_Q_PASS_EXCEPTION As PL_Q_CATCH_EXCEPTION, but do not invalidate the exception- term while calling PL_close_query(). This option is experimental. The example below opens a query to the predicate is_a/2 to find the ancestor of for some name. char * ancestor(const char *me) { term_t a0 = PL_new_term_refs(2); static predicate_t p; if ( !p ) p = PL_predicate("is_a", 2, "database"); PL_put_atom_chars(a0, me); PL_open_query(NULL, PL_Q_NORMAL, p, a0); ... } int PPLL__nneexxtt__ssoolluuttiioonn(_q_i_d___t _q_i_d) Generate the first (next) solution for the given query. The return value is TRUE if a solution was found, or FALSE to indicate the query could not be proven. This function may be called repeatedly until it fails to generate all solutions to the query. void PPLL__ccuutt__qquueerryy(_q_i_d) Discards the query, but does not delete any of the data created by the query. It just invalidate _q_i_d, allowing for a new call to PL_open_query() in this context. void PPLL__cclloossee__qquueerryy(_q_i_d) As PL_cut_query(), but all data and bindings created by the query are destroyed. int PPLL__ccaallll__pprreeddiiccaattee(_m_o_d_u_l_e___t _m_, _i_n_t _f_l_a_g_s_, _p_r_e_d_i_c_a_t_e___t _p_r_e_d_, _t_e_r_m___t _+_t_0) Shorthand for PL_open_query(), PL_next_solution(), PL_cut_query(), generating a single solution. The arguments are the same as for PL_open_query(), the return value is the same as PL_next_solution(). int PPLL__ccaallll(_t_e_r_m___t_, _m_o_d_u_l_e___t) Call term just like the Prolog predicate once/1. _T_e_r_m is called in the specified module, or in the context module if module_t = NULL. Returns TRUE if the call succeeds, FALSE otherwise. Figure 9.4 shows an example to obtain the number of defined atoms. All checks are omitted to improve readability. 99..66..99 DDiissccaarrddiinngg DDaattaa The Prolog data created and term-references needed to setup the call and/or analyse the result can in most cases be discarded right after the call. PL_close_query() allows for destructing the data, while leaving the term-references. The calls below may be used to destroy term-references and data. See figure 9.4 for an example. fid_t PPLL__ooppeenn__ffoorreeiiggnn__ffrraammee() Created a foreign frame, holding a mark that allows the system to undo bindings and destroy data created after it as well as providing the environment for creating term-references. This function is called by the kernel before calling a foreign predicate. void PPLL__cclloossee__ffoorreeiiggnn__ffrraammee(_f_i_d___t _i_d) Discard all term-references created after the frame was opened. All other Prolog data is retained. This function is called by the kernel whenever a foreign function returns control back to Prolog. void PPLL__ddiissccaarrdd__ffoorreeiiggnn__ffrraammee(_f_i_d___t _i_d) Same as PL_close_foreign_frame(), but also undo all bindings made since the open and destroy all Prolog data. void PPLL__rreewwiinndd__ffoorreeiiggnn__ffrraammee(_f_i_d___t _i_d) Undo all bindings and discard all term-references created since the frame was created, but does not pop the frame. I.e. the same frame can be rewinded multiple times, and must eventually be closed or discarded. It is obligatory to call either of the two closing functions to discard a foreign frame. Foreign frames may be nested. int count_atoms() { fid_t fid = PL_open_foreign_frame(); term_t goal = PL_new_term_ref(); term_t a1 = PL_new_term_ref(); term_t a2 = PL_new_term_ref(); functor_t s2 = PL_new_functor(PL_new_atom("statistics"), 2); int atoms; PL_put_atom_chars(a1, "atoms"); PL_cons_functor(goal, s2, a1, a2); PL_call(goal, NULL); /* call it in current module */ PL_get_integer(a2, &atoms); PL_discard_foreign_frame(fid); return atoms; } Figure 9.4: Calling Prolog 99..66..1100 FFoorreeiiggnn CCooddee aanndd MMoodduulleess Modules are identified via a unique handle. The following functions are available to query and manipulate modules. module_t PPLL__ccoonntteexxtt() Return the module identifier of the context module of the currently active foreign predicate. int PPLL__ssttrriipp__mmoodduullee(_t_e_r_m___t _+_r_a_w_, _m_o_d_u_l_e___t _*_m_, _t_e_r_m___t _-_p_l_a_i_n) Utility function. If _r_a_w is a term, possibly holding the module construct <_m_o_d_u_l_e>:<_r_e_s_t>this function will make _p_l_a_i_n a reference to <_r_e_s_t> and fill _m_o_d_u_l_e _* with <_m_o_d_u_l_e>. For further nested module constructs the inner most module is returned via _m_o_d_u_l_e _*. If _r_a_w is not a module construct _a_r_g will simply be put in _p_l_a_i_n. If _m_o_d_u_l_e _* is NULL it will be set to the context module. Otherwise it will be left untouched. The following example shows how to obtain the plain term and module if the default module is the user module: { module m = PL_new_module(PL_new_atom("user")); term_t plain = PL_new_term_ref(); PL_strip_module(term, &m, plain); ... atom_t PPLL__mmoodduullee__nnaammee(_m_o_d_u_l_e___t) Return the name of _m_o_d_u_l_e as an atom. module_t PPLL__nneeww__mmoodduullee(_a_t_o_m___t _n_a_m_e) Find an existing or create a new module with name specified by the atom _n_a_m_e. 99..66..1111 PPrroolloogg eexxcceeppttiioonnss iinn ffoorreeiiggnn ccooddee This section discusses PL_exception(), PL_throw() and PL_raise_exception(), the interface functions to detect and gen- erate Prolog exceptions from C-code. PL_throw() and PL_raise_exception() from the C-interface to raise an exception from foreign code. PL_throw() exploits the C-function longjmp() to return immediately to the innermost PL_next_solution(). PL_raise_exception() registers the exception term and returns FALSE. If a foreign predicate returns FALSE, while and exception-term is registered a Prolog exception will be raised by the virtual machine. Calling these functions outside the context of a function implementing a foreign predicate results in undefined behaviour. PL_exception() may be used after a call to PL_next_solution() fails, and returns a term reference to an exception term if an exception was raised, and 0 otherwise. If a C-function, implementing a predicate calls Prolog and detects an exception using PL_exception(), it can handle this exception, or return with the exception. Some caution is required though. It is nnoott allowed to call PL_close_query() or PL_discard_foreign_frame() afterwards, as this will invalidate the exception term. Below is the code that calls a Prolog defined arithmetic function (see arithmetic_function/1). If PL_next_solution() succeeds, the result is analysed and translated to a number, after which the query is closed and all Prolog data created after PL_open_foreign_frame() is destroyed. On the other hand, if PL_next_solution() fails and if an exception was raised, just pass it. Otherwise generate an exception (PL_error() is an internal call for building the standard error terms and calling PL_raise_exception()). After this, the Prolog environment should be discarded using PL_cut_query() and PL_close_foreign_frame() to avoid invalidating the exception term. static int prologFunction(ArithFunction f, term_t av, Number r) { int arity = f->proc->definition->functor->arity; fid_t fid = PL_open_foreign_frame(); qid_t qid; int rval; qid = PL_open_query(NULL, PL_Q_NORMAL, f->proc, av); if ( PL_next_solution(qid) ) { rval = valueExpression(av+arity-1, r); PL_close_query(qid); PL_discard_foreign_frame(fid); } else { term_t except; if ( (except = PL_exception(qid)) ) { rval = PL_throw(except); /* pass exception */ } else { char *name = stringAtom(f->proc->definition->functor->name); /* generate exception */ rval = PL_error(name, arity-1, NULL, ERR_FAILED, f->proc); } PL_cut_query(qid); /* donot destroy data */ PL_close_foreign_frame(fid); /* same */ } return rval; } int PPLL__rraaiissee__eexxcceeppttiioonn(_t_e_r_m___t _e_x_c_e_p_t_i_o_n) Generate an exception (as throw/1) and return FALSE. Below is an example returning an exception from foreign predicate: foreign_t pl_hello(term_t to) { char *s; if ( PL_get_atom_chars(to, &s) ) { Sprintf("Hello \"%s\"\n", s); PL_succeed; } else { term_t except = PL_new_term_ref(); PL_unify_term(except, PL_FUNCTOR_CHARS, "type_error", 2, PL_CHARS, "atom", PL_TERM, to); return PL_raise_exception(except); } } int PPLL__tthhrrooww(_t_e_r_m___t _e_x_c_e_p_t_i_o_n) Similar to PL_raise_exception(), but returns using the C longjmp() function to the innermost PL_next_solution(). term_t PPLL__eexxcceeppttiioonn(_q_i_d___t _q_i_d) If PL_next_solution() fails, this can be due to normal failure of the Prolog call, or because an exception was raised using throw/1. This function returns a handle to the exception term if an exception was raised, or 0 if the Prolog goal simply failed.. 99..66..1122 CCaattcchhiinngg SSiiggnnaallss ((SSooffttwwaarree IInntteerrrruuppttss)) SWI-Prolog offers both a C and Prolog interface to deal with software interrupts (signals). The Prolog mapping is defined in section 4.10. This subsection deals with handling signals from C. If a signal is not used by Prolog and the handler does not call Prolog in any way, the native signal interface routines may be used. Some versions of SWI-Prolog, notably running on popular Unix platforms, handle SIG_SEGV for guarding the Prolog stacks. If the application wishes to handle this signal too, it should use PL_signal() to install its handler after initialising Prolog. SWI-Prolog will pass SIG_SEGV to the user code if it detected the signal is not related to a Prolog stack overflow. Any handler that wishes to call one of the Prolog interface functions should call PL_signal() for its installation. void (*)() PPLL__ssiiggnnaall(_s_i_g_, _f_u_n_c) This function is equivalent to the BSD-Unix signal() function, regardless of the platform used. The signal handler is blocked while the signal routine is active, and automatically reactivated after the handler returns. After a signal handler is registered using this function, the native signal interface redirects the signal to a generic signal handler inside SWI-Prolog. This generic handler validates the environment, creates a suitable environment for calling the interface functions described in this chapter and finally calls the registered user-handler. By default, signals are handled asynchronously (i.e. at the time they arrive). It is inherently dangerous to call extensive code fragments, and especially exception related code from asynchronous handlers. The interface allows for _s_y_n_c_h_r_o_n_o_u_s handling of signals. In this case the native OS handler just schedules the signal using PL_raise(), which is checked by PL_handle_signals() at the call- and redo-port. This behaviour is realised by or-ing _s_i_g with the constant PL_SIGSYNC. Signal handling routines may raise exceptions using PL_raise_exception(). The use of PL_throw() is not safe. If a synchronous handler raises an exception, the exception is delayed to the next call to PL_handle_signals(); int PPLL__rraaiissee(_i_n_t _s_i_g) Register _s_i_g for _s_y_n_c_h_r_o_n_o_u_s handling by Prolog. Synchronous signals are handled at the call-port or if foreign code calls PL_handle_signals(). See also thread_signal/2. int PPLL__hhaannddllee__ssiiggnnaallss(_v_o_i_d) Handle any signals pending from PL_raise(). PL_handle_signals() is called at each pass through the call- and redo-port at a safe point. Exceptions raised by the handler using PL_raise_exception() are properly passed to the environment. The user may call this function inside long-running foreign functions to handle scheduled interrupts. This routine returns the number of signals handled. If a handler raises an exception, the return value is -1 and the calling routine should return with FALSE as soon as possible. 99..66..1133 MMiisscceellllaanneeoouuss 99..66..1133..11 TTeerrmm CCoommppaarriissoonn int PPLL__ccoommppaarree(_t_e_r_m___t _t_1_, _t_e_r_m___t _t_2) Compares two terms using the standard order of terms and returns -1, 0 or 1. See also compare/3. int PPLL__ssaammee__ccoommppoouunndd(_t_e_r_m___t _t_1_, _t_e_r_m___t _t_2) Yields TRUE if _t_1 and _t_2 refer to physically the same compound term and FALSE otherwise. 99..66..1133..22 RReeccoorrddeedd ddaattaabbaassee In some applications it is useful to store and retrieve Prolog terms from C-code. For example, the XPCE graphical environment does this for storing arbitrary Prolog data as slot-data of XPCE objects. Please note that the returned handles have no meaning at the Prolog level and the recorded terms are not visible from Prolog. The functions PL_recorded() and PL_erase() are the only functions that can operate on the stored term. Two groups of functions are provided. The first group (PL_record() and friends) store Prolog terms on the Prolog heap for retrieval during the same session. These functions are also used by recorda/3 and friends. The recorded database may be used to communicate Prolog terms between threads. record_t PPLL__rreeccoorrdd(_t_e_r_m___t _+_t) Record the term _t into the Prolog database as recorda/3 and return an opaque handle to the term. The returned handle remains valid until PL_erase() is called on it. PL_recorded() is used to copy recorded terms back to the Prolog stack. void PPLL__rreeccoorrddeedd(_r_e_c_o_r_d___t _r_e_c_o_r_d_, _t_e_r_m___t _-_t) Copy a recorded term back to the Prolog stack. The same record may be used to copy multiple instances at any time to the Prolog stack. See also PL_record() and PL_erase(). void PPLL__eerraassee(_r_e_c_o_r_d___t _r_e_c_o_r_d) Remove the recorded term from the Prolog database, reclaiming all associated memory resources. The second group (headed by PL_record_external()) provides the same functionality, but the returned data has properties that enable storing the data on an external device. It has been designed to make it possible to store Prolog terms fast an compact in an external database. Here are the main features: o _I_n_d_e_p_e_n_d_e_n_t _o_f _s_e_s_s_i_o_n Records can be communicated to another Prolog session and made visible using PL_recorded_external(). o _B_i_n_a_r_y The representation is binary for maximum performance. The returned data may contain 0-bytes. o _B_y_t_e_-_o_r_d_e_r _i_n_d_e_p_e_n_d_e_n_t The representation can be transferred between machines with different byte-order. o _N_o _a_l_i_g_n_m_e_n_t _r_e_s_t_r_i_c_t_i_o_n_s There are no memory alignment restrictions and copies of the record can thus be moved freely. For example, it is possible to use this representation to exchange terms using shared memory between different Prolog processes. o _C_o_m_p_a_c_t It is assumed that a smaller memory footprint will eventually outperform slightly faster representations. o _S_t_a_b_l_e The format is designed for future enhancements without breaking compatibility with older records. char * PPLL__rreeccoorrdd__eexxtteerrnnaall(_t_e_r_m___t _+_t_, _s_i_z_e___t _*_l_e_n) Record the term _t into the Prolog database as recorda/3 and return an opaque handle to the term. The returned handle remains valid until PL_erase_external() is called on it. It is allowed to copy the data and use PL_recorded_external() on the copy. The user is responsible for the memory management of the copy. After copying, the original may be discarded using PL_erase_external(). PL_recorded_external() is used to copy such recorded terms back to the Prolog stack. int PPLL__rreeccoorrddeedd__eexxtteerrnnaall(_c_o_n_s_t _c_h_a_r _*_r_e_c_o_r_d_, _t_e_r_m___t _-_t) Copy a recorded term back to the Prolog stack. The same record may be used to copy multiple instances at any time to the Prolog stack. See also PL_record_external() and PL_erase_external(). int PPLL__eerraassee__eexxtteerrnnaall(_c_h_a_r _*_r_e_c_o_r_d) Remove the recorded term from the Prolog database, reclaiming all associated memory resources. 99..66..1133..33 GGeettttiinngg ffiillee nnaammeess The function PL_get_file_name() provides access to Prolog filenames and its file-search mechanism described with absolute_file_name/3. Its existence is motivated to realise a uniform interface to deal with file-properties, search, naming conventions etc. from foreign code. int PPLL__ggeett__ffiillee__nnaammee(_t_e_r_m___t _s_p_e_c_, _c_h_a_r _*_*_n_a_m_e_, _i_n_t _f_l_a_g_s) Translate a Prolog term into a file name. The name is stored in the static buffer ring described with PL_get_chars() option BUF_RING. Conversion from the internal UNICODE encoding is done using standard C library functions. _f_l_a_g_s is a bit-mask controlling the conversion process. Options are: PL_FILE_ABSOLUTE Return an absolute path to the requested file. PL_FILE_OSPATH Return a the name using the hosting OS conventions. On MS-Windows, \ is used to separate directories rather than the canonical /. PL_FILE_SEARCH Invoke absolute_file_name/3. This implies rules from file_search_path/2are used. PL_FILE_EXIST Demand the path to refer to an existing entity. PL_FILE_READ Demand read-access on the result. PL_FILE_WRITE Demand write-access on the result. PL_FILE_EXECUTE Demand execute-access on the result. PL_FILE_NOERRORS Do not raise any exceptions. 99..66..1144 EErrrroorrss aanndd wwaarrnniinnggss PL_warning() prints a standard Prolog warning message to the standard error (user_error) stream. Please note that new code should consider using PL_raise_exception() to raise a Prolog exception. See also section 4.9. int PPLL__wwaarrnniinngg(_f_o_r_m_a_t_, _a_1_, _._._.) Print an error message starting with `[WARNING: ', followed by the output from _f_o_r_m_a_t, followed by a `]' and a newline. Then start the tracer. _f_o_r_m_a_t and the arguments are the same as for printf(2). Always returns FALSE. 99..66..1155 EEnnvviirroonnmmeenntt CCoonnttrrooll ffrroomm FFoorreeiiggnn CCooddee int PPLL__aaccttiioonn(_i_n_t_, _._._.) Perform some action on the Prolog system. _i_n_t describes the action, Remaining arguments depend on the requested action. The actions are listed in table 9.1. ___________________________________________________________________ | PL_ACTION_TRACE |Start Prolog tracer (trace/0). Requires| | |no arguments. | | PL_ACTION_DEBUG |Switch on Prolog debug mode (debug/0).| | |Requires no arguments. | | PL_ACTION_BACKTRACE |Print backtrace on current output| | |stream. The argument (an int) is the| | |number of frames printed. | | PL_ACTION_HALT |Halt Prolog execution. This action| | |should be called rather than Unix exit()| | |to give Prolog the opportunity to clean| | |up. This call does not return. The| | |argument (an int) is the exit code. See| | |halt/1. | | PL_ACTION_ABORT |Generate a Prolog abort (abort/0). This| | |call does not return. Requires no| | |arguments. | | PL_ACTION_BREAK |Create a standard Prolog break envi-| | |ronment (break/0). Returns after the| | |user types the end-of-file character.| || |Requires|no arguments. || | PL_ACTION_GUIAPP |Win32: Used to indicate the kernel that| | |the application is a GUI application if| | |the argument is not 0 and a console| | |application if the argument is 0. If| | |a fatal error occurs, the system uses| | |a windows messagebox to report this on| | |a GUI application and simply prints the| | |error and exits otherwise. | | PL_ACTION_WRITE |Write the argument, a char * to the| | |current output stream. | | PL_ACTION_FLUSH |Flush the current output stream. Re-| | |quires no arguments. | | PL_ACTION_ATTACH_CONSOLE|Attach a console to a thread if it does| |________________________|not_have_one.__See_attach_console/0._____| Table 9.1: PL_action() options 99..66..1166 QQuueerryyiinngg PPrroolloogg long PPLL__qquueerryy(_i_n_t) Obtain status information on the Prolog system. The actual argument type depends on the information required. _i_n_t describes what information is wanted. The options are given in table 9.2. ___________________________________________________________________ | PL_QUERY_ARGC |Return an integer holding the number of| | |arguments given to Prolog from Unix. | | PL_QUERY_ARGV |Return a char ** holding the argument| | |vector given to Prolog from Unix. | | PL_QUERY_SYMBOLFILE |Return a char * holding the current| | |symbol file of the running process. | | PL_MAX_INTEGER |Return a long, representing the maximal| | |integer value represented by a Prolog| | |integer. | | PL_MIN_INTEGER |Return a long, representing the minimal| | |integer value. | | PL_QUERY_VERSION |Return a long, representing the version| | |as 10; 000M* +100m* +p, where M is the | | |major, m the minor version number and | | |p the patch-level. For example, 20717| | |means 2.7.17. | | PL_QUERY_MAX_THREADS |Return the maximum number of threads| | |that can be created in this version.| | |Return values of PL_thread_self() are| | |between 0 and this number. | | PL_QUERY_ENCODING |Return the default stream encoding of| | |Prolog (of type IOENC). | | PL_QUERY_USER_CPU |Get amount of user CPU time of the| |________________________|process_in_milliseconds._________________| Table 9.2: PL_query() options 99..66..1177 RReeggiisstteerriinngg FFoorreeiiggnn PPrreeddiiccaatteess int PPLL__rreeggiisstteerr__ffoorreeiiggnn__iinn__mmoodduullee(_c_o_n_s_t _c_h_a_r _*_m_o_d_u_l_e_, _c_o_n_s_t _c_h_a_r _*_n_a_m_e_, _i_n_t _a_r_i_t_y_, _f_o_r_e_i_g_n___t _(_*_f_u_n_c_t_i_o_n_)_(_)_, _i_n_t _f_l_a_g_s) Register a C-function to implement a Prolog predicate. After this call returns successfully a predicate with name _n_a_m_e (a char *) and arity _a_r_i_t_y (a C int) is created in module _m_o_d_u_l_e. If _m_o_d_u_l_e is NULL, the predicate is created in the module of the calling context or if no context is present in the module user. When called in Prolog, Prolog will call _f_u_n_c_t_i_o_n. _f_l_a_g_s forms bitwise or'ed list of options for the installation. These are: ___________________________________________________________________ | PL_FA_NOTRACE |Predicate cannot be seen in the tracer | | PL_FA_TRANSPARENT |Predicate is module transparent | | PL_FA_NONDETERMINISTIC |Predicate is non-deterministic. See| | |also PL_retry(). | |_PL_FA_VARARGS__________|Use_alternative_calling_convention.______| Predicates may be registered either before or after PL_initialise(). When registered before initialisation the registration is recorded and executed after installing the system predicates and before loading the saved state. Default calling (i.e. without PL_FA_VARARGS) _f_u_n_c_t_i_o_n is passed the same number of term_t arguments as the arity of the predicate and, if the predicate is non-deterministic, an extra argument of type control_t (see section 9.6.1.1). If PL_FA_VARARGS is provided, _f_u_n_c_t_i_o_n is called with three arguments. The first argument is a term_t handle to the first argument. Further arguments can be reached by adding the offset (see also PL_new_term_refs()). The second argument is the arity, which defines the number of valid term-references in the argument vector. The last argument is used for non-deterministic calls. It is currently undocumented and should be defined of type void*. Here is an example: static foreign_t atom_checksum(term_t a0, int arity, void* context) { char *s; if ( PL_get_atom_chars(a0, &s) ) { int sum; for(sum=0; *s; s++) sum += *s&0xff; return PL_unify_integer(a0+1, sum&0xff); } return FALSE; } install_t install() { PL_register_foreign("atom_checksum", 2, atom_checksum, PL_FA_VARARGS); } int PPLL__rreeggiisstteerr__ffoorreeiiggnn(_c_o_n_s_t _c_h_a_r _*_n_a_m_e_, _i_n_t _a_r_i_t_y_, _f_o_r_e_i_g_n___t _(_*_f_u_n_c_t_i_o_n_)_(_)_, _i_n_t _f_l_a_g_s) Same as PL_register_foreign_in_module(), passing NULL for the _m_o_d_u_l_e. void PPLL__rreeggiisstteerr__eexxtteennssiioonnss__iinn__mmoodduullee(_c_o_n_s_t _c_h_a_r _*_m_o_d_u_l_e_, _P_L___e_x_t_e_n_s_i_o_n _*_e) Register a series of predicates from an array of defini- tions of the type PL_extension in the given _m_o_d_u_l_e. If _m_o_d_u_l_e is NULL, the predicate is created in the module of the calling context or if no context is present in the module user. The PL_extension type is defined as typedef struct PL_extension { char *predicate_name; /* Name of the predicate */ short arity; /* Arity of the predicate */ pl_function_t function; /* Implementing functions */ short flags; /* Or of PL_FA_... */ } PL_extension; For details, see PL_register_foreign_in_module(). Here is an example of its usage: static PL_extension predicates[] = { { "foo", 1, pl_foo, 0 }, { "bar", 2, pl_bar, PL_FA_NONDETERMINISTIC }, { NULL, 0, NULL, 0 } }; main(int argc, char **argv) { PL_register_extensions_in_module("user", predicates); if ( !PL_initialise(argc, argv) ) PL_halt(1); ... } void PPLL__rreeggiisstteerr__eexxtteennssiioonnss( _P_L___e_x_t_e_n_s_i_o_n _*_e) Same as PL_register_extensions_in_module() using NULL for the _m_o_d_u_l_e argument. 99..66..1188 FFoorreeiiggnn CCooddee HHooookkss For various specific applications some hooks re provided. PL_dispatch_hook_t PPLL__ddiissppaattcchh__hhooookk(_P_L___d_i_s_p_a_t_c_h___h_o_o_k___t) If this hook is not NULL, this function is called when reading from the terminal. It is supposed to dispatch events when SWI-Prolog is connected to a window environment. It can return two values: PL_DISPATCH_INPUT indicates Prolog input is available on file descriptor 0 or PL_DISPATCH_TIMEOUT to indicate a timeout. The old hook is returned. The type PL_dispatch_hook_t is defined as: typedef int (*PL_dispatch_hook_t)(void); void PPLL__aabboorrtt__hhooookk(_P_L___a_b_o_r_t___h_o_o_k___t) Install a hook when abort/0 is executed. SWI-Prolog abort/0 is implemented using C setjmp()/longjmp() construct. The hooks are executed in the reverse order of their registration after the longjmp() took place and before the Prolog top-level is reinvoked. The type PL_abort_hook_t is defined as: typedef void (*PL_abort_hook_t)(void); int PPLL__aabboorrtt__uunnhhooookk(_P_L___a_b_o_r_t___h_o_o_k___t) Remove a hook installed with PL_abort_hook(). Returns FALSE if no such hook is found, TRUE otherwise. void PPLL__oonn__hhaalltt(_v_o_i_d _(_*_f_)_(_i_n_t_, _v_o_i_d _*_)_, _v_o_i_d _*_c_l_o_s_u_r_e) Register the function _f to be called if SWI-Prolog is halted. The function is called with two arguments: the exit code of the process (0 if this cannot be determined on your operating system) and the _c_l_o_s_u_r_e argument passed to the PL_on_halt() call. See also at_halt/1. PL_agc_hook_t PPLL__aaggcc__hhooookk(_P_L___a_g_c___h_o_o_k___t _n_e_w) Register a hook with the atom-garbage collector (see garbage_collect_atoms/0 that is called on any atom that is reclaimed. The old hook is returned. If no hook is currently defined, NULL is returned. The argument of the called hook is the atom that is to be garbage collected. The return value is an int. If the return value is zero, the atom is nnoott reclaimed. The hook may invoke any Prolog predicate. The example below defines a foreign library for printing the garbage collected atoms for debugging purposes. #include #include static int atom_hook(atom_t a) { Sdprintf("AGC: deleting %s\n", PL_atom_chars(a)); return TRUE; } static PL_agc_hook_t old; install_t install() { old = PL_agc_hook(atom_hook); } install_t uninstall() { PL_agc_hook(old); } 99..66..1199 SSttoorriinngg ffoorreeiiggnn ddaattaa This section provides some hints for handling foreign data in Prolog. With foreign data, we refer to data that is used by foreign language predicates and needs to be passed around in Prolog. Excluding combinations, there are three principal options for storing such data o _N_a_t_u_r_a_l _P_r_o_l_o_g _d_a_t_a E.i. using the representation one would choose if there was no foreign interface required. o _O_p_a_q_u_e _p_a_c_k_e_d _P_r_o_l_o_g _d_a_t_a Data can also be represented in a foreign structure and stored on the Prolog stacks using PL_put_string_nchars() and retrieved using PL_get_string_chars(). It is generally good practice to wrap the string in a compound term with arity 1, so Prolog can identify the type. portray/1 rules may be used to streamline printing such terms during development. o _N_a_t_u_r_a_l _f_o_r_e_i_g_n _d_a_t_a_, _p_a_s_s_i_n_g _a _p_o_i_n_t_e_r An alternative is to pass a pointer to the foreign data. Again, this functor may be wrapped in a compound term. The choice may be guided using the following distinctions o _I_s _t_h_e _d_a_t_a _o_p_a_q_u_e _t_o _P_r_o_l_o_g With `opaque' data, we refer to data handled in foreign functions, passed around in Prolog, but of which Prolog never examines the contents of the data itself. If the data is opaque to Prolog, the chosen representation does not depend on simple analysis by Prolog, and the selection will be driven solely by simplicity of the interface and performance (both in time and space). o _H_o_w _b_i_g _i_s _t_h_e _d_a_t_a Is efficient encoding required? For examine, a boolean array may be expressed as a compound term, holding integers each of which contains a number of bits, or as a list of true and false. o _W_h_a_t _i_s _t_h_e _n_a_t_u_r_e _o_f _t_h_e _d_a_t_a For examples in C, constants are often expressed using `enum' or #define'd integer values. If prolog needs to handle this data, atoms are a more logical choice. Whether or not this mapping is used depends on whether Prolog needs to interpret the data, how important debugging is and how important performance is. o _W_h_a_t _i_s _t_h_e _l_i_f_e_t_i_m_e _o_f _t_h_e _d_a_t_a We can distinguish three cases. 1. The lifetime is dictated by the accessibility of the data on the Prolog stacks. Their is no way by which the foreign code when the data becomes `garbage', and the data thus needs to be represented on the Prolog stacks using Prolog data-types. (2), 2. The data lives on the `heap' and is explicitly allocated and deallocated. In this case, representing the data using native foreign representation and passing a pointer to it is a sensible choice. 3. The data lives as during the lifetime of a foreign predicate. If the predicate is deterministic, foreign automatic variables are suitable. if the predicate is non-deterministic, the data may be allocated using malloc() and a pointer may be passed. See section 9.6.1.1. 99..66..1199..11 EExxaammpplleess ffoorr ssttoorriinngg ffoorreeiiggnn ddaattaa In this section, we will outline some examples, covering typical cases. In the first example, we will deal with extending Prolog's data representation with integer-sets, represented as bit-vectors. Finally, we discuss the outline of the DDE interface. IInntteeggeerr sseettss with not-too-far-apart upper- and lower-bounds can be represented using bit-vectors. Common set operations, such as union, intersection, etc. are reduced to simple and'ing and or'ing the bit-vectors. This can be done in Prolog, using a compound term holding integer arguments. Especially if the integers are kept below the maximum tagged integer value (see current_prolog_flag/2), this representation is fairly space-efficient (wasting 1 word for the functor and and 7 bits per integer for the tags). Arithmetic can all be performed in Prolog too. For really demanding applications, foreign representation will perform better, especially time-wise. Bit-vectors are naturally expressed using string objects. If the string is wrapped in bitvector/1, lower-bound of the vector is 0, and the upper-bound is not defined, an implementation for getting and putting the sets as well as the union predicate for it is below. #include #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) static functor_t FUNCTOR_bitvector1; static int get_bitvector(term_t in, int *len, unsigned char **data) { if ( PL_is_functor(in, FUNCTOR_bitvector1) ) { term_t a = PL_new_term_ref(); PL_get_arg(1, in, a); return PL_get_string(a, (char **)data, len); } PL_fail; } static int unify_bitvector(term_t out, int len, const unsigned char *data) { if ( PL_unify_functor(out, FUNCTOR_bitvector1) ) { term_t a = PL_new_term_ref(); PL_get_arg(1, out, a); return PL_unify_string_nchars(a, len, (const char *)data); } PL_fail; } static foreign_t pl_bitvector_union(term_t t1, term_t t2, term_t u) { unsigned char *s1, *s2; int l1, l2; if ( get_bitvector(t1, &l1, &s1) && get_bitvector(t2, &l2, &s2) ) { int l = max(l1, l2); unsigned char *s3 = alloca(l); if ( s3 ) { int n; int ml = min(l1, l2); for(n=0; n)), making the type-problem less serious. Alternatively (used in the DDE interface), the interface code can maintain a (preferably variable length) array of pointers and return the index in this array. This provides better protection. Especially for debugging purposes, wrapping the handle in a compound is a good suggestion. 99..66..2200 EEmmbbeeddddiinngg SSWWII--PPrroolloogg iinn ootthheerr aapppplliiccaattiioonnss With embedded Prolog we refer to the situation where the `main' program is not the Prolog application. Prolog is sometimes embedded in C, C++, Java or other languages to provide logic based services in a larger application. Embedding loads the Prolog engine as a library to the external language. Prolog itself only provides for embedding in the C-language (compatible to C++). Embedding in Java is achieved using JPL using a C-glue between the Java and Prolog C-interfaces. The most simple embedded program is below. The interface function PL_initialise() mmuusstt be called before any of the other SWI-Prolog foreign language functions described in this chapter, except for PL_initialise_hook(), PL_new_atom(), PL_new_functor() and PL_register_foreign(). PL_initialise() interprets all the command-line arguments, except for the -t toplevel flag that is interpreted by PL_toplevel(). int main(int argc, char **argv) { #ifdef READLINE /* Remove if you don't want readline */ PL_initialise_hook(install_readline); #endif if ( !PL_initialise(argc, argv) ) PL_halt(1); PL_halt(PL_toplevel() ? 0 : 1); } int PPLL__iinniittiiaalliissee(_i_n_t _a_r_g_c_, _c_h_a_r _*_*_a_r_g_v) Initialises the SWI-Prolog heap and stacks, restores the Prolog state, loads the system and personal initialisation files, runs the at_initialization/1 hooks and finally runs the -g goal hook. Special consideration is required for argv[0]. On UUnniixx, this argument passes the part of the command-line that is used to locate the executable. Prolog uses this to find the file holding the running executable. The WWiinnddoowwss version uses this to find a _m_o_d_u_l_e of the running executable. If the specified module cannot be found, it tries the module libpl.dll, containing the Prolog runtime kernel. In all these cases, the resulting file is used for two purposes o See whether a Prolog saved-state is appended to the file. If this is the case, this state will be loaded instead of the default boot.prc file from the SWI-Prolog home directory. See also qsave_program/[1,2] and section 9.7. o Find the Prolog home directory. This process is described in detail in section 9.8. PL_initialise() returns 1 if all initialisation succeeded and 0 otherwise. In most cases, _a_r_g_c and _a_r_g_v will be passed from the main program. It is allowed to create your own argument vector, provided argv[0] is constructed according to the rules above. For example: int main(int argc, char **argv) { char *av[10]; int ac = 0; av[ac++] = argv[0]; av[ac++] = "-x"; av[ac++] = "mystate"; av[ac] = NULL; if ( !PL_initialise(ac, av) ) PL_halt(1); ... } Please note that the passed argument vector may be referred from Prolog at any time and should therefore be valid as long as the Prolog engine is used. A good setup in Windows is to add SWI-Prolog's bin directory to your PATH and either pass a module holding a saved-state, or "libpl.dll" as argv[0]. If the Prolog state is attached to a DLL (see the -dll option of plld, pass the name of this DLL. int PPLL__iiss__iinniittiiaalliisseedd(_i_n_t _*_a_r_g_c_, _c_h_a_r _*_*_*_a_r_g_v) Test whether the Prolog engine is already initialised. Returns FALSE if Prolog is not initialised and TRUE otherwise. If the engine is initialised and _a_r_g_c is not NULL, the argument count used with PL_initialise() is stored in _a_r_g_c. Same for the argument vector _a_r_g_v. void PPLL__iinnssttaallll__rreeaaddlliinnee() Installs the GNU-readline line-editor. Embedded applications that do not use the Prolog top-level should normally delete this line, shrinking the Prolog kernel significantly. Note that the Windows version does not use GNU readline. int PPLL__ttoopplleevveell() Runs the goal of the -t toplevel switch (default prolog/0) and returns 1 if successful, 0 otherwise. void PPLL__cclleeaannuupp(_i_n_t _s_t_a_t_u_s) This function performs the reverse of PL_initialise(). It runs the PL_on_halt() and at_halt/1 handlers, closes all streams (except for the `standard I/O' streams which are flushed only), deallocates all memory and restores all signal handlers. The _s_t_a_t_u_s argument is passed to the various termination hooks and indicates the _e_x_i_t_-_s_t_a_t_u_s. This function allows deleting and restarting the Prolog system in the same process. Use it with care, as PL_initialise() is a costly function. Unix users should consider using exec() (available as part of the clib package,). int PPLL__hhaalltt(_i_n_t _s_t_a_t_u_s) Cleanup the Prolog environment using PL_cleanup() and calls exit() with the status argument. As PL_cleanup() can only be called from the main thread, this function returns FALSE when called from another thread as the main one. 99..66..2200..11 TThhrreeaaddiinngg,, SSiiggnnaallss aanndd eemmbbeeddddeedd PPrroolloogg This section applies to Unix-based environments that have signals or multi-threading. The Windows version is compiled for multi-threading and Windows lacks proper signals. We can distinguish two classes of embedded executables. There are small C/C++-programs that act as an interfacing layer around Prolog. Most of these programs can be replaced using the normal Prolog executable extended with a dynamically loaded foreign extension and in most cases this is the preferred route. In other cases, Prolog is embedded in a complex application that---like Prolog---wants to control the process environment. A good example is Java. Embedding Prolog is generally the only way to get these environments together in one process image. Java applications however are by nature multi-threaded and appear to do signal-handling (software interrupts). To make Prolog operate smoothly in such environments it must be told not to alter the process environment. This is partly done at build-time and partly execution time. At build-time we must specify the use of software stack-overflow rather then the default hardware checks. This is done using sh configure --disable-segv-handling The resulting Prolog executable is about 10% slower than the normal executable, but behaves much more reliable in complicated embedded situations. In addition, as the process no longer handles segmentation violations, debugging foreign code linked to it is much easier. At runtime, it is advised to pass the flag -nosignals, which inhibits all default signal handling. This has a few consequences though: o It is no longer possible to break into the tracer using an interrupt signal (Control-C). o SIGPIPE is normally set to be ignored. Prolog uses return-codes to diagnose broken pipes. Depending on the situation one should take appropriate action if Prolog streams are connected to pipes. o Fatal errors normally cause Prolog to call PL_cleanup() and exit(). It is advised to call PL_cleanup() as part of the exit-procedure of your application. 99..77 LLiinnkkiinngg eemmbbeeddddeedd aapppplliiccaattiioonnss uussiinngg pplllldd The utility program plld (Win32: plld.exe) may be used to link a combination of C-files and Prolog files into a stand-alone executable. plld automates most of what is described in the previous sections. In the normal usage, a copy is made of the default embedding template \ldots/pl/include/stub.c. The main() routine is modified to suit your application. PL_initialise() mmuusstt be passed the program-name (_a_r_g_v_[_0_]) (Win32: the executing program can be obtained using GetModuleFileName()). The other elements of the command-line may be modified. Next, plld is typically invoked as: plld -o output stubfile.c [other-c-or-o-files] [plfiles] plld will first split the options into various groups for both the C-compiler and the Prolog compiler. Next, it will add various default options to the C-compiler and call it to create an executable holding the user's C-code and the Prolog kernel. Then, it will call the SWI-Prolog compiler to create a saved state from the provided Prolog files and finally, it will attach this saved state to the created emulator to create the requested executable. Below, it is described how the options are split and which additional options are passed. --hheellpp Print brief synopsis. --ppll _p_r_o_l_o_g Select the prolog to use. This prolog is used for two purposes: get the home-directory as well as the compiler/linker options and create a saved state of the Prolog code. --lldd _l_i_n_k_e_r Linker used to link the raw executable. Default is to use the C-compiler (Win32: link.exe). --cccc _C_-_c_o_m_p_i_l_e_r Compiler for .c files found on the command-line. Default is the compiler used to build SWI-Prolog (see current_prolog_flag/2) (Win32: cl.exe). --cc++++ _C_+_+_-_c_o_m_p_i_l_e_r Compiler for C++ sources (extensions .cpp, .cxx, .cc or .C) files found on the command-line. Default is c++ or g++ if the C-compiler is gcc) (Win32: cl.exe). --nnoossttaattee Just relink the kernel, do not add any Prolog code to the new kernel. This is used to create a new kernel holding additional foreign predicates on machines that do not support the shared-library (DLL) interface, or if building the state cannot be handled by the default procedure used by plld. In the latter case the state is created separately and appended to the kernel using cat <_k_e_r_n_e_l> <_s_t_a_t_e> > <_o_u_t>(Win32: copy /b <_k_e_r_n_e_l>+<_s_t_a_t_e> <_o_u_t>) --sshhaarreedd Link C, C++ or object files into a shared object (DLL) that can be loaded by the load_foreign_library/1predicate. If used with -c it sets the proper options to compile a C or C++ file ready for linking into a shared object --ddllll _W_i_n_d_o_w_s _o_n_l_y. Embed SWI-Prolog into a DLL rather than an executable. --cc Compile C or C++ source-files into object files. This turns plld into a replacement for the C or C++ compiler where proper options such as the location of the include directory are passed automatically to the compiler. --EE Invoke the C preprocessor. Used to make plld a replacement for the C or C++ compiler. --ppll--ooppttiioonnss _,_._._. Additional options passed to Prolog when creating the saved state. The first character immediately following pl-options is used as separator and translated to spaces when the argument is built. Example: -pl-options,-F,xpce passed -F xpce as additional flags to Prolog. --lldd--ooppttiioonnss _,_._._. Passes options to the linker, similar to -pl-options. --cccc--ooppttiioonnss _,_._._. Passes options to the C/C++ compiler, similar to -pl-options. --vv Select verbose operation, showing the various programs and their options. --oo _o_u_t_f_i_l_e Reserved to specify the final output file. --ll_l_i_b_r_a_r_y Specifies a library for the C-compiler. By default, -lpl (Win32: libpl.lib) and the libraries needed by the Prolog kernel are given. --LL_l_i_b_r_a_r_y_-_d_i_r_e_c_t_o_r_y Specifies a library directory for the C-compiler. By default the directory containing the Prolog C-library for the current architecture is passed. -g | -Iinclude-directory | -Ddefinition These options are passed to the C-compiler. By default, the include directory containing SWI-Prolog.h is passed. plld adds two additional * -Ddef flags: --DD____SWI_PROLOG__ Indicates the code is to be connected to SWI-Prolog. --DD____SWI_EMBEDDED__ Indicates the creation of an embedded program. _*_._o | _*_._c | _*_._C | _*_._c_x_x | _*_._c_p_p Passed as input files to the C-compiler _*_._p_l |_*_._q_l_f Passed as input files to the Prolog compiler to create the saved-state. * I.e. all other options. These are passed as linker options to the C-compiler. 99..77..11 AA ssiimmppllee eexxaammppllee The following is a very simple example going through all the steps outlined above. It provides an arithmetic expression evaluator. We will call the application calc and define it in the files calc.c and calc.pl. The Prolog file is simple: calc(Atom) :- term_to_atom(Expr, Atom), A is Expr, write(A), nl. The C-part of the application parses the command-line options, initialises the Prolog engine, locates the calc/1 predicate and calls it. The coder is in figure 9.5. #include #include #define MAXLINE 1024 int main(int argc, char **argv) { char expression[MAXLINE]; char *e = expression; char *program = argv[0]; char *plav[2]; int n; /* combine all the arguments in a single string */ for(n=1; n #include #include foreign_t pl_lowercase(term_t u, term_t l) { char *copy; char *s, *q; int rval; if ( !PL_get_atom_chars(u, &s) ) return PL_warning("lowercase/2: instantiation fault"); copy = malloc(strlen(s)+1); for( q=copy; *s; q++, s++) *q = (isupper(*s) ? tolower(*s) : *s); *q = '\0'; rval = PL_unify_atom_chars(l, copy); free(copy); return rval; } install_t install() { PL_register_foreign("lowercase", 2, pl_lowercase, 0); } Figure 9.6: Lowercase source file % gcc -I/usr/local/lib/pl-\plversion/include -fpic -c lowercase.c % gcc -shared -o lowercase.so lowercase.o % pl Welcome to SWI-Prolog (Version \plversion) Copyright (c) 1993-1996 University of Amsterdam. All rights reserved. For help, use ?- help(Topic). or ?- apropos(Word). 1 ?- load_foreign_library(lowercase). Yes 2 ?- lowercase('Hello World!', L). L = 'hello world!' Yes Figure 9.7: Compiling the C-source and loading the object file 99..1100 NNootteess oonn UUssiinngg FFoorreeiiggnn CCooddee 99..1100..11 MMeemmoorryy AAllllooccaattiioonn SWI-Prolog's heap memory allocation is based on the malloc(3) library routines. The stacks are allocated using mmap() on most Unix machines and using VirtualAlloc() on windows. SWI-Prolog provides the functions below as a wrapper around malloc(). Allocation errors in these functions trap SWI-Prolog's fatal-error handler, in which case PL_malloc() or PL_realloc() do not return. Portable applications must use PL_free() to release strings returned by PL_get_chars() using the BUF_MALLOC argument. Portable applications may use both PL_malloc() and friends or malloc() and friends but should not mix these two sets of functions on the same memory. void * PPLL__mmaalllloocc(_s_i_z_e___t _b_y_t_e_s) Allocate _b_y_t_e_s of memory. On failure SWI-Prolog's fatal error handler is called and PL_malloc() does not return. Memory allocated using these functions must use PL_realloc() and PL_free() rather than realloc() and free(). void * PPLL__rreeaalllloocc(_v_o_i_d _*_m_e_m_, _s_i_z_e___t _s_i_z_e) Change the size of the allocated chunk, possibly moving it. The _m_e_m argument must be obtained from a previous PL_malloc() or PL_realloc() call. void PPLL__ffrreeee(_v_o_i_d _*_m_e_m) Release memory. The _m_e_m argument must be obtained from a previous PL_malloc() or PL_realloc() call. 99..1100..22 CCoommppaattiibbiilliittyy bbeettwweeeenn PPrroolloogg vveerrssiioonnss Great care is taken to ensure binary compatibility of foreign extensions between different Prolog versions. Only much less frequently used stream interface has been responsible for binary incompatibilities. Source-code that relies on new features of the foreign interface can use the macro PLVERSION to find the version of SWI-Prolog.h and PL_query() using the option PL_QUERY_VERSION to find the version of the attached Prolog system. Both follow the same numbering schema explained with PL_query(). 99..1100..33 DDeebbuuggggiinngg FFoorreeiiggnn CCooddee Statically linked foreign code or embedded systems can be debugged normally. Most modern environments provide debugging tools for dynamically loaded shared objects or dynamic load libraries. The following example traces the code of lowercase using gdb(1) in a Unix environment. % gcc -I/usr/local/lib/pl-2.2.0/include -fpic -c -g lowercase.c % gcc -shared -o lowercase.so lowercase.o % gdb pl (gdb) r Welcome to SWI-Prolog (Version \plversion) Copyright (c) 1993-1996 University of Amsterdam. All rights reserved. For help, use ?- help(Topic). or ?- apropos(Word). ?- load_foreign_library(lowercase). (gdb) shared % loads symbols for shared objects (gdb) break pl_lowercase (gdb) continue ?- lowercase('HELLO', X). 99..1100..44 NNaammee CCoonnfflliiccttss iinn CC mmoodduulleess In the current version of the system all public C functions of SWI-Prolog are in the symbol table. This can lead to name clashes with foreign code. Someday I should write a program to strip all these symbols from the symbol table (why does Unix not have that?). For now I can only suggest to give your function another name. You can do this using the C preprocessor. If---for example---your foreign package uses a function warning(), which happens to exist in SWI-Prolog as well, the following macro should fix the problem. #define warning warning_ Note that shared libraries do not have this problem as the shared library loader will only look for symbols in the main executable for symbols that are not defined in the library itself. 99..1100..55 CCoommppaattiibbiilliittyy ooff tthhee FFoorreeiiggnn IInntteerrffaaccee The term-reference mechanism was first used by Quintus Prolog version 3. SICStus Prolog version 3 is strongly based on the Quintus interface. The described SWI-Prolog interface is similar to using the Quintus or SICStus interfaces, defining all foreign-predicate arguments of type +term. SWI-Prolog explicitly uses type functor_t, while Quintus and SICStus uses <_n_a_m_e> and <_a_r_i_t_y>. As the names of the functions differ from Prolog to Prolog, a simple macro layer dealing with the names can also deal with this detail. For example: #define QP_put_functor(t, n, a) PL_put_functor(t, PL_new_functor(n, a)) The PL_unify_*() functions are lacking from the Quintus and SICStus interface. They can easily be emulated or the put/unify approach should be used to write compatible code. The PL_open_foreign_frame()/PL_close_foreign_frame() combination is lacking from both other Prologs. SICStus has PL_new_term_refs(0), followed by PL_reset_term_refs() that allows for discarding term references. The Prolog interface for the graphical user interface package XPCE shares about 90% of the code using a simple macro layer to deal with different naming and calling conventions of the interfaces. CChhaapptteerr 1100.. GGEENNEERRAATTIINNGG RRUUNNTTIIMMEE AAPPPPLLIICCAATTIIOONNSS This chapter describes the features of SWI-Prolog for delivering applications that can run without the development version of the system installed. A SWI-Prolog runtime executable is a file consisting of two parts. The first part is the _e_m_u_l_a_t_o_r, which is machine dependent. The second part is the _r_e_s_o_u_r_c_e _a_r_c_h_i_v_e, which contains the compiled program in a machine-independent format, startup options and possibly user-defined _r_e_s_o_u_r_c_e_s, see resource/3 and open_resource/3. These two parts can be connected in various different ways. The most common way for distributed runtime applications is to _c_o_n_c_a_t_e_n_a_t_e the two parts. This can be achieved using external commands (Unix: cat, Windows: copy), or using the stand_alone option to qsave_program/2. The second option is to attach a startup script in front of the resource that starts the emulator with the proper options. This is the default under Unix. Finally, an emulator can be told to use a specified resource file using the -x command-line switch. qqssaavvee__pprrooggrraamm((_+_F_i_l_e_, _+_L_i_s_t_O_f_O_p_t_i_o_n_s)) Saves the current state of the program to the file _F_i_l_e. The result is a resource archive containing a saved-state that expresses all Prolog data from the running program and all user-defined resources. Depending on the stand_alone option, the resource is headed by the emulator, a Unix shell-script or nothing. _L_i_s_t_O_f_O_p_t_i_o_n_s is a list of <_K_e_y>=<_V_a_l_u_e> or <_K_e_y>(<_V_a_l_u_e>) pairs. The available keys are described in table 10.1. _________________________________________________________________________ |__KKeeyy________________||OOppttiioonn__||________TTyyppee____________||DDeessccrriippttiioonn__________________________________________________|| || local | --LL || K-bytes |Size (Limit) of local stack | | global | --GG || K-bytes |Size (Limit) of global stack | | trail | --TT || K-bytes |Size (Limit) of trail stack | | argument | --AA || K-bytes |Size (Limit) of argument stack | | goal | --gg || atom |Initialisation goal | | toplevel | --tt || atom |Prolog top-level goal | |_init_file___|--ff___||_____atom______|Personal_initialisation_file________|||||| | class | | atom |If runtime, only read resources | | | | |from the state (default). If | | | | |kernel, lock all predicates as | | | | |system predicates If development, | | | | |save the predicates in their | | | | |current state and keep reading | | | | |resources from their source (if | | | | |present). See also resource/3. | | autoload | | bool |If true, run autoload/0 first | | map | | file |File to write info on dump | | op | | save/standard |Save operator declarations? | | stand_alone | | bool |Include the emulator in the state | | emulator | | file |Emulator attached to the (stand- | | | | |alone) executable. Default is the | |____________|______|_______________|running_emulator.___________________| Table 10.1: <_K_e_y> = <_V_a_l_u_e> pairs for qsave_program/2 Before writing the data to file, qsave_program/2 will run autoload/0 to all required autoloading the system can discover. See autoload/0. Provided the application does not require any of the Prolog libraries to be loaded at runtime, the only file from the SWI-Prolog development environment required is the emulator itself. The emulator may be built in two flavours. The default is the _d_e_v_e_l_o_p_m_e_n_t _e_m_u_l_a_t_o_r. The _r_u_n_t_i_m_e _e_m_u_l_a_t_o_r is similar, but lacks the tracer. If the option stand_alone(true) is present, the emulator is the first part of the state. If the emulator is started it will test whether a boot-file (state) is attached to the emulator itself and load this state. Provided the application has all libraries loaded, the resulting executable is completely independent of the runtime environment or location where it was build. See also section 2.10.2.4. qqssaavvee__pprrooggrraamm((_+_F_i_l_e)) Equivalent to qsave_program(File, []). aauuttoollooaadd Check the current Prolog program for predicates that are referred to, are undefined and have a definition in the Prolog library. Load the appropriate libraries. This predicate is used by qsave_program/[1,2] to ensure the saved state will not depend on one of the libraries. The predicate autoload/0 will find all ddiirreecctt references to predicates. It does not find predicates referenced via meta-predicates. The predicate log/2 is defined in the library(quintus) to provide a quintus compatible means to compute the natural logarithm of a number. The following program will behave correctly if its state is executed in an environment where the library(quintus) is not available: logtable(From, To) :- From > To, !. logtable(From, To) :- log(From, Value), format('~d~t~8|~2f~n', [From, Value]), F is From + 1, logtable(F, To). However, the following implementation refers to log/2 through the meta-predicate maplist/3. Autoload will not be able to find the reference. This problem may be fixed either by loading the module library(quintus) explicitly or use require/1 to tell the system that the predicate log/2 is required by this module. logtable(From, To) :- findall(X, between(From, To, X), Xlist), maplist(log, Xlist, SineList), write_table(Xlist, SineList). write_table([], []). write_table([I|IT], [V|VT]) :- format('~d~t~8|~2f~n', [I, V]), write_table(IT, VT). vvoollaattiillee _+_N_a_m_e_/_A_r_i_t_y_, _._._. Declare that the clauses of specified predicates should nnoott be saved to the program. The volatile declaration is normally used to avoid that the clauses of dynamic predicates that represent data for the current session is saved in the state file. 1100..11 LLiimmiittaattiioonnss ooff qqssaavvee__pprrooggrraamm There are three areas that require special attention when using qsave_program/[1,2]. o If the program is an embedded Prolog application or uses the foreign language interface, care has to be taken to restore the appropriate foreign context. See section 10.2 for details. o If the program uses directives (:- goal. lines) that perform other actions then setting predicate attributes (dynamic, volatile, etc.) or loading files (consult, etc.), the directive may need to be prefixed with initialization/1. o Database references as returned by clause/3, recorded/3, etc. are not preserved and may thus not be part of the database when saved. 1100..22 RRuunnttiimmeess aanndd FFoorreeiiggnn CCooddee Some applications may need to use the foreign language interface. Object code is by definition machine-dependent and thus cannot be part of the saved program file. To complicate the matter even further there are various ways of loading foreign code: o _U_s_i_n_g _t_h_e _l_i_b_r_a_r_y_(_s_h_l_i_b_) _p_r_e_d_i_c_a_t_e_s This is the preferred way of dealing with foreign code. It loads quickly and ensures an acceptable level of independence between the versions of the emulator and the foreign code loaded. It works on Unix machines supporting shared libraries and library functions to load them. Most modern Unixes, as well as Win32 (Windows 95/NT) satisfy this constraint. o _S_t_a_t_i_c _l_i_n_k_i_n_g This mechanism works on all machines, but generally requires the same C-compiler and linker to be used for the external code as is used to build SWI-Prolog itself. To make a runtime executable that can run on multiple platforms one must make runtime checks to find the correct way of linking. Suppose we have a source-file myextension.c defining the installation function install(). If this file is compiled into a shared library, load_foreign_library/1 will load this library and call the installation function to initialise the foreign code. If it is loaded as a static extension, define install() as the predicate install/0: static foreign_t pl_install() { install(); PL_succeed; } PL_extension PL_extensions [] = { /*{ "name", arity, function, PL_FA_ },*/ { "install", 0, pl_install, 0 }, { NULL, 0, NULL, 0 } /* terminating line */ }; Now, use the following Prolog code to load the foreign library: load_foreign_extensions :- current_predicate(install, install), !, % static loaded install. load_foreign_extensions :- % shared library load_foreign_library(foreign(myextension)). :- initialization load_foreign_extensions. The path alias foreign is defined by file_search_path/2. By default it searches the directories <_h_o_m_e>/lib/<_a_r_c_h> and <_h_o_m_e>/lib. The application can specify additional rules for file_search_path/2. 1100..33 UUssiinngg pprrooggrraamm rreessoouurrcceess A _r_e_s_o_u_r_c_e is very similar to a file. Resources however can be represented in two different formats: on files, as well as part of the resource _a_r_c_h_i_v_e of a saved-state (see qsave_program/2). A resource has a _n_a_m_e and a _c_l_a_s_s. The _s_o_u_r_c_e data of the resource is a file. Resources are declared by declaring the predicate resource/3. They are accessed using the predicate open_resource/3. Before going into details, let us start with an example. Short texts can easily be expressed in Prolog source code, but long texts are cumbersome. Assume our application defines a command `help' that prints a helptext to the screen. We put the content of the helptext into a file called help.txt. The following code implements our help command such that help.txt is incorporated into the runtime executable. resource(help, text, 'help.txt'). help :- open_resource(help, text, In), copy_stream(In, user_output), close(In). copy_stream(In, Out) :- get0(In, C), copy_stream(C, In, Out). copy_stream(-1, _, _) :- !. copy_stream(C, In, Out) :- put(Out, C), get0(In, C2), copy_stream(C2, In, Out). The predicate help/0 opens the resource as a Prolog stream. If we are executing this from the development environment, this will actually return a stream to the file help.txt itself. When executed from the saved-state, the stream will actually be a stream opened on the program resource file, taking care of the offset and length of the resource. 1100..33..11 PPrreeddiiccaatteess DDeeffiinniittiioonnss rreessoouurrccee((_+_N_a_m_e_, _+_C_l_a_s_s_, _+_F_i_l_e_S_p_e_c)) This predicate is defined as a dynamic predicate in the module user. Clauses for it may be defined in any module, including the user module. _N_a_m_e is the name of the resource (an atom). A resource name may contain any character, except for $ and :, which are reserved for internal usage by the resource library. _C_l_a_s_s describes the what kind of object is stored in the resource. In the current implementation, it is just an atom. _F_i_l_e_S_p_e_c is a file specification that may exploit file_search_path/2 (see absolute_file_name/2). Normally, resources are defined as unit clauses (facts), but the definition of this predicate also allows for rules. For proper generation of the saved state, it must be possible to enumerate the available resources by calling this predicate with all its arguments unbound. Dynamic rules are useful to turn all files in a certain directory into resources, without specifying a resources for each file. For example, assume the file_search_path/2icons refers to the resource directory containing icon-files. The following definition makes all these images available as resources: resource(Name, image, icons(XpmName)) :- atom(Name), !, file_name_extension(Name, xpm, XpmName). resource(Name, image, XpmFile) :- var(Name), absolute_file_name(icons(.), [type(directory)], Dir) concat(Dir, '/*.xpm', Pattern), expand_file_name(Pattern, XpmFiles), member(XpmFile, XpmFiles). ooppeenn__rreessoouurrccee((_+_N_a_m_e_, _?_C_l_a_s_s_, _-_S_t_r_e_a_m)) Opens the resource specified by _N_a_m_e and _C_l_a_s_s. If the latter is a variable, it will be unified to the class of the first resource found that has the specified _N_a_m_e. If successful, _S_t_r_e_a_m becomes a handle to a binary input stream, providing access to the content of the resource. The predicate open_resource/3 first checks resource/3. When successful it will open the returned resource source-file. Otherwise it will look in the programs resource database. When creating a saved-state, the system normally saves the resource contents into the resource archive, but does not save the resource clauses. This way, the development environment uses the files (and modifications to the resource/3 declarations and/or files containing resource info thus immediately affect the running environment, while the runtime system quickly accesses the system resources. 1100..33..22 TThhee plrc pprrooggrraamm The utility program plrc can be used to examine and manipulate the contents of a SWI-Prolog resource file. The options are inspired by the Unix ar program. The basic command is: % plrc option resource-file member ... The options are described below. ll List contents of the archive. xx Extract named (or all) members of the archive into the current directory. aa Add files to the archive. If the archive already contains a member with the same name, the contents is replaced. Anywhere in the sequence of members, the options --class=_c_l_a_s_s and --encoding=_e_n_c_o_d_i_n_g may appear. They affect the class and encoding of subsequent files. The initial class is data and encoding none. dd Delete named members from the archive. This command is also described in the pl(1) Unix manual page. 1100..44 FFiinnddiinngg AApppplliiccaattiioonn ffiilleess If your application uses files that are not part of the saved program such as database files, configuration files, etc., the runtime version has to be able to locate these files. The file_search_path/2 mechanism in combination with the -palias command-line argument is the preferred way to locate runtime files. The first step is to define an alias for the top-level directory of your application. We will call this directory gnatdir in our examples. A good place for storing data associated with SWI-Prolog runtime systems is below the emulator's home-directory. swi is a predefined alias for this directory. The following is a useful default definition for the search path. user:file_search_path(gnatdir, swi(gnat)). The application should locate all files using absolute_file_name. Suppose gnatdir contains a file config.pl to define local configuration. Then use the code below to load this file: configure_gnat :- ( absolute_file_name(gnatdir('config.pl'), ConfigFile) -> consult(ConfigFile) ; format(user_error, 'gnat: Cannot locate config.pl~n'), halt(1) ). 1100..44..11 PPaassssiinngg aa ppaatthh ttoo tthhee aapppplliiccaattiioonn Suppose the system administrator has installed the SWI-Prolog runtime environment in /usr/local/lib/rt-pl-3.2.0. A user wants to install gnat, but gnat will look for its configuration in /usr/local/lib/rt-pl-3.2.0/gnat where the user cannot write. The user decides to install the gnat runtime files in /users/bob/lib/ gnat. For one-time usage, the user may decide to start gnat using the command: % gnat -p gnatdir=/users/bob/lib/gnat 1100..55 TThhee RRuunnttiimmee EEnnvviirroonnmmeenntt 1100..55..11 TThhee RRuunnttiimmee EEmmuullaattoorr The sources may be used to built two versions of the emulator. By default, the _d_e_v_e_l_o_p_m_e_n_t _e_m_u_l_a_t_o_r is built. This emulator contains all features for interactive development of Prolog applications. If the system is configured using --enable-runtime, make(1) will create a _r_u_n_t_i_m_e _v_e_r_s_i_o_n of the emulator. This emulator is equivalent to the development version, except for the following features: o _N_o _i_n_p_u_t _e_d_i_t_i_n_g The GNU library -lreadline that provides EMACS compatible editing of input lines will not be linked to the system. o _N_o _t_r_a_c_e_r The tracer and all its options are removed, making the system a little faster too. o _N_o _p_r_o_f_i_l_e_r profile/3 and friends are not supported. This saves some space and provides better performance. o _N_o _i_n_t_e_r_r_u_p_t Keyboard interrupt (Control-C normally) is not rebound and will normally terminate the application. o _c_u_r_r_e_n_t___p_r_o_l_o_g___f_l_a_g_(_r_u_n_t_i_m_e_, _t_r_u_e_) _s_u_c_c_e_e_d_s This may be used to verify your application is running in the runtime environment rather than the development environment. o _c_l_a_u_s_e_/_[_2_,_3 do not work on static predicates] This prolog-flag inhibits listing your program. It is only a very limited protection however. The following fragment is an example for building the runtime environment in \env{HOME}/lib/rt-pl-3.2.0. If possible, the shared- library interface should be configured to ensure it can serve a large number of applications. % cd pl-3.2.0 % mkdir runtime % cd runtime % ../src/configure --enable-runtime --prefix=$HOME % make % make rt-install The runtime directory contains the components listed below. This directory may be tar'ed and shipped with your application. __________________________________________________ |_README.RT____|Info_on_the_runtime_environment___| |_bin/<_a_r_c_h>/pl|The_emulator_itself_______________| |_man/pl.1_____|Manual_page_for_pl________________| |_swipl________|pointer_to_the_home_directory_(.)_| | lib/ |directory for shared libraries | |_lib/<_a_r_c_h>/__|machine-specific_shared_libraries_| CChhaapptteerr 1111.. TTHHEE SSWWII--PPRROOLLOOGG LLIIBBRRAARRYY This chapter documents the SWI-Prolog library. As SWI-Prolog provides auto-loading, there is little difference between library predicates and built-in predicates. Part of the library is therefore documented in the rest of the manual. Library predicates differ from built-in predicates in the following ways. o User-definition of a built-in leads to a permission-error, while using the name of a library predicate is allowed. o If autoloading is disabled explicitely or because trapping unknown predicates is disabled (see unknown/2 and current_prolog_flag/2), library predicates must be loaded explicitely. o Using libraries reduce the footprint of applications that don't need them. _T_h_e _d_o_c_u_m_e_n_t_a_t_i_o_n _o_f _t_h_e _l_i_b_r_a_r_y _i_s _j_u_s_t _s_t_a_r_t_e_d_. _M_a_t_e_r_i_a_l _f_r_o_m _t_h_e _s_t_a_n_d_a_r_d _p_a_c_k_a_g_e_s _s_h_o_u_l_d _b_e _m_o_v_e_d _h_e_r_e_, _s_o_m_e _m_a_t_e_r_i_a_l _f_r_o_m _o_t_h_e_r _p_a_r_t_s _o_f _t_h_e _m_a_n_u_a_l _s_h_o_u_l_d _b_e _m_o_v_e_d _t_o_o _a_n_d _v_a_r_i_o_u_s _l_i_b_r_a_r_i_e_s _a_r_e _n_o_t _d_o_c_u_m_e_n_t_e_d _a_t _a_l_l_. 1111..11 lists:: LLiisstt MMaanniippuullaattiioonn This library provides commonly accepted basic predicates for list manipulation in the Prolog community. Some additional list manipulations are built-in. Their description is in section 4.28. aappppeenndd((_?_L_i_s_t_1_, _?_L_i_s_t_2_, _?_L_i_s_t_3)) Succeeds when _L_i_s_t_3 unifies with the concatenation of _L_i_s_t_1 and _L_i_s_t_2. The predicate can be used with any instantiation pattern (even three variables). mmeemmbbeerr((_?_E_l_e_m_, _?_L_i_s_t)) Succeeds when _E_l_e_m can be unified with one of the members of _L_i_s_t. The predicate can be used with any instantiation pattern. nneexxttttoo((_?_X_, _?_Y_, _?_L_i_s_t)) Succeeds when _Y immediatly follows _X in _L_i_s_t. ddeelleettee((_+_L_i_s_t_1_, _?_E_l_e_m_, _?_L_i_s_t_2)) Delete all members of _L_i_s_t_1 that simultaneously unify with _E_l_e_m and unify the result with _L_i_s_t_2. sseelleecctt((_?_E_l_e_m_, _?_L_i_s_t_, _?_R_e_s_t)) Select _E_l_e_m from _L_i_s_t leaving _R_e_s_t. It behaves as member/2, returning the remaining elements in _R_e_s_t. Note that besides selecting elements from a list, it can also be used to insert elements. nntthh00((_?_I_n_d_e_x_, _?_L_i_s_t_, _?_E_l_e_m)) Succeeds when the _I_n_d_e_x-th element of _L_i_s_t unifies with _E_l_e_m. Counting starts at 0. nntthh11((_?_I_n_d_e_x_, _?_L_i_s_t_, _?_E_l_e_m)) Succeeds when the _I_n_d_e_x-th element of _L_i_s_t unifies with _E_l_e_m. Counting starts at 1. llaasstt((_?_L_i_s_t_, _?_E_l_e_m)) Succeeds if _E_l_e_m unifies with the last element of _L_i_s_t. If _L_i_s_t is a proper list last/2 is deterministic. If _L_i_s_t has an unbound tail, backtracking will cause _L_i_s_t to grow. rreevveerrssee((_+_L_i_s_t_1_, _-_L_i_s_t_2)) Reverse the order of the elements in _L_i_s_t_1 and unify the result with the elements of _L_i_s_t_2. ppeerrmmuuttaattiioonn((_?_L_i_s_t_1_, _?_L_i_s_t_2)) Permuation is true when _L_i_s_t_1 is a permutation of _L_i_s_t_2. The implementation can solve for _L_i_s_t_2 given _L_i_s_t_1 or _L_i_s_t_1 given _L_i_s_t_2, or even enumerate _L_i_s_t_1 and _L_i_s_t_2 together. ffllaatttteenn((_+_L_i_s_t_1_, _-_L_i_s_t_2)) Transform _L_i_s_t_1, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). Unify the resulting flat list with _L_i_s_t_2. Example: ?- flatten([a, [b, [c, d], e]], X). X = [a, b, c, d, e] ssuummlliisstt((_+_L_i_s_t_, _-_S_u_m)) Unify _S_u_m to the result of adding all elements in _L_i_s_t. _L_i_s_t must be a proper list holding numbers. See number/1 and is/2. for details on arithmetic. nnuummlliisstt((_+_L_o_w_, _+_H_i_g_h_, _-_L_i_s_t)) If _L_o_w and _H_i_g_h are integers with Low=< High, unify _L_i_s_t to a list [Low, Low +1, ...High]. See also between/3. 1111..11..11 SSeett MMaanniippuullaattiioonn The set predicates listed in this section work on ordinary unsorted lists. Note that this makes many of the operations order N2. For larger sets consider the use of ordered sets as implemented by library ordsets.pl, running most these operations in order N. See section 11.2. iiss__sseett((_+_S_e_t)) Succeeds if _S_e_t is a list (see is_list/1) without duplicates. lliisstt__ttoo__sseett((_+_L_i_s_t_, _-_S_e_t)) Unifies _S_e_t with a list holding the same elements as _L_i_s_t in the same order. If _l_i_s_t contains duplicates, only the first is retained. See also sort/2. Example: ?- list_to_set([a,b,a], X) X = [a,b] iinntteerrsseeccttiioonn((_+_S_e_t_1_, _+_S_e_t_2_, _-_S_e_t_3)) Succeeds if _S_e_t_3 unifies with the intersection of _S_e_t_1 and _S_e_t_2. _S_e_t_1 and _S_e_t_2 are lists without duplicates. They need not be ordered. ssuubbttrraacctt((_+_S_e_t_, _+_D_e_l_e_t_e_, _-_R_e_s_u_l_t)) Delete all elements of set `Delete' from `Set' and unify the resulting set with `Result'. uunniioonn((_+_S_e_t_1_, _+_S_e_t_2_, _-_S_e_t_3)) Succeeds if _S_e_t_3 unifies with the union of _S_e_t_1 and _S_e_t_2. _S_e_t_1 and _S_e_t_2 are lists without duplicates. They need not be ordered. ssuubbsseett((_+_S_u_b_s_e_t_, _+_S_e_t)) Succeeds if all elements of _S_u_b_s_e_t are elements of _S_e_t as well. 1111..22 ordsets:: OOrrddeerreedd SSeett MMaanniippuullaattiioonn Ordered sets are lists with unique elements sorted to the standard order of terms (see sort/2). Exploiting ordering, many of the set operations can be expressed in order N rather than N2 when dealing with unordered sets that may contain duplicates. The ordsets is available in a number of Prolog implementations. Our predicates are designed to be compatible with common practice in the Prolog community. The implementation is incomplete and relies partly on oset, an older ordered set library distributed with SWI-Prolog. New applications are advices to use ordsets. Some of these predicates match directly to corresponding list operations. It is adviced to use the versions from this library to make clear you are operating on ordered sets. oorrdd__eemmppttyy((_?_S_e_t)) True if _S_e_t is an empty ordered set. _S_e_t unifies with the empty list. lliisstt__ttoo__oorrdd__sseett((_+_L_i_s_t_, _-_O_r_d_S_e_t)) Convert a _L_i_s_t to an ordered set. Same as sort/2. oorrdd__aadddd__eelleemmeenntt((_+_S_e_t_, _+_E_l_e_m_e_n_t_, _-_N_e_w_S_e_t)) Add an element to an ordered set. _N_e_w_S_e_t is the same as _S_e_t if _E_l_e_m_e_n_t is already part of _S_e_t. oorrdd__ddeell__eelleemmeenntt((_+_S_e_t_, _+_E_l_e_m_e_n_t_, _-_N_e_w_S_e_t)) Delete _E_l_e_m_e_n_t from _S_e_t. Succeeds without changing _S_e_t if _S_e_t does not contain _E_l_e_m_e_n_t. oorrdd__iinntteerrsseecctt((_+_S_e_t_1_, _+_S_e_t_2)) True if the intersection of _S_e_t_1 and _S_e_t_2 is non-empty. oorrdd__iinntteerrsseeccttiioonn((_+_S_e_t_1_, _+_S_e_t_2_, _-_I_n_t_e_r_s_e_c_t_i_o_n)) True if _I_n_t_e_r_s_e_c_t_i_o_n is the intersection of _S_e_t_1 and _S_e_t_2. oorrdd__ddiissjjooiinntt((_+_S_e_t_1_, _+_S_e_t_2)) True if _S_e_t_1 and _S_e_t_2 have no common element. Negation of ord_intersect/2. oorrdd__ssuubbttrraacctt((_+_S_e_t_, _+_D_e_l_e_t_e_, _-_R_e_m_a_i_n_i_n_g)) True if _R_e_m_a_i_n_i_n_g contains the elements of _S_e_t that are not in set _D_e_l_e_t_e. oorrdd__uunniioonn((_+_S_e_t_1_, _+_S_e_t_2_, _-_U_n_i_o_n)) True if _U_n_i_o_n contains all elements from _S_e_t_1 and _S_e_t_2 oorrdd__uunniioonn((_+_S_e_t_1_, _+_S_e_t_2_, _-_U_n_i_o_n_, _-_N_e_w)) Defined as if ord_union(_S_e_t_1_, _S_e_t_2_, _U_n_i_o_n), ord_subtract(_S_e_t_2_, _S_e_t_1_, _N_e_w). oorrdd__ssuubbsseett((_+_S_u_b_, _+_S_u_p_e_r)) True if all elements of _S_u_b are in _S_u_p_e_r. oorrdd__mmeemmbbeerrcchhkk((_+_E_l_e_m_e_n_t_, _+_S_e_t)) True if _E_l_e_m_e_n_t appears in _S_e_t. Does not backtrack. Same as memberchk/2. 1111..33 assoc:: AAssssoocciiaattiioonn lliissttss Authors: _R_i_c_h_a_r_d _A_. _O_'_K_e_e_f_e_, _L_._D_a_m_a_s_, _V_._S_._C_o_s_t_a _a_n_d _M_a_r_k_u_s _T_r_i_s_k_a Elements of an association list have 2 components: A (unique) _k_e_y and a _v_a_l_u_e. Keys should be ground, values need not be. An association list can be used to fetch elements via their keys and to enumerate its elements in ascending order of their keys. The assoc module uses AVL trees to implement association lists. This makes inserting, changing and fetching a single element an O(log(N)) (where N denotes the number of elements in the list) expected time (and worst-case time) operation. aassssoocc__ttoo__lliisstt((_+_A_s_s_o_c_, _-_L_i_s_t)) _L_i_s_t is a list of Key-Value pairs corresponding to the associations in _A_s_s_o_c in ascending order of keys. eemmppttyy__aassssoocc((_-_A_s_s_o_c)) _A_s_s_o_c is unified with an empty association list. ggeenn__aassssoocc((_?_K_e_y_, _+_A_s_s_o_c_, _?_V_a_l_u_e)) Enumerate matching elements of _A_s_s_o_c in ascending order of their keys via backtracking. ggeett__aassssoocc((_+_K_e_y_, _+_A_s_s_o_c_, _?_V_a_l_u_e)) _V_a_l_u_e is the value associated with _K_e_y in the association list _A_s_s_o_c. ggeett__aassssoocc((_+_K_e_y_, _+_A_s_s_o_c_, _?_O_l_d_, _?_N_e_w_A_s_s_o_c_, _?_N_e_w)) _N_e_w_A_s_s_o_c is an association list identical to _A_s_s_o_c except that the value associated with _K_e_y is _N_e_w instead of _O_l_d. lliisstt__ttoo__aassssoocc((_+_L_i_s_t_, _?_A_s_s_o_c)) _A_s_s_o_c is an association list corresponding to the Key-Value pairs in _L_i_s_t. mmaapp__aassssoocc((_:_G_o_a_l_, _+_A_s_s_o_c)) _G_o_a_l_(_V_) is true for every value V in _A_s_s_o_c. mmaapp__aassssoocc((_:_G_o_a_l_, _+_A_s_s_o_c_I_n_, _?_A_s_s_o_c_O_u_t)) _A_s_s_o_c_O_u_t is _A_s_s_o_c_I_n with _G_o_a_l applied to all corresponding pairs of values. mmaaxx__aassssoocc((_+_A_s_s_o_c_, _?_K_e_y_, _?_V_a_l_u_e)) _K_e_y and _V_a_l_u_e are key and value of the element with the largest key in _A_s_s_o_c. mmiinn__aassssoocc((_+_A_s_s_o_c_, _?_K_e_y_, _?_V_a_l_u_e)) _K_e_y and _V_a_l_u_e are key and value of the element with the smallest key in _A_s_s_o_c. oorrdd__lliisstt__ttoo__aassssoocc((_+_L_i_s_t_, _?_A_s_s_o_c)) _A_s_s_o_c is an association list correpsond to the Key-Value pairs in _L_i_s_t, which must occur in ascending order of their keys. ppuutt__aassssoocc((_+_K_e_y_, _+_A_s_s_o_c_, _+_V_a_l_u_e_, _?_N_e_w_A_s_s_o_c)) _N_e_w_A_s_s_o_c is an association list identical to _A_s_s_o_c except that _K_e_y is associated with _V_a_l_u_e. This can be used to insert and change associations. 1111..44 ugraphs:: UUnnwweeiigghhtteedd GGrraapphhss Authors: _R_i_c_h_a_r_d _O_'_K_e_e_f_e _& _V_i_t_o_r _S_a_n_t_o_s _C_o_s_t_a _I_m_p_l_e_m_e_n_t_a_t_i_o_n _a_n_d _d_o_c_u_m_e_n_t_a_t_i_o_n _a_r_e _c_o_p_i_e_d _f_r_o_m _Y_A_P _5_._0_._1_. _T_h_e ugraph _l_i_b_r_a_r_y _i_s _b_a_s_e_d _o_n _c_o_d_e _o_r_i_g_i_n_a_l_l_y _w_r_i_t_t_e_n _b_y _R_i_c_h_a_r_d _O_'_K_e_e_f_e_. _T_h_e _c_o_d_e _w_a_s _t_h_e_n _e_x_t_e_n_d_e_d _t_o _b_e _c_o_m_p_a_t_i_b_l_e _w_i_t_h _t_h_e _S_I_C_S_t_u_s _P_r_o_l_o_g _u_g_r_a_p_h_s _l_i_b_r_a_r_y_. _C_o_d_e _a_n_d _d_o_c_u_m_e_n_t_a_t_i_o_n _h_a_v_e _b_e_e_n _c_l_e_a_n_e_d _a_n_d _s_t_y_l_e _h_a_s _b_e_e_n _c_h_a_n_g_e_d _t_o _b_e _m_o_r_e _i_n _l_i_n_e _w_i_t_h _t_h_e _r_e_s_t _o_f _S_W_I_-_P_r_o_l_o_g_. _T_h_e _u_g_r_a_p_h_s _l_i_b_r_a_r_y _w_a_s _o_r_i_g_i_n_a_l_l_y _r_e_l_e_a_s_e_d _i_n _t_h_e _p_u_b_l_i_c _d_o_m_a_i_n_. _Y_A_P _i_s _c_o_n_v_e_r_e_d _b_y _t_h_e _P_e_r_l _a_r_t_i_s_t_i_c _l_i_c_e_n_s_e_, _w_h_i_c_h _d_o_e_s _n_o_t _i_m_p_l_y _f_u_r_t_h_e_r _r_e_s_t_r_i_c_t_i_o_n_s _o_n _t_h_e _S_W_I_-_P_r_o_l_o_g _L_G_P_L _l_i_c_e_n_s_e_. The routines assume directed graphs, undirected graphs may be implemented by using two edges. Originally graphs where represented in two formats. The SICStus library and this version of ugraphs.pl only uses the _S_-_r_e_p_r_e_s_e_n_t_a_t_i_o_n. The S-representation of a graph is a list of (vertex-neighbors) pairs, where the pairs are in standard order (as produced by keysort) and the neighbors of each vertex are also in standard order (as produced by sort). This form is convenient for many calculations. Each vertex appears in the S-representation, also if it has no neighbors. vveerrttiicceess__eeddggeess__ttoo__uuggrraapphh((_+_V_e_r_t_i_c_e_s_, _+_E_d_g_e_s_, _-_G_r_a_p_h)) Given a graph with a set of _V_e_r_t_i_c_e_s and a set of _E_d_g_e_s, _G_r_a_p_h must unify with the corresponding S-representation. Note that the vertices without edges will appear in _V_e_r_t_i_c_e_s but not in _E_d_g_e_s. Moreover, it is sufficient for a vertice to appear in _E_d_g_e_s. ?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5], L). L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[]] In this case all vertices are defined implicitly. The next example shows three unconnected vertices: ?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5], L). L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[], 6-[], 7-[], 8-[]] ? vveerrttiicceess((_+_G_r_a_p_h_, _-_V_e_r_t_i_c_e_s)) Unify _V_e_r_t_i_c_e_s with all vertices appearing in graph _G_r_a_p_h. Example: ?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], L). L = [1, 2, 3, 4, 5] eeddggeess((_+_G_r_a_p_h_, _-_E_d_g_e_s)) Unify _E_d_g_e_s with all edges appearing in _G_r_a_p_h. In the next example: ?- edges([1-[3,5],2-[4],3-[],4-[5],5-[]], L). L = [1-3, 1-5, 2-4, 4-5] aadddd__vveerrttiicceess((_+_G_r_a_p_h_, _+_V_e_r_t_i_c_e_s_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with a new graph obtained by adding the list of _V_e_r_t_i_c_e_s to the _G_r_a_p_h. Example: ?- add_vertices([1-[3,5],2-[]], [0,1,2,9], NG). NG = [0-[], 1-[3,5], 2-[], 9-[]] ddeell__vveerrttiicceess((_+_V_e_r_t_i_c_e_s_, _+_G_r_a_p_h_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with a new graph obtained by deleting the list of _V_e_r_t_i_c_e_s and all the edges that start from or go to a vertex in _V_e_r_t_i_c_e_s to the _G_r_a_p_h. Example: ?- del_vertices([2,1], [1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[2,6],8-[]], NL). NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]] aadddd__eeddggeess((_+_G_r_a_p_h_, _+_E_d_g_e_s_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with a new graph obtained by adding the list of edges _E_d_g_e_s to the graph _G_r_a_p_h. Example: ?- add_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]], [1-6,2-3,3-2,5-7,3-2,4-5], NL). NL = [1-[3,5,6], 2-[3,4], 3-[2], 4-[5], 5-[7], 6-[], 7-[], 8-[]] ddeell__eeddggeess((_+_G_r_a_p_h_, _+_E_d_g_e_s_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with a new graph obtained by removing the list of _E_d_g_e_s from the _G_r_a_p_h. Notice that no vertices are deleted. In the next example: ?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]], [1-6,2-3,3-2,5-7,3-2,4-5,1-3], NL). NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]] ttrraannssppoossee((_+_G_r_a_p_h_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with a new graph obtained from _G_r_a_p_h by replacing all edges of the form V1-V2 by edges of the form V2-V1. The cost is O(|V|2). Notice that an undirected graph is its own transpose. Example: ?- transpose([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]], NL). NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]] nneeiigghhbboouurrss((_+_V_e_r_t_e_x_, _+_G_r_a_p_h_, _-_V_e_r_t_i_c_e_s)) Unify _V_e_r_t_i_c_e_s with the list of neighbours of vertex _V_e_r_t_e_x in _G_r_a_p_h. Example: ?- neighbours(4,[1-[3,5],2-[4],3-[], 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL). NL = [1,2,7,5] nneeiigghhbboorrss((_+_V_e_r_t_e_x_, _+_G_r_a_p_h_, _-_V_e_r_t_i_c_e_s)) American version of neighbours/3. ccoommpplleemmeenntt((_+_G_r_a_p_h_, _-_N_e_w_G_r_a_p_h)) Unify _N_e_w_G_r_a_p_h with the graph complementary to _G_r_a_p_h. Example: ?- complement([1-[3,5],2-[4],3-[], 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL). NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8], 4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8], 7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]] ccoommppoossee((_+_L_e_f_t_G_r_a_p_h_, _+_R_i_g_h_t_G_r_a_p_h_, _-_N_e_w_G_r_a_p_h)) Compose, by connecting the _d_r_a_i_n_s of _L_e_f_t_G_r_a_p_h to the _s_o_u_r_c_e_s of _R_i_g_h_t_G_r_a_p_h. Example: ?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L). L = [1-[4], 2-[1,2,4], 3-[]] uuggrraapphh__uunniioonn((_+_G_r_a_p_h_1_, _+_G_r_a_p_h_2_, _-_N_e_w_G_r_a_p_h)) _N_e_w_G_r_a_p_h is the union of _G_r_a_p_h_1 and _G_r_a_p_h_2. Example: ?- ugraph_union([1-[2],2-[3]],[2-[4],3-[1,2,4]],L). L = [1-[2], 2-[3,4], 3-[1,2,4]] ttoopp__ssoorrtt((_+_G_r_a_p_h_, _-_S_o_r_t)) Generate the set of nodes _S_o_r_t as a topological sorting of graph _G_r_a_p_h, if one is possible. A toplogical sort is possible if the graph is connected and acyclic. In the example we show how topological sorting works for a linear graph: ?- top_sort([1-[2], 2-[3], 3-[]], L). L = [1, 2, 3] ttoopp__ssoorrtt((_+_G_r_a_p_h_, _-_S_o_r_t_0_, _-_S_o_r_t)) Generate the difference list Sort-Sort0 as a topological sorting of graph _G_r_a_p_h, if one is possible. ttrraannssiittiivvee__cclloossuurree((_+_G_r_a_p_h_, _-_C_l_o_s_u_r_e)) Generate the graph Closure as the transitive closure of graph _G_r_a_p_h. Example: ?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L). L = [1-[2,3,4,5,6], 2-[4,5,6], 4-[6]] rreeaacchhaabbllee((_+_V_e_r_t_e_x_, _+_G_r_a_p_h_, _-_V_e_r_t_i_c_e_s)) Unify _V_e_r_t_i_c_e_s with the set of all vertices in graph _G_r_a_p_h that are reachable from _V_e_r_t_e_x. Example: ?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V). V = [1, 3, 5] 1111..55 nbset:: NNoonn--bbaacckkttrraacckkaabbllee sseett The library nb_set defines _n_o_n_-_b_a_c_k_t_r_a_c_k_a_b_l_e _s_e_t_s, implemented as binary trees. The sets are represented as compound terms and manipulated using nb_setarg/3. Non-backtrackable manipulation of datastructures is not supported by a large number of Prolog implementation, but it it has several advantages over using the database. It produces less garbage, is thread-safe, reentrant and deals with exceptions without leaking data. Similar to the assoc library keys can be any Prolog term, but it is not allowed to instantiate or modify a term. One of the ways to use this library is to generate unique values on backtracking _w_i_t_h_o_u_t generating _a_l_l solutions first, for example to act as a filter between a generator producing many duplicates and an expensive test routine, as outlines below. generate_and_test(Solution) :- empty_nb_set(Set), generate(Solution), add_nb_set(Solution, Set, true), test(Solution). eemmppttyy__nnbb__sseett((_?_S_e_t)) True if _S_e_t is a non-backtrackable emoty set. aadddd__nnbb__sseett((_+_K_e_y_, _!_S_e_t)) Add _K_e_y to _S_e_t. If _K_e_y is already a member of _S_e_t, add_nb_set/3 succeeds without modifying _S_e_t. aadddd__nnbb__sseett((_+_K_e_y_, _!_S_e_t_, _?_N_e_w)) If _K_e_y is not in _S_e_t and _N_e_w is unified to true _K_e_y is added to _S_e_t. If _K_e_y is in _S_e_t _N_e_w is unified to false. It can be used for many purposes: add_nb_set(+, +, false) Test membership add_nb_set(+, +, true) Succeed only if new member add_nb_set(+, +, Var) Succeed, bindin _V_a_r ggeenn__nnbb__sseett((_+_S_e_t_, _-_K_e_y)) Generate all members of _S_e_t on backtracking in the standard order of terms. To test membership, use add_nb_set/3. ssiizzee__nnbb__sseett((_+_S_e_t_, _-_S_i_z_e)) Unify _S_i_z_e with the number of elements in _S_e_t. nnbb__sseett__ttoo__lliisstt((_+_S_e_t_, _-_L_i_s_t)) Unify _L_i_s_t with a list of all elements in set in the standard order of terms (i.e. and _o_r_d_e_r_e_d _l_i_s_t). 1111..66 gensym:: GGeenneerraattee uunniiqquuee iiddeennttiiffiieerrss Gensym (GGeennerate SSyymmbols) is an old library for generating unique symbols (atoms). Such symbols are generated from a base atom which gets a sequence number appended. Of course there is no guarantee that `catch22' is not an already defined atom and therefore one must be aware these atoms are only unique in an isolated context. The SWI-Prolog gensym library is thread-safe. The sequence numbers are global over all threads and therefore generated atoms are unique over all threads. ggeennssyymm((_+_B_a_s_e_, _-_U_n_i_q_u_e)) Generate a unique atom from base _B_a_s_e and unify it with _U_n_i_q_u_e. _B_a_s_e should be an atom. The first call will return <_b_a_s_e>1, the next <_b_a_s_e>2, etc. Note that this is no warrant that the atom is unique in the system. rreesseett__ggeennssyymm((_+_B_a_s_e)) Restart generation of identifiers from _B_a_s_e at <_B_a_s_e>1. Used to make sure a program produces the same results on subsequent runs. Use with care. rreesseett__ggeennssyymm Reset gensym for all registered keys. This predicate is available for compatibility only. New code is strongly advice to avoid the use of reset_gensym or at least to reset only the keys used by your program to avoid unexpected site-effects on other components. 1111..77 check:: EElleemmeennttaarryy ccoommpplleetteenneessss cchheecckkss This library defines the predicate check/0 and a few friends that allow for a quick-and-dirty cross-referencing. cchheecckk Performs the three checking passes implemented by list_undefined/0, list_autoload/0 and list_redefined/0. Please check the definition of these predicates for details. The typical usage of this predicate is right after loading your program to get a quick overview on the completeness and possible conflicts in your program. lliisstt__uunnddeeffiinneedd Scans the database for predicates that have no definition. A predicate is considered defined if it has clauses, is declared using dynamic/1 or multifile/1. As a program is compiled calls are translated to predicates. If the called predicate is not yet defined it is created as a predicate without definition. The same happens with runtime generated calls. This predicate lists all such undefined predicates that are referenced and not defined in the library. See also list_autoload/0. Below is an example from a real program and an illustration how to edit the referencing predicate using edit/1. ?- list_undefined. Warning: The predicates below are not defined. If these are defined Warning: at runtime using assert/1, use :- dynamic Name/Arity. Warning: Warning: rdf_edit:rdfe_retract/4, which is referenced by Warning: 1-st clause of rdf_edit:undo/4 Warning: rdf_edit:rdfe_retract/3, which is referenced by Warning: 1-st clause of rdf_edit:delete_object/1 Warning: 1-st clause of rdf_edit:delete_subject/1 Warning: 1-st clause of rdf_edit:delete_predicate/1 ?- edit(rdf_edit:undo/4). lliisstt__aauuttoollooaadd Lists all undefined (see list_undefined/0) predicates that have a definition in the library along with the file from which they will be autoloaded when accessed. See also autoload/0. lliisstt__rreeddeeffiinneedd Lists predicates that are defined in the global module user as well as in a normal module. I.e. predicates for which the local definition overrules the global default definition. 1111..88 debug:: SSoommee rreeuussaabbllee ccooddee ttoo hheellpp ddeebbuuggggiinngg aapppplliiccaattiioonnss This library provides an structured alternative for putting print- statements into your source-code to trace what is going on. Debug messages are organised in _t_o_p_i_c_s that can be activated and de-activated without changing the source. In addition, if the application is compiled with the -O flag these predicates are removed using goal_expansion/2. Although this library can be used through the normal demand-loading mechanism it is adviced to load it explicitely before code using it to profit from goal-expansion, which removes these calls if compiled with optimisation on and records the topics from debug/3 and debugging/1 for list_debug_topics/0. ddeebbuugg((_+_T_o_p_i_c_, _+_F_o_r_m_a_t_, _+_A_r_g_s)) If _T_o_p_i_c is a selected debugging topic (see debug/1) a message is printed using print_message/2with level informational. _F_o_r_m_a_t and _A_r_g_s are interpreted by format/2. Here is a typical example: ..., debug(init, 'Initialised ~w', [Module]), ..., _T_o_p_i_c can be any Prolog term. Compound terms can be used to make categories of topics that can be activated using debug/1. ddeebbuuggggiinngg((_+_T_o_p_i_c)) Succeeds if _T_o_p_i_c is a selected debugging topic. It is intended to execute arbitrary code depending on the users debug topic selection. The construct (debugging(Topic) -> Code ; true) is removed if the code is compiled in optimise mode. ddeebbuugg((_+_T_o_p_i_c)) Select all registered topics that unify with _T_o_p_i_c for debugging. This call is normally used from the toplevel to activate a topic for debugging. If no matching _T_o_p_i_c is registered a warning is printed and the topic is registered for debugging as matching debug statements may be loaded later. Topics are de-activated using nodebug/1. nnooddeebbuugg((_+_T_o_p_i_c)) Deactivates topics for debugging. See debug/1 for the arguments. lliisstt__ddeebbuugg__ttooppiiccss List the current status of registered topics. See also debugging/0. aasssseerrttiioonn((_:_G_o_a_l)) This predicate is to be compared to the C-library assert() function. By inserting this goal you explicitely state you expect _G_o_a_l to succeed at this place. As assertion/1 calls are removed when compiling in optimized mode _G_o_a_l should not have side-effects. Typical examples are type-tests and validating invariants defined by your application. If _G_o_a_l fails the system prints a message, followed by a stack-trace and starts the debugger. In older versions of this library this predicate was called assume/1. Code using assume/1 is automatically converted while printing a warning on the first occurrence. 1111..99 readutil:: RReeaaddiinngg lliinneess,, ssttrreeaammss aanndd ffiilleess This library contains primitives to read lines, files, multiple terms, etc. The package clib provides a shared object (DLL) named readutil. If the library can locate this shared object it will use the foreign implementation for reading character codes. Otherwise it will use a Prolog implementation. Distributed applications should make sure to deliver the readutil shared object if performance of these predicates is critical. rreeaadd__lliinnee__ttoo__ccooddeess((_+_S_t_r_e_a_m_, _-_C_o_d_e_s)) Read the next line of input from _S_t_r_e_a_m and unify the result with _C_o_d_e_s _a_f_t_e_r the line has been read. A line is ended by a newline character or end-of-file. Unlike read_line_to_codes/3, this predicate removes trailing newline character. On end-of-file the atom end_of_file is returned. See also at_end_of_stream/[0,1]. rreeaadd__lliinnee__ttoo__ccooddeess((_+_S_t_r_e_a_m_, _-_C_o_d_e_s_, _?_T_a_i_l)) Diference-list version to read an input line to a list of character codes. Reading stops at the newline or end-of-file character, but unlike read_line_to_codes/2, the newline is retained in the output. This predicate is especially useful for readine a block of lines upto some delimiter. The following example reads an HTTP header ended by a blank line: read_header_data(Stream, Header) :- read_line_to_codes(Stream, Header, Tail), read_header_data(Header, Stream, Tail). read_header_data("\r\n", _, _) :- !. read_header_data("\n", _, _) :- !. read_header_data("", _, _) :- !. read_header_data(_, Stream, Tail) :- read_line_to_codes(Stream, Tail, NewTail), read_header_data(Tail, Stream, NewTail). rreeaadd__ssttrreeaamm__ttoo__ccooddeess((_+_S_t_r_e_a_m_, _-_C_o_d_e_s)) Read all input until end-of-file and unify the result to _C_o_d_e_s. rreeaadd__ssttrreeaamm__ttoo__ccooddeess((_+_S_t_r_e_a_m_, _-_C_o_d_e_s_, _?_T_a_i_l)) Difference-list version of read_stream_to_codes/2. rreeaadd__ffiillee__ttoo__ccooddeess((_+_S_p_e_c_, _-_C_o_d_e_s_, _+_O_p_t_i_o_n_s)) Read a file to a list of character codes. _S_p_e_c is a file- specification for absolute_file_name/3. _C_o_d_e_s is the resulting code-list. _O_p_t_i_o_n_s is a list of options for absolute_file_name/3 and open/4. In addition, the option tail(_T_a_i_l) is defined, forming a difference-list. rreeaadd__ffiillee__ttoo__tteerrmmss((_+_S_p_e_c_, _-_T_e_r_m_s_, _+_O_p_t_i_o_n_s)) Read a file to a list of prolog terms (see read/1). _S_p_e_c is a file-specification for absolute_file_name/3. _T_e_r_m_s is the resulting list of Prolog terms. _O_p_t_i_o_n_s is a list of options for absolute_file_name/3 and open/4. In addition, the option tail(_T_a_i_l) is defined, forming a difference-list. 1111..1100 netscape:: AAccttiivvaattiinngg yyoouurr WWeebb--bbrroowwsseerr This library deals with the very system dependent task of opening a web page in a browser. See also url and the HTTP package. wwwwww__ooppeenn__uurrll((_+_U_R_L)) Open _U_R_L in an external web-browser. The reason to place this in the library is to centralise the maintenance on this highly platform and browser specific task. It distinguishes between the following cases: o _M_S_-_W_i_n_d_o_w_s If it detects MS-Windows it uses win_shell/2 to open the _U_R_L. The behaviour and browser started depends on the Window and Windows-shell configuration, but in general it should be the behaviour expected by the user. o _O_t_h_e_r _p_l_a_t_f_o_r_m_s On other platforms it tests the environment variable (see getenv/2) named BROWSER or uses netscape if this variable is not set. If the browser is either mozilla or netscape, www_open_url/1 first tries to open a new window on a running using the -remote option of netscape. If this fails or the browser is not mozilla or netscape the system simply passes the URL as first argument to the program. 1111..1111 registry:: MMaanniippuullaattiinngg tthhee WWiinnddoowwss rreeggiissttrryy The registry is only available on the MS-Windows version of SWI-Prolog. It loads the foreign extension plregtry.dll, providing the predicates described below. This library only makes the most common operations on the registry available through the Prolog user. The underlying DLL provides a more complete coverage of the Windows registry API. Please consult the sources in pl/src/win32/foreign/plregtry.c for further details. In all these predicates, _P_a_t_h refers to a `/' separated path into the registry. This is _n_o_t an atom containing `/'-characters as used for filenames, but a term using the functor //2. Windows defines the following roots for the registry: classes_root, current_user, local_machine and users rreeggiissttrryy__ggeett__kkeeyy((_+_P_a_t_h_, _-_V_a_l_u_e)) Get the principal (default) value associated to this key. Fails silently of the key does not exist. rreeggiissttrryy__ggeett__kkeeyy((_+_P_a_t_h_, _+_N_a_m_e_, _-_V_a_l_u_e)) Get a named value associated to this key. rreeggiissttrryy__sseett__kkeeyy((_+_P_a_t_h_, _+_V_a_l_u_e)) Set the principal (default) value of this key. Creates (a path to) the key if this does not already exist. rreeggiissttrryy__sseett__kkeeyy((_+_P_a_t_h_, _+_N_a_m_e_, _+_V_a_l_u_e)) Associated a named value to this key. Creates (a path to) the key if this does not already exist. rreeggiissttrryy__ddeelleettee__kkeeyy((_+_P_a_t_h)) Delete the indicated key. sshheellll__rreeggiisstteerr__ffiillee__ttyyppee((_+_E_x_t_, _+_T_y_p_e_, _+_N_a_m_e_, _+_O_p_e_n_A_c_t_i_o_n)) Register a file-type. _E_x_t is the extension to associate. _T_y_p_e is the type name, often something link prolog.type. _N_a_m_e is the name visible in the Windows file-type browser. Finally, _O_p_e_n_A_c_t_i_o_n defines the action to execute when a file with this extension is opened in the Windows explorer. sshheellll__rreeggiisstteerr__ddddee((_+_T_y_p_e_, _+_A_c_t_i_o_n_, _+_S_e_r_v_i_c_e_, _+_T_o_p_i_c_, _+_C_o_m_m_a_n_d_, _+_I_f_N_o_t_R_u_n_n_i_n_g)) Associate DDE actions to a type. _T_y_p_e is the same type as used for the 2nd argument of shell_register_file_type/4, _A_c_t_i_o_n is the a action to perform, _S_e_r_v_i_c_e and _T_o_p_i_c specify the DDE topic to address and _C_o_m_m_a_n_d is the command to execute on this topic. Finally, _I_f_N_o_t_R_u_n_n_i_n_g defines the command to execute if the required DDE server is not present. sshheellll__rreeggiisstteerr__pprroolloogg((_+_E_x_t)) Default registration of SWI-Prolog, which is invoked as part of the initialisation process on Windows systems. As the source also explains the above predicates, it is given as an example: shell_register_prolog(Ext) :- current_prolog_flag(argv, [Me|_]), concat_atom(['"', Me, '" "%1"'], OpenCommand), shell_register_file_type(Ext, 'prolog.type', 'Prolog Source', OpenCommand), shell_register_dde('prolog.type', consult, prolog, control, 'consult(''%1'')', Me), shell_register_dde('prolog.type', edit, prolog, control, 'edit(''%1'')', Me). 1111..1122 url:: AAnnaallyyssiinngg aanndd ccoonnssttrruuccttiinngg UURRLL This library deals with the analysis and construction of a URL, UUniversal RResource LLocator. URL is the basis for communicating locations of resources (data) on the web. A URL consists of a protocol identifier (e.g. HTTP, FTP), and a protocol-specific syntax further defining the location. URLs are standardized in RFC-1738. The implementation in this library covers only a small portion of the defined protocols. Though the initial implementation followed RFC-1738 strictly, the current is more relaxed to deal with frequent violations of the standard encountered in practical use. This library contains code by Jan Wielemaker who wrote the initial version and Lukas Faulstich who added various extensions. ppaarrssee__uurrll((_?_U_R_L_, _?_P_a_r_t_s)) Construct or analyse a _U_R_L. _U_R_L is an atom holding a URL or a variable. _P_a_r_t_s is a list of components. Each component is of the format Name(_V_a_l_u_e). Defined components are: pprroottooccooll((_P_r_o_t_o_c_o_l)) The used protocol. This is, after the optional url:, an identifier separated from the remainder of the URL using :. parse_url/2 assumes the http protocol if no protocol is specified and the URL can be parsed as a valid HTTP url. In addition to the RFC-1738 specified protocols, the file: protocol is supported as well. hhoosstt((_H_o_s_t)) Host-name or IP-address on which the resource is located. Supported by all network-based protocols. ppoorrtt((_P_o_r_t)) Integer port-number to access on the _H_o_s_t. This only appears if the port is explicitly specified in the URL. Implicit default ports (e.g. 80 for HTTP) do _n_o_t appear in the part-list. ppaatthh((_P_a_t_h)) (File-) path addressed by the URL. This is supported for the ftp, http and file protocols. If no path appears, the library generates the path /. sseeaarrcchh((_L_i_s_t_O_f_N_a_m_e_V_a_l_u_e)) Search-specification of HTTP URL. This is the part after the ?, normally used to transfer data from HTML forms that use the `GET' protocol. In the URL it consists of a www-form-encoded list of _N_a_m_e=_V_a_l_u_e pairs. This is mapped to a list of Prolog _N_a_m_e=_V_a_l_u_e terms with decoded names and values. ffrraaggmmeenntt((_F_r_a_g_m_e_n_t)) Fragment specification of HTTP URL. This is the part after the # character. The example below illustrates the all this for an HTTP UTL. ?- parse_url('http://swi.psy.uva.nl/message.cgi?msg=Hello+World%21#x', P). P = [ protocol(http), host('swi.psy.uva.nl'), fragment(x), search([ msg = 'Hello World!' ]), path('/message.cgi') ]. By instantiating the parts-list this predicate can be used to create a URL. ppaarrssee__uurrll((_?_U_R_L_, _+_B_a_s_e_U_R_L_, _?_P_a_r_t_s)) Same as parse_url/2, but dealing a url that is relative to the given _B_a_s_e_U_R_L. This is used to analyse or construct a URI found in the document behind _B_a_s_e_U_R_L. gglloobbaall__uurrll((_+_U_R_L_, _+_B_a_s_e_U_R_L_, _-_A_b_s_o_l_u_t_e_U_r_l)) Transform a (possibly) relative URL into a global one. hhttttpp__llooccaattiioonn((_?_P_a_r_t_s_, _?_L_o_c_a_t_i_o_n)) Similar to parse_url/2, but only deals with the location part of an HTTP URL. That is, the path, search and fragment specifiers. In the HTTP protocol, the first line of a message is _A_c_t_i_o_n _L_o_c_a_t_i_o_n [HTTP/_H_t_t_p_V_e_r_s_i_o_n] _L_o_c_a_t_i_o_n is either an atom or a code-list. wwwwww__ffoorrmm__eennccooddee((_?_V_a_l_u_e_, _?_W_w_w_F_o_r_m_E_n_c_o_d_e_d)) Translate between a string-literal and the x-www-form-encoded representation used in path and search specifications of the HTTP protocol. Encoding implies mapping space to +, preserving alpha-numercial characters, map newlines to %0D%0A and anything else to %XX. When decoding, newlines appear as a single newline (10) character. 1111..1133 clp/bounds:: IInntteeggeerr BBoouunnddss CCoonnssttrraaiinntt SSoollvveerr Author: _T_o_m _S_c_h_r_i_j_v_e_r_s, K.U.Leuven The bounds solver is a rather simple integer constraint solver, implemented with attributed variables. Its syntax is a subset of the SICStus clp(FD) syntax. The bounds library is _n_o_t an _a_u_t_o_l_o_a_d library and therefore it must be loaded explicitly before using it via: :- use_module(library(bounds)). 1111..1133..11 CCoonnssttrraaiinnttss The following constraints are supported: _-_V_a_r iinn _+_R_a_n_g_e Varibale _V_a_r is restricted to be in range _R_a_n_g_e. A range is denoted by L..U where both _L and _U are integers. _-_V_a_r_s iinn _+_R_a_n_g_e A list of variables _V_a_r_s are restriced to be in range _R_a_n_g_e. ttuupplleess__iinn((_+_T_u_p_l_e_s_, _+_E_x_t_e_n_s_i_o_n)) Where _T_u_p_l_e_s is a list of tuples (lists) of variables and integers, each of length N, and _E_x_t_e_n_s_i_o_n is a list of tuples of integers, each of length N. Each tuple of _T_u_p_l_e_s is constrained to be in the relation defined by _E_x_t_e_n_s_i_o_n. See section 11.13.4 for an example. _?_E_x_p_r #> _?_E_x_p_r The left-hand expression is constrained to be greater than the right-hand expressions. _?_E_x_p_r #< _?_E_x_p_r The left-hand expression is constrained to be smaller than the right-hand expressions. _?_E_x_p_r #>= _?_E_x_p_r The left-hand expression is constrained to be greater than or equal to the right-hand expressions. _?_E_x_p_r #=< _?_E_x_p_r The left-hand expression is constrained to be smaller than or equal to the right-hand expressions. _?_E_x_p_r #= _?_E_x_p_r The left-hand expression is constrained to be equal to the right-hand expressions. _?_E_x_p_r #\= _?_E_x_p_r The left-hand expression is constrained to be not equal to the right-hand expressions. ssuumm((_+_V_a_r_s_,_+_O_p_,_?_V_a_l_u_e)) Here _V_a_r_s is a list of variables and integers, _O_p is one of the binary constraint relation symbols above and _V_a_l_u_e is an integer or variable. It represents the constraint (SUM_V_a_r_s) _O_p _V_a_l_u_e. lleexx__cchhaaiinn((_+_V_a_r_s_L_i_s_t_s)) The constraint enforces lexicographic ordering on the lists in the argument. The argument _V_a_r_s_L_i_s_t_s is a list of lists of variables and integers. The current implementation was contributed by Markus Triska. aallll__ddiiffffeerreenntt((_+_V_a_r_s)) Constrains all variabls in the list _V_a_r_s to be pairwise not equal. iinnddoommaaiinn((_+_V_a_r)) Unify variable _V_a_r with a value in its domain. Backtracks over all possible values from lowest to greatest. Contributed by Markus Triska. llaabbeell((_+_V_a_r_s)) Equivalent to labeling([], Vars). llaabbeelliinngg((_+_O_p_t_i_o_n_s_, _+_V_a_r_s)) All variables in the list _V_a_r_s are assigned values from their respective domains such that no constraint on them is violated. _O_p_t_i_o_n_s is a list of options. One set of options lets you choose the variable selection strategy: lleeffttmmoosstt Label the variables in the order they occur in _V_a_r_s from left to right. This is the default. ffff Label the variable whose domain contains the smallest number of elements among the remaining variables next. This is called "first-fail". The intention here is twofold: First, to detect infeasibility early by always considering the variable most likely to cause failure; second, to give priority to variables that are close to running out of domain elements. mmiinn Label the variable whose lower bound is the lowest among the remaining variables next. mmaaxx Label the variable whose upper bound is the highest among the remaining variables next. Another set of options lets you search for extrema: mmiinn((_E_x_p_r)) mmaaxx((_E_x_p_r)) Label the variables such that _E_x_p_r assumes the small- est/highest possible value. sseerriiaalliizzeedd((_+_S_t_a_r_t_s_,_+_D_u_r_a_t_i_o_n_s)) _S_t_a_r_t_s = [S1; :::;Sn] is a list of variables or integers, and _D_u_r_a_t_i_o_n_s = [D1;:::; Dn] is a list of non-negative integers. _S_t_a_r_t_s are constrained to denote the starting times of non-overlapping tasks, i.e., Si+ Di= _+_Q _P implies _Q, where _P and _Q are reifyable constraints. _+_Q #<= _+_P _P implies _Q, where _P and _Q are reifyable constraints. _+_P #<=> _+_Q _P and _Q are equivalent, where _P and _Q are reifyable constraints. In addition, instead of being a reifyable constraint, either _P or _Q can be a boolean variable that is the truth value of the corresponding constraint. The following constraints are reifyable: #=/2, #\=/2, #/2, #=/2. For example, to count the number of occurrences of a particular value in a list of constraint variables: o _U_s_i_n_g _c_o_n_s_t_r_a_i_n_t _i_m_p_l_i_c_a_t_i_o_n occurrences(List,Value,Count) :- occurrences(List,Value,0,Count). occurrences([],_,Count,Count). occurrences([X|Xs],Value,Acc,Count) :- X #= Value #=> NAcc #= Acc + 1, X #\= Value #=> NAcc #= Acc, occurrences(Xs,Value,NAcc,Count). o _U_s_i_n_g _r_e_i_f_i_e_d _c_o_n_s_t_r_a_i_n_t_s occurrences(List,Value,Count) :- occurrences(List,Value,0,Count). occurrences([],_,Count,Count). occurrences([X|Xs],Value,Acc,Count) :- X #= Value #=> B, NAcc #= Acc + B, occurrences(Xs,Value,NAcc,Count). 1111..1133..33 EExxaammppllee 11:: SSeenndd++MMoorree==MMoonneeyy The following is an implementation of the classic alphametics puzzle SEND + MORE = MONEY: :- use_module(library(bounds)). send([[S,E,N,D], [M,O,R,E], [M,O,N,E,Y]]) :- Digits = [S,E,N,D,M,O,R,Y], Carries = [C1,C2,C3,C4], Digits in 0..9, Carries in 0..1, M #= C4, O + 10 * C4 #= M + S + C3, N + 10 * C3 #= O + E + C2, E + 10 * C2 #= R + N + C1, Y + 10 * C1 #= E + D, M #>= 1, S #>= 1, all_different(Digits), label(Digits). 1111..1133..44 EExxaammppllee 22:: UUssiinngg ttuupplleess__iinn ffoorr aa ttrraaiinn sscchheedduullee This example demonstrates tuples_in/2. A train schedule is represented as a list Ts of quadruples, denoting departure and arrival places and times for each train. The _p_a_t_h_/_3 predicate given below constrains Ps to a feasible journey from A to D via 3 trains that are part of the given schedule. :- use_module(library(bounds)). schedule(Ts) :- Ts = [[1,2,0,1],[2,3,4,5],[2,3,0,1],[3,4,5,6],[3,4,2,3],[3,4,8,9]]. path(A, D, Ps) :- schedule(Ts), Ps = [[A,B,_T0,T1],[B,C,T2,T3],[C,D,T4,_T5]], tuples_in(Ps, Ts), T2 #> T1, T4 #> T3. An example query: ?- path(1, 4, Ps), flatten(Ps, Vars), label(Vars). Ps = [[1, 2, 0, 1], [2, 3, 4, 5], [3, 4, 8, 9]] 1111..1133..55 SSIICCSSttuuss ccllpp((FFDD)) ccoommppaattiibbiilliittyy Apart from the limited syntax, the bounds solver differs in the following ways from the SICStus clp(FD) solver: o inf _a_n_d sup The smallest lowerbound and greatest upperbound in bounds are max_integer and min_integer + 1. 1111..1144 clpqr:: CCoonnssttrraaiinntt LLooggiicc PPrrooggrraammmmiinngg oovveerr RRaattiioonnaallss aanndd RReeaallss Author: _L_e_s_l_i_e _D_e _K_o_n_i_n_c_k, K.U. Leuven This CLP(Q,R) system is a port of the CLP(Q,R) system of Sicstus Prolog by Christian Holzbaur: Holzbaur C.: OFAI clp(q,r) Manual, Edition 1.3.3, Austrian Research Institute for Artificial Intelligence, Vienna, TR-95-09, 1995. This manual is roughly based on the manual of the above mentioned CLP(Q,R) implementation. The CLP(Q,R) system consists of two components: the CLP(Q) library for handling constraints over the rational numbers and the CLP(R) library for handling constraints over the real numbers (using floating point numbers as representation). Both libraries offer the same predicates (with exception of bb_inf/4 in CLP(Q) and bb_inf/5 in CLP(R)). It is allowed to use both libraries in one program, but using both CLP(Q) and CLP(R) constraints on the same variable will result in an exception. Please note that the clpqr library is _n_o_t an _a_u_t_o_l_o_a_d library and therefore this library must be loaded explicitely before using it: :- use_module(library(clpq)). or :- use_module(library(clpr)). 1111..1144..11 SSoollvveerr pprreeddiiccaatteess The following predicates are provided to work with constraints: {}((_+_C_o_n_s_t_r_a_i_n_t_s)) Adds the constraints given by _C_o_n_s_t_r_a_i_n_t_s to the constraint store. eennttaaiilleedd((_+_C_o_n_s_t_r_a_i_n_t)) Succeeds if _C_o_n_s_t_r_a_i_n_t is necessarily true within the current constraint store. This means that adding the negation of the constraint to the store results in failure. iinnff((_+_E_x_p_r_e_s_s_i_o_n_, _-_I_n_f)) Computes the infimum of _E_x_p_r_e_s_s_i_o_n within the current state of the constraint store and returns that infimum in _I_n_f. This predicate does not change the constraint store. ssuupp((_+_E_x_p_r_e_s_s_i_o_n_, _-_S_u_p)) Computes the supremum of _E_x_p_r_e_s_s_i_o_n within the current state of the constraint store and returns that supremum in _S_u_p. This predicate does not change the constraint store. mmiinniimmiizzee((_+_E_x_p_r_e_s_s_i_o_n)) Minimizes _E_x_p_r_e_s_s_i_o_n within the current constraint store. This is the same as computing the infimum and equation the expression to that infimum. mmaaxxiimmiizzee((_+_E_x_p_r_e_s_s_i_o_n)) Maximizes _E_x_p_r_e_s_s_i_o_n within the current constraint store. This is the same as computing the supremum and equating the expression to that supremum. bbbb__iinnff((_+_I_n_t_s_, _+_E_x_p_r_e_s_s_i_o_n_, _-_I_n_f_, _-_V_e_r_t_e_x_, _+_E_p_s)) This predicate is offered in CLP(R) only. It computes the infimum of _E_x_p_r_e_s_s_i_o_n within the current constraint store, with the additional constraint that in that infimum, all variables in _I_n_t_s have integral values. _V_e_r_t_e_x will contain the values of _I_n_t_s in the infimum. _E_p_s denotes how much a value may differ from an integer to be considered an integer. E.g. when _E_p_s = 0.001, then X = 4.999 will be considered as an integer (5 in this case). _E_p_s should be between 0 and 0.5. bbbb__iinnff((_+_I_n_t_s_, _+_E_x_p_r_e_s_s_i_o_n_, _-_I_n_f_, _-_V_e_r_t_e_x)) This predicate is offered in CLP(Q) only. It behaves the same as bb_inf/5 but does not use an error margin. bbbb__iinnff((_+_i_n_t_s_, _+_E_x_p_r_e_s_s_i_o_n_, _-_I_n_f)) The same as bb_inf/5 or bb_inf/4 but without returning the values of the integers. In CLP(R), an error margin of 0.001 is used. dduummpp((_+_T_a_r_g_e_t_, _+_N_e_w_v_a_r_s_, _-_C_o_d_e_d_A_n_s_w_e_r)) Returns the constraints on _T_a_r_g_e_t in the list _C_o_d_e_d_A_n_s_w_e_r where all variables of _T_a_r_g_e_t have veen replaced by _N_e_w_V_a_r_s. This operation does not change the constraint store. E.g. in dump([X,Y,Z],[x,y,z],Cons) Cons will contain the constraints on X, Y and Z where these variables have been replaced by atoms x, y and z. 1111..1144..22 SSyynnttaaxx ooff tthhee pprreeddiiccaattee aarrgguummeennttss The arguments of the predicates defined in the subsection above are defined in table 11.1. Failing to meet the syntax rules will result in an exception. __________________________________________________________________________________________ | <_C_o_n_s_t_r_a_i_n_t_s>::= <_C_o_n_s_t_r_a_i_n_t> |single constraint | | | <_C_o_n_s_t_r_a_i_n_t> , <_C_o_n_s_t_r_a_i_n_t_s> |conjunction | | | <_C_o_n_s_t_r_a_i_n_t> ; <_C_o_n_s_t_r_a_i_n_t_s> |disjunction | | <_C_o_n_s_t_r_a_i_n_t> ::= <_E_x_p_r_e_s_s_i_o_n> < <_E_x_p_r_e_s_s_i_o_n> |less than | | | <_E_x_p_r_e_s_s_i_o_n> > <_E_x_p_r_e_s_s_i_o_n> |greater than | | | <_E_x_p_r_e_s_s_i_o_n> =< <_E_x_p_r_e_s_s_i_o_n> |less or equal | | | <=(<_E_x_p_r_e_s_s_i_o_n>, <_E_x_p_r_e_s_s_i_o_n>) |less or equal | | | <_E_x_p_r_e_s_s_i_o_n> >= <_E_x_p_r_e_s_s_i_o_n> |greater or equal | | | <_E_x_p_r_e_s_s_i_o_n> =\= <_E_x_p_r_e_s_s_i_o_n> |not equal | | | <_E_x_p_r_e_s_s_i_o_n> =:= <_E_x_p_r_e_s_s_i_o_n> |equal | | | <_E_x_p_r_e_s_s_i_o_n> = <_E_x_p_r_e_s_s_i_o_n> |equal | | <_E_x_p_r_e_s_s_i_o_n> ::= <_V_a_r_i_a_b_l_e> |Prolog variable | | | <_N_u_m_b_e_r> |Prolog number (float, integer) | | | +<_E_x_p_r_e_s_s_i_o_n> |unary plus | | | -<_E_x_p_r_e_s_s_i_o_n> |unary minus | | | <_E_x_p_r_e_s_s_i_o_n> + <_E_x_p_r_e_s_s_i_o_n> |addition | | | <_E_x_p_r_e_s_s_i_o_n> - <_E_x_p_r_e_s_s_i_o_n> |substraction | | | <_E_x_p_r_e_s_s_i_o_n> * <_E_x_p_r_e_s_s_i_o_n> |multiplication | | | <_E_x_p_r_e_s_s_i_o_n> / <_E_x_p_r_e_s_s_i_o_n> |division | | | abs(<_E_x_p_r_e_s_s_i_o_n>) |absolute value | | | sin(<_E_x_p_r_e_s_s_i_o_n>) |sine | | | cos(<_E_x_p_r_e_s_s_i_o_n>) |cosine | | | tan(<_E_x_p_r_e_s_s_i_o_n>) |tangent | | | exp(<_E_x_p_r_e_s_s_i_o_n>) |exponent | | | pow(<_E_x_p_r_e_s_s_i_o_n>) |exponent | | | <_E_x_p_r_e_s_s_i_o_n> ^ <_E_x_p_r_e_s_s_i_o_n> |exponent | | | min(<_E_x_p_r_e_s_s_i_o_n>, <_E_x_p_r_e_s_s_i_o_n>) |minimum | |_________________|_max(<_E_x_p_r_e_s_s_i_o_n>,_<_E_x_p_r_e_s_s_i_o_n>)_|maximum_____________________________|_ Table 11.1: CLP(Q,R) constraint BNF 1111..1144..33 UUssee ooff uunniiffiiccaattiioonn Instead of using the {}/1 predicate, you can also use the standard unification mechanism to store constraints. The following code samples are equivalent: o _U_n_i_f_i_c_a_t_i_o_n _w_i_t_h _a _v_a_r_i_a_b_l_e {X =:= Y} {X = Y} X = Y o _U_n_i_f_i_c_a_t_i_o_n _w_i_t_h _a _n_u_m_b_e_r {X =:= 5.0} {X = 5.0} X = 5.0 1111..1144..44 NNoonn--lliinneeaarr ccoonnssttrraaiinnttss The CLP(Q,R) system deals only passively with non-linear constraints. They remain in a passive state until certain conditions are satisfied. These conditions, which are called the isolation axioms, are given in table 11.2. ______________________________________________________________ | A =B *C |B or C is ground |A = 5 * C or A = B * | | | |4 | | |A and (B or C) are|20 = 5 * C or 20 = B | |______________|ground________________|*_4___________________|_ | A =B=C |C is ground |A = B / 3 | |______________|A_and_B_are_ground____|4_=_12_/_C____________|_ | X =min(Y; Z) |Y and Z are ground |X = min(4,3) | | X =max(Y; Z) |Y and Z are ground |X = max(4,3) | |_X_=abs(Y_)___|Y_is_ground___________|X_=_abs(-7)___________|_ | X =pow(Y; Z) |X and Y are ground |8 = 2 ^ Z | | X =exp(Y; Z) |X and Z are ground |8 = Y ^ 3 | |_X_=Y__^_Z___|Y_and_Z_are_ground_____|X_=_2_^_3_____________|_ | X =sin(Y ) X|is ground |1 = sin(Y) | | X =cos(Y ) Y|is ground |X = sin(1.5707) | |_X_=tan(Y_)___|______________________|______________________|_ Table 11.2: CLP(Q,R) isolating axioms 1111..1155 clp/clp_distinct:: WWeeaakk aarrcc ccoonnssiisstteenntt ``aallll__ddiissttiinncctt'' ccoonnssttrraaiinntt Author: _M_a_r_k_u_s _T_r_i_s_k_a The clp/clp_distinct module provides the following constraints: aallll__ddiissttiinncctt((_+_V_a_r_s)) The variables in _V_a_r_s are constrained to be pairwise distinct. All variables must already be assigned domains (via vars_in/2 or vars_in/3) when this constraint is posted. vvaarrss__iinn((_+_V_a_r_s_, _+_D_o_m_a_i_n)) Where _V_a_r_s is a list of variables and _D_o_m_a_i_n is a list of non-negative integers. Each variable of _V_a_r_s is constrained to be in _D_o_m_a_i_n. vvaarrss__iinn((_+_V_a_r_s_, _+_F_r_o_m_, _+_T_o)) Where _V_a_r_s is a list of variables, and 0<= From<= To. Each variable in _V_a_r_s is constrained to be in the discrete interval [From,To]. 1111..1155..11 EExxaammppllee 11 The all_distinct/1 constraint can detect various inconsistencies: ?- vars_in([X,Y,Z], [1,2]), all_distinct([X,Y,Z]). No 1111..1155..22 EExxaammppllee 22 In this example, 3 is assigned to Z without labeling any variables: ?- vars_in([X,Y], [1,2]), vars_in([Z], [1,2,3]), all_distinct([X,Y,Z]). X = _G180{1-2} Y = _G183{1-2} Z = 3 ; 1111..1155..33 EExxaammppllee 33 The clp_distinct module can be used in conjunction with clp/bounds. All relevant variables must still be assigned domains via one of the _v_a_r_s___i_n predicates before all_distinct/1 can be posted: :- use_module(library(bounds)). :- use_module(library(clp_distinct)). ?- [X,Y] in 1..2, vars_in([X,Y], [1,2]), all_distinct([X,Y]), label([X,Y]). X = 1 Y = 2 ; X = 2 Y = 1 ; 1111..1166 simplex:: SSoollvvee lliinneeaarr pprrooggrraammmmiinngg pprroobblleemmss Author: _M_a_r_k_u_s _T_r_i_s_k_a A linear programming problem consists of a set of (linear) constraints, a number of variables and a linear objective function. The goal is to assign values to the variables so as to maximize (or minimize) the value of the objective function while satisfying all constraints. Many optimization problems can be modeled in this way. Consider having a knapsack with fixed capacity C, and a number of items with sizes s(i) and values v(i). The goal is to put as many items as possible in the knapsack (not exceeding its capacity) while maximizing the sum of their values. As another example, suppose you are given a set of coins with certain values, and you are to find the minimum number of coins such that their values sum up to a fixed amount. Instances of these problems are solved below. The simplex module provides the following predicates: aassssiiggnnmmeenntt((_+_C_o_s_t_, _-_A_s_s_i_g_n_m_e_n_t)) _C_o_s_t is a list of lists representing the quadratic cost matrix, where element (i,j) denotes the cost of assigning entity i to entity j. An assignment with minimal cost is computed and unified with _A_s_s_i_g_n_m_e_n_t as a list of lists, representing an adjacency matrix. ccoonnssttrraaiinntt((_+_C_o_n_s_t_r_a_i_n_t_, _+_S_0_, _-_S)) Adds a linear or integrality constraint to the linear program corresponding to state _S_0. A linear constraint is of the form "Left Op C", where "Left" is a list of Coefficient*Variable terms (variables in the context of linear programs can be atoms or compound terms) and C is a non-negative numeric constant. The list represents the sum of its elements. _O_p can be =, =< or >=. The coefficient "1" can be omitted. An integrality constraint is of the form integral(Variable) and constrains Variable to an integral value. ccoonnssttrraaiinntt((_+_N_a_m_e_, _+_C_o_n_s_t_r_a_i_n_t_, _+_S_0_, _-_S)) Like constraint/3, and attaches the name _N_a_m_e (an atom or compound term) to the new constraint. ccoonnssttrraaiinntt__aadddd((_+_N_a_m_e_, _+_L_e_f_t_, _+_S_0_, _-_S)) _L_e_f_t is a list of Coefficient*Variable terms. The terms are added to the left-hand side of the constraint named _N_a_m_e. _S is unified with the resulting state. ggeenn__ssttaattee((_-_S_t_a_t_e)) Generates an initial state corresponding to an empty linear program. mmaaxxiimmiizzee((_+_O_b_j_e_c_t_i_v_e_, _+_S_0_, _-_S)) Maximizes the objective function, stated as a list of "Coefficient*Variable" terms that represents the sum of its elements, with respect to the linear program corresponding to state _S_0. _S is unified with an internal representation of the solved instance. mmiinniimmiizzee((_+_O_b_j_e_c_t_i_v_e_, _+_S_0_, _-_S)) Analogous to maximize/3. oobbjjeeccttiivvee((_+_S_t_a_t_e_, _-_O_b_j_e_c_t_i_v_e)) Unifies _O_b_j_e_c_t_i_v_e with the result of the objective function at the obtained extremum. _S_t_a_t_e must correspond to a solved instance. sshhaaddooww__pprriiccee((_+_S_t_a_t_e_, _+_N_a_m_e_, _-_V_a_l_u_e)) Unifies _V_a_l_u_e with the shadow price corresponding to the linear constraint whose name is _N_a_m_e. _S_t_a_t_e must correspond to a solved instance. ttrraannssppoorrttaattiioonn((_+_S_u_p_p_l_i_e_s_, _+_D_e_m_a_n_d_s_, _+_C_o_s_t_s_, _-_T_r_a_n_s_p_o_r_t)) _S_u_p_p_l_i_e_s and _D_e_m_a_n_d_s are both lists of positive numbers. Their respective sums must be equal. _C_o_s_t_s is a list of lists representing the cost matrix, where an entry (i,j) denotes the cost of transporting one unit from i to j. A transportation plan having minimum cost is computed and unified with _T_r_a_n_s_p_o_r_t in the form of a list of lists that represents the transportation matrix, where element (i,j) denotes how many units to ship from i to j. vvaarriiaabbllee__vvaalluuee((_+_S_t_a_t_e_, _+_V_a_r_i_a_b_l_e_, _-_V_a_l_u_e)) _V_a_l_u_e is unified with the value obtained for _V_a_r_i_a_b_l_e. _S_t_a_t_e must correspond to a solved instance. All numeric quantities are converted to rationals via rationalize/1, and rational arithmetic is used throughout solving linear programs. In the current implementation, all variables are implicitly constrained to be non-negative. This may change in future versions, and non-negativity constraints should therefore be stated explicitly. 1111..1166..11 EExxaammppllee 11 This is the "radiation therapy" example, taken from "Introduction to Operations Research" by Hillier and Lieberman. DCG notation is used to implicitly thread the state through posting the constraints: :- use_module(library(simplex)). post_constraints --> constraint([0.3*x1, 0.1*x2] =< 2.7), constraint([0.5*x1, 0.5*x2] = 6), constraint([0.6*x1, 0.4*x2] >= 6), constraint([x1] >= 0), constraint([x2] >= 0). radiation(S) :- gen_state(S0), post_constraints(S0, S1), minimize([0.4*x1, 0.5*x2], S1, S). An example query: ?- radiation(S), variable_value(S, x1, Val1), variable_value(S, x2, Val2). Val1 = 15 rdiv 2 Val2 = 9 rdiv 2 ; 1111..1166..22 EExxaammppllee 22 Here is an instance of the knapsack problem described above, where C = 8, and we have two types of items: One item with value 7 and size 6, and 2 items each having size 4 and value 4. We introduce two variables, x(1) and x(2) that denote how many items to take of each type. knapsack_constrain(S) :- gen_state(S0), constraint([6*x(1), 4*x(2)] =< 8, S0, S1), constraint([x(1)] =< 1, S1, S2), constraint([x(2)] =< 2, S2, S). knapsack(S) :- knapsack_constrain(S0), maximize([7*x(1), 4*x(2)], S0, S). An example query yields: ?- knapsack(S), variable_value(S, x(1), X1), variable_value(S, x(2), X2). X1 = 1 X2 = 1 rdiv 2 ; That is, we are to take the one item of the first type, and half of one of the items of the other type to maximize the total value of items in the knapsack. If items can not be split, integrality constraints have to be imposed: knapsack_integral(S) :- knapsack_constrain(S0), constraint(integral(x(1)), S0, S1), constraint(integral(x(2)), S1, S2), maximize([7*x(1), 4*x(2)], S2, S). Now the result is different: ?- knapsack_integral(S), variable_value(S, x(1), X1), variable_value(S, x(2), X2). X1 = 0 X2 = 2 That is, we are to take only the two items of the second type. Notice in particular that always choosing the remaining item with best performance (ratio of value to size) that still fits in the knapsack does not necessarily yield an optimal solution in the presence of integrality constraints. 1111..1166..33 EExxaammppllee 33 We are given 3 coins each worth 1, 20 coins each worth 5, and 10 coins each worth 20 units of money. The task is to find a minimal number of these coins that amount to 111 units of money. We introduce variables c(1), c(5) and c(20) denoting how many coins to take of the respective type: coins --> constraint([c(1), 5*c(5), 20*c(20)] = 111), constraint([c(1)] =< 3), constraint([c(5)] =< 20), constraint([c(20)] =< 10), constraint([c(1)] >= 0), constraint([c(5)] >= 0), constraint([c(20)] >= 0), constraint(integral(c(1))), constraint(integral(c(5))), constraint(integral(c(20))), minimize([c(1), c(5), c(20)]). coins(S) :- gen_state(S0), coins(S0, S). An example query: ?- coins(S), variable_value(S, c(1), C1), variable_value(S, c(5), C5), variable_value(S, c(20), C20). C1 = 1 C5 = 2 C20 = 5 1111..1177 prologxref:: CCrroossss--rreeffeerreennccee ddaattaa ccoolllleeccttiioonn lliibbrraarryy This library collects information on defined and used objects in Prolog sourcefiles. Typically these are predicates, but we expect the library to deal with other types of objects in the future. The library is a building block for tools doing dependency tracking in applications. Dependency tracking is useful to reveal the structure of an unknown program or detect missing components at compile-time, but also for program transformation or minimising a program saved-state by only saving the reachable objects. This section gives a partial description of the library API, providing some insight in how you can use it for analysing your program. The library should be further modularized, moving its knowledge about -for example- XPCE into a different file and allowing for adding knowledge about other libraries such as Logtalk. PPlleeaassee ddoo nnoott ccoonnssiiddeerr tthhiiss iinntteerrffaaccee rroocckk--ssoolliidd.. The library is exploited by two graphical tools in the SWI-Prolog environment. The XPCE frontend started by gxref/0 and described in section 3.7 and PceEmacs (section 3.4) which exploits this library for its syntax colouring. For all predicates described below, _S_o_u_r_c_e is the source that is processed. This is normally a filename in any notation acceptable to the file loading predicates (see load_files/2). Using the hooks defined in section 11.17.1 it can be anything else that can be translated into a Prolog stream holding Prolog source text. _C_a_l_l_a_b_l_e is a callable term (see callable/1). Callables do not carry a module qualifier unless the referred predicate is not in the module defined _S_o_u_r_c_e. xxrreeff__ssoouurrccee((_+_S_o_u_r_c_e)) Gather information on _S_o_u_r_c_e. If _S_o_u_r_c_e has already been processed and is still up-to-date according to the file timestamp, no action is taken. This predicate must be called on a file before information can be gathered. xxrreeff__ccuurrrreenntt__ssoouurrccee((_?_S_o_u_r_c_e)) _S_o_u_r_c_e has been processed. xxrreeff__cclleeaann((_+_S_o_u_r_c_e)) Remove the information gathered for _S_o_u_r_c_e xxrreeff__ddeeffiinneedd((_?_S_o_u_r_c_e_, _?_C_a_l_l_a_b_l_e_, _-_H_o_w)) _C_a_l_l_a_b_l_e is defined in _S_o_u_r_c_e. _H_o_w is one of dynamic(_L_i_n_e) Declared dynamic at _L_i_n_e thread_local(_L_i_n_e) Declared thread local at _L_i_n_e multifile(_L_i_n_e) Declared multifile at _L_i_n_e local(_L_i_n_e) First clause at _L_i_n_e foreign(_L_i_n_e) Foreign library loaded at _L_i_n_e constraint(_L_i_n_e) CHR Constraint at _L_i_n_e imported(_F_i_l_e) Imported from _F_i_l_e xxrreeff__ccaalllleedd((_?_S_o_u_r_c_e_, _?_C_a_l_l_a_b_l_e_, _?_B_y)) _C_a_l_l_a_b_l_e is called in _S_o_u_r_c_e by _B_y. xxrreeff__eexxppoorrtteedd((_?_S_o_u_r_c_e_, _?_C_a_l_l_a_b_l_e)) _C_a_l_l_a_b_l_e is public (exported from the module). xxrreeff__mmoodduullee((_?_S_o_u_r_c_e_, _?_M_o_d_u_l_e)) _S_o_u_r_c_e is a module-file defining the given module. xxrreeff__bbuuiilltt__iinn((_?_C_a_l_l_a_b_l_e)) True if _C_a_l_l_a_b_l_e is a built-in predicate. Currently this is assumed for all predicates defined in the system module and having the property built_in. Built-in predicates are not registered as `called'. 1111..1177..11 EExxtteennddiinngg tthhee lliibbrraarryy The library provides hooks for extending its rules it uses for finding predicates called by some programming construct. pprroolloogg::ccaalllleedd__bbyy((_+_G_o_a_l_, _-_C_a_l_l_e_d)) Where _G_o_a_l is a non-var subgoal appearing in called object (typically a clause-body). If it succeeds it must return a list of goals called by _G_o_a_l. As a special construct, if a term Callable +N is returned, N variable arguments are added to _C_a_l_l_a_b_l_e before further processing. For simple meta-calls a single fact suffices. Complex rules as used in the html_write library provided by the HTTP package examine the arguments and create a list of called objects. The current system cannot deal with the same name/arity in different modules that behave differently with respect to called arguments. 1111..1188 broadcast:: BBrrooaaddccaasstt aanndd rreecceeiivvee eevveenntt nnoottiiffiiccaattiioonnss The broadcast library was invented to realise GUI applications consisting of stand-alone components that use the Prolog database for storing the application data. Figure ???? illustrates the flow of information using this design The broadcasting service provides two services. Using the `shout' service, an unknown number of agents may listen to the message and act. The broadcaster is not (directly) aware of the implications. Using the `request' service, listening agents are asked for an answer one-by-one and the broadcaster is allowed to reject answers using normal Prolog failure. Shouting is often used to inform about changes made to a common database. Other messages can be ``save yourself'' or ``show this''. Requesting is used to get information while the broadcaster is not aware who might be able to answer the question. For example ``who is showing X?''. bbrrooaaddccaasstt((_+_T_e_r_m)) Broadcast _T_e_r_m. There are no limitations to _T_e_r_m, though being a global service, it is good practice to use a descriptive and unique principal functor. All associated goals are started and regardless of their success or failure, broadcast/1 always succeeds. Exceptions are passed. bbrrooaaddccaasstt__rreeqquueesstt((_+_T_e_r_m)) Unlike broadcast/1, this predicate stops if an associated goal succeeds. Backtracking causes it to try other listeners. A broadcast request is used to fetch information without knowing the identity of the agent providing it. C.f. ``Is there someone who knows the age of John?'' could be asked using ..., broadcast_request(age_of('John', Age)), If there is an agent (_l_i_s_t_e_n_e_r) that registered an `age-of' service and knows about the age of `John' this question will be answered. lliisstteenn((_+_T_e_m_p_l_a_t_e_, _:_G_o_a_l)) Register a _l_i_s_t_e_n channel. Whenever a term unifying _T_e_m_p_l_a_t_e is broadcasted, call _G_o_a_l. The following example traps all broadcasted messages as a variable unifies to any message. It is commonly used to debug usage of the library. ?- listen(Term, (writeln(Term),fail)). ?- broadcast(hello(world)). hello(world) Yes lliisstteenn((_+_L_i_s_t_e_n_e_r_, _+_T_e_m_p_l_a_t_e_, _:_G_o_a_l)) Declare _L_i_s_t_e_n_e_r as the owner of the channel. Unlike a channel opened using listen/2, channels that have an owner can terminate the channel. This is commonly used if an object is listening to broadcast messages. In the example below we define a `name-item' displaying the name of an identifier represented by the predicate name_of/2. :- pce_begin_class(name_item, text_item). variable(id, any, get, "Id visualised"). initialise(NI, Id:any) :-> name_of(Id, Name), send_super(NI, initialise, name, Name, message(NI, set_name, @arg1)), send(NI, slot, id, Id), listen(NI, name_of(Id, Name), send(NI, selection, Name)). unlink(NI) :-> unlisten(NI), send_super(NI, unlink). set_name(NI, Name:name) :-> get(NI, id, Id), retractall(name_of(Id, _)), assert(name_of(Id, Name)), broadcast(name_of(Id, Name)). :- pce_end_class. uunnlliisstteenn((_+_L_i_s_t_e_n_e_r)) Deregister all entries created with listen/3 whose _L_i_s_t_e_n_e_r unify. uunnlliisstteenn((_+_L_i_s_t_e_n_e_r_, _+_T_e_m_p_l_a_t_e)) Deregister all entries created with listen/3 whose _L_i_s_t_e_n_e_r and _T_e_m_p_l_a_t_e unify. uunnlliisstteenn((_+_L_i_s_t_e_n_e_r_, _+_T_e_m_p_l_a_t_e_, _:_G_o_a_l)) Deregister all entries created with listen/3 whose _L_i_s_t_e_n_e_r, _T_e_m_p_l_a_t_e and _G_o_a_l unify. lliisstteenniinngg((_?_L_i_s_t_e_n_e_r_, _?_T_e_m_p_l_a_t_e_, _?_G_o_a_l)) Examine the current listeners. This predicate is useful for debugging purposes. 1111..1199 record:: AAcccceessss nnaammeedd ffiieellddss iinn aa tteerrmm The library record provides named access to fields in a record represented as a compound term such as point(X, Y). The Prolog world knows various approaches to solve this problem, unfortunately with no consensus. The approach taken by this library is proposed by Richard O'Keefe on the SWI-Prolog mailinglist. The approach automates a technique commonly described in Prolog text-books, where access- and modification predicates are defined for the record type. Such predicates are subject to normal import/export as well as analysis by cross-referencers. Given the simple nature of the access predicates, an optimizing compiler can easily inline them for optimal preformance. A record is defined using the directive record/1. We introduce the library with a short example: :- record point(x:integer=0, y:integer=0). ..., default_point(Point), point_x(Point, X), set_x_of_point(10, Point, Point1), make_point([y(20)], YPoint), The principal functor and arity of the term used defines the name and arity of the compound used as records. Each argument is described using a term of the format below. <_n_a_m_e>[:<_t_y_p_e>][=<_d_e_f_a_u_l_t>] In this definition, <_n_a_m_e> is an atom defining the name of the argument. <_t_y_p_e> is an optional type specification as defined by must_be/2 from library error and <_d_e_f_a_u_l_t> is the default initial value. The <_t_y_p_e> defaults to any. If no default value is specified the default is an unbound variable. A record declaration creates a set of predicates through _t_e_r_m_- _e_x_p_a_n_s_i_o_n. We describe these predicates below. In this description, <_c_o_n_s_t_r_u_c_t_o_r> refers to the name of the record (`point' in the example above) and <_n_a_m_e> to the name of an argument (field). o _d_e_f_a_u_l_t__<_c_o_n_s_t_r_u_c_t_o_r>_(_-_R_e_c_o_r_d_) Create a new record where all fields have their default values. This is the same as make_<_c_o_n_s_t_r_u_c_t_o_r>([], Record). o _m_a_k_e__<_c_o_n_s_t_r_u_c_t_o_r>_(_+_F_i_e_l_d_s_, _-_R_e_c_o_r_d_) Create a new record where specified fields have the specified values and remaining fields have their default value. Each field is specified as a term <_n_a_m_e>(<_v_a_l_u_e>). See example in the introduction. o _m_a_k_e__<_c_o_n_s_t_r_u_c_t_o_r>_(_+_F_i_e_l_d_s_, _-_R_e_c_o_r_d_, _-_R_e_s_t_F_i_e_l_d_s_) Same as make_<_c_o_n_s_t_r_u_c_t_o_r>/2, but named fields that do not appear in _R_e_c_o_r_d are returned in _R_e_s_t_F_i_e_l_d_s. This predicate is motivated by option-list processing. See library option. o <_c_o_n_s_t_r_u_c_t_o_r>_<_n_a_m_e>_(_R_e_c_o_r_d_, _V_a_l_u_e_) Unify _V_a_l_u_e with argument in _R_e_c_o_r_d named <_n_a_m_e>. o _s_e_t__<_n_a_m_e>__o_f__<_c_o_n_s_t_r_u_c_t_o_r>_(_+_V_a_l_u_e_, _+_O_l_d_R_e_c_o_r_d_, _-_N_e_w_R_e_c_o_r_d_) Replace the value for <_n_a_m_e> in _O_l_d_R_e_c_o_r_d by _V_a_l_u_e and unify the result with _N_e_w_R_e_c_o_r_d. o _s_e_t__<_n_a_m_e>__o_f__<_c_o_n_s_t_r_u_c_t_o_r>_(_+_V_a_l_u_e_, _!_R_e_c_o_r_d_) Destructively replace the argument <_n_a_m_e> in _R_e_c_o_r_d by _V_a_l_u_e based on setarg/3. Use with care. o _n_b___s_e_t__<_n_a_m_e>__o_f__<_c_o_n_s_t_r_u_c_t_o_r>_(_+_V_a_l_u_e_, _!_R_e_c_o_r_d_) As above, but using non-backtrackable assignment based on nb_setarg/3. Use with _e_x_t_r_e_m_e care. o _s_e_t__<_c_o_n_s_t_r_u_c_t_o_r>__f_i_e_l_d_s_(_+_F_i_e_l_d_s_, _+_R_e_c_o_r_d_0_, _-_R_e_c_o_r_d_) Set multiple fields using the same syntax as make_<_c_o_n_s_t_r_u_c_t_o_r>/2, but starting with _R_e_c_o_r_d_0 rather than the default record. o _s_e_t__<_c_o_n_s_t_r_u_c_t_o_r>__f_i_e_l_d_s_(_+_F_i_e_l_d_s_, _+_R_e_c_o_r_d_0_, _-_R_e_c_o_r_d_, _-_R_e_s_t_F_i_e_l_d_s_) Similar to set_<_c_o_n_s_t_r_u_c_t_o_r>_fields/4, but fields not defined by <_c_o_n_s_t_r_u_c_t_o_r> are returned in _R_e_s_t_F_i_e_l_d_s. o _s_e_t__<_c_o_n_s_t_r_u_c_t_o_r>__f_i_e_l_d_(_+_F_i_e_l_d_, _+_R_e_c_o_r_d_0_, _-_R_e_c_o_r_d_) Set a single field specified as a term <_n_a_m_e>(<_v_a_l_u_e>). rreeccoorrdd((_+_S_p_e_c)) The construct :- record Spec, ... is used to define access to named fields in a compound. It is subject to term-expansion (see expand_term/2) and cannot be called as a predicate. See section 11.19 for details. CChhaapptteerr 1122.. HHAACCKKEERRSS CCOORRNNEERR This appendix describes a number of predicates which enable the Prolog user to inspect the Prolog environment and manipulate (or even redefine) the debugger. They can be used as entry points for experiments with debugging tools for Prolog. The predicates described here should be handled with some care as it is easy to corrupt the consistency of the Prolog system by misusing them. 1122..11 EExxaammiinniinngg tthhee EEnnvviirroonnmmeenntt SSttaacckk pprroolloogg__ccuurrrreenntt__ffrraammee((_-_F_r_a_m_e)) Unify _F_r_a_m_e with an integer providing a reference to the parent of the current local stack frame. A pointer to the current local frame cannot be provided as the predicate succeeds deterministically and therefore its frame is destroyed immediately after succeeding. pprroolloogg__ffrraammee__aattttrriibbuuttee((_+_F_r_a_m_e_, _+_K_e_y_, _-_V_a_l_u_e)) Obtain information about the local stack frame _F_r_a_m_e. _F_r_a_m_e is a frame reference as obtained through prolog_current_frame/1, prolog_trace_interception/4 or this predicate. The key values are described below. aalltteerrnnaattiivvee _V_a_l_u_e is unified with an integer reference to the local stack frame in which execution is resumed if the goal associated with _F_r_a_m_e fails. Fails if the frame has no alternative frame. hhaass__aalltteerrnnaattiivveess _V_a_l_u_e is unified with true if _F_r_a_m_e still is a candidate for backtracking. false otherwise. ggooaall _V_a_l_u_e is unified with the goal associated with _F_r_a_m_e. If the definition module of the active predicate is not user the goal is represented as <_m_o_d_u_l_e>:<_g_o_a_l>. Do not instantiate variables in this goal unless you kknnooww what you are doing! Note that the returned term may contain references to the frame and should be discarded before the frame terminates. ppaarreenntt__ggooaall If _V_a_l_u_e is instantiated to a callable term, find a frame executing the predicate described by _V_a_l_u_e and unify the arguments of _V_a_l_u_e to the goal arguments associated with the frame. This is intended to check the current execution context. The user must ensure the checked parent goal is not removed from the stack due to last-call optimisation and be aware of the slow operation on deeply nested calls. ccllaauussee _V_a_l_u_e is unified with a reference to the currently running clause. Fails if the current goal is associated with a foreign (C) defined predicate. See also nth_clause/3 and clause_property/2. lleevveell _V_a_l_u_e is unified with the recursion level of _F_r_a_m_e. The top level frame is at level `0'. ppaarreenntt _V_a_l_u_e is unified with an integer reference to the parent local stack frame of _F_r_a_m_e. Fails if _F_r_a_m_e is the top frame. ccoonntteexxtt__mmoodduullee _V_a_l_u_e is unified with the name of the context module of the environment. ttoopp _V_a_l_u_e is unified with true if _F_r_a_m_e is the top Prolog goal from a recursive call back from the foreign language. false otherwise. hhiiddddeenn _V_a_l_u_e is unified with true if the frame is hidden from the user, either because a parent has the hide-childs attribute (all system predicates), or the system has no trace-me attribute. ppcc _V_a_l_u_e is unified with the program-pointer saved on behalf of the parent-goal if the parent-goal is not owned by a foreign predicate. aarrgguummeenntt((_N)) _V_a_l_u_e is unified with the _N-th slot of the frame. Argument 1 is the first argument of the goal. Arguments above the arity refer to local variables. Fails silently if _N is out of range. pprroolloogg__cchhooiiccee__aattttrriibbuuttee((_+_C_h_o_i_c_e_P_o_i_n_t_, _+_K_e_y_, _-_V_a_l_u_e)) Extract attributes of a choice-point. _C_h_o_i_c_e_P_o_i_n_t is a reference to a choice-point as passed to prolog_trace_interception/4on the 3-th argument. _K_e_y specifies the requested information: ppaarreenntt Requests a reference to the first older choice-point. ffrraammee Requests a reference to the frame to which the choice-point refers. ttyyppee Requests the type. Defined values are clause (the goal has alternative clauses), foreign (non-deterministic foreign predicate), jump (clause internal choice-point), top (first dummy choice-point), catch (catch/3 to allow for undo), debug (help the debugger), or none (has been deleted). This predicate is used for the graphical debugger to show the choice-point stack. ddeetteerrmmiinniissttiicc((_-_B_o_o_l_e_a_n)) Unifies its argument with true if the clause in which is appears has not created any choice-points since it was started. There are few realistic situations for using this predicate. It is used by the prolog/0 toplevel to check whether Prolog should prompt the user for alternatives. 1122..22 IInntteerrcceeppttiinngg tthhee TTrraacceerr pprroolloogg__ttrraaccee__iinntteerrcceeppttiioonn((_+_P_o_r_t_, _+_F_r_a_m_e_, _+_C_h_o_i_c_e_, _-_A_c_t_i_o_n)) Dynamic predicate, normally not defined. This predicate is called from the SWI-Prolog debugger just before it would show a port. If this predicate succeeds the debugger assumes the trace action has been taken care of and continues execution as described by _A_c_t_i_o_n. Otherwise the normal Prolog debugger actions are performed. _P_o_r_t denotes the reason to activate the tracer (`port' in the 4/5-port, but with some additions: ccaallll Normal entry through the call-port of the 4-port debugger. rreeddoo Normal entry through the call-port of the 4-port debugger. The redo port signals resuming a predicate to generate alternative solutions. uunniiffyy The unify-port represents the _n_e_c_k instruction, signalling the end of the head-matching process. This port is normally invisible. See leash/1 and visible/1. eexxiitt The exit-port signals the goal is proved. It is possible for the goal to have alternative. See prolog_frame_attribute/3 to examine the goal-stack. ffaaiill The fail-port signals final failure of the goal. eexxcceeppttiioonn((_E_x_c_e_p_t)) An exception is raised and still pending. This port is activated on each parent frame of the frame generating the exception until the exception is caught or the user restarts normal computation using retry. _E_x_c_e_p_t is the pending exception-term. bbrreeaakk((_P_C)) A break instruction is executed. _P_C is program counter. This port is used by the graphical debugger. ccuutt__ccaallll((_P_C)) A cut is encountered at _P_C. This port is used by the graphical debugger. to visualise the effect of the cut. ccuutt__eexxiitt((_P_C)) A cut has been executed. See cut_call(_P_C) for more information. _F_r_a_m_e is a reference to the current local stack frame, which can be examined using prolog_frame_attribute/3. _C_h_o_i_c_e is a reference to the last choice-point and can be examined using prolog_choice_attribute/3. _A_c_t_i_o_n should be unified with one of the atoms continue (just continue execution), retry (retry the current goal) or fail (force the current goal to fail). Leaving it a variable is identical to continue. Together with the predicates described in section 4.38 and the other predicates of this chapter this predicate enables the Prolog user to define a complete new debugger in Prolog. Besides this it enables the Prolog programmer monitor the execution of a program. The example below records all goals trapped by the tracer in the database. prolog_trace_interception(Port, Frame, _PC, continue) :- prolog_frame_attribute(Frame, goal, Goal), prolog_frame_attribute(Frame, level, Level), recordz(trace, trace(Port, Level, Goal)). To trace the execution of `go' this way the following query should be given: ?- trace, go, notrace. pprroolloogg__sskkiipp__lleevveell((_-_O_l_d_, _+_N_e_w)) Unify _O_l_d with the old value of `skip level' and than set this level according to _N_e_w. New is an integer, or the special atom very_deep (meaning don't skip). The `skip level' is a global variable of the Prolog system that disables the debugger on all recursion levels deeper than the level of the variable. Used to implement the trace options `skip' (sets skip level to the level of the frame) and `up' (sets skip level to the level of the parent frame (i.e., the level of this frame minus 1). 1122..33 AAddddiinngg ccoonntteexxtt ttoo eerrrroorrss:: pprroolloogg__eexxcceeppttiioonn__hhooookk The hook prolog_exception_hook/4 has been introduced in SWI-Prolog 5.6.5 to provide dedicated exception handling facilities for application frameworks. For example non-interactive server applications that wish to provide extensive context for exceptions for offline debugging. pprroolloogg__eexxcceeppttiioonn__hhooookk((_+_E_x_c_e_p_t_i_o_n_I_n_, _-_E_x_c_e_p_t_i_o_n_O_u_t_, _+_F_r_a_m_e_, _+_C_a_t_c_h_e_r_F_r_a_m_e)) This hook predicate, if defined in the module user, is between raising an exception and handling it. It is intended to allow a program adding additional context to an exception to simplify diagnosing the problem. _E_x_c_e_p_t_i_o_n_I_n is the exception term as raised by throw/1 or one of the bullt-in predicates. The output argument _E_x_c_e_p_t_i_o_n_O_u_t describes the exception that is actually raised. _F_r_a_m_e is the innermost frame. See prolog_frame_attribute/3 and the library prolog_stack for getting information from this. _C_a_t_c_h_e_r_F_r_a_m_e is a reference to the frame calling the matching catch/3 or none of the exception is not caught. The hook is run in `nodebug' mode. If it succeeds _E_x_c_e_p_t_i_o_n_O_u_t is considered the current exception. If it fails, _E_x_c_e_p_t_i_o_n_I_n is used for further processing. The hook is _n_e_v_e_r called recursively. The hook is _n_o_t allowed to modify _E_x_c_e_p_t_i_o_n_O_u_t in such as way that it no longer unifies with the catching frame. Typically, prolog_exception_hook/4 is used to fill the second argument of error(_F_o_r_m_a_l_, _C_o_n_t_e_x_t) exceptions. _F_o_r_m_a_l is defined by the ISO standard, while SWI-Prolog defines _C_o_n_t_e_x_t as a term context(_L_o_c_a_t_i_o_n_, _M_e_s_s_a_g_e). _L_o_c_a_t_i_o_n is bound to a term <_n_a_m_e>/<_a_r_i_t_y> by the kernel. This hook can be used to add more information on the calling context, such as a full stack trace. Applications that use exceptions as part of normal processing must do a quick test of the environment before starting expensive gathering information on the state of the program. The hook can call trace/0 to enter trace mode immediately. For example imagine an application performing an unwanted division by zero while all other errors are expected and handled. We can force the debugger using the hook definition below. Run the program in debug mode (see debug/0) to preserve as much as possible of the error context. user:prolog_exception_hook(error(evaluation_error(zero_divisor), _), _, _, _) :- trace, fail. 1122..44 HHooookkss uussiinngg tthhee eexxcceeppttiioonn pprreeddiiccaattee This section describes the predicate exception/3, which can be defined by the user in the module user as a multifile predicate. Unlike the name suggests, this is actually a _h_o_o_k predicate that has no relation to Prolog exceptions as defined by the ISO predicates catch/3 and throw/1. The predicate exception/3 is called by the kernel on a couple of events, allowing the user to `fix' errors just in time events. The mechanism allows for _l_a_z_y creation of objects such as predicates. eexxcceeppttiioonn((_+_E_x_c_e_p_t_i_o_n_, _+_C_o_n_t_e_x_t_, _-_A_c_t_i_o_n)) Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just in time'. The values for _E_x_c_e_p_t_i_o_n are described below. See also catch/3 and throw/1. If this hook predicate succeeds it must instantiate the _A_c_t_i_o_n argument to the atom fail to make the operation fail silently, retry to tell Prolog to retry the operation or error to make the system generate an exception. The action retry only makes sense if this hook modified the environment such that the operation can now succeed without error. uunnddeeffiinneedd__pprreeddiiccaattee _C_o_n_t_e_x_t is instantiated to a term _N_a_m_e/_A_r_i_t_y. _N_a_m_e refers to the name and _A_r_i_t_y to the arity of the undefined predicate. If the definition module of the predicate is not _u_s_e_r, _C_o_n_t_e_x_t will be of the form <_M_o_d_u_l_e>:<_N_a_m_e>/<_A_r_i_t_y>. If the predicate fails Prolog will generate an existence_error exception. uunnddeeffiinneedd__gglloobbaall__vvaarriiaabbllee _C_o_n_t_e_x_t is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. 1122..55 HHooookkss ffoorr iinntteeggrraattiinngg lliibbrraarriieess Some libraries realise an entirely new programming paradigm on top of Prolog. An example is XPCE which adds an object-system to Prolog as well as an extensive set of graphical primitives. SWI-Prolog provides several hooks to improve the integration of such libraries. See also section 4.4 for editing hooks and section 4.9.3 for hooking into the message system. pprroolloogg__lliisstt__ggooaall((_:_G_o_a_l)) Hook, normally not defined. This hook is called by the 'L' command of the tracer in the module user to list the currently called predicate. This hook may be defined to list only relevant clauses of the indicated _G_o_a_l and/or show the actual source-code in an editor. See also portray/1 and multifile/1. pprroolloogg::ddeebbuugg__ccoonnttrrooll__hhooookk((_:_A_c_t_i_o_n)) Hook for the debugger-control predicates that allows the creator of more high-level programming languages to use the common front-end predicates to control de debugger. For example, XPCE uses these hooks to allow for spying methods rather then predicates. _A_c_t_i_o_n is one of: ssppyy((_S_p_e_c)) Hook in spy/1. If the hook succeeds spy/1 takes no further action. nnoossppyy((_S_p_e_c)) Hook in nospy/1. If the hook succeeds spy/1 takes no further action. If spy/1 is hooked, it is advised to place a complementary hook for nospy/1. nnoossppyyaallll Hook in nospyall/0. Should remove all spy-points. This hook is called in a failure-driven loop. ddeebbuuggggiinngg Hook in debugging/0. It can be used in two ways. It can report the status of the additional debug-points controlled by the above hooks and fail to let the system report the others or it succeed, overruling the entire behaviour of debugging/0. pprroolloogg::hheellpp__hhooookk((_+_A_c_t_i_o_n)) Hook into help/0 and help/1. If the hook succeeds, the built-in actions are not executed. For example, ?- help(picture). is caught by the XPCE help-hook to give help on the class _p_i_c_t_u_r_e. Defined actions are: hheellpp User entered plain help/0 to give default help. The default performs help(help/1), giving help on help. hheellpp((_W_h_a_t)) Hook in help/1 on the topic _W_h_a_t. aapprrooppooss((_W_h_a_t)) Hook in apropos/1 on the topic _W_h_a_t. 1122..66 HHooookkss ffoorr llooaaddiinngg ffiilleess All loading of source-files is achieved by load_files/2. The hook prolog_load_file/2 can be used to load Prolog code from non-files or even load entirely different information, such as foreign files. pprroolloogg__llooaadd__ffiillee((_+_S_p_e_c_, _+_O_p_t_i_o_n_s)) Load a single object. If this call succeeds, load_files/2 assumes the action has been taken care of. This hook is only called if _O_p_t_i_o_n_s does not contain the stream(_I_n_p_u_t) option. The hook must be defined in the module user. The http_load provides an example, loading Prolog sources directly from an HTTP server. pprroolloogg::ccoommmmeenntt__hhooookk((_+_C_o_m_m_e_n_t_s_, _+_P_o_s_, _+_T_e_r_m)) This hook allows for processing ---structured--- comments encountered by the compiler. The reader collects all comments found from the current position to the end of the next term. It calls this hook providing a list of _P_o_s_i_t_i_o_n-_C_o_m_m_e_n_t in _C_o_m_m_e_n_t_s, the start-position of the next term in _P_o_s and the next term itself in _T_e_r_m. All positions are stream-position terms. This hook is exploited by the documentation system. See stream_position_data/3. See also read_term/3. 1122..77 RReeaaddlliinnee IInntteerraaccttiioonn The following predicates are available if current_prolog_flag(readline, true) succeeds. They allow for di- rect interaction with the GNU readline library. See also readline(3) rrll__rreeaadd__iinniitt__ffiillee((_+_F_i_l_e)) Read a readline initialisation file. Readline by default reads ~/.inputrc. This predicate may be used to read alternative readline initialisation files. rrll__aadddd__hhiissttoorryy((_+_L_i_n_e)) Add a line to the Control-P/Control-N history system of the readline library. rrll__wwrriittee__hhiissttoorryy((_+_F_i_l_e_N_a_m_e)) Write current history to _F_i_l_e_N_a_m_e. Can be used from at_halt/1 to save the history. rrll__rreeaadd__hhiissttoorryy((_+_F_i_l_e_N_a_m_e)) Read history from _F_i_l_e_N_a_m_e, appending to the current history. CChhaapptteerr 1133.. GGLLOOSSSSAARRYY OOFF TTEERRMMSS aannoonnyymmoouuss [[vvaarriiaabbllee]] The variable _ is called the _a_n_o_n_y_m_o_u_s variable. Multiple occurrences of _ in a single _t_e_r_m are not _s_h_a_r_e_d. aarrgguummeennttss Arguments are _t_e_r_m_s that appear in a _c_o_m_p_o_u_n_d _t_e_r_m. _A_1 and _a_2 are the first and second argument of the term myterm(_A_1_, _a_2). aarriittyy Argument count (is number of arguments) of a _c_o_m_p_o_u_n_d _t_e_r_m. aasssseerrtt Add a _c_l_a_u_s_e to a _p_r_e_d_i_c_a_t_e. Clauses can be added at either end of the clause-list of a _p_r_e_d_i_c_a_t_e. See assert/1 and assertz/1. aattoomm Textual constant. Used as name for _c_o_m_p_o_u_n_d terms, to represent constants or text. bbaacckkttrraacckkiinngg Searching process used by Prolog. If a predicate offers multiple _c_l_a_u_s_e_s to solve a _g_o_a_l, they are tried one-by-one until one _s_u_c_c_e_e_d_s. If a subsequent part of the proof is not satisfied with the resulting _v_a_r_i_a_b_l_e _b_i_n_d_i_n_g, it may ask for an alternative _s_o_l_u_t_i_o_n (= _b_i_n_d_i_n_g of the _v_a_r_i_a_b_l_e_s), causing Prolog to reject the previously chosen _c_l_a_u_s_e and try the next one. bbiinnddiinngg [[ooff aa vvaarriiaabbllee]] Current value of the _v_a_r_i_a_b_l_e. See also _b_a_c_k_t_r_a_c_k_i_n_g and _q_u_e_r_y. bbuuiilltt--iinn [[pprreeddiiccaattee]] Predicate that is part of the Prolog system. Built in predicates cannot be redefined by the user, unless this is overruled using redefine_system_predicate/1. bbooddyy Part of a _c_l_a_u_s_e behind the _n_e_c_k operator (:-). ccllaauussee `Sentence' of a Prolog program. A _c_l_a_u_s_e consists of a _h_e_a_d and _b_o_d_y separated by the _n_e_c_k operator (:-) or it is a _f_a_c_t. For example: parent(X) :- father(X, _). Expressed ``X is a parent if X is a father of someone''. See also _v_a_r_i_a_b_l_e and _p_r_e_d_i_c_a_t_e. ccoommppiillee Process where a Prolog _p_r_o_g_r_a_m is translated to a sequence of instructions. See also _i_n_t_e_r_p_r_e_t_e_d. SWI-Prolog always compiles your program before executing it. ccoommppoouunndd [[tteerrmm]] Also called _s_t_r_u_c_t_u_r_e. It consists of a name followed by _N _a_r_g_u_m_e_n_t_s, each of which are _t_e_r_m_s. _N is called the _a_r_i_t_y of the term. ccoonntteexxtt mmoodduullee If a _t_e_r_m is referring to a _p_r_e_d_i_c_a_t_e in a _m_o_d_u_l_e, the _c_o_n_t_e_x_t _m_o_d_u_l_e is used to find the target module. The context module of a _g_o_a_l is the module in which the _p_r_e_d_i_c_a_t_e is defined, unless this _p_r_e_d_i_c_a_t_e is _m_o_d_u_l_e _t_r_a_n_s_p_a_r_e_n_t, in which case the _c_o_n_t_e_x_t _m_o_d_u_l_e is inherited from the parent _g_o_a_l. See also module_transparent/1. ddyynnaammiicc [[pprreeddiiccaattee]] A _d_y_n_a_m_i_c predicate is a predicate to which _c_l_a_u_s_e_s may be _a_s_s_e_r_ted and from which _c_l_a_u_s_e_s may be _r_e_t_r_a_c_ted while the program is running. See also _u_p_d_a_t_e _v_i_e_w. eexxppoorrtteedd [[pprreeddiiccaattee]] A _p_r_e_d_i_c_a_t_e is said to be _e_x_p_o_r_t_e_d from a _m_o_d_u_l_e if it appears in the _p_u_b_l_i_c _l_i_s_t. This implies that the predicate can be _i_m_p_o_r_t_e_d into another module to make it visible there. See also use_module/[1,2]. ffaacctt _C_l_a_u_s_e without a _b_o_d_y. This is called a fact because interpreted as logic, there is no condition to be satisfied. The example below states john is a person. person(john). ffaaiill A _g_o_a_l is said to haved failed if it could not be _p_r_o_v_e_n. ffllooaatt Computers crippled representation of a real number. Represented as `IEEE double'. ffoorreeiiggnn Computer code expressed in other languages than Prolog. SWI-Prolog can only cooperate directly with the C and C++ computer languages. ffuunnccttoorr Combination of name and _a_r_i_t_y of a _c_o_m_p_o_u_n_d term. The term foo(_a_, _b_, _c) is said to be a term belonging to the functor foo/3. foo/0 is used to refer to the _a_t_o_m foo. ggooaall Question stated to the Prolog engine. A _g_o_a_l is either an _a_t_o_m or a _c_o_m_p_o_u_n_d term. A _g_o_a_l succeeds, in which case the _v_a_r_i_a_b_l_e_s in the _c_o_m_p_o_u_n_d terms have a _b_i_n_d_i_n_g or _f_a_i_l_s if Prolog fails to prove the _g_o_a_l. hhaasshhiinngg _I_n_d_e_x_i_n_g technique used for quick lookup. hheeaadd Part of a _c_l_a_u_s_e before the _n_e_c_k instruction. This is an atom or _c_o_m_p_o_u_n_d term. iimmppoorrtteedd [[pprreeddiiccaattee]] A _p_r_e_d_i_c_a_t_e is said to be _i_m_p_o_r_t_e_d into a _m_o_d_u_l_e if it is defined in another _m_o_d_u_l_e and made available in this _m_o_d_u_l_e. See also chapter 5. iinnddeexxiinngg Indexing is a technique used to quickly select candidate _c_l_a_u_s_e_s of a _p_r_e_d_i_c_a_t_e for a specific _g_o_a_l. In most Prolog systems, including SWI-Prolog, indexing is done on the first _a_r_g_u_m_e_n_t of the _h_e_a_d. If this argument is instantiated to an _a_t_o_m, _i_n_t_e_g_e_r, _f_l_o_a_t or _c_o_m_p_o_u_n_d term with _f_u_n_c_t_o_r, _h_a_s_h_i_n_g is used quickly select all _c_l_a_u_s_e_s of which the first argument may _u_n_i_f_y with the first argument of the _g_o_a_l. iinntteeggeerr Whole number. On all implementations of SWI-Prolog integers are at least 64-bit signed values. When linked to the GNU GMP library, integer arithmetic is unbounded. See also current_prolog_flag/2, flags bounded, max_integer and min_integer. iinntteerrpprreetteedd As opposed to _c_o_m_p_i_l_e_d, interpreted means the Prolog system attempts to prove a _g_o_a_l by directly reading the _c_l_a_u_s_e_s rather than executing instructions from an (abstract) instruction set that is not or only indirectly related to Prolog. mmeettaa--pprreeddiiccaattee A _p_r_e_d_i_c_a_t_e that reasons about other _p_r_e_d_i_c_a_t_e_s, either by calling them, (re)defining them or querying _p_r_o_p_e_r_t_i_e_s. mmoodduullee Collection of predicates. Each module defines a name-space for predicates. _b_u_i_l_t_-_i_n predicates are accessible from all modules. Predicates can be published (_e_x_p_o_r_t_e_d) and _i_m_p_o_r_t_e_d to make their definition available to other modules. mmoodduullee ttrraannssppaarreenntt [[pprreeddiiccaattee]] A _p_r_e_d_i_c_a_t_e that does not change the _c_o_n_t_e_x_t _m_o_d_u_l_e. Sometimes also called a _m_e_t_a_-_p_r_e_d_i_c_a_t_e. mmuullttiiffiillee [[pprreeddiiccaattee]] Predicate for which the definition is distributed over multiple source-files. See multifile/1. nneecckk Operator (:-) separating _h_e_a_d from _b_o_d_y in a _c_l_a_u_s_e. ooppeerraattoorr Symbol (_a_t_o_m) that may be placed before its _o_p_e_r_a_n_d (prefix), after its _o_p_e_r_a_n_d (postfix) or between its two _o_p_e_r_a_n_d_s (infix). In Prolog, the expression a+b is exactly the same as the canonical term +(a,b). ooppeerraanndd _A_r_g_u_m_e_n_t of an _o_p_e_r_a_t_o_r. pprreecceeddeennccee The _p_r_i_o_r_i_t_y of an _o_p_e_r_a_t_o_r. Operator precedence is used to interpret a+b*c as +(a, *(b,c)). pprreeddiiccaattee Collection of _c_l_a_u_s_e_s with the same _f_u_n_c_t_o_r (name/_a_r_i_t_y). If a _g_o_a_l is proved, the system looks for a _p_r_e_d_i_c_a_t_e with the same functor, then used _i_n_d_e_x_i_n_g to select candidate _c_l_a_u_s_e_s and then tries these _c_l_a_u_s_e_s one-by-one. See also _b_a_c_k_t_r_a_c_k_i_n_g. pprriioorriittyy In the context of _o_p_e_r_a_t_o_r_s a synonym for _p_r_e_c_e_d_e_n_c_e. pprrooggrraamm Collection of _p_r_e_d_i_c_a_t_e_s. pprrooppeerrttyy Attribute of an object. SWI-Prolog defines various _*___p_r_o_p_e_r_t_y predicates to query the status of predicates, clauses. etc. pprroovvee Process where Prolog attempts to prove a _q_u_e_r_y using the available _p_r_e_d_i_c_a_t_e_s. ppuubblliicc lliisstt List of _p_r_e_d_i_c_a_t_e_s exported from a _m_o_d_u_l_e. qquueerryy See _g_o_a_l. rreettrraacctt Remove a _c_l_a_u_s_e from a _p_r_e_d_i_c_a_t_e. See also _d_y_n_a_m_i_c, _u_p_d_a_t_e _v_i_e_w and _a_s_s_e_r_t. sshhaarreedd Two _v_a_r_i_a_b_l_e_s are called _s_h_a_r_e_d after they are _u_n_i_f_i_e_d. This implies if either of them is _b_o_u_n_d, the other is bound to the same value: ?- A = B, A = a. A = a, B = a ssiinngglleettoonn [[vvaarriiaabbllee]] _V_a_r_i_a_b_l_e appearing only one time in a _c_l_a_u_s_e. SWI-Prolog normally warns for this to avoid you making spelling mistakes. If a variable appears on purpose only once in a clause, write it as _ (see _a_n_o_n_y_m_o_u_s). Rules for naming a variable and avoiding a warning are given in section 2.15.1.5. ssoolluuttiioonn _B_i_n_d_i_n_g_s resulting from a successfully _p_r_o_v_en _g_o_a_l. ssttrruuccttuurree Synonym for _c_o_m_p_o_u_n_d term. ssttrriinngg Used for the following representations of text: a packed array (see section 4.23, SWI-Prolog specific), a list of character codes or a list of one-character _a_t_o_m_s. ssuucccceeeedd A _g_o_a_l is said to have _s_u_c_c_e_e_d_e_d if it has been _p_r_o_v_e_n. tteerrmm Value in Prolog. A _t_e_r_m is either a _v_a_r_i_a_b_l_e, _a_t_o_m, integer, float or _c_o_m_p_o_u_n_d term. In addition, SWI-Prolog also defines the type _s_t_r_i_n_g ttrraannssppaarreenntt See _m_o_d_u_l_e _t_r_a_n_s_p_a_r_e_n_t. uunniiffyy Prolog process to make two terms equal by assigning variables in one term to values at the corresponding location of the other term. For example: ?- foo(a, B) = foo(A, b). A = a, B = b Unlike assignment (which does not exist in Prolog), unification is not directed. uuppddaattee vviieeww How Prolog behaves when a _d_y_n_a_m_i_c _p_r_e_d_i_c_a_t_e is changed while it is running. There are two models. In most older Prolog systems the change becomes immediately visible to the _g_o_a_l, in modern systems including SWI-Prolog, the running _g_o_a_l is not affected. Only new _g_o_a_l_s `see' the new definition. vvaarriiaabbllee A Prolog variable is a value that `is not yet bound'. After _b_i_n_d_i_n_g a variable, it cannot be modified. _B_a_c_k_t_r_a_c_k_i_n_g to a point in the execution before the variable was bound will turn it back into a variable: ?- A = b, A = c. No ?- (A = b; true; A = c). A = b ; A = _G283 ; A = c ; No See also _u_n_i_f_y. CChhaapptteerr 1144.. SSWWII--PPRROOLLOOGG LLIICCEENNSSEE CCOONNDDIITTIIOONNSS AANNDD TTOOOOLLSS SWI-Prolog licensing aims at a large audience, combining ideas from the Free Software Foundation and the less principal Open Source Initiative. The license aims at: o Make SWI-Prolog itself and its libraries are `As free as possible'. o Allow for easy integration of contributions. See section 14.2. o Free software can build on SWI-Prolog without limitations. o Non-free (open or proprietary) software can be produced using SWI-Prolog, although contributed pure GPL-ed components cannot be used. To achieve this, different parts of the system have different licenses. SWI-Prolog programs consists of a mixture of `native' code (source compiled to machine instructions) and `virtual machine' code (Prolog source compiled to SWI-Prolog virtual machine instructions, covering both compiled SWI-Prolog libraries and your compiled application). For maximal coherence between free licenses, we start with the two prime licenses from the Free Software Foundation, the GNU General Public License (GPL) and the Lesser GNU General Public License (LGPL), after which we add a proven (used by the GNU-C compiler runtime library as well as the GNU _C_l_a_s_s_P_a_t_h project) exception to deal with the specific nature of compiled virtual machine code in a saved state. 1144..11 TThhee SSWWII--PPrroolloogg kkeerrnneell aanndd ffoorreeiiggnn lliibbrraarriieess The SWI-Prolog kernel and our foreign libraries are distributed under the LLGGPPLL. A Prolog executable consists of the combination of these `native' code components and Prolog virtual machine code. The SWI-Prolog plrc utility allows for disassembling and re-assembling these parts, a process satisfying article 66bb of the LGPL. Under the LGPL SWI-Prolog can be linked to code distributed under arbitrary licenses, provided a number of requirements are fullfilled. The most important requirement is that, if an application replies on a _m_o_d_i_f_i_e_d version of SWI-Prolog, the modified sources must be made available. 1144..11..11 TThhee SSWWII--PPrroolloogg PPrroolloogg lliibbrraarriieess Lacking a satisfactory technical solution to handle article 66 of the LGPL, this license cannot be used for the Prolog source code that is part of the SWI-Prolog system (both libraries and kernel code). This situation is comparable to libgcc, the runtime library used with the GNU C-compiler. Therefore, we use the same proven license terms as this library. The libgcc license is the with a special exception. Below we rephrased this exception adjusted to our needs: _A_s _a _s_p_e_c_i_a_l _e_x_c_e_p_t_i_o_n_, _i_f _y_o_u _l_i_n_k _t_h_i_s _l_i_b_r_a_r_y _w_i_t_h _o_t_h_e_r _f_i_l_e_s_, _c_o_m_p_i_l_e_d _w_i_t_h _a _F_r_e_e _S_o_f_t_w_a_r_e _c_o_m_p_i_l_e_r_, _t_o _p_r_o_d_u_c_e _a_n _e_x_e_c_u_t_a_b_l_e_, _t_h_i_s _l_i_b_r_a_r_y _d_o_e_s _n_o_t _b_y _i_t_s_e_l_f _c_a_u_s_e _t_h_e _r_e_s_u_l_t_i_n_g _e_x_e_c_u_t_a_b_l_e _t_o _b_e _c_o_v_e_r_e_d _b_y _t_h_e _G_N_U _G_e_n_e_r_a_l _P_u_b_l_i_c _L_i_c_e_n_s_e_. _T_h_i_s _e_x_c_e_p_t_i_o_n _d_o_e_s _n_o_t _h_o_w_e_v_e_r _i_n_v_a_l_i_d_a_t_e _a_n_y _o_t_h_e_r _r_e_a_s_o_n_s _w_h_y _t_h_e _e_x_e_c_u_t_a_b_l_e _f_i_l_e _m_i_g_h_t _b_e _c_o_v_e_r_e_d _b_y _t_h_e _G_N_U _G_e_n_e_r_a_l _P_u_b_l_i_c _L_i_c_e_n_s_e_. 1144..22 CCoonnttrriibbuuttiinngg ttoo tthhee SSWWII--PPrroolloogg pprroojjeecctt To achieve maximal coherence using SWI-Prolog for Free and Non-Free software we advice the use of the LGPL for contributed foreign code and the use of the GPL with SWI-Prolog exception for Prolog code for contributed modules. As a rule of thumb it is advised to use the above licenses whenever possible and only use a strict GPL compliant license only if the module contains other code under strict GPL compliant licenses. 1144..33 SSooffttwwaarree ssuuppppoorrtt ttoo kkeeeepp ttrraacckk ooff lliicceennssee ccoonnddiittiioonnss Given the above, it is possible that SWI-Prolog packages and extensions will rely on the GPL. The predicates below allow for registering license requirements for Prolog files and foreign modules. The predicate eval_license/0 reports which components from the currenly configured system are distributed under copy-left and open source enforcing licenses (the GPL) and therefore must be replaced before distributing linked applications under non-free license conditions. eevvaall__lliicceennssee Evaluate the license conditions of all loaded components. If the system contains one or more components that are licenced under GPL-like restrictions the system indicates this program may only be distributed under the GPL license as well as which components prohibit the use of other license conditions. lliicceennssee((_+_L_i_c_e_n_s_e_I_d_, _+_C_o_m_p_o_n_e_n_t)) Register the fact that _C_o_m_p_o_n_e_n_t is distributed under a license identified by _L_i_c_e_n_s_e_I_d. The most important _L_i_c_e_n_s_e_I_d's are: sswwiippll Indicates this module is distributed under the GNU General Public License (GPL) with the SWI-Prolog exception: _A_s _a _s_p_e_c_i_a_l _e_x_c_e_p_t_i_o_n_, _i_f _y_o_u _l_i_n_k _t_h_i_s _l_i_b_r_a_r_y _w_i_t_h _o_t_h_e_r _f_i_l_e_s_, _c_o_m_p_i_l_e_d _w_i_t_h _S_W_I_-_P_r_o_l_o_g_, _t_o _p_r_o_d_u_c_e _a_n _e_x_e_c_u_t_a_b_l_e_, _t_h_i_s _l_i_b_r_a_r_y _d_o_e_s _n_o_t _b_y _i_t_s_e_l_f _c_a_u_s_e _t_h_e _r_e_s_u_l_t_i_n_g _e_x_e_c_u_t_a_b_l_e _t_o _b_e _c_o_v_e_r_e_d _b_y _t_h_e _G_N_U _G_e_n_e_r_a_l _P_u_b_l_i_c _L_i_c_e_n_s_e_. _T_h_i_s _e_x_c_e_p_t_i_o_n _d_o_e_s _n_o_t _h_o_w_e_v_e_r _i_n_v_a_l_i_d_a_t_e _a_n_y _o_t_h_e_r _r_e_a_s_o_n_s _w_h_y _t_h_e _e_x_e_c_u_t_a_b_l_e _f_i_l_e _m_i_g_h_t _b_e _c_o_v_e_r_e_d _b_y _t_h_e _G_N_U _G_e_n_e_r_a_l _P_u_b_l_i_c _L_i_c_e_n_s_e_. This should be the default for software contributed to the SWI-Prolog project as it allows the community to prosper both in the free and non-free world. Still, people using SWI-Prolog to create non-free applications must contribute sources to improvements they make to the community. llggppll This is the default license for foreign-libraries linked with SWI-Prolog. Use PL_license() to register the condition from foreign code. ggppll Indicates this module is strictly Free Software, which implies it cannot be used together with any module that is incompatible to the GPL. Please only use these conditions when forced by other code used in the component. Other licenses known to the system are guile, gnu_ada, x11, expat, sml, public_domain, cryptix, bsd, zlib, constlgpl_compatible and gpl_compatible. New licenses can be defined by adding clauses for the multifile predicate license:license/3. Below is an example. The second argument is either gpl or lgpl to indicate compatibility to these licenses. Other values cause the license to interpreted as _p_r_o_p_r_i_e_t_a_r_y. Proprietary licenses are reported by eval_license/0. See the file boot/license.pl for details. :- multifile license:license/3. license:license(mylicense, lgpl, [ comment('My personal license'), url('http://www.mine.org/license.html') ]). :- license(mylicense). lliicceennssee((_+_L_i_c_e_n_s_e_I_d)) Intented as a directive in Prolog source files. It takes the current filename and calls license/2. void PPLL__lliicceennssee(_c_o_n_s_t _c_h_a_r _*_L_i_c_e_n_s_e_I_d_, _c_o_n_s_t _c_h_a_r _*_C_o_m_p_o_n_e_n_t) Intended for the install() procedure of foreign libraries. This call can be made _b_e_f_o_r_e PL_initialise(). 1144..44 LLiibbrraarryy pprreeddiiccaatteess 1144..44..11 check check/0 Program completeness and consistency list_undefined/0 List undefined predicates list_autoload/0 List predicates that require autoload list_redefined/0 List locally redefined predicates 1144..44..22 lists append/3 Concatenate lists delete/3 Delete all matching members from a list flatten/2 Transform nested list into flat list intersection/3 Set intersection is_set/1 Type check for a set list_to_set/2 Remove duplicates member/2 Element is member of a list nextto/3 Y follows X in List nth0/3 N-th element of a list (0-based) nth1/3 N-th element of a list (1-based) numlist/3 Create list of integers in interval permutation/2 Test/generate permutations of a list reverse/2 Inverse the order of the elements in a list select/3 Select element of a list subset/2 Check subset relation for unordered sets subtract/3 Delete elements that do not satisfy condition sumlist/2 Add all numbers in a list union/3 Union of two sets 1144..44..33 ordsets ord_empty/1 Test empty ordered set list_to_ord_set/2 Create ordered set ord_add_element/3 Add element to ordered set ord_del_element/3 Delete element from ordered set ord_intersect/2 Test non-empty intersection ord_intersection/3 Compute intersection ord_disjoint/2 Test empty intersection ord_subtract/3 Delete set from set ord_union/3 Union of two ordered sets ord_union/4 Union and difference of two ordered sets ord_subset/2 Test subset ord_memberchk/2 Deterministically test membership 1144..44..44 ugraphs vertices_edges_to_ugraph/3Create unweighted graph vertices/2 Find vertices in graph edges/2 Find edges in graph add_vertices/3 Add vertices to graph del_vertices/3 Delete vertices from graph add_edges/3 Add edges to graph del_edges/3 Delete edges from graph transpose/2 Invert the direction of all edges neighbors/3 Find neighbors of vertice neighbours/3 Find neighbors of vertice complement/2 Inverse presense of edges compose/3 top_sort/2 Sort graph topologically top_sort/3 Sort graph topologically transitive_closure/2 Create transitive closure of graph reachable/3 Find all reachable vertices ugraph_union/3 Union of two graphs 1144..44..55 www_browser www_open_url/1 Open a web-page in a browser 1144..44..66 readutil read_line_to_codes/2 Read line from a stream read_line_to_codes/3 Read line from a stream read_stream_to_codes/2Read contents of stream read_stream_to_codes/3Read contents of stream read_file_to_codes/3 Read contents of file read_file_to_terms/3 Read contents of file to Prolog terms 1144..44..77 registry This library is only available on Windows systems. registry_get_key/2 Get principal value of key registry_get_key/3 Get associated value of key registry_set_key/2 Set principal value of key registry_set_key/3 Set associated value of key registry_delete_key/1 Remove a key shell_register_file_type/4Register a file-type shell_register_dde/6 Register DDE action shell_register_prolog/1 Register Prolog 1144..44..88 url parse_url/2 Analyse or construct a URL parse_url/3 Analyse or construct a relative URL global_url/3 Make relative URL global http_location/2 Analyse or construct location www_form_encode/2 Encode or decode form-data 1144..44..99 clp/bounds in/2 Define interval for variable #>/2 Greater than constraint #=/2 Greater or equal constraint #=/2 Constraint equivalence #<=/2 Constraint implication to the left #=>/2 Constraint implication to the right all_different/1 Constraint all values to be unique indomain/1 Enumerate values from domain label/1 Solve constraints for variables labeling/2 Solve constraints for variables lex_chain/1 Constraint on lexicographic ordering sum/3 Constraint sum of variables tuples_in/2 Symbolic constraints on tuples serialized/2 Constraint intervals to be serialized 1144..44..1100 clp/clp_distinct all_distinct/1 Demand distinct values vars_in/2 Declare domain of variable as set vars_in/3 Declare domain of variable as interval 1144..44..1111 clp/simplex assignment/2 Solve assignment problem constraint/3 Add linear constraint to state constraint/4 Add named linear constraint to state gen_state/1 Create empty linear program maximize/3 Maximize objective function in to linear constraints minimize/3 Minimize objective function in to linear constraints objective/2 Fetch value of objective function shadow_price/3 Fetch shadow price in solved state transportation/4 Solve transportation problem variable_value/3 Fetch value of variable in solved state 1144..44..1122 clpqr entailed/1 Check if constraint is entailed inf/2 Find the infimum of an expression sup/2 Find the supremum of an expression minimize/1 Minimizes an expression maximize/1 Maximizes an expression bb_inf/3 Infimum of expression for mixed-integer problems bb_inf/4 Infimum of expression for mixed-integer problems bb_inf/5 Infimum of expression for mixed-integer problems dump/3 Dump constraints on variables 1144..44..1133 prologxref prolog:called_by/2 (hook) Extend cross-referencer xref_built_in/1 Examine defined built-ins xref_called/3 Examine called predicates xref_clean/1 Remove analysis of source xref_current_source/1 Examine cross-referenced sources xref_defined/3 Examine defined predicates xref_exported/2 Examine exported predicates xref_module/2 Module defined by source xref_source/1 Cross-reference analysis of source 1144..44..1144 broadcast broadcast/1 Send event notification broadcast_request/1 Request all agents listen/2 Listen to event notifications listen/3 Listen to event notifications unlisten/1 Stop listening to event notifications unlisten/2 Stop listening to event notifications unlisten/3 Stop listening to event notifications listening/3 Who is listening to event notifications? 1144..44..1155 record record/1 Define named fields in a term Bibliography [Anjewierden & Wielemaker, 1989] A. Anjewierden and J. Wielemaker. Extensible objects. ESPRIT Project 1098 Technical Report UvA-C1-TR-006a, University of Amsterdam, March 1989. [BIM, 1989] _B_I_M _P_r_o_l_o_g _r_e_l_e_a_s_e _2_._4. Everberg, Belgium, 1989. [Bowen & Byrd, 1983] D. L. Bowen and L. M. Byrd. A portable Prolog compiler. In L. M. Pereira, editor, _P_r_o_c_e_e_d_i_n_g_s _o_f _t_h_e _L_o_g_i_n _P_r_o_g_r_a_m_m_i_n_g _W_o_r_k_s_h_o_p _1_9_8_3, Lisabon, Portugal, 1983. Universidade nova de Lisboa. [Bratko, 1986] I. Bratko. _P_r_o_l_o_g _P_r_o_g_r_a_m_m_i_n_g _f_o_r _A_r_- _t_i_f_i_c_i_a_l _I_n_t_e_l_l_i_g_e_n_c_e. Addison-Wesley, Reading, Massachusetts, 1986. [Butenhof, 1997] David R. Butenhof. _P_r_o_g_r_a_m_m_i_n_g _w_i_t_h _P_O_S_I_X _t_h_r_e_a_d_s. Addison-Wesley, Read- ing, MA, USA, 1997. [Clocksin & Melish, 1987] W. F. Clocksin and C. S. Melish. _P_r_o_g_r_a_m_m_i_n_g _i_n _P_r_o_l_o_g. Springer- Verlag, New York, Third, Revised and Extended edition, 1987. [Demoen, 2002] Bart Demoen. Dynamic attributes, their hProlog implementation, and a first evaluation. Report CW 350, Department of Computer Science, K.U.Leuven, Leuven, Belgium, oct 2002. URL = http://www.cs.kuleuven.ac.be/publicaties/rapporten/cw/CW350.abs.html. [Deransart _e_t _a_l_., 1996] P. Deransart, A. Ed-Dbali, and L. Cervoni. _P_r_o_l_o_g_: _T_h_e _S_t_a_n_d_a_r_d. Springer-Verlag, New York, 1996. [Fr"uhwirth, ] T. Fr"uhwirth. Thom Fruehwirth's constraint handling rules web- site. http://www.informatik.uni- ulm.de/pm/mitarbeiter/fruehwirth/chr- intro.html. [Fr"uhwirth, 1998] T. Fr"uhwirth. Theory and Practice of Constraint Handling Rules. In P. Stuckey and K. Marriot, editors, _S_p_e_c_i_a_l _I_s_s_u_e _o_n _C_o_n_s_t_r_a_i_n_t _L_o_g_i_c _P_r_o_g_r_a_m_m_i_n_g, volume 37, October 1998. [Graham _e_t _a_l_., 1982] Susan L. Graham, Peter B. Kessler, and Marshall K. McKusick. gprof: a call graph execution profiler. In _S_I_G_P_L_A_N _S_y_m_p_o_s_i_u_m _o_n _C_o_m_p_i_l_e_r _C_o_n_s_t_r_u_c_t_i_o_n, pages 120--126, 1982. [Hodgson, 1998] Jonathan Hodgson. validation suite for conformance with part 1 of the standard, 1998, http://www.sju.edu/~jhodgson/pub/suite.tar.gz. [Holzbaur, 1990] Christian Holzbaur. Realization of forward checking in logic program- ming through extended unification. Report TR-90-11, Oesterreichisches Forschungsinstitut fuer Artificial In- telligence, Wien, Austria, 1990. [Kernighan & Ritchie, 1978] B. W. Kernighan and D. M. Ritchie. _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e. Prentice-Hall, Englewood Cliffs, New Jersey, 1978. [O'Keefe, 1990] R. A. O'Keefe. _T_h_e _C_r_a_f_t _o_f _P_r_o_l_o_g. MIT Press, Massachussetts, 1990. [Pereira, 1986] F. Pereira. _C_-_P_r_o_l_o_g _U_s_e_r_'_s _M_a_n_u_a_l, 1986. [Qui, 1997] _Q_u_i_n_t_u_s _P_r_o_l_o_g_, _U_s_e_r _G_u_i_d_e _a_n_d _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l. Berkhamsted, UK, 1997. [Sterling & Shapiro, 1986] L. Sterling and E. Shapiro. _T_h_e _A_r_t _o_f _P_r_o_l_o_g. MIT Press, Cambridge, Massachusetts, 1986. 1330 Index 'MANUAL' _l_i_b_r_a_r_y, 43 UCS, 76 --disable-segv-handling, 1045 ugraph _l_i_b_r_a_r_y, 1123 -lpl _l_i_b_r_a_r_y, 1046 ugraph_union/3, 1136 -lreadline _l_i_b_r_a_r_y, 1074 ugraphs _l_i_b_r_a_r_y, 1123, 1318 .pl, 91 ugraphs.pl _l_i_b_r_a_r_y, 1123 .pro, 91 Unicode, 76 ?=/2, 195 unifiable/3, 196 =:=/2, 445 unify_with_occurs_check/2, 186 /\/2, 479 union/3, 1095 =\=/2, 444 Unix, 7 |/2, 204 unix, 60 #=/2, 1197 unix/1, 21, 558 #>=/2, 1195 unknown/2, 63, 628, 683, 1075 #>/2, 1193 unlisten/1, 1273 #=/2, 1216 673, 676, 678, 692, 1304 >=/2, 443 user profile file, 39 >/2, 440 UTF-8, 76 ^/2, 495 utf-8, 122 ///2, 457 ->/2, 205 var/1, 12, 166, 703, 864 =/2, 1214 win_exec/2, 547, 550, 551 >>/2, 476 win_has_menu/0, 572 ;/2, 203 win_insert_menu/2, 572--574 *->/2, 206 win_insert_menu_item/4, 572, 574 =@=/2, 188 win_registry_get_value/3, 553 \=@=/2, 189 win_shell/2, 547, 551, 552, 1172 @>=/2, 193 win_window_pos/1, 571 @>/2, 192 Window interface, 8 */2, 453, 1207 window_title/2, 570 @=