PLOGHELP TERMSINPOP Jonathan Laventhol, 22 July 1985 Revised by Kathryn Seifert, August 1986 Revised by Robert Duncan, May 1987 POP-11 procedures for manipulating Prolog terms and variables. prolog_readterm() -> prolog_readterm_to() -> prolog_write() prolog_maketerm({}*, , ) -> prolog_complexterm() -> prolog_functor() -> prolog_arity() -> prolog_arg(, ) -> prolog_arg_nd(, ) -> prolog_args() -> {}* prolog_args_nd() -> {}* prolog_appargs(, ) -> {}* prolog_appargs_nd(, ) -> {}* prolog_deref() -> prolog_undefvar() -> prolog_full_deref() -> prolog_var_number() -> prolog_newvar() -> prolog_generalise() -> prolog_instance() -> prolog_unify(, ) -> prolog_unifyc(, , ) Keywords: POP-11, Prolog, mixed language programming, prolog terms, prolog variables CONTENTS - (Use g to access required sections) -- INTRODUCTION -- HOW PROLOG TERMS ARE REPRESENTED -- PROCEDURES FOR MANIPULATING PROLOG TERMS -- DEREFERENCING -- EQUALITY ON PROLOG OBJECTS -- KEEPING STRUCTURES BUILT BY PROLOG OVER BACKTRACKING -- MISCELLANEOUS PROCEDURES -- SECRETS -- RELATED DOCUMENTATION -- INTRODUCTION ------------------------------------------------------- This HELP file describes in detail the current facilities and procedures provided for manipulating Prolog terms and variables in POP-11. The representation of Prolog terms changed in V.11 POPLOG, and a description of these changes is given in PLOGHELP * OLDPLOGTERMS. -- HOW PROLOG TERMS ARE REPRESENTED ----------------------------------- In general, it is not necessary to know much about how Prolog terms are represented in POPLOG. In particular, the following procedures enable you to read and write Prolog terms using the Clocksin and Mellish "core Prolog" syntax: prolog_readterm() -> returns a Prolog term read from PROGLIST and terminated by a dot prolog_readterm_to() -> returns a Prolog term read from PROGLIST and terminated by the word W prolog_write() writes the Prolog term T to CUCHAROUT (See HELP * PROGLIST, HELP * CUCHAROUT) However, for developing some programs in a mixture of Prolog and POP-11, it is useful to know how Prolog terms are represented in POPLOG and what correspondences with POP-11 structures can be relied on. The following are the basic rules. Note that to understand Prolog datastructures one must also understand the notion of "dereferencing" (see below). PROLOG ATOMS are represented by POP-11 words. (Quoted atoms are read from PROGLIST as POP-11 strings, but converted by the Prolog parser into words.) PROLOG VARIABLES have their own datatype. See section below. PROLOG LISTS are represented by POP-11 lists (i.e. built from pairs). PROLOG COMPLEX TERMS are represented by their own datatype. This is an improvement introduced in Version 11 and the procedures described in this file are now the preferred ones. Any other POP-11 object is considered "atomic" in the sense that its functor is itself and it has arity zero. Good examples are numbers and the empty list [], but the same rule applies for all other data types not catered for above (for example: strings, booleans, vectors and procedures). -- PROCEDURES FOR MANIPULATING PROLOG TERMS --------------------------- prolog_maketerm({}*, , ) -> 'prolog_maketerm' takes any number of items I which will correspond to the arguments of the prologterm T being constructed, a word F corresponding to the functor of the term, and an integer A indicating the arity of the term. The procedure builds a prologterm T with the given functor and arity, taking the items I off the stack. Constructs a pair if the functor is "." and arity is 2. If arity is zero then the functor is taken to be 'atomic' and is returned. Mishaps if the arity is less than zero or is not an integer, or if the arity is greater than zero and the functor is not a word. prolog_complexterm() -> Returns true if T is a prologterm or a pair. Returns false for any other object (thus, T should already be dereferenced). prolog_functor() -> Returns the word W representing the principal functor of the term T. If T is not a complex term then it is its own functor, and so is returned. The procedure has an updater, but you should not, in general, update the functors of terms. The updater will only allow you to change the functors of prologterms, not of lists or any other object. This procedure replaces prolog_predword. prolog_arity() -> Returns the number of arguments of the given term. If T is not a complex term then I will be 0. This procedure used to be known as prolog_nargs. prolog_arg(, ) -> Dereferences and returns the Nth argument of T. Mishaps if N is less than 1 or is not an integer, or if N is greater than the arity of T. This does not have an updater, since that would be meaningless for a dereferencing procedure. Compare prolog_arg_nd. prolog_arg_nd(, ) -> Like prolog_arg, but returns the Nth argument of T WITHOUT dereferencing. Unlike prolog_arg this has an updater, to be used with great caution: it changes the N'th element of a term at the top level. (See warning at end of file: copy the term first). prolog_args() -> {}* Returns all the (dereferenced) arguments of T - i.e. leaves them on the stack. prolog_args_nd() -> {}* Returns all the arguments of T WITHOUT dereferencing. prolog_appargs(, ) -> {}* Applies the given procedure to each dereferenced argument of T. prolog_appargs_nd(, ) -> {}* Like prolog_appargs, but does not de-reference. (See also REF * FASTPROCS) -- DEREFERENCING ------------------------------------------------------ Prolog variables consist of chains of the datastructure "prologvar". This is structurally the same as a reference (see HELP * REFERENCES), that is, it has a single field known as the "content". Whenever we want the value of a Prolog variable, we run down the chain of prologvars until we get to a content which isn't a prologvar, or is an uninstantiated prologvar - this process is known as "dereferencing". If the content isn't a prologvar, then this value is the "real" value. Uninstantiated variables are represented by prologvars which point to themselves -- but there is no need to know the representation of Prolog variables beyond that they usually consist of chains of prologvars, of unknown length. In order to get the "real" value of a Prolog variable, you apply the procedure prolog_deref to it. Indeed, there is no other safe way of getting the content of a prologvar; if you ever want the value of a Prolog variable, use prolog_deref and you will get the dereferenced, real, value. If the result is a Prolog variable, then your original variable is uninstantiated. prolog_deref() -> Dereferences V. If V isn't a Prolog variable, then it is returned. If V is a Prolog variable, then its "real" value will be returned. Usually this will be a Prolog term or other object. If V is uninstantiated, then the result will be a prologvar. This procedure only dereferences the top level of the term V, and so the result can contain components which are themselves not fully dereferenced. Since prologvars are very similar to references, one possible version of the deref procedure might be the following: define prolog_deref(V) -> V; while isref(V) and cont(V) /== V do cont(V) -> V; endwhile enddefine; prolog_undefvar() -> True if V is an uninstantiated variable record. This is not the same thing as the Prolog predicate var/1. To get that behaviour, you need to do prolog_undefvar(prolog_deref(V)). Following the model using the more familiar references, this procedure might be written like this: define prolog_undefvar(V); isref(V) and cont(V) == V enddefine; prolog_full_deref() -> Returns a copy C of T; if T contains any chains of Prolog variables, they are removed in C. Now any Prolog variables which are still in C will be uninstantiated ones. prolog_var_number() -> Returns a integer for the prologvar V or FALSE if V is not a Prolog variable. This number will be the same number as the variable prints in the 'underscore notation' of Prolog. It is the lowest number of any variable which is sharing with V. It is possible to reset the numbering by giving V as false, but you are advised not to do this. prolog_newvar() -> Creates a new prologvar V (suitable for use as argument to e.g. prolog_var_number). Other complex objects (eg procedures, processes) can be manipulated by Prolog. These just form other classes of atomic structure (Prolog cannot discern any internal structure). -- EQUALITY ON PROLOG OBJECTS ----------------------------------------- The POP-11 equality procedure, =, can be applied to Prolog terms and variables and works as follows: - complex terms are compared in functor and arity and then recursively by arguments; - variables are dereferenced before comparison; - uninstantiated variables are compared with == (i.e. identity). This gives the same behaviour as the Prolog predicate ==/2. -- KEEPING STRUCTURES BUILT BY PROLOG OVER BACKTRACKING --------------- Prolog structures are built up by the successive instantiation of Prolog variables. Two important things happen to structures when backtracking occurs: 1. When Prolog returns to a choicepoint, any variables which were instantiated after it originally left that point will lose their bindings, and become uninstantiated again. This means that structures built using these variables "disintegrate". 2. Any variables that were first introduced in that period cease to have meaningful values. It is important to be aware of this if you wish to make use of Prolog structures in POP-11 programs. If you assign a structure built by Prolog to a POP-11 variable and then allow Prolog to backtrack to a point before the structure was created (for instance, if you return to the top level interpreter, which works basically on a "repeat, read, call, write, fail" pattern) you will find that the structure mysteriously disappears. This will not happen if you are only passing out simple values (for instance numbers and words) from Prolog, because of the way that these are automatically dereferenced. The procedure 'prolog_full_deref' (see above) creates a new copy of structures without intermediate variable records, and these are immune to disintegration of the first sort. However, if the structures to be kept contain uninstantiated variables, because of the second problem, it is necessary to create a copy of the structure that contains other structures in their place. The following procedures enable this to be done: prolog_generalise() -> As 'prolog_full_deref', except that any uninstantiated variables in T are returned as special VARIABLE TOKENS in I. This is the best way to make a copy of a Prolog term that will survive unchanged when Prolog backtracks. prolog_instance() -> The inverse of prolog_generalise. Takes a structure that may contain "variable tokens" and returns a copy T with real Prolog variables instead. -- MISCELLANEOUS PROCEDURES ------------------------------------------- prolog_unify(, ) -> Unifies A with B. If either is uninstantiated , then one becomes instantiated and is pushed onto the chain of references. Returns true if successful. However, if it fails (returns FALSE), it may leave some variables instantiated - you should therefore use prolog_unifyc (see below) where this is likely to occur. prolog_unifyc(, , ) Unifies A with B. If successful, the continuation passing procedure P is applied (see DOC * CONTINUATION). -- SECRETS ------------------------------------------------------------ There are other POP-11 procedures for working with Prolog objects. In general, you are advised not to use them. They are for the internal workings of the Prolog system. Here is some specific advice: NEVER alter the value of a Prolog variable in any other way than prolog_unify. You can build structures which can cause the POP-11 system to hang. Unification is the only safe way to do it. NEVER alter any structures built by the Prolog system. Copy them first, then alter your copy. In particular, don't use the updater of prolog_functor on a structure built by the Prolog system. -- RELATED DOCUMENTATION ---------------------------------------------- DOC * CONTINUATION How continuation passing procedures in POP-11 relate to Prolog. Slightly out of date. PLOGHELP * MIXED_LANGUAGES Overview of interface between Prolog and other languages. PLOGHELP * PLOGTOPOP How to call POP-11 from Prolog. PLOGHELP * PROCESSES How to create POP-11 processes which use Prolog procedures. PLOGHELP * PROLOG_BARRIER_APPLY POP-11 procedure which applies a procedure inside a Prolog 'barrier'. PLOGHELP * PROLOG_EVAL How to evaluate the Prolog representation of a POP-11 expression. PLOGHELP * PROLOG_INVOKE POP-11 procedure which invokes a Prolog term. PLOGHELP * PROLOG_VALOF POP-11 procedure which returns the current value of a Prolog predicate. HELP * COPYDATA POP-11 procedure for copying data-structures. --- C.all/plog/help/termsinpop ----------------------------------------- --- Copyright University of Sussex 1987. All rights reserved. ----------