Download as pdf or txt
Download as pdf or txt
You are on page 1of 400



    
$%"!$"!%&$'&$" $"" +%$(%$"'%)&$!%$$&"&  
%%"&"!!' $)(&""!%'&&"!"!&!&$!&!%#$!
*   

"!&&%%"&"!#$""$&"$
Aociation Prolog

HERITAGE

PROLOG II+

REFERENCE MANUAL

© PrologIA
Aociation Prolog
2 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 3

Contents

Contents.............................................................................................................3

Introduction ......................................................................................................9
Standardization..................................................................................9
Performances ....................................................................................9
Modularity ......................................................................................10
Communication with the outside world ...........................................10
Programming environment..............................................................10
Graphics interface ...........................................................................10

About this manual .........................................................................................13

Guarantee and liabilities...............................................................................15


Copyright.................................................................................................15

0. Getting started .....................................................................................R 0 - 1


0.1 Lesson 1 : Starting a Prolog session........................................R 0 - 1
0.2 Lesson 2 : An example program ..............................................R 0 - 2
0.3 Lesson 3 : The editor ...............................................................R 0 - 4
0.4 The most frequent errors...........................................................R 0 - 5
0.4.1 Code overflow..............................................................R 0 - 5
0.4.2 Interruption. .................................................................R 0 - 5
0.4.3 Errors identified during insertion .................................R 0 - 6
0.4.4 File errors.....................................................................R 0 - 6
0.4.5 Syntax errors................................................................R 0 - 6
0.4.6 Execution errors...........................................................R 0 - 7

1. The basic elements...............................................................................R 1 - 1


1.1 Notation....................................................................................R 1 - 1
1.2 The set of characters .................................................................R 1 - 2
1.3 Variables...................................................................................R 1 - 3
1.4 Constants..................................................................................R 1 - 4
1.5 Terms and trees......................................................................... R 1 - 8
1.6 Operators................................................................................R 1 - 13
1.7 Rules and specified facts......................................................... R 1 - 13
1.8 General mechanisms of Prolog...............................................R 1 - 15
1.9 Complete syntax of Prolog II+...............................................R 1 - 17

© PrologIA
Aociation Prolog
4 Reference Manual HERITAGE

1.9.1 The syntactic level...................................................... R 1 - 18


1.9.2 The operators............................................................. R 1 - 19
1.9.3 The lexical level ......................................................... R 1 - 21
1.9.4 The characters............................................................ R 1 - 22
1.9.5 Accented characters ................................................... R 1 - 24
1.10. The macro processor ..............................................................R 1 - 26

2. Control of program execution ........................................................... R 2 - 1


2.1 Control......................................................................................R 2 - 1
2.2 Freeze........................................................................................R 2 - 9
2.3 Infinite trees ............................................................................R 2 - 11
2.4 Some advice about recursive programming .............................R 2 - 12
2.5 Metastructures.........................................................................R 2 - 14
2.5.1 Creation..................................................................... R 2 - 14
2.5.2 Recovery.................................................................... R 2 - 15
2.5.3 Forced unification...................................................... R 2 - 15
2.5.4 Output ....................................................................... R 2 - 16
2.5.5 Example..................................................................... R 2 - 16

3. Structuring rules and modification.................................................. R 3 - 1


3.1 Introduction...............................................................................R 3 - 1
3.1.1 Predicate qualification.................................................. R 3 - 1
3.1.2 Functor qualification.................................................... R 3 - 2
3.1.3 Simplification of notation ............................................ R 3 - 3
3.1.4 Some simple rules for use ........................................... R 3 - 3
3.1.5 Standard modules and prefixes.................................... R 3 - 4
3.2 Terminology..............................................................................R 3 - 5
3.3 Identifier syntax ........................................................................R 3 - 6
3.3.1. Parameterization of the writing of a complete identifier R 3 - 7
3.4 Context for Reading and Writing..............................................R 3 - 7
3.4.1 Reading ....................................................................... R 3 - 8
3.4.2 Writing........................................................................ R 3 - 8
3.4.3 Simplified notation of the identifier sequence of a .................
context......................................................................... R 3 - 9
3.4.4 Notation in Prolog..................................................... R 3 - 10
3.4.5 Primitives for the contexts and the identifier families. R 3 - 11
3.5 Modules..................................................................................R 3 - 13
3.5.1 Definition of a module............................................... R 3 - 14
3.5.2 Source module........................................................... R 3 - 14
3.5.3 Object module ........................................................... R 3 - 17
3.6 Summary of how to use identifiers, contexts and modules......R 3 - 17

© PrologIA
Aociation Prolog

HERITAGE Introduction 5

3.6.1 Identifiers...................................................................R 3 - 17
3.6.2 Abbreviated notation and contexts..............................R 3 - 18
3.6.3 Modules.....................................................................R 3 - 19
3.7 Adding, deleting and searching for rules.................................R 3 - 20
3.8 Manipulation of compiled modules.........................................R 3 - 31

4. Predefined data operations.................................................................R 4 - 1


4.1 Type testing rules......................................................................R 4 - 1
4.2 Arithmetic and boolean operations............................................R 4 - 2
4.3 Assignment...............................................................................R 4 - 7
4.4 String operations.......................................................................R 4 - 9
4.5 Composition and decomposition of objects ............................ R 4 - 10
4.6 Comparing any terms..............................................................R 4 - 14

5. Input and Output ................................................................................R 5 - 1


5.0 General information..................................................................R 5 - 1
5.1 Input .........................................................................................R 5 - 2
5.1.1 Input rules....................................................................R 5 - 3
5.1.2 Modifying the input unit ..............................................R 5 - 8
5.2 Output.......................................................................................R 5 - 8
5.2.1 Output..........................................................................R 5 - 9
5.2.2 Modifying the output unit ..........................................R 5 - 12
5.3 Loading and adapting the drawing module..............................R 5 - 13
5.4 Declaration of operators.......................................................... R 5 - 14

6. The environment..................................................................................R 6 - 1
6.1 How to leave Prolog..................................................................R 6 - 1
6.2 Automatic start-up of a Prolog program....................................R 6 - 1
6.3 Program editing ........................................................................R 6 - 2
6.3.1 Modifying groups of rules...........................................R 6 - 2
6.3.2 Editing and recompiling a source module.....................R 6 - 3
6.3.3 Editing any type of text file ..........................................R 6 - 4
6.4 Date, time and measurements....................................................R 6 - 4
6.5 Link to the system.....................................................................R 6 - 5
6.6 Program debugger ....................................................................R 6 - 6
6.6.1 Trace mode...................................................................R 6 - 6
6.6.2 Interactive mode ...........................................................R 6 - 7
6.6.2.1 Break points.....................................................R 6 - 7
6.6.2.2 Advancing in the code ......................................R 6 - 8
6.6.2.3 Ending execution..............................................R 6 - 9
6.6.2.4 Displaying information ....................................R 6 - 9

© PrologIA
Aociation Prolog
6 Reference Manual HERITAGE

6.6.2.5 Additional information about execution......... R 6 - 14


6.6.2.6 Configuration ................................................ R 6 - 16
6.6.3 Activation of a debugging mode ................................ R 6 - 17
6.6.4 Management of break points ..................................... R 6 - 18
6.6.5 Commands in interactive mode.................................. R 6 - 18
6.6.6 Example..................................................................... R 6 - 20
6.7 Modification and display of the current state...........................R 6 - 23
6.8 Automatic space and stack management..................................R 6 - 24

7. Extending Prolog with other languages........................................... R 7 - 1


7.1 Principles of the data transfer functions ....................................R 7 - 2
7.2 Simple data transfer functions...................................................R 7 - 3
7.2.1 Argument type test....................................................... R 7 - 3
7.2.2 Transferring simple data from Prolog to another ...................
language ...................................................................... R 7 - 4
7.2.3 Transferring simple data from an external language ..............
to Prolog...................................................................... R 7 - 6
7.3 Functions to transfer any type of term.......................................R 7 - 7
7.3.1 Using character strings................................................ R 7 - 8
7.3.2 Using array structures ................................................. R 7 - 9
7.3.2.1 Description of how a term is coded ............... R 7 - 10
7.3.2.2 Identifiers ...................................................... R 7 - 13
7.3.2.3 Description of the transfer functions ............. R 7 - 14
7.4 Principle of the descriptor method...........................................R 7 - 15
7.4.1 Descriptive elements.................................................. R 7 - 15
7.4.2 Static declaration........................................................ R 7 - 16
Descriptor table ......................................................... R 7 - 16
7.4.3 Dynamic declaration.................................................. R 7 - 17
7.5 Shared data..............................................................................R 7 - 18
7.5.1 Example of a shared data zone................................... R 7 - 19
7.6 Adding external functions .......................................................R 7 - 20
7.6.1 Example of how to define a built-in predicate............ R 7 - 21
7.7 Adding external functions using direct calls............................R 7 - 23
7.7.1 CallC primitive........................................................... R 7 - 23
7.7.2 Prolog conventions for data transfer.......................... R 7 - 24
7.7.2.1 Convention for parameters without ............................
a return value................................................. R 7 - 25
7.7.2.2 Convention for the function's return .............. R 7 - 25
7.7.2.3 Convention for parameters with .................................
a return value................................................. R 7 - 25
7.7.3 Example: a simple way to call a C function................ R 7 - 28

© PrologIA
Aociation Prolog

HERITAGE Introduction 7

8. How to launch a Prolog goal with a C program ..............................R 8 - 1


8.1 Basic theory..............................................................................R 8 - 1
8.2 Initializing Prolog .....................................................................R 8 - 4
8.3 Stacking a Prolog goal..............................................................R 8 - 6
8.4 Programming............................................................................R 8 - 7
8.5 Simple method for calling a Prolog goal...................................R 8 - 8
8.5.1. Description...................................................................R 8 - 8
8.5.2. Example .......................................................................R 8 - 9
8.6 Other functions.......................................................................R 8 - 10

9. Interruptions........................................................................................R 9 - 1
9.1 Concepts...................................................................................R 9 - 1
9.2 Description of the interfaces .....................................................R 9 - 2
9.3 Complete example.....................................................................R 9 - 3

10. Edinburgh extensions.....................................................................R 10 - 1


10.1 Syntax.....................................................................................R 10 - 1
10.1.1 General information ...................................................R 10 - 1
10.1.2 Operators ...................................................................R 10 - 2
10.2 control.....................................................................................R 10 - 3
10.3 Manipulation of rules..............................................................R 10 - 5
10.4 Predefined data operations ......................................................R 10 - 6
10.4.1 type testing rules ........................................................R 10 - 6
10.4.2 Arithmetic operations .................................................R 10 - 7
10.4.3 Composition and decomposition of objects................R 10 - 8
10.4.4 Comparing any terms...............................................R 10 - 11
10.5 Input and output....................................................................R 10 - 12
10.5.1 Introduction..............................................................R 10 - 12
10.5.2 Input.........................................................................R 10 - 14
10.5.2.1 Interpreting character strings......................R 10 - 14
10.5.2.2 Predicates...................................................R 10 - 15
10.5.3 Output......................................................................R 10 - 17
10.6 The environment....................................................................R 10 - 19
10.7 Translation of DCG ..............................................................R 10 - 20

© PrologIA
Aociation Prolog
8 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 9

Introduction

The requirements of users of Artificial Intelligence are changing. As AI programs


are industrialized, they become larger, they manipulate large amounts of data, they
communicate with other software.

In response to these demands, PrologIA offers you a new system: Prolog II+.
While maintaining the features which have made Prolog II such a success, this
product offers the following new features:
• performance levels
• modularity
• standardization
• open to the external environment
• programming environment
• graphics interface

Standardization

• Availability of a standard Mode, strongly inspired by the latest decisions


from the ISO standardization group, in the context of the ISO Prolog Standard.

Performances

• Incremental compilation. The complete transparency of this compilation


makes it possible to benefit from the speed of a compiled language, without having
to sacrifice the flexibility of an interpreted language.

• Optimization of terminal recursivity, making it possible to program iterative


processes recursively, which is the most natural strategy in Prolog, and without
causing memory overflow.

• Dynamic garbage collection in the Prolog work space (stacks, code,


dictionary). A new technique enables us to achieve better garbage collection.

• Dynamic reallocation of Prolog work space.

• Highly optimized compilation of certain predefined rules, especially


arithmetical rules.

• Infinite precision integers.

© PrologIA
Aociation Prolog
10 Reference Manual HERITAGE

Modularity

• Modularity: a new definition proposed for the standard.

• It is possible to write big programs thanks to the modules, which are


compiled separately, and can be loaded and unloaded as required.

• Run-time makes it possible to distribute stand-alone applications.

Communication with the outside world

• Two-way links with other languages: Calls can be written in Prolog to sub-
programs written in other languages. A Prolog program can be called from any
other program (even when different solutions are obtained in succession). All the
possible cross-call situations have now been provided for.

• Communication with other applications.

• Completely open data structures, with the interface needed for inter-language
communication, using all data types, with no restriction on the type of term (which,
for example, can include both variables and identifiers). It is possible to share
common zones (arrays) with other programs.

• SQL Interface between Prolog and the DBMS.

• Manipulation of large fact bases.

• Numerical data (integers and reals) is homogeneous with other languages


supported by the host system, including their extended representations.

Programming environment

• Rule manipulation (assert, clause/rule, list etc…) is integrated with the


compiler and functions on the compiled rules.

• Recovery of asynchronous interruptions in Prolog II+, allowing for example,


the management of highly interactive environments (mouse, windows, etc ...).

• High level Debugger allowing rapid preparation of big programs.

• Built-in editor coupled with the incremental compilation.

Graphics interface

• Library that is portable between various environments.

• Object definition: windows, menus, buttons, ….

© PrologIA
Aociation Prolog

HERITAGE Introduction 11

• Drawing composition.

• Dialog management.

© PrologIA
Aociation Prolog
12 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 13

About this manual

Prolog II+ documentation is contained in two volumes. The first is the Reference
Manual, which gives a precise description of the language and its uses. It applies to
all implementationsof Prolog II+ (except where specifically noted). The second
volume is the User's Manual, describing all the features which are specific to a
particular computer and its operating system. Each type of machine therefore has
its own user's manual.
To install Prolog II+ and use it, please refer to Chapters 1 and 2 of the User's
Manual.
The Reference Manual starts with an elementary introduction to Prolog and its
practical uses. The second chapter then gives a more advanced theoretical
introduction to Prolog. The following chapters deal with predefined rules
concerning program control, rule manipulation, data operations, input-output, the
environment, the debugger and the editor. The following chapters concern Prolog
II+ and communication with the external environment. We explain how to add
predefined rules written by the user, how to make cross-calls or declare shared data
zones for use by Prolog and other languges, and how to intercept interruptions and
activate a Prolog process. Finally, the last chapter describes the library of primitives
specific to the Edinburgh syntax.
As a supplement to this manual we have added some Appendices, which also apply
to all implementations. They give details about some of the topics discussed in the
Reference Manual. In particular, you will find details of the differences between the
Prolog II interpreter and the Prolog II+ compiler, and some example programs to
illustrate how Prolog can be used.
The User's Manual specifies in detail how your computer performs certain
functions described in the Reference Manual. It deals with file name structure,
saved state management, the use of the memory, and explains how to start Prolog.
The second part of this manual describes all the features which are specific to this
version; everything that has been added or removed in comparison with the basic
version, and the boundary values for constants.
The following texts are also well worth consulting:
Prolog, theoretical principles and current trends.
A. Colmerauer, H. Kanoui, M. Van Caneghem,
TSI vol 2, number 4, 1983.
Prolog
F. Giannesini, H. Kanoui, R. Pasero, M. Van Caneghem,
Addison-Wesley, 1986.
In addition, for programming in Edinburgh syntax:
Prolog Programming for Artificial Intelligence
Ivan Bratko, Addison-Wesley, International Computer Science Series, 1986.

© PrologIA
Aociation Prolog
14 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 15

Guarantee and liabilities

PrologIA offers no guarantee, tacit or explicit, concerning either this manual or the
software described, its qualities, performance or its suitability for any application
whatsoever.

PrologIA cannot be made liable for damage of any sort, whether direct or indirect,
resulting from a fault in the program or the manual, even if the company has been
advised that such damage might occur. In particular, PrologIA cannot take
responsibility for data memorized or used; this includes costs of recovery or
duplication of such data.

Nevertheless, the purchaser is entitled to the statutory guarantee, in such cases, and
to the extent to which the statutory guarantee is applicable, notwithstanding any
exclusions or limitations.

Copyright

This manual and the software it describes are protected by copyright. According to
the legislation concerning these rights, this manual and software must not be copied
or adapted, either wholly or in part, without the written consent of PrologIA, except
within the bounds of normal use or to create a back-up copy. However, these
exceptions do not authorize the user to create copies to be used by a third party,
regardless of whether or not they are to be sold.

Prolog II is a registered trademark of PrologIA.

© PrologIA
Aociation Prolog
16 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

0. Getting started

0.1 Lesson 1 : Starting a Prolog session


0.2 Lesson 2 : An example program
0.3 Lesson 3 : Using the editor
0.4 The most frequent errors

In this manual's examples, user input is written in italics teletype


characters, and computer output is written in normal teletype
characters.

0.1 Lesson 1 : Starting a Prolog session

To begin this lesson, we will start a simple Prolog session by typing:


$ prolog

which starts Prolog with an initial (empty) state called initial.po. The character "$"
is the system prompt. The character ">" is the Prolog prompt. The various
different ways of starting Prolog are described in the User's Manual.

In our case, the screen displays the following:


Prolog II+ Version ...
Code : ...
>

The character ">" informs you that you are in the Prolog environment and that the
interpreter is waiting for a command.

To get started, let us try a simple command, to print the message "Hello World":
> out("Hello World") line;
"Hello World"
{}
>

Now, let us try our first small program. To do this, we first get into insertion mode
( insert command). The system is now ready to read rules (or comments) and will
compile them in memory as they are read.Here, we enter three rules asserting that
Peter, John and Mary live respectively in Paris, Marseille and Paris :
> insert;
live_in(Peter,Paris) ->;
live_in(John,Marseille) ->;
live_in(Mary,Paris) ->;;
{ }
>
Aociation Prolog
R 0 - 2 Reference Manual HERITAGE

Note that every rule is terminated by the character ";" and that the insertion is
terminated by an additional ";". Rules are inserted in the order they are entered.
This can be checked by typing the command list (which displays rules in the current
module).
> list;

live_in(Peter,Paris) ->;
live_in(John,Marseille) ->;
live_in(Mary,Paris) ->;

{ }
>

We can now ask some questions : Where does Peter live ?


> live_in(Peter,x);
{ x=Paris}
>

Who lives in Paris ?


> live_in(x,Paris);
{ x=Peter}
{ x=Mary}
>

Who lives where ?


> live_in(x,y);
{ x=Peter, y=Paris}
{ x=John, y=Marseille}
{ x=Mary, y=Paris}
>

Every time, the system's answer is the set of values to be given to the variables
appearing in the question in order to satisfy the corresponding relation. To
terminate the session, type the command :
>quit;
Bye......
$

which brings you back to the command interpreter of the system.

0.2 Lesson 2 : An example program

This example uses the menu.p2 program frequently described in Prolog literature.
This program is in the examples directory of your Prolog II+ Kit. For this lesson,
you must first copy menu.p2 into your current directory. Then start Prolog as
explained in the previous section, and insert menu.p2 by typing:
$ prolog
PROLOG II+ ...

> echo insert("menu.p2");

© PrologIA
Aociation Prolog

HERITAGE Getting started R 0 - 3

insert reads rules on the file specified, and inserts them in the current module.
When the input file has been read, the current input switches back to the keyboard,
which is the default input unit. The echo primitive displays the rules at the console
as the file is read:
" the menu "
hors_d_oeuvre(Artichauts_Melanie) ->;
hors_d_oeuvre(Truffes_sous_le_sel) ->;
hors_d_oeuvre(Cresson_oeuf_poche) ->;
meat(Grillade_de_boeuf) ->;
meat(Poulet_au_tilleul) ->;
fish(Bar_aux_algues) ->;
fish(Chapon_farci) ->;
dessert(Sorbet_aux_poires) ->;
dessert(Fraises_chantilly) ->;
dessert(Melon_en_surprise) ->;
" main_course "
main_course(p) ->meat(p);
main_course(p) ->fish(p);
" composition of a meal "
meal(e,p,d) ->hors_d_oeuvre(e)
main_course(p) dessert(d);
" calorific value for a portion "
calories(Artichauts_Melanie,150) ->;
calories(Cresson_oeuf_poche,202) ->;
calories(Truffes_sous_le_sel,212) ->;
calories(Grillade_de_boeuf,532) ->;
calories(Poulet_au_tilleul,400) ->;
calories(Bar_aux_algues,292) ->;
calories(Chapon_farci,254) ->;
calories(Sorbet_aux_poires,223) ->;
calories(Fraises_chantilly,289) ->;
calories(Melon_en_surprise,122) ->;
" calorific value of a meal "
value(e,p,d,v) ->
calories(e,x)
calories(p,y)
calories(d,z)
sumof(x,y,z,v);
" balanced meal "
balanced_meal(e,p,d) ->
meal(e,p,d)
value(e,p,d,v)
smaller(v,800);
" miscellaneous "
sumof(a,b,c,d) ->
val(add(a,add(b,c)),d);
smaller(x,y) ->val(inf(x,y),1); ;
{ }
>

© PrologIA
Aociation Prolog
R 0 - 4 Reference Manual HERITAGE

Let's try this program out: what are the main courses ?
> main_course(p);
{ p=Grillade_de_boeuf}
{ p=Poulet_au_tilleul}
{ p=Bar_aux_algues}
{ p=Chapon_farci}

What are the hors-d'oeuvres?


> hors_d_oeuvre(x);
{ =Artichauts_Melanie}
{ =Truffes_sous_le_sel}
{ =Cresson_oeuf_poche}

This lesson stops here and we save the current module "" (module with the prefix
""), by typing:
> save([""],"menu.mo") quit;
Bye........

This saved state will be used in the next lesson.

0.3 Lesson 3 : The editor

The purpose of this lesson is to show how to use Prolog's built-in editor very
simply, to manipulate a group of rules. On machines which have a window
environment and a mouse, copy/paste, may be easier.

First, start Prolog and load the saved module containing the menu.p2 program,
assuming it has been saved with save:
...
> load("menu.mo");
{}
>

If exit was used to leave the file, Prolog is started with the saved state containing the
menu.p2 program, as we left it at the end of the previous lesson:
....
>

Let us suppose we want to change the menu, and replace the rules below:
a meat(Grillade_de_boeuf) ->;
b meat(Poulet_au_tilleul) ->;

with:
c meat(Veau_marengo) ->;
d meat(Poulet_roti) ->;

Start by calling the editor:


> edit(meat/1);

© PrologIA
Aociation Prolog

HERITAGE Getting started R 0 - 5

where the notation meat/1 denotes the group of rules concerning the relation meat
applying to 1 argument.

This activates the editor, which displays the rules that define the meat relation. You
can now perform the modifications as desired, and leave the editor. You should
check that Prolog has re-read the new definitions:
> list(meat/1);
meat(Veau_marengo) -> ;
meat(Poulet_roti) -> ;
{}

You can now execute the modified program, and we end with quit since we do not
want to keep the current state.
> meat(p);
{ p=Veau-Marengo}
{ p=Poulet-roti}
> main-course(p);
{ p=Veau-Marengo}
{ p=Poulet-roti}
{ p=Bar-aux-algues}
{ p=Chapon-farci}
> quit ;
Bye .......

0.4 The most frequent errors

This section explains some of the most frequent errors which may occur when
using Prolog II+.

0.4.1 Code overflow.

CODE OVERFLOW
Prolog must be re-started with more space for the code (option -c on the command
line). If the automatic reallocation system is not deactivated when Prolog starts, a
certain number of reallocations will occur before overflow, and the code will then
take up all the space available on the Prolog machine. In this case, you must if
possible increase Prolog’s total memory, or else verify the functioning of the
program, which is doubtless abnormal.

0.4.2 Interruption.

Program execution can be interrupted at any time with an interruption character


(often <Control-C> <return>).

© PrologIA
Aociation Prolog
R 0 - 6 Reference Manual HERITAGE

> insert;
rr -> rr;;
{}
> rr;
<Ctrl-C>
USER INTERRUPT
{}
>

0.4.3 Errors identified during insertion

RULE ALREADY DEFINED

This error occurs because the user has violated the following principle: all rules
having the same name and arity must be consecutive (two rules having the same
name/arity cannot be separated by a comment or a rule with a different name/arity).
The configurations given below are therefore incorrect .
qq(x) -> ;
rr(y) -> ;
qq(z) -> ;

because the rule rr is wrongly placed.


WARNING. This error will not occur if you use the reinsert or insertz primitive,
because it overwrites or completes the existing group of rules with this group's new
definition. In particular, using reinsert in the case described above no error will
occur and the group of qq access rules will contain only the last rule.

0.4.4 File errors

EOF ON INPUT FILE


This is a warning rather than an error message. It advizes that reading of the input
file is completed. Input switches back automatically to the keyboard.

ERROR IN OPENING FILE


Advizes that the file does not exist or that access to it is impossible The command
can simply be reiterated once the necessary corrections have been performed.

0.4.5 Syntax errors

The meanings of most of the syntax error messages are clear. If necessary, please
refer to the syntax specifications in Chapter 1 for additional explanations.
Explanations of some of these messages are given below.

UNIT BADLY PLACED


> insert;
main-course(x) ->meat(,beef);;
-> "," : UNIT BADLY PLACED

© PrologIA
Aociation Prolog

HERITAGE Getting started R 0 - 7

This error message shows where the syntax was not respected. In this case, an
argument is missing.

" MISSING AT THE END OF THE STRING


> insert;
meat("beef
-> " MISSING AT THE END OF THE STRING

A string must be contained on one line only, if the line is not hidden. Remember
that a string starts and finishes with the character ("). If (") is part of a string, it
must be doubled.

THIS TERM CANNOT BE A RULE HEAD


> insert;
p(x) ->;;
-> v41(v60) : THIS TERM CANNOT BE A RULE HEAD

The only correct access to a rule is an identifier starting with two letters in Prolog II
syntax. Therefore, the head cannot be a variable (whose name starts with only one
letter) a number or a string.

Remember that the name of a variable, a relation or a constant is a sequence of


words separated by a "_" and that it is possible to terminate it with one or more
apostrophes, if so desired. A word is made up of one or several letters possibly
followed by digits.

If the first word of the name starts with at least two letters, it is the name of a relation
or a constant (this is called an identifier in the Prolog II syntax) and it is a correct
access to a rule. If not, it is the name of a variable. For example :

x, x12, x_toto_a25, a', a12'', b_titi''

are names of variables.

bonjour, xx'', qq_toto_25, ww2'_i, how_are_you, 'with some blanks'

are names of relations or constants.

0.4.6 Execution errors

THIS TERM CANNOT BE A GOAL

The following example uses the rule: exec(p) ->p ;


> exec(outm("hello"));
hello{ }
>

The variable p in the exec rule is replaced by outm("hello") which is executed


without any difficulty. But:
> exec(x);

© PrologIA
Aociation Prolog
R 0 - 8 Reference Manual HERITAGE

-> THIS TERM CANNOT BE A GOAL


>

causes an error because the variable p is free when execution is attempted.

BAD ARGUMENT TYPE


This error occurs when the user attempts to execute a built-in predicate with one
argument of an unexpected type. The relevant argument is usually displayed with
the message.

CALL TO AN UNDEFINED RULE


The system is attempting to execute an undefined rule while in error mode (flag uE).
To make the execution fail on purpose, use the predefined rule fail.

There are several possible results, defined by a flag in the Prolog start-up command,
when execution of an undefined predicate is attempted:
uW : displays a warning and continues program execution,
uF : fails,
uE : generates the error.

The other execution error messages related to the use of block, block_exit, and val
need no explanation.

We recommend that you start Prolog with the -f uE option, which provides a precise
diagnosis when an incorrect call is made to a rule which does not exist (caused by a
typing error for example). If you want to call a rule, and cause a failure if it does
not exist, first test that it is present, with current_predicate.

© PrologIA
Aociation Prolog

HERITAGE

1. The basic elements


1.1 Notation
1.2 The set of characters
1.3 Variables
1.4 Constants
1.5 Terms and trees
1.6 Operators
1.7 Rules and specified facts
1.8 General mechanisms of Prolog
1.9 Complete syntax of Prolog II+
1.10 The macro processor

1.1 Notation
In this manual, context free rules will be used to describe the syntax of the formulas
occurring in Prolog. The notation used here is the same as that adopted by the
Prolog standardization commission:

• Non-terminal symbols are represented by identifiers and terminals are in double


quote marks "…".

• The symbol "=" is used as the rewrite symbol, and a rule ends with a ";". The
elements of the right member of a rule are separated by ",".

• Elements enclosed by curly brackets {…} may occur any number of times
(including zero).

• Elements enclosed by square brackets […] are optional.

• A vertical bar …|… signifies that the two elements it separates are alternatives.
When brackets are used (…|…), this means that the result of the alternative
appears in a list of symbols.

• A dash "-" is used to indicate exceptions.

• The functioning of some re-writing rules depends on which syntax options have
been selected: rule whose first member is indexed by P are only activated if the
Prolog II syntax is selected (for example separator P ). Rules whose first
member is indexed by E are only activated if the Edinburgh syntax is selected
(for example graphic_charE).

• Other rules indexed by letters control options chosen at start-up, and are only
valid in certain cases.

©PrologIA
Aociation Prolog
R1-2 Reference Manual HERITAGE

The complete Prolog syntax is given at the end of this chapter. The following pages
contain some fairly simple extracts from this syntax, with explanatory comments.

1 . 2 The set of characters


The user can choose from two sets of characters; the set defined by ISO code 8859-
1 (see Appendix), or the set available on the host machine (see User's Manual). In
this manual we will only describe the ISO set. If the host set is chosen this will
augment or reduce the sub-sets letter and graphic_char with characters not existing
in the ISO set (see U3-2).

Below is a simple description of the characters needed in Prolog. The complete


description is in Section 1.9.

letter = "A" | … | "Z" | "a" | … | "z"


| "À" … "ß" - "" | "à" … "ÿ" - "÷"
letterI = "\", accent_escape ;

digit = "0" | … | "9" ;


alpha = letter | digit | "_" ;
separator = "(" | ")" | "[" | "]" | "{" | "}" |
"|" | "," ;
separatorP= ";" | "." | "<" | ">" ;

special_char= "%" | "'" | """ | "_" | "!" | "`" ;


special_charE= ";" ;

graphic_char = "#" | "$" | "&" | "*" | "+" | "-" | "/" | ":"


| "=" | "?" | "\" | "@" | "^" | "~"
| NBSP1 … "¿" | "" | "÷" ;
graphic_charE = "." | "<" | ">" ;

character = letter | digit | separator | graphic_char | special_char


;

The following changes can be made without altering meaning:


- spaces can be inserted anywhere except inside constants and variables;
- spaces can be removed anywhere except from strings and except if their
removal causes the creation of new constants or variables by juxtaposing
together old ones;

1Non Breaking SPace.

©PrologIA
Aociation Prolog

HERITAGE The basic elements R1-3

There are several ways of inserting comments into a program. From the syntactical
point of view, a comment is identical to a space, and can be inserted anywhere a
space is permitted:

• The character "%" indicates the beginning of a comment which starts at the "%"
and finishes at the end of the same line.

• The symbols "|*", "*|" and "/*", "*/" are also used to denote a comment, which
consists of these symbols and the characters they enclose.

These symbols are not interchangeable. If a comment starts with a "|*" it must end
with a "*|" and if it starts with a "*/" it must end with a "/*". In addition, these
comments can be nested: for example the following text is regarded as being a
single comment:

|* second com- |* first comment *| ment *|

• A character string written at the higher level, i.e. where a rule is expected, is also
taken to have the value of a comment.

1 . 3 Variables
Variables are used to denote constants as well as more complex entities. Here is
their syntax:

variable = "_" , {alpha} ;


variable = extended_var ;

extended_var P = letter, [ (digit | "_"), {alpha} ], { "'" } ;


extended_var E = big_letter, [ {alpha} ] ;

So, for variables, there is a basic syntax and an extended syntax, of which there are
two: Prolog II or Edinburgh. When starting Prolog II+ you must indicate whether
you wish to use a different syntax from the extended Prolog II syntax. In addition,
since these two syntaxes are incompatible,2 it is not possible to have both extensions
at the same time.

2In Prolog II, the expression x is a variable, but not in Edinburgh Prolog. Similarly, the name
Pierre is not a variable in Prolog II, but it is in Edinburgh!

©PrologIA
Aociation Prolog
R1-4 Reference Manual HERITAGE

Here are some examples of correct variables :

Prolog II syntax Edinburgh syntax


x X
x' X_12_plus
x' ' Prix
x12 _prix
p_rix X1Y2
y33' _33
y_en_a'
_prix
_123

and some examples of expressions which are not correct variables:

Prolog II syntax Edinburgh syntax


ph X'
xx x12
prix prix
1er_x y_en_a

1 . 4 Constants
The simplest data items are constants. There are four types: identifiers, integers, real
numbers and character strings.

identifier = prefix , prefix_limit , abbreviated_id ;


identifier = abbreviated_id ;

identifierE = prefix , prefix_limit ,


"'", graphic_symbol, "'" ;
identifierE = graphic_symbol ;

abbreviated_id = name - extended_var ;


abbreviated_id = "'", { (character - "'") | "'""'" }, "'";

prefix_limit = ":" ;
prefix = [ name , { prefix_limit , name } ] ;

name = letter , { alpha } ;

integer_number = digits ;
integer_number = "0b", binary_number ;
integer_number = "0o", octal_number ;
integer_number = "0x", hex_number ;
integer_number = "0'", character ;

©PrologIA
Aociation Prolog

HERITAGE The basic elements R1-5

real_number = digits, ".", digits, ("E"|"e"|"D"|"d"),


[ ["+"|"-"], digits];
real_numberS = digits, ".", digits,
[ ("E"|"e"|"D"|"d"), [ ["+"|"-"],digits]
];

binary_number = binary_digit , { binary_digit } ;

octal_number = octal_digit , { octal_digit } ;

hex_number = hex_digit , { hex_digit } ;

digits = digit , { digit } ;

string = """ , { quoted_char } , """ ;

quoted_char = character - ( """ | "\" | newline) | """" ;


quoted_chari0 = "\" ;
quoted_chari1 = "\", format_escape ;

format_escape = "b" | "f" | "n" | "r" | "t" | "\" | newline |


octal_digit, octal_digit, octal_digit |
("x" | "X"), hex_digit, hex_digit ;

Identifiers

Identifiers have two external representations: a complete representation and an


abbreviated one. The former includes a prefix specifying the family to which the
identifier belongs; in the abbreviated representation, the prefix does not appear, but it
is specified with complete unambiguity by certain reading-writing conventions.
These concepts are explained in full in Chapter 3.

The presence of the character ":" indicates that the representation of the identifier is
complete. This character can be redefined and replaced by a graphic character, as
described in Chapter 3.

The following complete identifiers are correct and all represent different identifiers:
data:peter grammar:singular
x:peter lexicon:name
sys:write sys:env:files
:peter grammar:plural

Please note: the empty string is a valid prefix, and thus the identifier :peter is
syntactically correct.

The following identifier is not complete


peter

©PrologIA
Aociation Prolog
R1-6 Reference Manual HERITAGE

The syntaxes for abbreviated representation of identifiers and for variables are very
similar, and together they define what is referred to as an "identifier" in many other
programming languages. To help distinguish between them, it is useful to
remember that in the Prolog II syntax, variables start with one letter or the character
"_", whereas the abbreviated representations of identifiers start with at least two
letters. In the Edinburgh syntax they are differentiated by the first character; for
variables it must be upper-case or the "_" character, and for abbreviated
representations of identifiers it must be lower-case.

Here are some examples of correct abbreviated identifiers:

Prolog II syntax Edinburgh syntax


apple i10
apple’ apple
apple12 ***
§

and some examples of incorrect identifiers (in the Prolog II syntax):

Prolog II syntax Edinburgh syntax


x Apple
1st_rabbit 1st_rabbit
a_go_go apple’
here's_harry

Numbers

The syntax for numbers in Prolog II+ is virtually the same as in most other
programming languages.

Integers are signed and are normally used to represent any value. Prolog II+ accepts
several integer syntaxes.

An integer can be expressed in the following bases: 2, 8, 10, 16. To do this, the
integer mantissa must be preceded by 0b, 0o, 0, 0x respectively. A non-prefixed
mantissa will be considered as decimal base by default. Small integers less than
256 can also be expressed using the prefix 0' followed by a character, and the
integer value will then be the character code3 . For example, the following
expressions represent integers:

3 Be careful with extended characters. Their value depends on the chosen mode: ISO 8859-1 or
the host machine code.

©PrologIA
Aociation Prolog

HERITAGE The basic elements R1-7

Expression: Value:
0b110 6
0o110 72
0110 110
0x110 272
0'A 65

It should be noted, that in contrast to other languages, real numbers must include an
explicit exponent. Therefore the expression -12.34 does not define a real number,
but a pointed pair formed by the integers -12 and 34. On the other hand, 12.34e0 is
a correct real. This is the default choice in Prolog II syntax, but it can be modified
via an option on the command line at start-up, to obtain a standard syntax (see
section 2.3 of the User's Manual).
Reals are encoded in double precision, corresponding to the double type in the IEEE
64 bits standard. The letter introducing the exponent can be e, E, d or D, but e and E
are preferable.

Character strings

Character strings are enclosed by double quotes """. All the printable characters
can appear in a string without any special precautions, except for the """ character
which must be doubled, and if appropriate the "\" character which must be doubled
if interpretation of "\" is active (see the behavior options in section U 2.3.). For
example, the string below is correct:

"please handle "" and \\ with caution"

In general, the "\" does not necessarily have to be doubled. When interpretation of
"\" is active (see section 2.3 of the user's manual), it must be doubled if it forms an
expression (escape sequence) representing another character, with the characters that
follow it. In all other cases there is no need to do so.
"Use \ followed by RETURN to ignore an end of line
"Hexadecimal codes must start with \\x"

When interpretation of "\" is active (rules denoted by i1), several expressions


starting with "\" can be used to represent a character.

The following expressions make it possible to specify certain non-printable


characters in the definition of a string :
\b backspace

\f form feed
\n newline. When this character is written, if necessary it is replaced by the
character(s) required to produce a new line on the output unit.
\r carriage return
\t tabulation

©PrologIA
Aociation Prolog
R1-8 Reference Manual HERITAGE

Other expressions can be used to represent characters not existing on the host
machine (see section 1.9.5).

Any character in a string can be specified by means of the number which is its
internal code. For example, the expressions "\033" and "\x1B" both define a string
consisting of a single character whose code is 27. The null character (i.e. the
character whose internal code is the number 0) must not appear in character strings.

A character string can take up several lines. To do this, the last character on each
relevant line except the last one must be "\". The "\" and the end of line character
will be ignored. For example, the expression:

"this is a stri\
ng on two lines"

defines the same string as "this is a string on two lines".

Please note: When writing a Prolog program, a symbolic data item can be
represented either by a character string, or by an identifier. Since identifiers are
themselves coded as atomic objects, it is generally agreed that they constitute a more
efficient representation of symbolic objects than strings.

1 . 5 Terms and trees


All data items manipulated in Prolog are trees, which may be infinite. First of all let
us describe these trees informally as follows:

They are formed by nodes which are labeled:

• either by a constant, in which case there are no sons,

• or by the character "period" in which case there are exactly two sons,

• or by " <>" or "<->" or " <-\ ->" or " <-\ -\ ->" or … where the number of dashes
corresponds to the number of sons.

Here are two examples of finite trees:

• <--->
/ \ / | \
"a" • ___/ | \____
/ \ / | \
"b" • plus <---> <--->
/ \ / | \ / | \
"c" nil times 5 8 times 5 8

Figure 1.1

©PrologIA
Aociation Prolog

HERITAGE The basic elements R1-9

Figure 1.2 is an example of an infinite tree.

<--->
/ | \
or "c" <--->
/ | \
and "a" <--->
/ | \
and <---> "b"
/ | \
or "c" <--->
/ | \
and "a" <--->
/ | \
and <---> "b"
/ | \
or "c" <--->
/ | \
and "a" <--->
/ | \
and <---> "b"
/ | \
Figure 1.2

The drawing of trees can be simplified as shown in figure 1.3.

identifier instead of <--- ... ->


/ | | \ / | | | \
x1 x2 ... xn identifier x1 x2 ... xn
Figure 1.3

Of course, this simplification presupposes that n is not zero. The last two trees can
therefore be represented in standard form as:

plus or
/ \ / \
times times "c" and
/ \ / \ / \
5 8 5 8 "a" and
/ \
or "b"
/ \
"c" and
/ \
"a" and
/ \
or "b"
/ \
"c" and
/ \
"a" and
/ \
or "b"
/ \
Figure 1.4

©PrologIA
Aociation Prolog
R 1 - 10 Reference Manual HERITAGE

The notion of an infinite tree is sufficiently new (and therefore unfamiliar) to justify
spending some time clarifying this concept. Basically, a tree is infinite if it
possesses an infinite branch. We are especially interested in those infinite trees
which, together with finite trees, form the set of rational trees, that is trees whose
set of subtrees is finite. Look again at the last two examples in figure 1.4. The set
of their subtrees is given in figure 1.5.

{ <---> , <---> , plus , times , 5 , 8 }


/ | \_____ / | \
/ | \ times 5 8
plus <---> <--->
/ | \ / | \
times 5 8 times 5 8

{ <--->, <--->, <--->, or,and,"a","b","c"}


/ | \ / | \ / | \
or "c" <---> and "a" <---> t <---> "b"
/ | \ / | \ / | \
and "a" <---> and <---> "b" or "c" <--->
/ | \ / | \ / | \
and <---> "b" or "c" <---> and "a" <--->
/ | \ / | \ / | \
or "c" <---> and "a" <---> and <---> "b"
Figure 1.5

These sets are finite and so the trees in figure 1.4 are rational trees. Since a rational
tree contains a finite set of subtrees we can represent it using a finite diagram:
which merges all the nodes which produce the same subtrees (figure 1.6).

Figure 1.6

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 11

If we do not merge all the nodes, we obtain figure 1.7.

Figure 1.7

We must therefore be very careful, because different diagrams can represent the
same tree.

In order to represent trees we use formulas called terms. First, let us examine the
concept of a strict term:

strict_term = variable | identifier | constant


| "[]"
| "< >" ;
strict_termP = | "(", strict_term, ".", strict_term, ")"
strict_termE = | "[", strict_term, "|", strict_term, "]"
strict_termP = "<", strict_term , { "," , strict_term } , ">" ;
strict_termE = "<>(", strict_term , { "," , strict_term } , ")" ;

Strict terms are "true" terms. However, for the sake of convenience, we will extend
the syntax of strict terms (without altering their meaning) by permitting:

•P The addition and removal of parentheses, with the convention that:


t1.t2.…tn represents (t1.(t2.(… .tn) ));

•E The addition and removal of brackets, with the convention that:


[t1,t2,…,tn] represents [t1 | [t2 | …[tn | [] ] ]] and
[t1,t2,…,tn| t] represents [t1 | [t2 | …[tn | t] ]];

• The writing of: id(t1,t2,...,tn) instead of <id,t1,t2,...,tn>, on condition that id is


an identifier and n is not 0.

This leads to a more general concept of a term :


love(Peter.Paul.John.nil,father_of(x))

©PrologIA
Aociation Prolog
R 1 - 12 Reference Manual HERITAGE

and the corresponding strict term is:


<love,(Peter.(Paul.(John.nil))),<father_of,x>>

To transform a term into a tree, it is necessary to assign trees to its variables. This
operation is called tree assignment, which is a set X of the form:

X={x1:=x1, x2:=x2, …}

where the xi's are distinct variables and the ri's are trees. We also introduce the
following notations: if x1,x2 are two trees and if ri,r2,…,rn is a sequence of n trees
then (x1.x2) and <ri,r2,…,rn> denote respectively the trees:

• <-- ... ->


/ \ / | \
R 1 r2 R 1 r2 rn
Figure 1.8

If t is a strict term containing a subset of the set of variables of the tree assignment X
= {x1:=r i, x2:=r 2, …} then the expression t/X will denote the tree obtained by
replacing the variables xi by the corresponding trees ri. More precisely:

- t/X = ri if t = xi ;

- t/X = value of k if t is the constant k;

- t/X = (t1/X.t2/X) if t = (t1.t2);


- t/X = [t1/X | t2/X)] if t = [t1 | t2] ;

- t/X = <t1/X,…,tn/X> if t = <t1,...,tn>.


- t/X =<>(t1/X, … , tn/X) if t = <>(t1, … , tn).

If t1 and t2 are terms, then the formulas t1 = t2 and t1  t2 are respectively an


equation and an inequation A set S of such formulas is a system (of equations and
inequations). The tree assignment X is called a solution of the system:

S = {p1=q1, p2=q2, …}  {s1  t1, s2  t2, …}

if X contains the same variable as S and if X is such that the trees pi/X are
respectively equal to the trees qi/X and that the trees si/X are respectively different
from the trees ti/X.

Using these concepts it is now possible to represent the first tree in figure 1.1 by:

("a"."b"."c".nil)/{} or ["a","b","c"] / {} depending on the chosen syntax

the second tree in figure 1.1 by:

plus(times(l2,l1),times(l2,l1)) /{} or

plus(x,x)/X, with X solution of {x=times(l2,l1)},

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 13

and the tree in figure 1.6 by:

x/X, with X solution of {x=or("c",and("a",and(x,"b")))}.

1 . 6 Operators
The operators represent a clear and flexible way of expressing certain trees.

For example, although the internal representation of the term


(mul(sub(5,3),add(5,3)) is the same as for (5 - 3) * (5 + 3), the second expression
is obviously easier to read than the first.

The syntax of expressions written using the operators is as follows:

exprn = prefix_opn,d , exprd ;


exprn = exprg , postfix_opn,g ;
exprn = exprg , infix_opn,g,d , exprd ;
exprn = expr n-1 ;
expr0 = pterm ;

prefix_opn,d = identifier | graphic_symbol ;


postfix_opn,g = identifier | graphic_symbol ;
infix_opn,g,d = identifier | graphic_symbol ;

1 . 7 Rules and specified facts


From a theoretical point of view, a Prolog program defines a subset A of the set R
of trees. The elements of A are called specified facts and, in general, we can
associate a declarative sentence with each of them. Figure 1.9 gives some examples
of such associations. The set A of specified facts is generally infinite and, in a
manner of speaking, forms an immense database. We will see later that the
execution of a program can be seen as a consultation of part of this database. Of
course this database cannot be stored in explicit form. It must be represented by a
finite amount of information which is sufficient to deduce all the information
contained in the database. To do this, the set A of facts is defined by a finite set of
rules of the form:
t0 -> t1 … tn
where the number n can be zero and where the ti's are terms.

©PrologIA
Aociation Prolog
R 1 - 14 Reference Manual HERITAGE

is_son_of for « Jack is Mary's son»


/ \
Jack Mary

plus for « 2 and 2 make 4 »


/ | \
suc suc suc
| | |
suc suc suc
| | |
0 0 suc
|
suc
|
0

infinite_sequence for « 1 1 1 ... is an infinite sequence »


|

/ \
1 •
/ \
1 •
/ \
1 ...
Figure 1.9

Below is a simplified version of the rule syntax:4

3.1 ruleE = term , "." ;


3.2 ruleE = term , ":-" , term { "," , term }, "." ;
3.3 ruleP = term , "->", { term }, ";" ;

The following restriction is very important:

The term which is the first member of a rule (rule head) must be:
- either an identifier
or
- a tuple whose first argument is an identifier

For example, the terms: go,father_of(x,y) or <father_of, x, y> can be correct rule
heads, while - contrary to what happens in Prolog II - terms such as <<father_of,
x>, y> or <masc.sing, x, y> cannot.

For the moment, we will ignore the concept of a parasite which, as we will see later,
is an ad hoc way of calling subprograms not written in Prolog.

4The complete rule syntax is given in the last section of this chapter.

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 15

Rules of the form:


t0 -> t1 …tn

generate a set (usually infinite) of particular rules which operate on the following
trees:
t0/X  t1/X … tn/X

These rules are obtained by considering all possible tree assignment containing the
variables of the generating rule:
X = {x1:=s1,… ,xm:=sm}

Each of these particular rules:


r0  ri … rn

can be interpreted in two ways:

(1) as a rewrite rule:


r0 can be rewritten as the sequence ri… rn,
and thus, when n=0, as:
r0 can be executed.

(2) as a logical implication applying to a subset of trees A:


ri, r2, … and rn elements of A, implies r0 an element of A.
In this case, if n=0, the implication reduces to:
r0 an element of A.

Depending on which of these interpretations we take, specified facts can be defined


as follows:

Definition 1: The specified facts are the trees that can be executed in one or more
steps by means of the rewrite rules.

Definition 2: The set of specified facts is the smallest subset A of trees which
satisfy the logical implications.

It can be shown that the smallest set of Definition 2 exists and that Definitions 1
and 2 are equivalent.

1 . 8 General mechanisms of Prolog


We have now discussed the implicit information contained in a Prolog II program,
but we have not shown how a Prolog program executes. This execution aims to
solve the following problem:

Given a set of rules which is a recursive definition of a set A of particular trees


called the facts.

©PrologIA
Aociation Prolog
R 1 - 16 Reference Manual HERITAGE

Given a sequence of terms T 0 = t 1 … t n and the set of its variables


{x1,… ,xm}.

Find all the tree assignments X={x1:=ri,… ,xm:=rm} for which the trees t1/X,…
,tn/X are facts.

To solve this problem the computer produces all the derivations of the form:

(T0,S0)  (T1,S1) (T2,S2) …

The Ti's are sequences of terms called goals and the Si's are systems of equations
and inequations having at least one solution. S0 is the empty system: { }. The
derivation (Ti,Si)  (Ti + 1,Si + 1), is best explained by the following three lines:

(1) (q0 q1 … qn , S)

(2) p0 -> p1 … pm

(3) (p1 … pm q1 … qn , S  {q0=p0})

The first line represents the form of the current pair (Ti,Si), the second, the rule
which is applied and the third, the resulting pair (Ti + 1,Si + 1). Before applying the
rule it is necessary to rename its variables so that none of them occur in (Ti,Si). It
is also necessary to check that the new system Si + 1, which is obtained by adding
the equation {q 0 =p 0 } to S i', has at least one solution. This check is called
unification of q0 with p0.

The purpose of the previously defined derivations is to compute the pairs (Tj,Sj)
whose Tj sequence is empty and which can therefore be derived from (T0,{}). It
can be shown that the tree assignments X which solve Sj are the answers to our
problem. The result printed by the computer is a simplified form of the system Sj in
which inequations are omitted.

It can be shown that Prolog II+ checks perfectly whether a system of equations and
inequations has at least one solution.

From a more practical point of view, when Prolog is called, the computer displays
the prompt ">", meaning that Prolog is waiting for a sequence of goals T0=t1 … tn.
It will try to execute these goals in every possible way ((T0,{}) …  (Tj,Sj)with Tj
empty), and will then print the corresponding systems S j. Just as we have a
constraint on rules, we also have the following constraint on goals.

At each step, the leftmost branches of the trees representing the goal to be
executed must be represented by an identifier.

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 17

Parasites provide Prolog with the use of external subprograms. To explain how
these subprograms are called we have to go back to the first of the three lines which
describe the general mechanism of Prolog: if q0 is a parasite, then instead of trying
to apply a rule, the system will execute the corresponding subprogram. Some
parasites appear in the predefined rules which create the interface between external
sub-programs and Prolog rules. This set of predefined rules constitutes a complete
programming environment allowing the user to perform the tasks described below.

• To control and to modify program execution (see Chapter 2 - Control of


program execution);

• To structure and modify the set of rules which constitutes the current Prolog
program (see Chapter 3 - Structuring and modifying rules);

• To have access to standard arithmetical functions and string processing (see


Chapter 4 - Predefined data operations);

• To manage input and output (see Chapter 5 - Input and output);

• To communicate with the host system (see Chapter 6 - The environment).

The programmer can also introduce an additional set of predefined rules referring to
his own parasites written in a language other than Prolog (C, Fortran, Pascal, …).
(see chapter 7 "Extension with external languages" or Appendix D "Adding external
rules (parasite method)".

Two predefined rules are directly related to the fundamental mechanism of Prolog:
dif and eq.

dif is the most important one. It introduces an inequation into a system of equations
and inequations. More precisely, the execution of dif(x,y) adds the inequation x  y
to Si and checks that this new system Si +1 still has a solution.

eq introduces an equation in a similar manner.

eq(x,x) ->;

The following rules are not exactly predefined rules, but the Prolog system behaves
as if these rules exist. They are use to transform a list of goal into a single goal.

p.q-> p q ;
nil -> ;

1 . 9 Complete syntax of Prolog II+


This section gives the complete syntax of Prolog II+, together with some examples
and additional comments. The notation used is that of the Prolog standardization
committee (please see the first section of this chapter).

©PrologIA
Aociation Prolog
R 1 - 18 Reference Manual HERITAGE

1.9.1 The syntactic level


1 program =  rule | directive  ;
2.10 directiveP =7 "->",  pterm , ";" ;
2.21 directiveE =7 ":-", expr1199 , "." ;
3.10 ruleP = term , "->",  pterm , ";" ;
3.21 ruleE = term, "." ;
4.1 termP = expr1000 , [ "." , term ] ;
4.2 termE = expr1200 ;
5 termlist = expr999,  "," , expr999  ;
6.12 exprn = prefix_opn,d , exprd ;
6.2 exprn = exprg , postfix_opn,g ;
6.3 exprn = exprg , infix_opn,g,d , exprd ;
6.42 exprn = exprn-1 ;
6.5 expr0 = pterm ;
7.1 pterm = ( identifier | variable ) , [ "(" , termlist , ")"];
7.23 pterm = ( identifier | variable ) , "[" , term , "]";
7.3 ptermP = "<", termlist , ">" ;
7.44 pterm = "< >", [ "(", termlist ,")" ];
7.55 pterm = "", termlist , "" ;
7.66 pterm = "[" , listexpr , "]" | "[ ]" ;
7.7 pterm = constant | "!" | "/?", integer_number ;
7.8 pterm = "(" , term , ")" ;
8.1 listexpr = expr999, [ "," , listexpr ] ;
8.2 listexpr = expr999, "|" , expr999;

Notes:

0. Defines the syntax in Prolog II mode.

1. Defines the syntax in Edinburgh mode.

2. exprn represents the sequence of rules expr1 ... expr1000 in Prolog II syntax,
and expr1 ... expr1200 in Edinburgh syntax.

3. Rule 7.2 expresses an alternative syntax for references to components in an


array, which produces optimal access times. For example, if table is the name
of an array (defined using the predefined rule def_array) then the two
expressions table(10) and table[10] are equivalent. However, the compiler
will translate the second form more efficiently.

4. Rules 7.3 and 7.4 define two alternative tuple syntaxes. In Edinburgh syntax,
only the second syntax is available. The equivalences are as follows:

<x,y>  x , y )

5. Rule 7.5 is used to describe context-free grammars (in order to write


syntactical analyzers in Prolog).

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 19

6. In Prolog II syntax, rule 4 and rules 7.6, 8.1 and 8.2 define two alternative
syntaxes for list notation. The equivalences are as follows:

[a|b]  a.b

[a,b]  a . b . nil

[a,b,c,d]  a . b . c . d . nil

[a,b,c|d]  a.b.c.d

In Prolog II syntax, the two list syntaxes can still be used together in the same
program

[ a , b | c.d.nil]  a . [b , c , d]

7. Some terms considered to be directives are simply declarations and not


predefined rules (e.g. module, end_module). They must not be preceded by "->"
or ":-" as stated in rules 2.1 and 2.2.

1.9.2 The operators


The operators are used to extend term syntax dynamically. There are three distinct
types of operator; prefixed, postfixed and infixed.

10 prefix_opn,d = identifier | graphic_symbol ;


11 postfix_opn,g = identifier | graphic_symbol ;
12 infix_opn,g,d = identifier | graphic_symbol ;

It should be noted that in Prolog II syntax, the operators are not authorized at the
first level of terms in the rule body, and that the expression must be bracketed in
such a case. In Edinburgh syntax, there is no restriction.

The type of operator is indicated by a convention which defines the order of


precedence of the operands according to the precedence n of the operator.

type precedence operator type operand(s) prec. example


fx n opn,d d:= n-1 - (- 1)
fy n opn,d d:= n
xf n opn,g g:= n-1
yf n opn,g g:= n
xfx n opn,g ,d g:= n-1, d:= n-1 val(1'<'2,x)
xfy n opn,g ,d g:= n-1, d:= n a,b,cE
yfx n opn,g ,d g:= n, d:= n-1 val(1/2/3,x)

The following table describes the operators in Prolog II+ syntax. The table
indicates the syntactic term constructed corresponding to each operator.

©PrologIA
Aociation Prolog
R 1 - 20 Reference Manual HERITAGE

operator precedence type constructed term


'<' 700 xfx sys:inf(t1,t2)
'=<' 700 xfx sys:infe(t1,t2)
'>' 700 xfx sys:sup(t1,t2)
'>=' 700 xfx sys:supe(t1,t2)
=\= 700 xfx sys:'=\='(t1,t2)
=:= 700 xfx sys:eql(t1,t2)
+ 500 yfx sys:add(t1,t2)
- 500 yfx sys:sub(t1,t2)
'/\' 500 yfx sys:'/\'(t1,t2)
'\/' 500 yfx sys:'\/'(t1,t2)
* 400 yfx sys:mul(t1,t2)
/ 400 yfx sys:div(t1,t2)
mod 400 yfx sys:mod(t1,t2)
rem 400 yfx sys:rem(t1,t2)
'<<' 400 yfx sys:'<<'(t1,t2)
'>>' 400 yfx sys:'>>'(t1,t2)
^ 200 xfy sys:'^'(t1,t2)
** 200 xfx sys:'**'(t1,t2)
+1 200 fx sys:add(t1)
-1 200 fx sys:sub(t1)

Note 1 : The trees corresponding to the unary operators + and - are evaluated when
analyzed if their argument is an integer constant.

Note 2 : Operators can be written with single quotes. Their only function, in
Prolog II+, is to extend identifier syntax. Therefore the only functional
notation for a functor declared as an operator is the tuple notation. If you
are unsure about the constructed term, it can always be tested by splitting
the term:
> eq(F(X,Y),1'<'2);
{F=inf, X=1, Y=2}

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 21

1.9.3 The lexical level


This syntax defines the same units as are recognized by the primitive
read_unit(x,y) . This is probably where the areas of greatest difference
between Prolog II and Prolog II+ are to be found.

Notes :

1. Rule L4 defines the basic syntax for variables; two extensions to this syntax
are given by rule L5.P (Prolog II syntax) and rule L5.E (Edinburgh syntax).
In both cases the extension is the same: a sub-set of names, which would have
been abbreviated representations of identifiers in the basic syntax, is added to
the set of variables.

These two extensions are optional and are mutually incompatible. It is the
user who chooses the syntax when starting a Prolog session: please refer to
the User's Manual.

2. Some combinations are illegal, such as "/*", "*/", "|*", "*|".

3. A command line option can make the exponent optional, but this creates an
ambiguity with lists in Prolog II syntax: 1.2 is read as a real in input. This
rule is only valid if this option is chosen. Please refer to the User's Manual,
section 2.3.

4. Rules L2.1 and L2.2 define the basic identifier syntax. Rules L2.3 and L2.4
define the extension for the Edinburgh syntax.

5. Rule L2.3 is necessary to show how an abbreviated identifier represented by a


graphic_symbol acquires its complete representation. Since the character
delimiting the abbreviated identifier's prefix is itself a graphic character, the
representation would be ambiguous if the quotes were not added. For
example, the parser sees sys::- as the identifier sys immediately followed by
the identifier ::- whereas it sees sys:':-' as the predefined identifier :- in the
sys family.

©PrologIA
Aociation Prolog
R 1 - 22 Reference Manual HERITAGE

L1 unit = identifier | separator | variable


| constant | graphic_symbol ;

L2.1 identifier = prefix , prefix_limit , abbreviated_id ;


L2.2 identifier = abbreviated_id ;

L2.3E identifier5 = prefix , prefix_limit ,


"'", graphic_symbol, "'" ;
L2.4E identifier4 = graphic_symbol ;

L3.1 abbreviated_id = name - extended_var ;


L3.2 abbreviated_id = "'",  (character - "'") | "' '" , "'";

L4 variable1 = "_" , alpha | extended_var ;

L5.P extended_var = letter, [ (digit | "_"), alpha ] ,  "'" ;


L5.E extended_var = big_letter, [ {alpha} ] ;

L6 prefix = [ name ,  prefix_limit , name  ] ;

L7 constant = integer_number | real_number | string ;

L8 integer_number = digits ;

L9 real_number = digits, ".", digits, ("E"|"e"|"D"|"d"),


[ ["+"|"-"],digits];
L9.1S real_number3 = digits, ".", digits,
[ ("E"|"e"|"D"|"d"), [ ["+"|"-"],digits]
];

L10 string = """ ,  string_char  , """ ;

L11 name = letter ,  alpha  ;

L12 digits = digit ,  digit  ;

L13.P graphic_symbol2 = "->" | graphic_c,  graphic_c | "." ;


L13.E graphic_symbol2 =  graphic_c ;

L14.1 comment = "|*",  character  , "*|" ;


L14.2 comment = "/*",  character  , "*/" ;
L14.3 comment = "%",  character  , newline ;

1.9.4 The characters


Rules whose left-hand member are indexed by I are only active when the Prolog II+
execution mode is the ISO mode (see U2.3). Rules whose left-hand member are
indexed by H are only active when the Prolog II+ execution mode is the host mode
(see U2.3).

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 23

host_letter denotes any host system character commonly recognized as a character


which is not part of the ISO set 8859-1. In the same way, host_graphic_char
denotes any printable character from the host system which is neither an alpha, nor
a separator, nor a special_char and is not known to the ISO set 8859-1.

A description adapted to the host machine character set will be given in the User's
Manual in section 3.3.
Rule C6.2 represents the same set of characters as rules C7.2 and C8.1, but the
three rules are not all valid simultaneously. C6.2 with a P index is valid in
Marseilles syntax, C7.2 and C8.1 with an E index are valid in Edinburgh syntax.
When the syntax changes these characters act differently.
Rule C5 is valid if the character delimiting the prefix and suffix in the complete
identifiers has not been redefined. It can then have the value of a graphic character.

C1 big_letter = "A" | … | "Z" ;


C2 letter = big_letter | "a" | … | "z"
| "À" … "ß" - "" | "à" … "ÿ" - "÷";
C2.1 letterH = host_letter;
C2.21 letterI, i1 = "\", accent_escape ;

C3.1 binary_digit = "0" | "1" ;


C3.2 octal_digit = "0" | … | "7" ;
C3.3 digit = "0" | … | "9" ;
C3.4 hex_digit = digit | "a" | "b" | "c" | "d" | "e" | "f"
| "A" | "B" | "C" | "D" | "E" | "F";

C4 alpha = letter | digit | "_";


C5 prefix_limit = ":" ;

C6.1 separator = "(" | ")" | "[" | "]" | "{" | "}" |


"|" | "," ;
C6.2 separatorP= ";" | "." | "<" | ">" ;

C7.1 special_char= "%" | "'" | """ | "_" | "!" | "`" ;


C7.2 special_charE= ";" ;
C8 graphic_c = graphic_char ;

C8.1 graphic_charE = ";" | "<" | ">" ;


C8.2 graphic_char = "#" | "$" | "&" | "*" | "+" | "-" | "/" | ":"
| "=" | "?" | "\" | "@" | "^" | "~"
| NBSP … "¿" | "" | "÷" ;
C8.3 graphic_charH = host_graphic_char ;

C9 character = letter | digit | separator |


graphic_char | special_char ;

©PrologIA
Aociation Prolog
R 1 - 24 Reference Manual HERITAGE

C10 string_char = character - ( """ | "\") | """" ;


C10.1 string_chari0 = "\";
C10.2 string_chari1 = "\", format_escape ;
C10.31string_charI, i1 = "\", accent_escape ;

C111 accent_escape = accent , accent_letter | "~a"


| ~A | ~n | ~N | ~o"
" " " " " " "
| "~O" | "cc"| "CC" | "ae" | "AE"
| "BB" | "/o" | "/O" | ""y"| "'y"| "'Y"
| "-d"|"-D" | "pp" | "PP" | "oa"| "oA" ;

C123 accent = " ` " | " ' " | "^ " | ": " ;

C13 accent_letter = "a" | "e" | "i" | "o" | "u"


| "A" | "E" | "I" | "O" | "U" ;

C142 format_escape = "b" | "f" | "n" | "r" | "t" | "\"


| newline
| octal_digit, octal_digit, octal_digit
| ("x" |"X"), hex_digit, hex_digit ;

1.9.5 Accented characters


A behavior option (see section 2.3 of the user's manual) defines the mode for
reading the character "\". When interpretation of "\" is active, the rules are denoted
by i1. If it is not active the rules are denoted by i0. Rules denoted in this way are
exclusive. Their validity depends on which option you have chosen.

The following notes only apply when interpretation of the "\" is active.

Notes :

1. Prolog II+ has an execution mode (see U2.3) in which accent_escape is not
authorized and is replaced by format_escape. In this mode, these rules (C2.2,
C10.3, C11) are not valid. In all other cases, accent_escape can be used as
input to specify accented characters. For output, Prolog uses an
accent_escape for the accented characters in the ISO set 8859-1 that do not
exist in the host system character set.

2. In the same way as for accent_escape, format_escape can always be used in


input to specify accented characters. For output, Prolog uses format_escape
for characters not existing in the host system character set and which cannot
be represented by an accent_escape (in host mode for example).

3. A ":" character in an accent_escape represents a diacritic diaeresis:

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 25

Example:

no\:el <=> noël

Table 1
Accented characters in the ISO code 8859-1

128 144 160 176 192 208 224 240


0 À -D à 
1 Á Ñ á ñ
2 Â Ò â ò
3 Ã Ó ã ó
4 Ä Ô ä ô
5 Å Õ å õ
6 Æ Ö æ ö
7 Ç  ç ÷
8 È Ø è ø
9 É Ù é ù
10 Ê Ú ê ú
11 Ë Û ë û
12 ì Ü ì ü
13 í oI í oI
14 î Ý î ý
15 ï ß ï ÿ

The table below shows the accented characters and their corresponding expression
in the form of accent_escape . For example, you can observe that the following two
character strings:

"tel maître, tel élève" et "tel ma\^itre, tel \'el\`eve"

are equivalent.

©PrologIA
Aociation Prolog
R 1 - 26 Reference Manual HERITAGE

Table 2 : «accent_escape»'s used by Prolog II+

128 144 160 176 192 208 224 240


0 `A -D `a -d
1 'A ~N 'a ~n
2 ^A `O ^a `o
3 ~A 'O ~a 'o
4 :A ^O :a ^o
5 oA ~O oa ~o
6 AE :O ae :o
7 CC cc
8 `E /O `e /o
9 'E `U 'e `u
10 ^E 'U ^e 'u
11 :E ^U :e ^u
12 `I :U `i :u
13 'I 'Y 'i 'y
14 ^I PP ^i pp
15 :I BB :i :y

1.10. The macro processor


It is possible to write a few very simple macros (or aliases) in Prolog II+ in order to
increase the readability of the programs. This functionality operates by means of a
compiling directive (not a predicate):

set_alias(i,t)
Defines an alias.
From the place where and moment when this directive is detected, the reader
replaces certain occurrences of the identifier i (called an alias) with the term t
(called value). This definition is deactivated at the end of compiling of the
highest level of nesting.
The value t must be an integer, real or character string.
The alias i must be an identifier.
Only identifiers positioned as arguments (not rule heads) and not explicitly
prefixed in the text are replaced by the alias value. It is therefore possible to
conserve an identifier with the same abbreviated name as an alias, by prefixing
it explicitly in the text. It is therefore also logical that the prefix of the alias
should be ignored in the directive. Nevertheless, if this alias is already
defined, reading of a directive with an alias explicitly prefixed in the text will
prevent it being replaced, and will therefore allow it to be redefined
(accompanied by a warning message).

©PrologIA
Aociation Prolog

HERITAGE The basic elements R 1 - 27

The val/1 predicates makes it possible to define an alias using another alias.
Examples with comments:
> insert;
set_alias(foo,44);
set_alias(foo,55); 44 is redefined as 55
-> set_alias(44,55) : BAD ARGUMENT TYPE

> insert;
set_alias(macro1,22);
set_alias(aa:macro1, 44); Here the prefixing is the means of redefinition
WARNING: macro1 ALREADY DEFINED, NEW VALUE TAKEN INTO ACCOUNT
rg1(macro1)->;
rg1(aa:macro1)->;
-> insert; Here, 2nd level of compiling nesting
set_alias(macro2,val(2 * macro1)); Definition using another macro
rg2(macro2)->;
rg2(macro1)->;
; We return to the 2nd compiling level
macro1(macro2)->; Automatic protection of rule heads
macro1(macro1)->;
;
{}
> rg1(I);
{I=44} Here the new value is taken into account
{I=aa:macro1} Here, no replacement of prefixed identifier
> rg2(I);
{I=88}
{I=44} The macro defined at the 1st compiling level
has been taken into account in the 2nd level
> macro1(I);
{I=88} The macro defined in the 2nd compiling level
has been taken into account in the first level
{I=44}
> insert; Here a new compiling operation starts
rg(macro1)->;
rg(macro2)->;
;
{}
> rg(I);
{I=macro1} The definitions have been cancelled
{I=macro2}

NB: A macro appearing as the left-hand operand of an infixed operator must


be parenthesized. Example:
?- insert.
set_alias(foo,44).
oper(X) :- foo >= X.
oper(X) :- (foo) >= X.
.
list.
oper(_345) :-
val(foo,_348),
_348 >= _345 .
oper(_345) :-
44 >= _345 .

©PrologIA
Aociation Prolog
R 1 - 28 Reference Manual HERITAGE

©PrologIA
Aociation Prolog

HERITAGE

2. Control of program execution

2.1 Control
2.2 Freeze
2.3 Infinite trees
2.4 Some advice about recursive programming
2.5 Metastructures

2.1 Control

At each stage in program execution, the Prolog interpreter must make two choices:

(1) It selects one goal in a sequence of goals to be executed. The first element of
the sequence is always chosen, i.e. to execute the sequence q0 q1 … qn it
selects q0, and then processes the remaining ones.

(2) To execute a goal, a rule must be selected whose head unifies with the goal to
be executed. Here also, the first candidate rule is chosen.

This process can be summarized by the following Prolog program:


execute(nil) -> ;
execute(t.l) -> rule(t,q) execute(q) execute(l);

where rule(t,q) is a predefined rule (see Chapter 3) which matches successively with
all the rules of the program whose head matches t and whose body matches q.

Program execution is controlled by modifying or restricting these two choices. If


they remain as described above, some Prolog programs may loop and therefore not
behave as expected. The following two examples illustrate this:

Example 1: A typical case is transitivity. If we try to execute


taller(Michel,x)

using the program below, the original goal will be generated. The program loops
and ends in a stack overflow or a user interrupt. The program can be written
correctly by removing the "left recursivity".
taller(Michel,Alain) ->;
taller(Alain,Henry) ->;
taller(x,y) -> taller(x,z) taller(z,y);

>taller(Michel,x);
{x=Alain}
{x=Henry}

© PrologIA
R2-2 Reference Manual Aociation Prolog

HERITAGE

LOCAL STACK OVERFLOW1

"A correct solution"

taller'(Michel,Alain) ->;
taller'(Alain,Henry) ->;

taller(x,z) -> taller'(x,y) taller_or_equal(y,z);

taller_or_equal(x,x) ->;
taller_or_equal(x,y) -> taller(x,y);

Example 2:

This example enumerates all the lists constructed with 1. If we keep the same
(wrong) order of rules, the infinite list will be computed first. By changing their
order, we can obtain the correct solution.
number(1.x) -> number(x);
number(nil) ->;

>number(x);
LOCAL STACK OVERFLOW

The cut "!"


When a Prolog program executes it achieves a sequence of goals in all
possible manners. But if a rule containing a "!" (or cut) is used to achieve a
goal q, the execution of this "!" will prevent the machine from choosing the
alternative rules which could have achieved this goal q. This limits the size of
the search space; it is as if the "!" makes Prolog forget the other possible
ways of achieving q.
The "!" can only appear among the terms constituting the right-hand member
of a rule. The choices which remain to be examined, and which execution of
the "!" makes Prolog forget are as follows:

- rules having the same head as the rule containing the "!";

- rules which could have been used to execute the terms between the start
of the body and the "!".
The use of this parasite is illustrated by the example below.
color(red) ->;
color(blue) ->;
size(big) ->;
size(small) ->;
choice1(x.y) -> color(x) size(y);
choice1("that's all") ->;
choice2(x.y) -> ! color(x) size(y);

1If the automatic reallocation system is not deactivated when Prolog starts, a certain number of
reallocations will occur before overflow.

© PrologIA
Aociation Prolog Control of program execution R2-3
HERITAGE

choice2("that's all") ->;


choice3(x.y) -> color(x) ! size(y);
choice3("that's all") ->;
choice4(x.y) -> color(x) size(y) !;
choice4("that's all") ->;

>choice1(u);
{u=red.big}
{u=red.small}
{u=blue.big}
{u=blue.small}
{u="that's all"}
>choice2(u);
{u=red.big}
{u=red.small}
{u=blue.big}
{u=blue.small}
>choice3(u);
{u=red.big}
{u=red.small}
>choice4(u);
{u=red.big}
>choice1(u) !;
{u=red.big}

One way to understand the "!" is to consider it as an annotation which is


added to a program to make it more efficient. Of course this is only useful if
we are interested solely by the first solution provided by the program. On the
next page are some typical uses of the "!".
"First Solution Only"
first_solution_only(b) -> b !;

"If Then Else"


if_then_else(p,a,b) -> p ! a;
if_then_else(p,a,b) -> b;

"Not"
not(p) -> p ! fail;
not(p) ->;

In the case of not, unexpected results may be obtained, if p contains free


variables. Here is an illustration:
man(Michel) ->;

woman(x) -> not(man(x));

> woman(Cristina);
{}
> woman(Michel);
> woman(x) eq(x,Cristina);
>

^(X,Y)
X must be a variable and Y can be any term.

© PrologIA
R2-4 Reference Manual Aociation Prolog

HERITAGE

^(X, Y) means "there exists X such that Y is true", and is equivalent to a call to
Y. It only makes sense to use this predicate (which is also an operator) in the
predicates bagof/3 and setof/3, to indicate the existential variables and remove
them from the set of free variables.

bagof(x, p, l)
For each different instantiation of the set of goal p's free variables, bagof(x, p,
l) unifies l with the list of all the solutions x when p is executed. These
variables are non existential and do not occur in the term x. Each list l is
constructed according to the order of the solutions found. E.g.:
aa(2,1) -> ;
aa(1,2) -> ;
aa(1,1) -> ;
aa(2,2) -> ;
aa(2,1) -> ;
>bagof(X, aa(X,Y),L);
{Y=1, L= 2.1.2.nil}
{Y=2, L= 1.2.nil}
> bagof(X,Y^aa(X,Y),L);
{L=2.1.1.2.2.nil}
>

block(e,b), block_exit(e)
block is a predefined rule which immediately ends the execution of a goal b.
In most cases, it is used for error recovery. We can state that:

- To execute block(e,b), b is executed, having first created an imaginary


pair of parentheses, labeled e, that enclose the goal b.

- block_exit(e) immediately aborts execution of all goals enclosed by the


pair of parentheses labeled e and deletes any choice points waiting for
these goals. The execution then continues as normal, after the
parentheses labeled by e.
In addition

• A label is a Prolog term; two labeled pairs of parentheses are considered


identical if their labels can be unified.

• If there are several pairs of parentheses labeled by e, block_exit(e) stops


at the innermost pair.

• If block_exit(e) does not find any pair of parentheses labeled e then


command level is reached. If e is an integer, the error message
corresponding to e is displayed, otherwise the following message is
displayed: 'block_exit' WITH NO MATCHING 'block'.

This mechanism is also used by the Prolog error management system. An


error occurring during execution causes the goal block_exit(i) to be executed,
and i is the error number. This enables the user to recover all Prolog errors
and process them in his application.

© PrologIA
Aociation Prolog Control of program execution R2-5
HERITAGE

When compiling optimizations are active (option -f o1 when Prolog starts),


compiling of block is optimized, and in some cases the decompiling of such a
goal will be equivalent but not identical to the original goal. When the goal
block(e,b) appears in a rule body, it will be decompiled as block(e',_,b').
The built-in predicate quit generates a block_exit(14). It is defined as follows:
quit -> block_exit(14);
quit(i) -> block_exit(14,i);

As an example here is a program which reads a sequence of commands:


execute_command ->

block(end_command,always(read_and_exec));

read_and_exec -> outm("?") in_char'(k) exec(k);

exec("q") -> block_exit(end_command);


exec("f") -> block_exit(16); | Interruption |
exec("n") ->;

always(p) -> repeat p fail;

repeat ->;
repeat -> repeat;

In this example, the command "q" uses block_exit to go back up to the


execute_command level. The command "f" simulates a Prolog error and
returns control to block which processes the Prolog errors (since 16 cannot be
unified with end_command). If there is no such block Prolog command level
is reached.

block(e, c, b), block_exit(e, c)


These rules function in the same way as the previous ones, but with two
"labels" e and c, instead of one. b is the goal to be executed and block (e, c, b)
starts its execution. The subsequent execution of block_exit with two
arguments will generate a search for a block whose first two arguments unify
with the two arguments of block_exit.
When compiling optimizations are active (option -f o1 when Prolog starts),
compiling of block is optimized, and in some cases the decompiling of such a
goal will be equivalent but not identical to the original goal. When the goal
block(e,c,b) appears in a rule body, it will be decompiled as block(e',c',b').

Together, these two predefined rules constitute a refinement of the error


recovery mechanism. In practical use, e corresponds to the type of the
expected error, and c corresponds to "additional information" produced by the
detection mechanism.
A great many built-in predicates use this second label as an error complement.
Often the argument causing the error is transmitted. In a debugging phase,
this may seem insufficient, and so to remedy this the following object
modules are supplied in the kit; dbgbase.mo, dbggraph.mo and dbgedin.mo.
Once they have been loaded, they provide even more complete messages. The
second argument of block will be unified with a term in the form:

© PrologIA
R2-6 Reference Manual Aociation Prolog

HERITAGE

calling predicate or < calling predicate, error complement>


When block_exit(e,c) is executed in an environment "parenthesized" by
block(e'b), block_exit(e,c) behaves like (block_exit(e). Conversely, when
block_exit(e) is executed in an environment "parenthesized" by block(e',c',b),
block_exit(e) behaves like block_exit(e,nil).

Errors and Prolog sub-sessions


Everything written above concerning the block / block_exit error recovery
mechanism is true within a single Prolog session. When an error is
transmitted through one or more sub-sessions (e.g. when a goal is started by a
menu), two restrictions should be noted:
- block_exit's second argument (often used as an error complement) is
not transmitted. It will always be nil.
- block_exit's first argument is only transmitted if it is an integer.
Otherwise the integer 317 is propagated, for the error: 'block_exit'
WITH NO MATCHING 'block'.

Interruption
A Prolog program can be interrupted at any time by typing a certain key,
depending on the system used (for example <Ctrl-C>). This interruption is
processed by the Prolog error management system and corresponds to error
16. So this interruption can be recovered by the user. Otherwise, the Prolog
command level is reached and the message: USER INTERRUPT is
displayed.

bound(x)
bound(x) is executed if x is bound and fails otherwise. A variable is
considered bound if it has been unified:

- Either with a constant (integer, real, identifier, string),

- Or with a term like t1.t2,

- Or with a term like <t1.t2,… ,tn> or ff(t1,t2,… ,tn).

dif(t1,t2)

The predefined rule dif(t 1 ,t2 ) is used to constrain t1 and t2 to represent


different trees. As soon as this constraint can no longer be satisfied,
backtracking will occur. The implementation of dif uses a similar mechanism
to freeze.
Here are two interesting relations which can be written with dif : out_of(x,l)
which ensures that x will never be an element of the list l, and all_different(l)
which checks that the list l does not contain the same element twice.
out_of(x,nil) ->;
out_of(x,y.l)-> dif(x,y) out_of(x,l);

all_different(nil) ->;

© PrologIA
Aociation Prolog Control of program execution R2-7
HERITAGE

all_different(x.l) -> out_of(x,l) all_different(l);

Using these two primitives, the user can write a program to calculate
permutations. Simply assert that a list of integers is considered and that each
integer appears only once in the list.
permutation(x1,x2,x3,x4) fl
all_different(x1.x2.x3.x4.nil)
digit(x1) digit(x2) digit(x3) digit(x4);

digit(1) ->;
digit(2) ->;
digit(3) ->;
digit(4) ->;

It is clear in this example that Prolog first introduces all the inequalities before
executing the standard non-deterministic program. This results in a much
clearer and more efficient program.
The use of dif also makes it possible to write programs which would behave
incorrectly if they were defined using the cut. For example, the definition of
the relation "x is an element of l with a value of v" can be written as follows:
element(x,nil,false) ->;
element(x,x.l,true) ->;
element(x,y.l,v) -> dif(x,y) element(x,l,v);

> element(x,1.2.nil,v);
{x=1, v=true}
{x=2, v=true}
{x#1, x#2, v=false}

If this relation is defined using the ! primitive, a certain number of abnormal


phenomena are produced:
element(x,nil,false) ->;
element(x,x.l,true) -> ! ;
element(x,y.l,v) -> element(x,l,v);

> element(x,1.2.nil,v);
{x=1, v=true} % a single solution !!
> element(2,4.2.3.nil,false);
{} % success !!

default(t1, t2)
The predefined rule default enables the following check to be performed: if t1
can be executed then it will be executed in all possible ways, otherwise t2 is
executed. At first sight, it is easy to think that this primitive could be
performed using '!', but in fact this is impossible.
Here is an example of how to use this rule:
answer(p) -> default(p,outml("nobody"));
man(john) ->;
man(peter) ->;

© PrologIA
R2-8 Reference Manual Aociation Prolog

HERITAGE

> answer(man(x));
{x=john}
{x=peter}
> answer(woman(x));
nobody
{}

eq(t1, t2)
Unification of t1 and t2: simply corresponds to the rule eq(x,x) ->;

fail
Predefined rule which always causes a failure (backtrack).

findall(x, p, l)
Unifies l with the list of all solutions x when p is executed.

free(x)
Is executed if x is not bound.

list_of(x, y, p, l)
Provides a sorted list, with no repetitions, of all individuals that fulfill a certain
requirement.
x is a variable.
y is a list of variables.
p is a Prolog term containing at least all these variables.
For each set of values of y, this primitive unifies l with the list of values of x so
that p is true (i.e. so that p executes).
The order of the list l is identical to the order defined on terms (see
term_cmp/3).
Example: Prolog containing the following data base:
man(big, michel, 184) ->;
man(big, alain, 183) ->;
man(big, henry, 192) ->;
man(small, nicolas, 175) ->;
man(small, julien, 176) ->;
man(small, gilles, 120) ->;

> list_of(x,t.nil,man(t,x,h),l);
{t=big, l=alain.henry.michel.nil}
{t=small, l=gilles.julien.nicolas.nil}

not(X)
Is described by the following rules :
not(X) :- X,!,fail.
not(X).

repeat
Is described by the following rules :
repeat ->;
repeat -> repeat;

© PrologIA
Aociation Prolog Control of program execution R2-9
HERITAGE

setof(x, p, l)
For each different instantiation of the set of goal p's free variables, setof(x, p,
l) unifies l with the list of all the solutions x when p is executed. The variables
are non existential and do not occur in the term x. Each list l is sorted and
contains no repetitions. Its order is identical to the order defined on the terms
(see term_cmp/3).
Example:
aa(2,1) -> ;
aa(1,2) -> ;
aa(1,1) -> ;
aa(2,2) -> ;
aa(2,1) -> ;
>setof(X, aa(X,Y),L);
{Y=1, L= 1.2.nil}
{Y=2, L= 1.2.nil}
> setof(X,Y^aa(X,Y),L);
{L=1.2.nil}
>

or(x,y)
Defines a logical "or", transparent to the cut. Example:
> op(900,xfy,or);
{}
> enum(i,4) (eq(i,1) or eq(i,2));
{i=1}
{i=2}
> enum(i,4) ([eq(i,3),'!'] or [outl(no),fail]);
no
no
{i=3}
>

2.2 Freeze
This predefined rule efficiently solves a problem which often occurs in Prolog: the
need to postpone certain decisions for as long as possible. In concrete terms, freeze
gives the user the ability to delay program execution until sufficient information is
available, or to wait for a given variable to be assigned a value before continuing.
This feature combines the advantages of declarative programming with efficient
execution.

freeze(x,q)
The purpose of this rule is to postpone the execution of q as long as x is
unknown. To be more precise,

(1) If x is unbound, freeze(x,q) is executed and the execution of q is


delayed (that is, q is frozen). q will be executed as soon as x becomes
bound.

(2) If x is bound then q is executed normally.

© PrologIA
R 2 - 10 Reference Manual Aociation Prolog

HERITAGE

It is the programmer's responsibility to make sure that a frozen variable will be


unfrozen in the future, so that the goal will not remain on hold eternally. Since
no check is made by the Prolog, this can lead to solutions which are too
general.
N.B. When there are frozen goals on the variables of a question they are
printed in a special way:
> freeze(x,foo);
{x~foo.nil}

Here are some examples of the use of freeze :


Example 1: We want to compute plus(x,y,z), that is, we want to solve the
equation z=x+y only when x and y are both known.
sum(x,y,z) -> freeze(x,freeze(y,sum1(x,y,z)));

sum1(x,y,z) -> val(add(x,y),z);

Example 2: We can do better. Let us suppose that we want to solve the


equation only when at least two of the variables x, y, z are known. Here, the
variable u becomes bound when one of the additions is performed, and thus
prevents the other redundant additions from being carried out.
sum(x,y,z) ->
freeze(x,freeze(y,either(u,sum1(x,y,z))))
freeze(y,freeze(z,either(u,sum2(x,y,z))))
freeze(x,freeze(z,either(u,sum3(x,y,z))));

sum1(x, y, z) -> val(x+y, z);


sum2(x, y, z) -> val(z-y, x);
sum3(x, y, z) -> val(z-x, y);

either(u,p) -> free(u) / eq(u,Cst) p;


either(u,p) ->;

Example 3: This example shows how to use variables to control a program


from the outside. The rule number given in example 2, section 2.1 of this
chapter, loops. To stop it looping, we can simply add an external condition:
length(l,n) which ensures that the length of list l is less than or equal to n.
Now number works properly:
length(l,n) -> freeze(l,length'(l,n));

length'(nil,n) -> ;
length'(e.l,n) ->
dif(n,0) val(sub(n,1),n') length(l,n');

number(1.x) -> number(x);


number(nil) ->;
>length(l,5) number(l);
{x=1.1.1.1.1.nil}
{x=1.1.1.1.nil}
{x=1.1.1.nil}
{x=1.1.nil}
{x=1.nil}
{x=nil}

© PrologIA
Aociation Prolog Control of program execution R 2 - 11
HERITAGE

When nothing remains to be executed, some goals may remain frozen on a


few variables which are still free.
Note 1: The compiling optimizations do not make it possible to activate
frozen goals as soon as the rule head is unified. They can only be activated on
the first goal of the non optimized body. In particular, the following example
will fail:
> insert;
number(<i>) -> integer(i);
link(<1>) ->;;
{}
> freeze(x, link(x)) number(x);
>
Indeed, since the type test predicates are optimized, link(<i>) will not be
unfrozen because there are no other goals in the body of number/1.

2.3 Infinite trees


This paragraph gives some practical information on how to use infinite trees in
Prolog II+. Firstly, some predefined rules only function on finite trees. In particular
in cannot read an infinite tree and assert cannot add rules containing infinite trees.

infinite
no_infinite
These rules are used to define the way in which the result will be printed: the
infinite option must be activated if you want to print solutions containing
infinite trees.
The following program uses freeze to check that a tree represents and will
always represent a finite tree. It is an indirect way of implementing the
occur_check test. It checks that a tree does not have two identical subtrees in
the same branch.
finite_tree(x) -> finite_branch(x,nil);

finite_branch(x,l) -> freeze(x,finite_branch'(x,l));

finite_branch'(x,l) ->
out_of(x,l) dominates(x,l') finite_branches(l',x.l);

finite_branches(nil,l) ->;
finite_branches(x.l',l) ->
finite_branch(x,l) finite_branches(l',l);

dominates(x1.x2,x1.x2.nil) -> !;
dominates(x,x') -> tuple(x) ! split(x,x');
dominates(x,nil) ->;

infinite_flag
The value of this symbol (0 or 1) indicates whether infinite or no_infinite is
active. This value can be tested using the predefined rule val.

© PrologIA
R 2 - 12 Reference Manual Aociation Prolog

HERITAGE

equations(t,t',l)
This predefined rule is used to transform a finite or infinite tree t into a list of
equations l which has the solution t. t' indicates the variable which has the
solution t. This is the primitive that is used to print solutions when the infinite
option is active. Let us see how it could be used in an example:
> infinite eq(x,ff(ff(x))) equations(x,t',l) out(t')
outm(" : ") outl(l) ;

v131 : eq(v131,ff(v131)).nil

{x=v131, v131=ff(v131), l=eq(t',ff(t')).nil}


> eq(x,ff(ff(x)));
{x=v120,v120=ff(v120)}

However, one of the main uses of this rule is to add infinite trees. The assert
primitive is used (see next chapter) to add a rule.
add_infinite_tree(t) ->
equations(t,t',l)
assert(my_tree(t'),l) ;

> infinite eq(x, ff(ff(x))) add_infinite_tree(x) ;


{x=v131, v131=ff(v131)}
> list(my_tree/1) ;
my_tree(x11) -> eq(x11, ff(x11)) ;
{}
> my_tree(x) ;
{x=v131, v131=ff(v131)}

2.4 Some advice about recursive programming

The Prolog II+ system includes an automatic garbage collector. It is extremely


efficient, and is capable of storing in the stacks only the data you really need. This
enables the user to make full use of the recursive program definitions. In addition,
certain programming techniques may help you to recover even more space. In
practical terms, this means making skillful use of the choice points cut, and
obtaining maximum benefit from the optimization of recursivity and terminal
calling offered by the Prolog II+ compiler. Use of these techniques will enable you
to write programs which endlessly call themselves without ever overflowing. The
example below will help to make this clearer:
> insert;
repeat -> out(1) repeat ;;
{}
> repeat ;
11111111111111111111111...

The program above will run endlessly without overflowing, because the recursion
operates on the last literal in the rule. In contrast, the program below will overflow,
because the recursion will accumulate the literals to be executed (non terminal
recursion):
repeat -> out(1) repeat out(2);

© PrologIA
Aociation Prolog Control of program execution R 2 - 13
HERITAGE

> repeat ;
11111111111111111111111...
-> RECURSION STACK OVERFLOW1
>

Also, the information to be stored will accumulate because certain choices remain
for the executed rule. The execution of the goal using the following definition will
generate an overflow error by accumulation of choice points.
> insert;
repeat -> repeat ;
repeat ->;;
{}
> repeat fail;
-> RECURSION STACK OVERFLOW2
>

In contrast, the following program will run indefinitely (fortunately, we can interrupt
it with Control-C!):
repeat -> ;
repeat -> repeat;

The choice cut "!" enables the garbage collector to recover extra space, by removing
the choice points. It should be noted however, that if the "!" is placed at the end of a
rule, we lose the terminal recursivity.
repeat -> out(1) repeat !;
repeat ->;

The above program will generate an overflow error (the "!" is a literal to be
executed), while the program below will run indefinitely:
repeat -> out(1) ! repeat ;
repeat ->;

2.5 Metastructures

2.5.1 Creation

In PrologII+ you can attach a variable to a list of terms. This is called a meta-
structure or an allocated variable and allocated terms.

The special feature of these variables is that unification with a known term or with
another allocated variable is replaced by calls to user predicates.

1If the automatic reallocation system is not deactivated when Prolog starts, a certain number of
reallocations will occur before overflow.

2If the automatic reallocation system is not deactivated when Prolog starts, a certain number of
reallocations will occur before overflow.

© PrologIA
R 2 - 14 Reference Manual Aociation Prolog

HERITAGE

An attempt to unify an allocated variable with a known term is replaced by as many


calls as there are terms in the list attached to this variable. In the same way, an
attempt to unify two allocated variables will entail a series of successive calls to all
the predicates contained in each of the two lists.

The parameters for each predicate are imposed. The first parameter will be the
allocated variable itself, the second parameter will be the term we are trying to unify
it with, and the third parameter will be the corresponding allocated term in the list.

A term can be linked to a variable using two built-in predicates: new_tlv/3 and
add_tlv/3 (TLV: Term Linked to Variable).

new_tlv(v, t, i)
Attaches term t to variable v. The list of terms allocated to variable v will
therefore be reduced to a single item: the term t. If v was already an allocated
variable, the previous list is lost. If v is not a variable an error is generated.
The third argument i must be an identifier. It is the name of the user rule
described above (arity 3) that will be called when an attempt is made to unify
variable v with a known term or with another allocated variable.

add_tlv(v, t, i)
Adds term t to the variable v. The list of terms allocated to variable v will
therefore be increased by one item: term t. If v was not already an allocated
variable, this predicate has the same effect as the previous one. If v is not a
variable an error is generated. The third argument i has the same meaning as
in the previous predicate.

The order in which the user predicates will be called is not specified.

Example:
> insert;
rule1(V,T,A) -> outm("Rule1 ") out(T) outm(" ") outl(A);
rule2(V,T,A) -> outm("Rule2 ") out(T) outm(" ") outl(A);
rule3(V,T,A) -> outm("Rule3 ") out(T) outm(" ") outl(A);
;
{}
> new_tlv(V,1.2.nil, rule1) add_tlv(V,3.4.nil,rule2)
add_tlv(V,5.6.nil,rule3) eq(V,foo);
Rule1 foo 1.2.nil
Rule2 foo 3.4.nil
Rule3 foo 5.6.nil
{V@rule1(1.2.nil).rule2(3.4.nil).rule3(5.6.nil).nil}

A combination of these two predicates can easily be obtained by a call to the


predicate:

set_tlv(v, l)
where l must be a list of elements having the form i(t), i and t having the same
signification that in the two last predicates. If the list l has N elements, the call
of this predicate is equivalent to a first call to new_tlv/3, followed by N-1 calls
to add_tlv/3.

© PrologIA
Aociation Prolog Control of program execution R 2 - 15
HERITAGE

Example:
> set_tlv(X,foo(1).aa(2).nil);
{X@foo(1).aa(2).nil}

2.5.2 Recovery

The list of terms allocated to a variable can be obtained by means of the following
predicate:

get_tlv(v, l)
Unifies l with the list formed by the terms allocated to variable v. Each of
these terms is encapsulated by the user predicate called when an attempt is
made to unify this variable with another allocated variable or a known term.
This list l therefore takes the form: id1(t1).id2(t2)....nil in which each
identifier id (user predicate) is associated with the corresponding term. If v is
not a variable, l is unified with nil.
Example:
> new_tlv(V,1.2.nil, rule1) add_tlv(V,3.4.nil,rule2)
add_tlv(V,5.6.nil,rule3) get_tlv(V,T);
{V@rule1(1.2.nil).rule2(3.4.nil).rule3(5.6.nil).nil,
T=rule1(1.2.nil).rule2(3.4.nil).rule3(5.6.nil).nil}

2.5.3 Forced unification

Normal unification (without calling user predicates) can be forced between an


allocated variable and a known term or another allocated variable. This unification is
performed by means of a special predicate:

unify_tlv(t1, t2)
Performs normal unification between the two terms t1 and t2. Let's look at all
the possible cases:
- If t1 and t2 are not allocated variables the predicate is equivalent to eq/2.
- If t1 is an allocated variable:
- If t2 is an ordinary variable, it will therefore become an allocated
variable when it is unified with t1.
- If t2 is a known term, t1 will therefore become this known term when
it is unified with t2 (the list of allocated terms will then be lost).
- If t2 is also an allocated variable, when t1 and t2 have unified they will
designate an allocated variable whose list of allocated terms is the
concatenation of the two initial lists from t1 and t2.
Example:
> new_tlv(V,1.2.nil,foo) unify_tlv(V,3);
{V=3}
> new_tlv(V,1.2.nil,foo) unify_tlv(Z,V);
{V=Z,V@foo(1.2.nil).nil,Z@foo(1.2.nil).nil}

© PrologIA
R 2 - 16 Reference Manual Aociation Prolog

HERITAGE

> new_tlv(V,1.2.nil,foo) new_tlv(X,3.4.nil,faa)


unify_tlv(V,X);
{V=X,V@foo(1.2.nil).faa(3.4.nil).nil,
X@foo(1.2.nil).faa(3.4.nil).nil}

2.5.4 Output

The allocated variables of a question are printed in a special way: <variable


name>@<term>

The term after @ is the list of terms allocated to the variable, presented in an
identical manner to the get_tlv/2 predicate.

Example:
> new_tlv(x,zz,foo);
{x@foo(zz).nil}

2.5.5 Example

This program attaches a variable to the set of its possible values. If there is only one
value left, it is assigned to the variable.
insert;
% If X is a new variable, attaches the set of
% values L to it, otherwise attaches the intersection
be_in(X,L) -> get_tlv(X,L1) be_in(L1, X, L);
be_in(nil,X,L) -> ! new_set(X,L);
be_in(L1,X,L) -> get_values(L1, L2) inters(L,L2,L3)
attach_or_affect(X, L3);

% Attaches X to the list L of its possible values


new_set(X,L) -> new_tlv(X,L,verify_in);

get_values([],[])->!;
get_values(t_ag(L1).L2, L)-> get_values(L2,L3)
conc(L1,L3,L);

% Concatenation of 2 lists
conc(nil,L,L)->;
conc(X.L1,L2,X.L3) -> conc(L1,L2,L3);

attach_or_affect(X,[F]) -> !
unify_tlv(X,F); %only one value possible ==> we assign
attach_or_affect(X,L) -> dif(L,nil)
new_set(X,L); % new set possible

% The 3rd argument is the intersection of the 2 lists


inters([],L,[])->;
inters(x.l,l1,x.l2)-> member(x,l1) ! inters(l,l1,l2);
inters(x.l,l1,l2)-> inters(l,l1,l2);

% User predicate
verify_in(V_arlibc, T_unifie, T_att) ->
member(T_unifie,T_att)
unify_tlv(V_arlibc, T_unifie);
; % End of insertion
{}

© PrologIA
Aociation Prolog Control of program execution R 2 - 17
HERITAGE

> % some executions


be_in(x,[1,2,3,4]) be_in(x,[1,3,7]) be_in(x,[1,7,8]);
{x=1}
> be_in(x,[4,5,6]) be_in(x,[7,8,9]) ; % Failure
> be_in(x,[1,2,3,4,5]) be_in(y,[1,6,7,8]) eq(x,y);
{x=1,y=1}
> be_in(x,[1,2,3,4,5]) be_in(y,[1,2,6,7,8]) eq(x,y);
{x=1,y=1}
{x=2,y=2}

© PrologIA
R 2 - 18 Reference Manual Aociation Prolog

HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

3. Structuring rules and modification

3.1 Introduction
3.2 Terminology
3.3 Identifier syntax
3.4 Reading and writing context
3.5 Modules
3.6 Summary of how to use identifiers, contexts and modules
3.7 Adding, deleting and searching for rules
3.8 Manipulation of compiled modules

This chapter deals with the concepts of module, identifier family, and
reading/writing context, which have been introduced with two aims in mind:

• The achievement of program modularity and independence, by allowing the


partitioning of the set of identifiers being used.

• The ability to manage Prolog programs containing a very large number of rules.
This has been achieved by dividing the set of rules into different modules.

3.1 Introduction
The concept of a module results from the need to partition the rules in a large
program into functional groups which we call modules.

3.1.1 Predicate qualification

To enable different modules to be elaborated independently, we need a method by


which the predicate names of the modules are automatically made independent.

The simplest method is to extend the rule names by systematically prefixing them
with the module name. In this way, we implicitly partition the rules by partitioning
the rule names; semantically, the situation is exactly the same as a Prolog without
modules. We will call this prefix a qualifier.
<rule name> ::= <prefix> : <suffix>
<prefix> ::= <letter> <alpha num>
<suffix> ::= <letter> <alpha num>

Examples :
lexicon:data(1) ->;
lexicon:data(2) ->;
lexicon:pn(X) -> ...
...

grammar:sentence(X) -> lexicon:pn(X1) grammar:sv(X2)...


grammar:error_message(M) -> sys:write(M);
grammar:data(8) ->;
Aociation Prolog
R3-2 Reference Manual HERITAGE

...

The rule names of different modules are different by definition, since they have
different qualifiers (it is important to emphasise that the prefix+suffix sequence is
not a structure, but an indivisible identifier).

The basic concept is therefore a partitioning of rule symbols (or rule names), which
results in a partitioning of the corresponding rules. Each partition is called a
module. This concept is completely dynamic: when a rule is created with a rule
name belonging to an unused partition, this corresponds to the creation of a new
module.

All the modules are on the same level, and the concept of nested modules does not
exist.

Please note.
To be compatible with the Prolog II interpreter, the prefix syntax has been extended
to simulate inclusion, using ":" inside the prefix. For example, Base:Normal:data
is an identifier whose prefix is "Base:Normal", and whose suffix is "data".

3.1.2 Functor qualification

To maintain the symmetry between data and programs, the same partitioning is used
for rule symbols and functor symbols. Functor qualification also makes it possible
to guarantee that certain names will not interfere with other modules (designation of
a temporary file, opaque data type, etc.).

To clarify notation, a specific notation has been created for certain functors called
generics. These functors can be used as "global" symbolic names (in the sense that
they are identical in all modules).
<functor name> ::= <rule name> | <generic name>

<generic name> ::= : <suffix>

Examples of generic names:


:john, :data, :sentence, :singular

Generic identifiers correspond to those used by default for user names when no
module declaration is made.

3.1.3 Simplification of notation

It is relatively cumbersome to have to systematically specify the qualifiers, and this


can easily be avoided in source texts by indicating the start and end of the rules in a
module. The qualifications are then performed automatically when the module is
read.

The previous example can thus be written as follows in the source text:

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R3-3

module("lexicon");
data(1) ->;
data(2) ->;
pn(X) -> ...
end_module("lexicon");
module("grammar");
sentence(X) -> lexicon:pn(X1) sv(X2)...
error_message(M) -> sys:write(M);
data(8)...
end_module("grammar");

Any identifier written without the ":" character is said to be written in simplified (or
non qualified) notation. In the source text, it is represented by its suffix only.

The only convention is that if the qualifier is different from the module qualifier, the
complete (i.e. qualified) form of the rule identifier must be specified. In the
subsequent sections we describe other directives which are used to simplify notation
further.

By default, the qualification rule is the same for rule names and functor names.

Example in Edinburgh syntax:


module("test"). /* -- defined program -- */
myprint(X) :- ... test:myprint(X) :- ...
data(1). test:data(1).
data(:john). test:data(:john).
do_print1(L) :- test:do_print1(L) :-
C =.. [myprint|L], C =.. [test:myprint|L],
call(C). sys:call(C).
do_print2(L) :- test:do_print2(L) :-
C =.. [write|L], C =.. [sys:write|L],
call(C). sys:call(C).
do_list_data :- test:do_list_data :-
listing(data/1). sys:listing(test:data/1).
end_module("test").

3.1.4 Some simple rules for use

One simple way to use the modules is to use generic names to write the same data in
several modules, and to prefix all rule call names which are not in the current
module or the system module. For example:
> insert;
module("lexicon");
np(:john) ->;
np(:marie) ->;
....
end_module("lexicon");

module("grammar");
proper_name(X) -> lexicon:np(X);
...
end_module("grammar");
;
> grammar:proper_name(X);
{X=john}

© PrologIA
Aociation Prolog
R3-4 Reference Manual HERITAGE

....

If you are not sure about the qualifier that has been created for an identifier, you can
use the predefined rule string_ident/3 to discover the associated prefix.

External names can be specified in the module heading, which avoids having to
qualify them, and is similar to an import declaration in a standard programming
language. However this does not prevent you from using other names, provided
they are explicitly qualified.
The example above can thus be written:
module("grammar",["lexicon",["np"]]);
proper_name(X) -> np(X);
...
end_module("grammar");

3.1.5 Standard modules and prefixes

When Prolog is started without specifying the initial state the standard initial state
(file initial.po) is loaded in the working memory.

The initial state consists of three modules:

- The module containing the predefined rules, corresponding to the "sys" prefix.

- The modules constituting the supervisor, whose prefixes have the reserved form
"sys: ...".

- The default module for the user's programs, corresponding to the empty prefix
"".

3.2 Terminology

A large number of misunderstandings have arisen in the past because the same word
has been used to denote both a Prolog object and the character string which
represents it, and so here we will attempt to define a precise terminology. Although
this ambiguity is not particularly troublesome in normal Prolog, it leads to extreme
confusion when dealing with modules: a sequence of alphanumerical characters in a
module M1, may not represent the same object as that denoted by the same
character sequence in a module M2 (in other words the corresponding objects
cannot be unified).

Identifier
An identifier is an element of the set of non-structured objects, whose external
representation complies with identifier syntax.

Complete representation of an identifier

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R3-5

This is a character sequence which is the unique and non-ambiguous


representation of a identifier-type object, whatever the conventions for reading
and writing. It follows that we will refer to this character sequence as the
complete identifier. A complete identifier is formed by concatenating the
characters of a prefix, the character ";", and an abbreviation of the identifier
called, naturally enough, an abbreviated identifier.

Identifier family
A family "p" will be the set of all identifiers having the prefix "p". A family
will be denoted by the string corresponding to the prefix attached to the names
it contains.
Thus, sys:out, sys:in belong to the family "sys".
In the same way, sys:env:files belongs to the family "sys:env", :peter belongs
to the family "".

Reading and writing operations


These operations associate a Prolog object (internal representation) with a
character sequence (external representation) or vice versa.

Context for reading and writing


Rules governing the transition from an abbreviated identifier to a complete
identifier (or vice-versa) during a reading or writing operation.

Abbreviated representation of an identifier


This is an external representation of an identifier without prefix. The
complete representation can be determined in a non-ambiguous way by means
of the reading/writing conventions (or the reading/writing context). Two
identical abbreviated representations may represent different objects when
they are in different contexts, but they will always represent the same object
when they are in the same reading/writing context.

Module "p"
In a program, this module consists of all rules and facts whose access
identifier has the prefix "p" (here, the Prolog arrays are treated as facts). This
is therefore a dynamic concept: the modules evolve according to the state of
the program. The concept of a module is thus defined as the grouping
together of rules and facts whose access identifiers belong to the same family.

3.3 Identifier syntax

The syntax of the identifiers is extended so that they can be grouped by prefix. The
syntax of a complete identifier is thus:

full_identifier = prefix , prefix_limit , abbreviated_identifier ;


prefix_limit = ":";
prefix = [ name, { prefix_limit, name } ];
abbreviated_identifier = name ;
name = letter, { letter | digit | "_" } ;

© PrologIA
Aociation Prolog
R3-6 Reference Manual HERITAGE

Therefore the following complete identifiers are correct and all represent different
identifiers:
:peter grammar:plural
data:peter grammar:singular
sys:write lexicon:name
sys:env:files

The following identifier is not a complete identifier:


peter

NB: It is important to be able to distinguish syntactically between complete


identifiers and abbreviated identifiers. The decision as to which complete name is
associated with an abbreviated name, is governed by the reading/writing context
(this concept is developed below).

It should also be emphasised that the ":" is NOT an operator: the name does not
represent a divisible object, only the character string representing it can be
decomposed. When we refer to an abbreviated name, we are therefore referring to
the corresponding character string, and it is the reading context alone which enables
us to determine which Prolog object is concerned:

I/O with naming


conventions (context) analysis
abbreviated identifier ——> complete identifier——> identifier
character string character string Prolog object

Standard Prologs can easily be integrated into this structure: identifier syntax
corresponds to the abbreviated notation, and the convention for their extension is to
prefix them with"". This is the default convention when Prolog II+ starts.

3.3.1. Parameterization of the writing of a complete identifier

Until now, and in the remainder of this manual, the character separating the suffix
from the prefix in the representation of a complete identifier has always been shown
as the character ":". This character is chosen by default to fulfill this purpose.

However, you can replace it with a graphic character by executing the built-in
predicate set_prefix_limit/1.

set_prefix_limit(s)
s must be a string comprising one graphic character. It becomes the character
separating the prefix from the suffix when a complete identifier is written.
Example:
> set_prefix_limit("$");
{}
> ident(sys$ident);
{}
> string_ident(x,y,a$a$ident);
{x="a$a",y="ident"}

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R3-7

prefix_limit(s)
Unifies s with the character separating the prefix from the suffix when a
complete identifier is written. Example:
> prefix_limit(x) set_prefix_limit("$") prefix_limit(y);
{x=":", y="$"}

When you change the way complete identifiers are written, you must take great care
and be aware of the consequences. If the separating character is defined
dynamically, you must take account of the representations of identifiers that appear
statically in the data of Prolog or C programs. In addition, when nested prefix
notation is used for a module ("Base:Normal:Data"), the name of the module may
change if this primitive has been used.

A C function is available to find out which character is currently in use. It is


described in Chapter 7.

3.4 Context for Reading and Writing

A reading/writing context defines the conventions for the transition from an


abbreviated identifier to a complete identifier for a reading operation (and vice-versa
for a writing operation). At any given time, one and only one context is used, this is
the current reading/writing context.

A context can be defined in abstract form by the pair:

(sequence of complete identifiers, default prefix)

3.4.1 Reading

When an abbreviated identifier is read, it is identified with the first identifier in the
sequence having the same abbreviation. If no such identifier exists, it is extended by
the default prefix.

For example, let us suppose we have the following context1

("sys:out" "sys:outm" "m:out", "m1")

Using this context, the following character sequences are read:

Abbreviated identifier Complete identifier


out --> sys:out
mastic --> m1:mastic
outm --> sys:outm

1The precise notation for these specifications in Prolog II+ is given below: see Section 3.4.4

© PrologIA
Aociation Prolog
R3-8 Reference Manual HERITAGE

3.4.2 Writing

The names are written in the most abbreviated form allowed by the context. If we
want to write an identifier having the prefix p and the abbreviation a, the abbreviated
representation is written a

1. if the identifier appears in the identifier sequence and is the first in the
sequence to have the abbreviation a,

2. if the default prefix is p and no identifier in the sequence has the


abbreviation a.
In all other cases, the complete representation is written.

The existence of these two conditions ensures that reading/writing operations


performed in the same context are reversible. For example, using the above context,
the following character sequences are written:

Complete identifier External representation


sys:out --> out
m:out --> m:out
m1:mastic --> mastic
sys:outm --> outm
b:c:toto --> b:c:toto

3.4.3 Simplified notation of the identifier sequence of a context

Most programs use predefined rules, which means that to use the abbreviated
representation of their names, these names must all be listed explicitly in the
definition of the context. In order to simplify context definition, we will use the
concepts of an explicit sequence and an implicit sequence. The notation of the
sequence is lightened by allowing a set of identifiers in the sequence to be denoted
implicitly by their prefix.

The "sequence of complete identifers" in a context can thus be represented by a


pair:

(explicit sequence of identifiers, implicit sequence of identifiers)

in which the implicit sequence represents the identifier families in the program,
denoted by their prefix. A context can now be described in abstract form by the
following structure:

((explicit sequence, implicit sequence), default prefix)

Below is an example of such a lightened description for the following sequence:


"m1:out", "m2:peter", all identifiers in the family "m4",
all identifiers in the family "sys":

(("m1:out" "m2:peter", "m4" "sys"), "a:b")

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R3-9

However there is a danger of confusing the concept of a sequence of identifiers for


a reading/writing context, with the concept of an identifier family in a program. The
set of identifiers used in a program increases with time, and thus the reading/writing
operations become non-reversible.

To solve this problem, we use the concept of an identifier family which is closed for
the context. This identifier family is a sub-set of a given name family, and is locked
by a special declaration (close_context_dictionary/1) which can only be modified by
ad hoc primitives (add_implicit/2, remove_implicit/2).

"sys"family locked for co ntext operations

in others
out. ...
.

sub-set used for implicit


definitions of contexts

Therefore, in any context operation concerning a sequence of identifiers denoted


implicitly by their prefix, the set concerned is

- either the locked sub-set, if the family is closed for the context,

- or otherwise the set of identifiers for the complete set. This set consists of all
the identifiers which have appeared in the program history with the relevant
prefix.

An example of an identifier family closed for the context is the family "sys". The
locked sub-set contains the set of identifiers for the rules and predefined functions
in Prolog II+.

We will use the term good context, to refer to a context in which all the implicit
sequences are closed for the context. A good context guarantees that the reading
and writing operations are repeatable and reversible.

An example will help to understand these concepts. Let us suppose we have the
following abstract context:

(("m1:out" "m2:peter", "sys"), "a:b")

Reading of an abbreviated identifier out will produce m1:out, since the first
identifier in the explicit sequence has the same abbreviation.

© PrologIA
Aociation Prolog
R 3 - 10 Reference Manual HERITAGE

Reading of an abbreviated identifier paul will produce a:b:paul, since this


abbreviation does not match with any element in the explicit sequence, or with an
abbreviated identifier in the locked sub-set of the family "sys".

Reading of an abbreviated identifier nil will produce sys:nil since this identifier is
part of the locked sub-set of the family "sys" closed for the context .

Writing of sys:out will produce sys:out, since the first identifier in the sequence
having the abbreviation out has a different prefix.

3.4.4 Notation in Prolog

The explicit sequence of identifiers of a context is represented in Prolog by an


alternating list in which we group the names having the same prefix:
prefix1.list_of_abbreviated_names1,…
prefixn.list_of_abbreviated_namesn.nil

Thus the explicit sequence "m1:out" "m1:outm" "jf:init" "m2:toto" "m2:peter" will
be represented as follows in infixed notation:
"m1".("out"."outm".nil)
."jf".("init".nil)
."m2".("toto"."peter".nil)
.nil

or in notation with square brackets:


["m1",["out","outm"],
"jf",["init"],
"m2",["toto","peter"] ]

3.4.5 Primitives for the contexts and the identifier families

set_context (Identification, ExplicitSequence, ImplicitSequence, Default)


This command makes it possible both to describe a context and to activate it
as the current reading/writing context. When this command is executed, the
context described is memorized in the environment module in the following
form:
sys:env:context(identification,
explicit_sequence,
implicit_sequence,
default_prefix) ->;

When a new context is activated, the old one is no longer taken into account.
The argument identification must be an identifier or a string. The second
argument must be an alternating list as described in the previous section. The
third argument is a list of strings representing prefixes, and the fourth
argument is a string defining the default prefix.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 11

When Prolog starts, the current reading/writing context is the good context
defined by the following command:
set_context("user", [ ], ["sys"], "")

As another example, the second abstract context defined in section 3.4.3 above
will be defined and activated by the command:
> set_context(No2, ["m1",["out"],"m2",["peter"]],
["sys"], "a:b");

set_context(Identification)
Reactivates a context by giving its identification, once it has been defined.

Note 1:
When defining contexts which do not contain the family "sys" in the
implicit sequence, it is important to bear in mind that nil does not
generally represent the end of list marker sys:nil : it is the default prefix
and the explicit sequence which perform this function. Consequently,
errors may result when using predefined rules which take these values as
an argument. In this situation, it is recommended to use the complete
name sys:nil, or the equivalent notation [ ].

Note 2:
When a rule contains a context declaration, it comes into effect as soon as
the rule is executed, (and not when the rule is read). In the example
below, the context is not modified, and the abbreviated identifier "peach"
is identified with ":peach", since the reading context when the rule is read
is "user".
Prolog II+, ...
>insert;
apple ->
set_context("new",["other",["peach"]],[],"def");
peach;
peach ->;;
{}
>

current_context(t0)
current_context(t0, t1, t2, t3)
Unifies t0 with the term identifying the current reading/writing context, and
unifies t1, t2, t3 with, respectively, the term defining the explicit sequence, the
term defining the implicit sequence, and the context's default prefix.

close_context_dictionary(s)
Closes the identifier family s for context operations. From the moment this
command is executed, s remains in the same state, ie, no new identifier
belonging to this family will be taken into account for context operations.

© PrologIA
Aociation Prolog
R 3 - 12 Reference Manual HERITAGE

add_implicit (s1, s2)


Adds the identifier with abbreviated name s2 to the locked sub-set of the
family s1 closed for the context. If s1 is not a prefix for a family closed for
the context, an error occurs.

remove_implicit (s1, s2)


The opposite operation: removes the identifier with abbreviated name s2 from
the set of identifiers taken into account for the context of the closed family s1.
If this command is applied to the family "sys", it has the same effect, for
abbreviated identifiers, as the un-reserving of reserved names.
Let us suppose that we wish to delete the identifier sys:dictionary from the set
of identifiers taken into account for context operations concerning the "sys"
family. The following example shows the result obtained:
> string_ident(p,a,dictionary)
outl(sys:dictionary.dictionary);
dictionary.dictionary
{p="sys", a="dictionary"}
> remove_implicit("sys","dictionary");
{}
> string_ident(p,a,dictionary)
outl(sys:dictionary.dictionary);
sys:dictionary.dictionary
{p="", a="dictionary"}

dictionary
The abbreviated form of accesses in the family having the same prefix as the
reading/writing context's default prefix is written on the current output.

dictionary (s1)
Unifies s1 with the list of prefixes of user modules present in memory.

dictionary (s1,t0)
Unifies t0 withthe list of access identifier/arity forms of rules in the module
s1. Example:
> insert;
aa:bb(1) ->;
aa:cc(1,2) ->;;
> dictionary("aa",L);
{L=aa:bb/1.aa:cc/2.nil}

file_dictionary(f, l_pref)
Unifies l_pref with the list of prefixes of the modules (containing rules)
present in file f. This file must contain compiled prolog code, and is therefore
an object module or a binary state for start-up. It is obtained using one of the
save predicates exit, save_state, save.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 13

3.5 Modules
A definition of modules in Prolog must be able to deal efficiently with situations as
varied as those that can be found, for example, in a natural language system. In
such a system, there are essentially two modules: the first is a lexicon containing
many names from the data base and the grammar, and few rule names. The second
is the grammar, containing mainly its own names, and calls to the lexicon. Let us
look at the following example:
lexicon:pn(data:Peter, grammar:singular ) -> ;
lexicon:pn(data:John, grammar:singular ) -> ;
...
lexicon:verbø(data:smiles, grammar:singular ) -> ;
...
lexicon:adj(data:plural, grammar:plural ) -> ;
...

grammar:sentence(x,z) -> grammar:sn(x,y,g) grammar:vp


(y,z,g);
grammar:sn(x.l,l,g) -> lexicon:pn (x,g)
...

The fundamental reason for creating the reading context system described in the
previous sections was to define conventions that would make it possible to simplify
the writing of identifiers in such extreme situations as this one.

It is easy to construct a context which will allow us to write the lexicon module
using only abbreviated identifiers. The prefix which covers the greatest number of
identifiers is taken as the default prefix, and the rule names are represented in the
explicit sequence as follows:
set_context(:lex
, ["grammar", ["singular", "plural"],
"lexicon", ["pn", "verbø", "adj"] ]
,[]
,"data" )

3.5.1 Definition of a module

A module "p" is a grouping together of all the rules, facts, evaluable functions,
assigned identifiers (using assign) and arrays whose access identifier belongs to the
family "p" (ie have the prefix "p"), in a given program, and at a given time.
Identifiers from the family "p" can appear in other modules, but not as access
identifiers (ie head predicate names). This concept of a module is dynamic: when a
rule is deleted or created the module which corresponds to its access identifier is
modified accordingly.

More simplistically, we can say that a module is a grouping together of all rules and
facts whose access identifiers have the same prefix.

A module can exist in text form (before reading), or in internal form (after reading).
We will refer to a source module for the first case, and an object module for the
second.

© PrologIA
Aociation Prolog
R 3 - 14 Reference Manual HERITAGE

In a source module, the heading of the module defines the context for reading its
rules. Once a module has been read, the current reading/writing context, which was
in effect before reading, is restored.

3.5.2 Source module

To define a source module, we must first define:


- the module's reading and writing context,
- an optional rule for initialization of the module,
- the module's actual rules.

The context is used to read the source module when it is compiled. It is also used
for reading when the module is decompiled (using the list or editm primitives).

If the module initialization rule exists2 it is executed automatically as soon as


module compilation ends, with the current execution context, not the module's
reading context. This rule or group of rules has no argument, and its access
identifier is: the identifier ini_module prefixed by the module prefix.

A source module therefore consists of a sequence of rules enclosed by two


directives:
sys:module( access_prefix, ... );
....
sys:end_module( access_prefix );

Note. If the source module has not been constructed in this way (e.g. the rules have
been compiled using insert or assert, in any order), the editm primitive can be used
to reconstruct it in this form.

The declarations module and end_module are to be used in the Prolog rule insertion
mode (see insert paragraph 3.6). Consequently, the Prolog elements enclosed by
these two directives must be rules (or comments, which are ignored). The module
declaration begins the definition of a module, and end_module ends it.

The argument denoting the access prefix in the module directive must be the same
as that which appears in the end_module directive, and all the rules enclosed by
these two directives must have an access identifier with this prefix. This convention
prevents naming errors during reading.

In simple terms, the module directive means "ihe following rules must be inserted
with the writing context defined here, checking that the rules to be read possess (or
acquire) the desired prefix".

2 If the module is modified, i.e. part of the module is recompiled (using reinsert or insertz) or
reloaded (using reload), the initialization rule is only executed if it is one of the modified rules.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 15

The complete version of the directive module includes a definition of the module's
reading context (see the description of contexts, section 3.4):
sys:module( access_prefix,
explicit_sequence,
implicit_sequence,
default_prefix)

If all the arguments are not given, the following default values apply (we will assume
that the reading context of the directive sys:module, allows abbreviation):
module(p) <=> module( p, [], ["sys"], p )
module(p,s) <=> module( p, s, ["sys"], p )
module(p,s,i) <=> module( p, s, i, p )

When the sys:omodule(context) directive replaces a module directive, the module


reading context is defined by the character string context . This context is defined
beforehand by calling the set_context primitive or by a previous module directive. If
this context does not exist, the omodule(context) directive is equivalent to the
module(context) directive, when the default rules apply.

The reading context defined by the module's header is used to read the rest of the
module, including the sys:end_module directive. The context existing before
reading is then restored.

If, when the module is read, a rule or a fact is created with an access identifier whose
prefix differs from that of the module, an error is generated.

The two example modules at the beginning of section 3.5 can thus be written in
different ways:

1st example
module("grammar");
sentence(x,z) -> sn(x,y,g) vp(y,z,g);
sn(x.l,l,g) -> lexicon:pn(x,g);
...
end_module("grammar");

2nd example
module("grammar", ["lexicon",["pn","verbø", ...]]);
sentence(x,z) -> sn(x,y,g) vp(y,z,g);
sn(x.l,l,g) -> pn(x,g);
...
end_module("grammar");

3rd example
module( "lexicon"
, ["lexicon", ["pn", "verbø", "adj"],
"grammar", ["singular", "plural" ]]
, [ ]
, "data");
pn(Peter,singular) ->;
pn(John,singular) ->;
...
verbø(smiles,singular ) ->

© PrologIA
Aociation Prolog
R 3 - 16 Reference Manual HERITAGE

...
adj(data:plural,plural) ->;
...
end_module("lexicon");

Words entered by the user will be read with the context defined by:
set_context( :my_entry, [ ], [ ], "data" ) ;

Using the concept of a reading context for the module, we can redefine more clearly
certain primitives used within a module:
module("example", ["example", ["out"]] ) ;
out(x) -> nicer(x,y) sys:out(y);
...
explain(x) -> out(x) TellSomethingAbout(x);
end_module("example");

In the example below, the initialization part of the module is used to add the relevant
rule to the module as a Prolog built-in predicate. It will also be used to call this rule
using the abbreviated identifier, if the current context contains the sys module of
predefined rules:
module("parser");
ini_module ->
assert(sys:parse(x),parse(x,nil).nil)
add_implicit("sys","parse");
parse(l1,l2) -> sentence(l1,l2);
...
end_module("parser");

3.5.3 Object module

Manipulation of object modules concerns internal representations, and so the


concept of a context is not involved.

The load and save primitives are used to load and save several object modules.

If a binary start-up state or a file of object modules contains a module "m"


comprising a rule named m:ini_module, then this rule is automatically executed
when the binary state or object file has been loaded.

When an object module is saved on file, it is saved with a dictionary which makes it
possible to rename the prefixes when loading. It is thus possible to solve name
conflict problems, whatever they may be, and to construct programs which do not
interfere with the data they manipulate; or on the contrary, to define data base and
lexicon type programs, whose names can be merged.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 17

3.6 Summary of how to use identifiers, contexts and modules

3.6.1 Identifiers

Identifiers are Prolog objects that are used to construct other Prolog objects. They
can be used in two different ways:
- as predicates to define a rule (section 3.1.1.)
- as functors to be used as data (section 3.1.2.)

Prolog identifiers (see section 3.3) always have the same syntax:
prefix:suffix

The prefix and suffix are character sequences conforming to the chosen syntax
(Prolog II or Edinburgh). ":" can be replaced by a graphic character (see
set_prefix_limit).

The advantage of this syntax is that a large set of identifiers can be identified simply
from a specific part of their name.

The term identifier family prefixed "wotsit", refers to all identifiers (predicates and
functors) whose name is written wotsit:suffix (section 3.2.).

The term module prefixed "wotsit", or module "wotsit", refers to all rules and/or
arrays and/or static variables whose access identifier is written wotsit:suffix
(section 3.2.).

Advice. If you want to have an invariable identifier for all programs that is easy to
write and remember, choose the empty prefix for this identifier. In the sections
above (section 3.1.2) it is called the generic functor.

3.6.2 Abbreviated notation and contexts

Very often a situation arises where the vast majority of the identifiers to process are
all written with the same prefix. To avoid having to repeat this prefix continually, we
need to have an abbreviated form of identifier representation.

To achieve this goal, and thus simplify program implementation and legibility, we
have conventions for simplified representation of identifiers, which determine each
individual Prolog data item. These conventions are called reading/writing contexts
(see section 3.4).

Conversion between the internal encoding of the data item and its external
representation is only carried out during reading and writing operations.

A reading/writing context performs the following function:

© PrologIA
Aociation Prolog
R 3 - 18 Reference Manual HERITAGE

Unless other instructions are received, when an abbreviated identifier


representation is read it must take the default prefix pref, except for the following
abbreviated representations id1, id2, id3, … which take respectively the prefixes
pref1, pref2, pref3, … . Whenever anything has to be written, (i.e. when the
shortest possible representation must be constructed), the Prolog identifier we
wanted to write must be obtained after rereading.

A context therefore indicates which prefix must be attributed to the simplified


representation of an identifier so that its complete representation is obtained. This is
why the context is defined by:
- a list of explicit prefix attributions,
- a default prefix for other cases.

Such a context is completely defined. It is referred to as a healthy context.

Properties:
• The list of explicit attributions is processed from left to right.
• If an abbreviated representation appears several times in the list, it is given the
first associated prefix (i.e. the leftmost prefix).
• The strings declared in the context do not all need to correspond to existing
identifiers. If Prolog has to create or read an identifier, it will consult this list of
potential representations.

Writing can be further shortened in the definition of the context. When you want to
include a whole identifier family in the explicit list, instead of giving an exhaustive
list you can simply specify the family's name. This is considered to be an implicit
attribution, equivalent to calculating the explicit list which stems from it and
inserting it in the existing list, each time a prefix is attributed.

A context is therefore defined by:


- a list of explicit prefix attributions,
- a list of implicit prefix attributions,
- a default prefix for other cases.

and its definition in Prolog (sections 3.4.4. and 3.4.5.):


set_context(Id, ExplicitList, ImplicitList, Default);

This context now becomes dependent on time, since the families designated for an
implicit attribution may grow over a period of time.

To re-establish a healthy context, and remove this unknown part in the case of
implicit attributions, the family must be "closed". This means that when the family
is closed, the explicit list it represents is calculated and memorized once and for all.
The context is once more completely defined and invariable.

3.6.3 Modules

Since Prolog is incremental, with no data types, there is no constraint on the order of
rule insertion.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 19

However, you can group together all the rules of a single module and define them at
the same time. You can also define different reading conventions for this group,
compared to those of the execution context. Provided the context is healthy, it is
thus possible to make the module definition autonomous.

A module can thus be defined by stating:


- a reading/writing context for the module,
- a set of groups of rules,
- (optional) a module initialization rule to execute just after compiling or loading
the rules.

A module can be defined using the module or omodule declaration (section 3.5.2):
insert; insert;
module(p,e,i,d); equivalent to ->set_context(p,e,i,d)
->prefix_verif_mode(p)
rules… rules…
end_module(p); ->exec(p:ini_module);
->restore_context;
… …
; ;

Warning. If you use implicit conventions in a module context, even a healthy


context, the implicit attributions will only occur if the family has been defined
beforehand. Similarly, if you use rules outside a module in a module initialization
rule, the initialization will only be successful if the these rules have been defined
beforehand.

This means that although there are no order constraints on the groups of rules,
constraints may apply to the order in which the modules are compiled or loaded.

It is very important to mention that the notions of files and modules are fully
independent. A source file can include several modules, and the same module name
can appear in several files loaded simultaneously.

3.7 Adding, deleting and searching for rules

The Prolog II+ system comprises a compiler which translates your Prolog source
programs into an object language whose "level" (ie proximity to the host machine)
varies from one machine to another. Nevertheless, in all circumstances it is much
more efficient than simple interpretation of the Prolog source code. On the other
end, it is difficult to restore the exact source text of certain rules because variable
names disappear.

The Prolog II+ compiler is incremental (translation is performed rule by rule), and
transparent (rules are compiled and indexed as soon as they are written, without
having to give any particular command).

© PrologIA
Aociation Prolog
R 3 - 20 Reference Manual HERITAGE

By default Prolog II+ optimizes the compiling of certain rules; arithmetical


expressions, type tests or the built-in predicates val, assign and block. This makes
execution of these rules more efficient, but also has an effect on some other built-in
predicates (such as rule, debug or freeze). Therefore, there is a Prolog II+
activation option enabling you to remove these compiling optimizations (see the
User's Manual for more details).

To minimise the time required to choose a rule that can be used to execute a specific
goal, when Prolog II+ compiles a group of rules it creates an image of the group. It
puts in this group all the rules whose first argument or value are identical. In this
way it creates several separate groups of rules, and to execute any single goal either
all or none of the rules in any one group will be chosen. This type of processing is
called indexing. If indexing is removed, this is the same as leaving all the group’s
rules available as valid choices.

In the text and programs that follow, the term identifier/integer denotes a group of
rules for which the access identifier of the head is identifier, and the number of
arguments is integer.

Before we go on to describe the primitives, the reader should take note of two very
important consequences of rule group modifications, which will affect the program's
execution.

1. When a group of compiled rules is modified (rules are added or deleted), its
indexation is deleted, and so the index primitive must be used to restablish it.

2. If a group of rules is modified while one of its rules is being executed (the choice
is still on standby), the behavior of the execution (for backtracking or a subsequent
call), depends to a very great extent on the configuration of the rules (determined by
the group's structure, the current rule, the modified rule).

As far as possible, it is preferable either to exhaust the choices before modifying the
rules, or otherwise to delete the indexation before the rules are executed and
modified.

Another technique to improve performance is has been introduced into Prolog II+; a
new type of rule called “non compiled facts”. The aim of this technique is to
optimize management of problems by handling facts dynamically. To verify a fact,
there is no point in optimizing the execution of the rule body since it is non existent,
but on the other hand it is important to improve accesses to the arguments.

For the “non compiled facts”, Prolog II+ will install an indexing process based on
all the fact’s arguments, so that at execution time access to the relevant facts is
virtually instantaneous. It is not possible to delete the indexing installed on “non
compiled facts”.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 21

assert(t, q)
asserta(t,q)
Compiles and adds a rule at the beginning of a group.
t must be a term capable of being a rule head, that is, an identifier or a tuple
whose first argument is an identifier (eg <ident, arg1, … argn> or ident(arg1,
… argn), these two notations are equivalent). q must be a list of terms.
The execution of assert(t,q) compiles and adds the rule above the group of
rules having the same "name" as t, that is at the beginning of the group
corresponding to t. For example, the following two commands
assert(conc(e.x, y, e.z), conc(x, y, z).nil);
assert(conc(nil, y, y), nil);

written in this order, have the effect of adding the program


conc(nil, y, y) ->;
conc(e.x, y, e.z) -> conc(x, y, z);

Do not allow the adding of rules containing infinite trees: however this can be
achieved with the predefined rule equations (see section 2.3).

assert''(t,q)
assertz(t,q)
Compiles and adds a rule at the end of a group.
Function in the same way as assert, but the rule is added below the group
corresponding to t, and not above. Example: the two following commands, in
the order shown, produce the insertion of the same conc program as above:
assert''(conc(nil, y, y), nil);
assert''(conc(e.x, y, e.z), conc(x, y, z).nil);

Do not allow the adding of rules containing infinite trees: however this can be
achieved with the predefined rule equations (see section 2.3).

assertn(t, q, n)
Compiles and adds a rule at the n-th position in the group.
Functions in the same way as assert, but the rule is added at the n-th position
in the group corresponding to t. Example:
assert(myrule(2), nil);
assertn(myrule(0),nil,1);
assertn(myrule(1),nil,2);

typed in this order, have the effect of adding the following program:
myrule(0) ->;
myrule(1) ->;
myrule(2) ->;
Cannot be used to add rules containing infinite trees; this is done using the
predefined rule equations (See section 2.3).

© PrologIA
Aociation Prolog
R 3 - 22 Reference Manual HERITAGE

current_predicate(i/a)
Tests for presence of a rule.
Executes if there exists a rule with access identifier i and arity a. If a is a
variable, and i is known, this primitive lists in succession all the values of a
corresponding to a rule with access i. If i is not known (i.e. is a variable), the
rule unifies the argument in sucession with all the i/a forms of the rules in the
module specified by the default prefix of the current context. i and a cannot
be free variables at the same time.

discontiguous(i/a)
Enables a rule group to be discontiguous.
When a rule with access identifier i and arity a is compiled using the insert
predicate, it will be added at the end of its group. This directive makes it
possible to split rule groups within one or several files. Note that this
directive does not have any effect on compiling performed using the reinsert
predicate, which will overwrite the existing rule group with the newly detected
group. This is a compiling directive, not a predicate. This means it can appear
in the middle of a source you are compiling but cannot be located in a rule
body.

dynamic(i/a)
Declares a group of dynamic rules.
All Prolog II+ rule groups are dynamic, i.e. they can be modified. This
directive therefore has no effect and only exists to ensure compatibility with
the Prolog standard. This is a compiling directive, not a predicate. This
means it can appear in the middle of a source you are compiling but cannot be
located in a rule body.

ensure_loaded(f)
Ensures compiling of a file is performed once only.
Compiles file f at the location of the directive if this file has not already been
compiled during this same compiling phase, otherwise does nothing. At the
end of compiling the highest nesting level, and therefore for a new compiling
phase, the file is no longer considered to have been compiled. The file f is
compiled using the same mode as the mode used by the higher level
compiling predicate (insert, reinsert, insertz).
This is a compiling directive, not a predicate. This means it can appear in the
middle of a source you are compiling but cannot be located in a rule body.

fasserta(t)
fassertz(t)
Adds an uncompiled fact.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 23

These rules add an uncompiled fact, at the start (fasserta) or end (fassertz) of
its group. Assertion is extremely fast and enables you to manage very large
fact bases. In addition, since these facts are indexed through a preliminary
call to the init_fassert primitive, they can be accessed with good
performances. The term t must have the form of a rule head, i.e. a tuple whose
first element is an identifier. You cannot mix compiled rules (assert, insert)
and uncompiled facts (fassert) in the same group. Here is an example:
> fasserta(myrule(1,2,3,4.nil,<44,"abc">,6,1.2.2e0.nil));

freplace(t, n_arg, t1)


Replaces an unindexed argument into an uncompiled fact.
Replaces the argument of rank n_arg with the term t1 in the facts that unify
with t. These facts must be created using either the fasserta or fassertz
predicate. This argument should not be an indexing argument (see
init_fassert predicate). Here is an example:
> freplace(myrule(1,2,3,x,y,z,t), 7, 345);

freplace(i/a, n_reg, n_arg, t1)


Replaces an unindexed argument into an uncompiled fact.
Replaces the argument of rank n_arg with the term t1 in the fact of rank
n_reg in the group with identifier i and arity a. This fact must be created
using either the fasserta or the fassertz predicate. This argument should not
be an indexing argument (see init_fassert predicate). Here is an example:
> freplace(myrule/7, 2, 7, 345);

fretract(t)
Rapid deletion of an uncompiled fact.
Deletes the uncompiled facts that unify with t in a very efficient way. The
search for these facts is very fast and benefits from the optimizations
implemented for access to non compiled facts. These facts must be created
using either the fasserta or the fassertz predicate. As soon as a fact unifying
with t is found, it is deleted.
If a suitable fact is invisible at decompiling time it is deleted, and the primitive
executes without unifying t's free variables.
Here is an example:
> fretract(myrule(1,2,3,x,y,z,t));

fretractall(t)
Rapidly deletes all the non compiled facts corresponding to a pattern.
Very efficiently deletes in a single operation all the facts unifying with t.
These facts must be non compiled, and created by one of the two predicates
fasserta and fassertz. t must make it possible to identify an index for this fact
base using the following method: all arguments of the goal that are not free
must be atoms, and must denote a combination of arguments corresponding to
an indexing combination defined for this fact base. If this is not the case an
error is generated. Example:
> init_fassert(bb/3,(1.2.3).(1.2).nil);
{}
> fasserta(bb(1,2,3));
{}

© PrologIA
Aociation Prolog
R 3 - 24 Reference Manual HERITAGE

> fasserta(bb(1,2,x));
{}
> fasserta(bb(1,2,1.2));
{}
> fasserta(bb(1,1,1.1));
{}
> fretractall(bb(1,x,3));

-> <bb(1,v36,3)> : THE COMBINATION CORRESPONDING TO THE


ARGUMENTS DOES NOT EXIST

> fretractall(bb(1.2,2,x));

-> <bb(1.2,2,v59)> : AN INDEXED ARGUMENT IS NOT ATOMIC

> fretractall(bb(1,2,x));
{}
> list(bb/3);
bb(1,1,1.1) -> ;

{}

hidden_rule(x)
Hides rules for decompilation.
Makes rules "non visible for rule". If x is in the form i/a where i is an
identifier and a is an integer, this primitive concerns the group of rules with
access i and arity a. If x is a string, it concerns all rules in the module x. "Not
visible for rule" means that it is not decompilable, i.e. it cannot be
reconstructed as a Prolog source. Therefore, none of the primitives to
decompile or print these rules will have any effect.

hidden_debug(x)
Hides the accesses to rules.
Makes rules "non visible for debug'. If x is in the form i/a, where i is an
identifier and a is an integer, this primitive concerns the group of rules with
access i and arity a. If x is a string, it concerns all rules in the module x. "Not
visible for debug" means that the access is hidden. The debugger will not
show the calls to this group of rules, or the calls made in the body of rules in
this group. If a visible rule is called in the body of a non visible rule, only the
body of the visible rule will be displayed. Predefined rules that return rule
accesses (e.g. dictionary), ignore these "hidden for debug" rules. It should be
noted that to decompile these rules, you must use built-in predicates that
decompile rules according to their access identifier and arity, and not global
decompiling rules (i.e. that only require a module name).

hidden(x)
Hides rules.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 25

If x is in the form i/a, where i is an identifier and a is an integer, this primitive


concerns the group of rules with access i and arity a. If x is a string, it
concerns all rules in the module x. Makes the rules non visible for
decompiling and for the debugger or primitives that show the accesses. This
primitive is equivalent to the following sequence of goals: hidden_rule(x)
hidden_debug(x).

include(f)
Includes the compiling of a file.
Compiles file f at the location of the directive. Everything therefore takes
place as if the directive was replaced by the content of file f. File f is compiled
using the same mode as the mode used by the higher level compiling predicate
(insert, reinsert, insertz).
This is a compiling directive, not a predicate. This means it can appear in the
middle of a source you are compiling but cannot be located in a rule body.

init_fassert(i/a, l)
Describes the indexing for a group of uncompiled facts.
Initializes a group of uncompiled facts with access identifier i and arity a.
Argument l is a list (terminated by nil) indicating the indexing combination
chosen for these facts' arguments. This list is arranged according to the
indexing priority. Each element in this list indicates a combination and must
have one of the following values:
- either a list of integers (possibly terminated by nil) indicating a combination
of the arguments to index or one integer if there is only one argument in the
combination. The corresponding hash-code table will then have a default size
(512 entries).
- or a 2-element tuple, formed by:
- in the first argument, the list described above.
- in the second argument, an integer indicating the size of the hash-
code table for this combination.
This predicate must be called before fasserta or fassertz. It can be called
several times for the same rule group, provided the argument l is the same for
the different calls. Here is an example:
> init_fassert(myrule/7, (1.2.3). (4.5.nil). 5. <6,200>.
<2.6,300>. nil);
In this example we choose :
- as a first choice, multiple indexing on the combination of arguments 1, 2 and
3,
- another mutiple indexing on the combined arguments 4 and 5,
- an indexing on argument 5 by itself,
- an indexing on argument 6 alone, with a 200-entries hash-code table,
- and finally an indexing on the combined arguments 2 and 6, with a 300-
entries hash-code table.

© PrologIA
Aociation Prolog
R 3 - 26 Reference Manual HERITAGE

At run-time, an indexing combination is selected according to the type of the


actual arguments: priority is given to integers, reals, identifiers and character
strings. The combinations are tried in their order of appearance in the list. If
amongst the arguments in the first combination, some do not have one of the
types indicated above, then the next combination is tried, and so on.
NB: - After deleting a whole group of uncompiled facts using
suppress(identifier/arity), init_fassert needs to be called again before
to use the fasserta or fassertz primitives.
- Deletion of all the rules in a group does not delete the definition of
indexing. init_fassert must not be repeated (e.g. after several
suppress(i/a,n)).
- The use of the edit and editm primitives on uncompiled facts
transforms them into compiled rules (just like suppress/insert).

initialization(B)
Initializes a rule group.
Includes goal B in the list of goals that will be executed as soon as compiling
of the file that contains this directive has finished. This is a compiling
directive not a predicate. This means that it can appear in the middle of a
source you are compiling, but cannot be located in a rule body. This list of
goals will be executed provided no errors have been detected during
compiling.

insert
insertz
reinsert
Inserts rules.
This predefined rule switches the system into a mode in which statements
(rules) are added in the order they are read on the current input unit. The
directives and declarations are executed and taken into account respectively
immediately they are detected. The insert mode ends either when an empty
statement is found (finds a ";;" in Prolog II syntax) or if the end of the input
file is reached.
Example:
>insert;
conc(nil, y, y) ->;
conc(e.x, y, e.z) -> conc(x, y, z); ;
{}

If an error is found, of syntax for example, a warning is displayed and a


certain number of characters (principally all the characters up to a ";", or up to
the end of a line) are ignored. Insertion then continues. At the end of
insertion, insert generates error 86 and the error complement indicates the
number of errors found during the insertion. The rules are automatically
indexed according to the first argument, as they are input.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 27

Depending on the warning mode chosen at Prolog start-up, when the rules are
read a warning is displayed if a singleton variable appears. A singleton
variable is a variable only appearing once in the rule, and is therefore
theoretically of no use. The warning is not displayed for the anonymous
variable _ .
insert is used to define groups of rules, reinsert is used to redefine groups of
rules, and insertz is used to complete groups of rules by adding alternatives at
the end.
insert causes an error when a group which already exists and has not been
declared discontiguous (predicate discontiguous/1) is read, whereas insertz
appends the new rules at the end of the existing group and reinsert replaces
the previous group with the new definition .
Warning.
This can be dangerous. If an error is made concerning the number of
arguments in a rule inside a group, use of reinsert will cause the previous rules
to be erased when reading of the group continues. In the same way, because
insertz is used to define a group of rules in several pieces (i.e. mixed with
other rules), errors concerning the number of arguments or mix-ups with very
similar predicate names will not be visible.
When a module m is read, the context defined by the module heading is
memorized in the module in the form of a rule
m:module_context(A1,A2,A3,A4) where A1, A2, A3, A4 have values defining
the module's reading context (this rule is used by module editing primitives
such as editm).
insert(f)
insertz(f)
reinsert(f)
Inserts rules from a file.
Function in the same way as insert, but the statements are read on the file
indicated. If the echo mode has been activated (see echo rule), the rules are
displayed on the console as they are read.
When a module m is read, the name of the module's source file is memorized
in the module in the form of a rule m:module_file(s) where s is a string
representing the file name (this rule is used by module editing primitives such
as editm).
is_uncompiled(i/a)
Successes if the rules constituting the group named i of arity (number of
arguments) a. is a set of uncompiled facts, else fails.

list
Lists the current module.
Lists all the rules in the module specified by the default prefix of the current
context.

© PrologIA
Aociation Prolog
R 3 - 28 Reference Manual HERITAGE

list(t)
Lists the group(s) of rules indicated by t, on the current output.
t can be a sequence of one or more terms, having the following forms (i
denotes an identifier, a an integer, and v a variable).
i/a All rules constituting the group named i of arity (number of arguments) a.
i/v All rules whose access is i, whatever their arity.
v/a All rules whose arity is a.
i Equivalent to i/v.
Example:
> list(num.bin/2);

list(s)
Lists a module.
s must be a character string. All rules prefixed by s are listed on the current
output.

list(i/a,n)
Lists one rule.
i must be an identifier, and a an integer. Rule number n in the group named i
and with arity (number of arguments) a is listed on the current output.

multifile(i/a)
Enables a rule group to be discontiguous.
Compiling directive identical to the discontiguous/1 directive.

not_defined(s,l)
Finds the accesses of a module that are not defined.
Unifies l with the list of accesses belonging to module s that are not defined.
The accesses are written i/a, where i is the access identifier and a is its arity.
Note: this predefined rule activates the garbage collector on the dictionary
before providing the result.
Example:
> insert;
module("agency");
travel(v,d,h,s) -> transport(v,t)
stay(v,h,n)
duration(d)
multiply(n,d,p)
add(p,t,s);
transport(Rome,1200) ->;
transport(London,800) ->;
transport(Tunis,2000) ->;
end_module("agency");
;
{}
> dictionary("agency",l);
{l=agency:module_context / 4.agency:transport / 2.
agency:voyage / 4.nil}
> not_defined("agency",l);
{l=agency:add / 3.agency:duration / 1. agency:multiply / 3.
agency:stay / 3.nil}

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 29

predefined(t)
Tests whether a pattern corresponds to a predefined rule.
Executes successfully if t is a term corresponding to a predefined rule call.
rule(t,q)
Searches for rules corresponding to a given pattern.
This primitive is executed as many times as there are rules whose head unifies
with t and the body with q. If no such rule exists, rule(t,q) fails. t must be
either an identifier or a tuple whose first argument is a known identifier.
The rule primitive uses the rule indexation when possible (see no_index).
Example of use of rule (applying to the conc program given above):
>rule(conc(x,y,z),q);
{x=nil,z=y,q=nil}
{x=v149.v150,z=v149.v151,q=conc(v150,y,v151).nil}
>

rule(n,t,q)
Searches for rules corresponding to a given pattern.
Functions in the same way as rule(t,q) but, in addition, n is unified with the
rank of the rule in its group.
Example:
>rule(n,conc(x,y,z),q);
{n=1,x=nil,z=y,q=nil}
{n=2,x=v172.v173,z=v172.v174,q=conc(v173,y,v174).nil}
>rule(n,conc(x,y,z),conc(x',y',z').l);
{n=2,x=v263.x',z=v263.z',y'=y,l=nil}
>rule(1,conc(x,y,z),q);
{x=nil,z=y,q=nil}
>

rule(n,a,t,q)
Searches for rules having a given name.
a must be an identifier, or a tuple whose first argument is an identifier. For
each rule with access identifier a, this primitive executes by unifying n with
the rank of the rule in its group, t with the rule head, and q with the rule body.
This version of rule provides a means of searching for rules whose names are
known, but not their pattern.
Example:
conc(nil,x2,x2) ->;
conc(e.x1,x2,e.r) -> conc(x1,x2,r);
conc(x1,x2,x3,r) -> conc(x1,x2,u) conc(u,x3,r);;
> rule(n,conc,t,q);
{n=1,t=conc(v124,v125,v126,v127),
q=conc(v124,v125,v128).conc(v128,v126,v127).nil}
{n=1,t=conc(nil,v125,v125),q=nil}
{n=2,t=conc(v127.v128,v125,v127.v129),
q=conc(v128,v125,v129).nil}

rule_nb(i/a,n)
rule_nb(i,n)
Counts the number of rules in a group.

© PrologIA
Aociation Prolog
R 3 - 30 Reference Manual HERITAGE

i must be an identifier when this rule is called, and a an integer. n is then


unified with the number of rules in the group with the name i and the "arity"
(number of arguments) a. In its second form, only the group having the
lowest arity is considered.

retract(t,q)
Searches for and deletes rules corresponding to a given pattern.
This primitive executes as many times as there are rules whose head unifies
with t, and whose body unifies with q. It uses rule indexation if possible, or
otherwise tries each rule in successive order. If such a rule does not exist,
retract(t,q) fails. t must either be an identifier, or a tuple whose first argument
is a known identifier.
If a matching rule is invisible for decompilation, the rule is deleted and the
primitive executes without unifying the free variables of t and q.

suppress(i/a)
Deletes a whole group of rules. i must be an identifier, and a an integer. All
the rules in the group named i and with arity (number of arguments) a are
deleted. If there is no rule, when the predicate executes it may3 print a
warning.
Here is an example:
data(1) ->;
data(2) ->;
data(3) ->;;
>data(x);
{x=1}
{x=2}
{x=3}
>suppress(data/1);
{}
>data(x);
WARNING : call to undefined rule
>

suppress(i/a,n)
Deletes one rule.
i must be an identifier, and a and n are two integers. The nth rule in the group
having the name i and the arity (number of arguments) a is deleted. If there is
no such rule, when the predicate executes it may4 print a warning.
Example:
data(1) ->;
data(2) ->;
data(3) ->;;

3This depends on the warning level chosen by a Prolog start-up option.

4This depends on the warning level chosen by a Prolog start-up option.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 31

>data(x);
{x=1}
{x=2}
{x=3}
>suppress(data/1, 2);
{}
>data(x);
{x=1}
{x=3}
>

3.8 Manipulation of compiled modules

index(i/a)
Indexes a group of compiled rules.
Indexes the first argument in the group of compiled rules whose access
identifier is i and whose arity is a. If the rule is already indexed, nothing
happens. This rule can be used to accelerate the execution speed of rules
created using assert, which are not automatically indexed unlike rules created
using insert. It has no effect on the non compiled facts.

kill_module(s)
Deletes module.
s must be a string or a list of strings. All the rules in each module denoted in
s are deleted, its arrays are de-allocated and its identifier assignments are
undone. If a module does not exist, a message may5 be displayed and the
processing continues.

load(f,l)
load(f)
Loading saved modules.
f is a file name (character string) and l is a substitutory list of prefixes. This
command loads the saved modules in the file f, which must have been created
using the command save. If the module initialization rules exist they are
executed.
l is a list having the form <pref1 . subs1> . … . <prefk . subsk> . nil which
specifies the renaming of the loaded modules: pref1 will be substituted by
subs1, pref2 by subs2, etc. If a module to rename is not present, the system
ignores the substitution and a message may6 be displayed.
Example:
>load("myfile.mo", <"data"."donnees">.nil);
{}

5This depends on the warning level chosen by a Prolog start-up option.

6This depends on the warning level chosen by a Prolog start-up option.

© PrologIA
Aociation Prolog
R 3 - 32 Reference Manual HERITAGE

If an attempt is made to load an element (rule or array) which is already


known, this produces an error ("multiple definition").
The second version, load(f), is equivalent to load(f,nil).

no_index(i/a)
Removes indexation from a compiled rule group.
Removes indexation from the group of compiled rules whose access identifier
is i, and whose arity is a. If the rule is not indexed, nothing happens. It is
advisable to use this rule before dynamically handling rules read by insert, so
that the modifications will always be taken into account in the same way. It
has no effect on the non compiled facts.

reload(f)
reload(f,l)
Loading saved modules.
Functions in the same way as load, except that when an element is redefined,
the version found in the file replaces the one in memory, without producing an
error.

save(l,f)
Saving modules.
f is a file name (character string) and l is a list of prefixes (character strings).
This command saves all the elements (rules, static variables and arrays) from
the modules corresponding to the specified prefixes, in the file f. If a module
does not exist, a message may7 be displayed, and the save continues.
Example:
>save(""."data"."dict".nil, "myfile.mo");
{}

The file produced is an object code file. This code can only be exploited by a
Prolog machine. By memorizing programs in this way, it is possible to
achieve faster reloading than from the source files.

save_state(s)
Saves a start-up state.
Saves the whole program (rules, arrays, assigned identifiers, including the
Prolog II+ supervisor) in a file named s (where s is a string) which can then
be used as a start-up file. This primitive has the same effect as exit(s) but
without leaving Prolog.

7This depends on the warning level chosen by a Prolog start-up option.

© PrologIA
Aociation Prolog

HERITAGE Structuring and modifying rules R 3 - 33

© PrologIA
Aociation Prolog

HERITAGE
Aociation Prolog

HERITAGE

4. Predefined data operations

4.1 Type testing rules


4.2 Arithmetical and boolean operations
4.3 Assignment
4.4 String operations
4.5 Composition and decomposition of objects.
4.6 Comparison of any terms

4.1 Type testing rules

These rules are used to determine an object's type. If the argument is a free variable,
the rules make no sense and thus fail.

ident(t)
Checks that t is an identifier.

integer(t)
Checks that t is an integer.

real(t)
Checks that t is a real.

double(t)
Identical with real(t).

dot(t)
Checks whether t has the form t1.t2 or [ t1 | t2 ].

string(t)
Checks whether t is a string.

tuple(t)
Checks whether t is a term having the form(t1 … tn) or <t1 … tn>.

The following primitives concern the "state" of the variables, and thus operate in a
similar way to the type testing rules.

©PrologIA
Aociation Prolog
R4-2 Manuel de Référence HERITAGE

bound(x)
bound(x) is executed if x is bound and fails otherwise. A variable is
considered bound if it has been unified:

- Either with a constant (integer, real, identifier, string),


- Or with a term like t1.t2,
- Or with a term like <t1.t2,… ,tn> or ff(t1,t2,… ,tn).

free(x)
Is executed if x is not bound, and fails otherwise.

var_time(x,n)
A variable's creation date
x must be an unbound variable. This predefined rule unifies n with a certain
"creation date" of a variable x. n is an integer which identifies a unique
variable; two variables have the same date if, and only if, they are linked to
each other (the compiler uses this same number to print unbound variables -
see example below).
Example:
>eq(x,y) var_time(x,_tx) var_time(y,_ty) var_time(z,_tz)
out(x.y.z) line;
v35.v35.v172
{y=x,_tx=35,_ty=35,_tz=172}
>

A variable's creation date corresponds to a concept of "time" which is virtually


the same as for the Prolog clock: time progresses when goals are executed,
and reverses during backtracking. In the following example, the variable x is
created three times; it can be seen that it possesses the same creation date each
time.
>enum(i,3) var_time(x,t);
{i=1,t=35}
{i=2,t=35}
{i=3,t=35}
>

Warning. The value of variables' creation dates may be affected when the
garbage collector compacts the stack space.

4.2 Arithmetic and boolean operations

An expression is evaluated using the predefined rule val. The result is either an
integer, a real, an identifier or a string. Booleans are represented by the integers 0
and 1.

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R4-3

val(t1, t2)
tval(t1, t2)
Evaluate the expression t1 and produces the result t2. The expression to be
evaluated is constructed recursively from constants, identifiers and evaluable
functions. When decompiling or debugging, the optimizations (provided they
are not deactivated when Prolog starts) of the code generated for the call to the
val predicate do not make it possible to reconstitute the original term, but
rather an equivalent term. In addition, they momentarily suspend the
automatic space and stack management mechanism. However the tval
predicate is not optimized. You may prefer to use it instead of val when using
memory intensive programs in which val frequently handles complex terms.
In this way you will avoid having to manage the memory "by hand".
Examples:
>val(add(mul(2, add(3, 4)), 1000), x);
{x=1014}
>val(add(mul(2e0, add(3, 4e0)), 1000), x);
{x=1.014000000000000e+03}
>val(2 * (3 + 4) + 1000, x);
{x=1014}

The arithmetical functions can have different types of arguments: they are
automaticaly converted to the most general type (the types are as follows, in
decreasing order: real, integer). If a function to be evaluated has an incorrect
number of arguments or if any of its arguments are of the wrong type, val
generates an error. This error can be recovered with the predefined rule block.
• The value of a number or string is equal to that number or string.

• The value of an indexed array (external or internal) is equal to the value of


the corresponding element in the array. For example:
>def-array(tab,100) assign(tab[50],3);
{}
>val(tab[50],_x);
{_x=3}

• The value of an identifier i is defined as follows:

(1) If a term t has been assigned to term i(using the rule assign described
in the next section) then the value of i is t;

(2) If nothing has been assigned to i then the value of i is itself.

Example:
>assign(un, 1);
{}
>val(un, x) val(deux, y);
{x=1,y=deux}

Certain evaluable functions can also be expressed using operators. The evaluable
functions are:

©PrologIA
Aociation Prolog
R4-4 Manuel de Référence HERITAGE

add(t1, t2) or t1 + t2
value( add(t1,t2)) = value(t1 + value( t2)
The value of t1 and t2 must be an integer or real number value.

sub(t1, t2) or t1 - t2
value( sub(t1,t2)) = value(t1) - value( t2)
The value of t1 and t2 must be an integer or real number value

mul(t1, t2) or t1 * t2
value(mul(t1,t2)) = value( t1) x value( t2)
The value of t1 and t2 must be an integer or real number value.

div(t1, t2) or t1 / t2
value(div(t1,t2)) = value( t1) / value( t2)
The values of t1 and t2 must be an integer or real number value.

mod(t1, t2) or t1 mod t2


value(mod(t1, t2)) = value(t1) modulo value(t2).
mod (modulo) is different from rem (remainder) when the operands t1 and t2
have opposing signs. In this case the second operand (t2) is added to the
remainder of the integer division of t1 by t2 (remainder).
The values of t1 and t2 must be integer values.

rem(t1, t2) or t1 rem t2


value( rem(t1,t2)) = remainder of the integer division of t1 by t2.
The values of t1 and t2 must be integer values.

eql(t1, t2) or t1 =:= t2 or =:=(t1, t2)


value(eql(t1, t2)) = if value (t1) = valeur (t2) then 1 else 0
The arguments can be of different types.
If t1 and t2 are arithmetical, automatic type conversion is carried out before the
evaluation.

'=\='(t1, t2) or t1 =\= t2


value(=\=(t1, t2)) = if value(t1)  value(t2) then 1 else 0.
If t1 and t2 are arithmetical, automatic type conversion is carried out before the
evaluation.

inf(t1, t2) or t1 '<' t2


value( inf(t1,t2)) = if value(t1) < value( t2) then 1 else 0 .
For integers or reals, the relation < is used between the numbers. For strings,
alphabetical order is used, and for identifiers, alphabetical order on the
associated strings.

infe(t1, t2) or t1 '=<' t2


value(infe(t1, t2)) = if value(t1)  value (t2) then 1 else 0. (See inf)

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R4-5

sup(t1, t2) or t1 '>' t2


value(sup(t1, t2)) = if value(t1) > value (t2) then 1 else 0. (See inf)

supe(t1, t2) or t1 '>=' t2


value(supe(t1, t2)) = if value(t1) value (t2) then 1 else 0. (See inf)

if(t, t1, t2)


value( if(t,t1,t2)) = if (value( t) 0) then value( t2) else value( t1).

sign(t)
value(sign(t))= if value(t) = 0 then 0, if value(t) < 0 then -1, else 1.
The value of t must be an integer or a real number.

ceiling(t)
value(ceiling(t))= - (floor(-value(t))) .
The value of t must be an integer or a real number. The result is an integer.

floor(t)
value(floor(t)) = floor(value(t)) .
The value of t must be an integer or a real number. The result is an integer.

round(t)
value(round(t))= integer part (value(t)+0.5).
The value of t must be an integer or a real number. The result is an integer.

trunc(t)
value( trunc(t)) = the value of t is converted into an integer.
The value of t must be an integer or a real number.

float(t)
value( float(t)) = the value of t is converted into a real number.
The value of t must be an integer or a real number.

double(t)
value( double(t)) = the value of t is converted into a real number.
The value of t must be an integer or a real number.

abs(t)
value( abs(t)) = absolute value(value( t)).
The value of t must be an integer or a real number.

The following functions must be applied to integer arguments. They give an integer
result.

'/\'(t1,t2)
value('/\'(t1,t2)) = bit by bit 'and' between t1 and t2.
The values of t1 and t2 must be integers.

©PrologIA
Aociation Prolog
R4-6 Manuel de Référence HERITAGE

'\/'(t1,t2)
value('\/'(t1,t2)) = bit by bit 'or' between t1 and t2.
The values of t1 and t2 must be integers.

'<<'(t1,t2)
value('<<'(t1,t2)) = t1 offset by t2 bits to the left.
The values of t1 and t2must be integers.

'>>'(t1,t2)
value('>>'(t1,t2)) = t1 offset t2 bits to the right.
The values of t1 and t2must be integers.

'~'(t)
value('~'(t)) = bit by bit complement of t.
The value of t must be an integer.

The following functions give a real number result, and must be applied to integer or
real number arguments. The trigonometric functions work with angles expressed in
radian units.

atan(t)
value( atan(t)) = arc tangent(value( t)).

cos(t)
value( cos(t)) = cosine(value( t)).

exp(t)
value( exp(t)) = exponential(value( t)).

ln(t)
value( ln(t)) = Napierian logarithm(value( t)).

rad(t)
value( rad(t)) = radian conversion(value( t)).
Converts degrees to radians.

sin(t)
value( sin(t)) = sine(value( t)).

sqrt(t)
value( sqrt(t)) = square root(value( t)).

tan(t)
value( tan(t)) = tangent(value( t)).

t1 ** t2
value(t1 ** t2) = value(t1) to the power value(t2).

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R4-7

4.3 Assignment
assign(i, t)
tassign(i, t)
cassign(i, t)
Assign the term t to identifier i. t can be any Prolog term. The rule functions
as if i were becoming the name of a variable which is "global" (subsequently
accessible during the execution of any goal), "static" (resists backtracking)
and has the value t. Therefore, this is standard assignment, as it occurs in
Fortran, Pascal, etc … The optimizations of the code generated for the call to
the assign predicate momentarily suspend the automatic space and stack
management mechanism (provided they are not deactivated when Prolog
starts). However the tassign predicate is not optimized. You may prefer to use
it instead of assign when using memory intensive programs in which assign
frequently handles complex terms. In this way you will avoid having to
manage the memory "by hand". The cassign predicate is similar to tassign but
allows to keep the constraints (dif, freeze) and the attributes (metastructures)
linked to the variables of t.

Example:
>assign(file_name, "myfile.txt");
{}
>val(file_name,x)
{x="myfile.txt"}
>

In Prolog, these static variables can be seen as a particularly efficient way of


writing specified facts (or rules without bodies). From the user's point of
view, it is undoubtedly convenient to consider that the use of assign and val
given above is equivalent to:
>retract(file_name(x), nil);
>assert(file_name("myfile.txt"), nil);
{}
>file_name(x);
{x="myfile.txt"}
>
Example: it is possible to assign any term, not just constants.
>assign(myterm, jean.<34,"bond street">.O_ther_info);
{}
>val(myterm,x) val(myterm,y);
{x=jean.<34,"bond street">.v64,y=jean.<34,"bond
street">.v65}
>

©PrologIA
Aociation Prolog
R4-8 Manuel de Référence HERITAGE

assign(tab(i), t) or assign(tab[i], t)
assign(tab(i), t) or tassign(tab[i], t)
Assigns the term t to the element of rank i in the array tab, which must have
been previously defined as an array with def_array.
To obtain access to array elements (in val), the notations tab(i) and tab[i] are
equivalent. However, they are not represented by the same Prolog terms, and
use of the notation tab[i] enables the compiler to optimize access to the array.
In practice, the notation tab[i] will only be used to denote elements in an
array. The same applies to these predicates as above: assign is optimized,
tassign is not.

backtrack_term
Predefined array in the sys module, with a length of 100 (possible indices
between 1 and 100) that can be manipulated using built-in predicates val or
tval and assign or tassign. The values it is assigned are lost during
backtracking. Each array element is set to 0. Example:
> insert;
test(i) -> assign(backtrack_term[1],111)
val(backtrack_term[1],i);
test(i) -> val(backtrack_term[1],i);
;
{}
> test(i);
{i=111}
{i=0}

def_array(i, n)
Dynamically defines a Prolog term array named i of size n. This array will
behave like a variable which is "global" (subsequently accessible during
execution of any goal), and "static" (resists backtracking). Each array element
is set to the integer 0. Legal values for the index are between 1 and n.
If an array with the same name already exists:
- if the arrays are the same size, nothing happens
- if the sizes are different, an error is generated.
Access and assignment work in the same way as in arrays in other
programming languages (see above; val for access and assign for
assignment). The array is deallocated when you kill the module it belongs to
(i.e. the rules with the same prefix), or when you execute the kill_array
predicate.
"stack management "

inc(i) -> val(i + 1),x) assign(i,x);

dec(i) -> val(i - 1),x) assign(i,x);

initialize -> assign(pointer,0) def_array(stack,100);

push(v) ->
inc(pointer)
val(inf(pointer,100),1)

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R4-9

!
val(pointer,p)
assign(stack(p),v);
push(v) -> outm("stack overflow") line fail;

pop(v) ->
val(eql(pointer,0),0)
!
val(stack(pointer),v)
dec(pointer);
pop(v) -> outm("stack error") line fail;

> initialize;
{}
> push(12345);
{}
> push(23456);
{}
> pop(x);
{x=23456}
> pop(x);
{x=12345}
> pop(x);
stack error

redef_array(i, n)
Similar to def_array, but if the array i already exists, this predicate redefines
its size with the value n, It conserves existing assignments for the valid indices,
and initializes the new elements if necessary.

is_array(i,t)
Checks that the identifier i effectively denotes an array, and unifies t with its
size.

kill_array(i)
Deletes array i. If the array is not defined, when the predicate executes a
warning may1 be printed.

1This depends on the warning level chosen by an Prolog start-up option.

©PrologIA
Aociation Prolog
R 4 - 10 Manuel de Référence HERITAGE

4.4 String operations


char_code(c,n)
Returns an integer n representing the internal code for character c. This code
is either an ISO2 code or the host machine code. If c is an identifier whose
representation (not including quotes) is just one character, the corresponding
code is unified with n.
Example:
>char_code("A",n) char_code('A',n);
{n=65}
>char_code(c,65);
{c="A"}

conc_string(s1,s2,s3)
Lists all the triplets of strings s1, s2, s3 such that s3 is the concatenation of s1
and s2. s1, s2, and s3 must be sufficiently known to produce finite sets of
triplets, i.e. either the third known argument, or two of the three known
strings.
Example:
>conc_string("ab", "cd", s);
{s="abcd"}
>conc_string(s1, s2, "abcd");
{s1="",s2="abcd"}
{s1="a",s2="bcd"}
{s1="ab",s2="cd"}
{s1="abc",s2="d"}
{s1="abcd",s2=""}

substring(s1,i,j,s2)
Extracts a substring of length j from the string s1 beginning at position i, and
attempts to unify it with s2.
Example:
>substring("1234567890", 3, 4, x);
{x="3456"}

find_pattern(s1,s2,n)
Unifies n with the position of the start of string s2 within string s1. If s2 is
not found, find_pattern fails.
Example:
>find_pattern("1234567890", "3456", p);
{p=3}
>find_pattern("1234567890", "abcd", p);
>

2This is the ISO code 8859-1 (see table at the end of section 1.9). This character set is the 8 bit
extended American ASCII set with accented characters

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R 4 - 11

Please note: this primitive is defined in the external module prouser.c.


Careless modification of the corresponding source may cause it to
malfunction. In the supplied source, string length is restricted to 256
characters.

4.5 Composition and decomposition of objects


arg2(n,t1,t2)
Unifies t2 with the length or the element of rank n of a tuple, a list or a string.

(1) If t1 is a string then if


n = 0, t2 := length(t1)
n  0, t2 := nth character in the string t1

(2) If t1 is a list then if


n = 0, t2:=number of elements of the list
n  0, t2:=nth argument in the list t1

(3) If t1 is a tuple then if


n = 0, t2:=the number of arguments in the tuple
n  0, t2:=nth argument in the tuple t1
Examples:
>arg(0,"abcdef",x);
{x=6}
>arg(3,"abcdef",x);
{x="c"}
>arg(0,aa.bb.cc.dd.ee.ff.nil,x);
{x=6}
>arg(3,aa.bb.cc.dd.ee.ff.nil,x);
{x=cc}
>arg(0,<aa,bb,cc,dd,ee,ff>,x);
{x=6}
>arg(3,<aa,bb,cc,dd,ee,ff>,x);
{x=cc}

arg(n, t1, t2)


The corresponding primitive in the Prolog II interpreter has been renamed
arg2 in the compiler. arg/3 is a predefined primitive in Edinburgh syntax.

conc_list_string(l, s)
Concatenates the strings in list l to create string s.

©PrologIA
Aociation Prolog
R 4 - 12 Manuel de Référence HERITAGE

Example :
>conc_list_string("How "."are "."you "."?".nil, x);
{x="How are you ?"}

copy_term(t1, t2)
Makes a copy of the term t1 in which each free variable (constrained or not) is
replaced by a new variable without constraints, and unifies this copy with t2.
This means the two terms are represented by the same tree, apart from the
variable names. t1 is any prolog term, even an infinite one.
Example :
>copy_term(one(2.x,y), t);
{t=one(2.v33,v31)}

copy_term_with_constraints(t1, t2)
Identical to the predicate copy_term/2 but copies the constraints onto the
variables.

enum(i,k1, k2)
enum(i,k2)
k1 and k2 must be known integers. If k1 > k2 the rule fails. By definition, this
rule can be executed in k2 - k1 + 1 ways. The first way is to unify i and k1;
the second is to unify i and k1 +1, etc …; the final way is to unify i and k2.
Example:
>enum(i,5,9);
{i=5}
{i=6}
{i=7}
{i=8}
{i=9}

The second version, enum(i,k), is equivalent to enum(i,1,k).

gensymbol(i)
Creates a new identifier in the form idn where n is an integer, and unifies it
with i.

list_string(l, s )
Creates a string s from the list of characters l.
Example:
>list_string("H"."e"."l"."l"."o".nil, x);
{x="Hello"}

list_tuple(l, t )
Composes a tuple t from the list of arguments l.
Example:
>list_tuple(111.aaa.222."Hello".nil,x);
{x=<111,aaa,222,"Hello">}

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R 4 - 13

member(x,l)
Unifies x with item in list l in succession. Is described by the following rules:
member(x, x.l) ->;
member(x, _.l) -> member(x, l);

setarg(n, t1, t2)


Replaces the element of rank n in term t1 with t2. t1 must be a list or a tuple.
The initial term is restored when backtracking occurs.
Example:
> reinsert;
newarg(55) ->;
newarg(66) ->;;
> eq(x, 1.2.3.nil) newarg(y) arg2(2,x,e1) setarg(2,x,y)
arg2(2,x,e2);
{x=1.55.3.nil, y=55, e1=2, e2=55}
{x=1.66.3.nil, y=66, e1=2, e2=66}

split(t, l )
Splits a string or a tuple into a list of its components. When split(t, l ) is
executed t must be known; we then have the following:

- If t is a string, l is unified with a list of its characters.


- If t is a tuple, l is unified with the list of its arguments.
- Fails otherwise
Example:
> split("abcde",x);
{x="a"."b"."c"."d"."e".nil}
> split(kill(John,Peter.Mary),x);
{ x=kill.John.(Peter.Mary).nil}

string_ident(s1,s2,i)
string_ident(s,i)
Defines the link between an identifier and its representation as a string. If the
identifier does not exist it is created. In the first version, the identifier which
has the prefix s1 and the abbreviated representation s2 is made to correspond
to strings s1 and s2, and vice-versa.
Example:
> string_ident(p, i, guests:john);
{ p="guests", i="john"}
> string_ident("guests", "John", x)
{ x=guests:John}
>

In the second version, the current reading/writing context is used, to define the
link between identifier i and its representation s. s can be a complete or
abbreviated representation.
Example (in the standard context):
>string_ident(s,sys:outm);
{s="outm"}

©PrologIA
Aociation Prolog
R 4 - 14 Manuel de Référence HERITAGE

string_integer(s,n)
Makes string s correspond to integer n and vice versa.
Example:
>string_integer(s,123);
{s="123"}
>string_integer("-0123",n);
{n=-123}

string_real(s,r)
Makes string s correspond to real r and vice versa.
Example:
>string_real(s,12.34e5) string_real(s,x);
{s="1.234000000000000e+06",x=1.234000000000000e+06}
>string_real(s,1d110) string_real(s,x);
{s="1.000000000000000e+110",x=1.000000000000000e+110}

string_double(s, d)
Identical with string_real(s,d).

string_term(s, t, s',n)
string_term(s, t, s')
string_term(s, t)
Attempts to read from the string s a Prolog term that will be unified with t. s'
is the unused part of string s. If a variable appears in the string s, a free
Prolog variable is created.
Conversely, if s is not known, it is unified with a string corresponding to the
term t, as out(t) would output it. The argument n is used to specify the
maximum size of the string, if it is more than 400 (400 < n < 32768). An error
occurs if the string becomes longer than this maximum size. If n is not
specified, a default value of 400 is used. When string_term is used this way,
s' is ignored and t can be any term at all, and can even contain variables and
complex structures.
>string_term(s,myterm(x,1.2e0),s') string_term(s,x,s');
{s="myterm(v14,1.200000000000000e+00)",x=myterm(v15,1.2000
00000000000e+00),
s'=""}
>string_term("1.2,3)",t,s') string_term(s,t,s');
{t=1.2,s'=",3)",s="1.2"}

term_vars(t, l)
Unifies l with the list of free variables in t, including constraints if any, t is any
Prolog term, even an infinite one.
Example :
>term_vars(one(2.x,y,y), t);
{t=x.y.nil}

4.6 Comparing any terms

©PrologIA
Aociation Prolog

HERITAGE Opérations prédéfinies sur les données R 4 - 15

It is possible to compare any two Prolog terms. To do this, the following increasing
order has been defined:

- variables
- reals
- integers
- identifiers
- character strings
- tuples with length < 2.
- lists
- tuples with length >= 2.

For two variables, the system compares their memory location. For two integers or
reals it compares their values. For two character strings or two atoms it compares
their alphanumeric order. For two lists it compares the first two items found that are
different. For two tuples it first compares their lengths and if they are of equal
length it compares the first two items found that are different. The comparison
predicate is as follows:

term_cmp(X, Y,V)
Compares terms X and Y, unifies V with the integer -1 if X precedes Y, 1 if Y
precedes X, 0 if the terms X and Y are formally equal. Here are some
examples:
> term_cmp(1e0,1,V);
{V=-1}
> term_cmp(foo,zebra,V);
{V=-1}
> term_cmp(short,short,V);
{V=0}
> term_cmp(shorter,short,V);
{V=1}
> term_cmp(foo(a),foo(b),V);
{V=-1}
> term_cmp(foo(aa),foo(bb),V);
{V=-1}
> term_cmp(X,X,V);
{V=0}
> term_cmp(Y,X,V);
{V=-1}
> term_cmp(_,_,V);
{V=-1}
> term_cmp("foo",foo,V);
{V=1}
> term_cmp(1.2.3.nil,1.1.3.4.nil,V);
{V=1}
> term_cmp(1.2.nil,<1,2>,V);
{V=-1}
> term_cmp(1.2.nil,<X>,V);
{V=1}

term_cmpv(X, Y, V)
Compares X and Y in the same way as term_cmp, but without taking account
of the variables appearing in terms X and Y. For the term_cmpv predicate, two
distinct variables are considered identical. Example:

©PrologIA
Aociation Prolog
R 4 - 16 Manuel de Référence HERITAGE

Example:
> term_cmpv(foo(V1),foo(V2),V);
{V=0}

Two list sorting predicates are provided: sort/2 and keysort/2. To perform sorting,
they use the term_cmp/3 predicate described above internally.

sort(L1, L2)
L2 is unified with the list of items in L1 sorted in increasing order. In this list,
multiple items are only kept once. Example:
> sort(4.7.foo.3.4.1.nil,L);
{L=1.3.4.7.foo.nil}

keysort(L1, L2)
L2 is unified with the list of items in L1 sorted in increasing order. In this list,
multiple items are kept. Example:
> keysort(4.7.foo.3.4.1.nil,L);
{L=1.3.4.4.7.foo.nil}

These same predicates allow you to insert an additional argument to indicate the
user predicate employed to compare terms. This user predicate's arity must be equal
to 3. The first two arguments will receive the terms to compare, while the 3rd will
return the result of the comparison (-1, 0 or 1).

sort(L1, L2, C_ompar)


L2 is unified with the list of items in L1 sorted in the order specified by the
C_ompar predicate. In this list, multiple items are only kept once. The sort/2
predicate described above is simply a special version of this predicate, that
gives the C_ompar argument the value term_cmp. Example:
> insert;
compar_tuple(P1(X), P2(Y), R) -> term_cmp(X,Y,R);
;
> sort(aa(4).bb(7).cc(foo).dd(3).aa(4).ff(1).nil,L,
compar_tuple);
{L=ff(1).dd(3).aa(4).bb(7).cc(foo).nil}

keysort(L1, L2, C_ompar)


L2 is unified with the list of items in L1 sorted in the order specified by the
predicate C_ompar. In this list, the multiple items are kept. The keysort/2
predicate described above is simply a special version of this predicate, that
gives the C_ompar argument the value term_cmp. Example:
> insert;
compar_tuple(P1(X), P2(Y), R) -> term_cmp(X,Y,R);
;
> keysort(aa(4).bb(7).cc(foo).dd(3).aa(4).ff(1).nil,L,
compar_tuple);
{L=ff(1).dd(3).aa(4).aa(4).bb(7).cc(foo).nil}

©PrologIA
Aociation Prolog

HERITAGE

5. Input and Output

5.0 General information


5.1 Input
5.2 Output
5.3 Loading and adapting the drawing module
5.4 Declaration of operators

The input/output devices used by a Prolog II+ program (keyboard, screen, files,
etc.) are represented by objects called input/output units. These units are represented
in written form by a character string1. If necessary, this string also represents
information which identifies the unit in relation to the operating system: file-name
etc.

At any given moment, the Prolog II+ system "knows" a certain number of
input/output units: these are units which were opened previously, and have not yet
been closed. The descriptors for these units are stored in a type of stack: the unit at
the top of the stack is called the current unit. In principle, all input/output operations
are performed using the corresponding current unit. At start-up, the system
automatically opens an input unit and an output unit, (both called console) which are
the current units. Usually, these units are associated with the keyboard and the
screen of the computer or terminal which Prolog has been started from.

Changing the unit (i.e. executing input(f) or output(f)) does not close the current
unit or change its state. Instead, a new unit is opened, if necessary, and is placed at
the top of the stack, above the previous current unit. In this way, the latter can be
restored to its previous status when the new current unit is closed.

The number of units which can be open simultaneously depends on the host
machine.

5.0 General information

Each created input/output unit is of a specific type and has a specific opening mode.
The different possible types are:
- :console: unit type Prolog creates automatically at start-up.
- :text: text format disk file.
- :binary: binary format disk file.
- :memory_file: memory file described below.
- :unix_pipe: Inter-process communication pipe (UNIX).

1Window units can also be represented by integers.

© PrologIA
Aociation Prolog
R5-2 Reference Manual HERITAGE

- :graphic_area, :tty_area, :edit_area: graphic units.

The different possible opening modes are:


:read: the unit is opened for reading..
:write: the unit is opened for writing. If a physical object with the same name
already exists (disk file), it will be replaced by the newly created one.
:append: the unit is opened for writing. If a physical object with the same
name already exists (disk file), this is the object that will be opened, and the
subsequent writing will be concatenated in it. This opening mode can be
defined by a convention about the unit name, stipulating that in this case the
name must end with "+". The name of the file associated with the unit is the
unit name, minus the "+". For example output("file+") will open the file
called "file" in append mode.

The following types of unit can be opened for both reading and writing: :console,
:tty_area , :edit_area, and :memory_file.

memory_file(s)
memory_file(s,n)
Creates a "memory file" unit called s. In the first version of the predicate, the
character buffer is 400 characters long. In the second version, the buffer has
the length n or the nearest value to it, given that the minimum allocated size is
400 characters, and the maximum allocated size is 32K characters. This unit
can be used as input and output. It can be the current input unit and the
current output unit simultaneously. If the buffer is too small for the writing
operations performed in it, it automatically doubles its size, although it never
exceeds 32K characters. The unit will be physically closed when it is closed
for both reading and writing. This unit can be used in the same way as the
files.

The unit types and opening modes can be obtained using the following predicate:

current_file(x)
current_file(x,t,m)
Unifies x in succession with the names of the units open for reading and/or
writing. Unifies t with the unit's type, and m with the opening mode.

5.1 Input
The standard character buffer provided by Prolog for an input unit is limited to 400
characters. If a line is longer than this, Prolog behaves as if there were a space after
the 400th character. The rest of the line is read once the 400 previous characters
have been exhausted.

It is recommended to use shorter lines! Remember that:


- primitives that start by reading all the spaces will read the Carriage Return in the
same way as the blank character,

© PrologIA
Aociation Prolog

HERITAGE Input and Output R5-3

- space can appear anywhere between lexical units,


- strings, identifiers, integers and real mantissae can be written on several lines,
by masking the Carriage Return with the '\' character, if the option for
interpretation of '\' is active (see section U2.3.).

5.1.1 Input rules

eol
Tests for an end of line in input.
Tests whether an end of line has been reached. To be more precise; if the next
character to be read is an end-of-line mark, eol executes, otherwise its
execution fails.
Example:
> in_char'(c) eol;
a<CR>
{c="a"}
> in_char'(c) eol;
a<space><CR>
>

eof
Tests for an end of input.
Tests whether any characters are left to input on the current unit, i.e. tests
whether the next read will cause error 104: END OF FILE. If this is not the
case, execution of eof fails. Obviously this primitive cannot execute on the
console or in a TTY window, since these are terminal mode units, which
always have characters, sometimes as a result of user input.
Example :
> input("empty_file") eof input("console");
{}
>

in_char(t)
Reads a character.
Reads the next character, transforms it into a string of length 1 and attempts to
unify it with t. The end of a line is considered as a space character.
Note: although the end of line character is treated as a space by other
primitives that analyze the read characters, for this primitive it will have the
value "\n".
Please note: all commands (goal sequence) end at the ";". When in_char is
launched on the command line, the first character to be read is the one
immediately after ";". This is often "end-of-line".
Example:
> in_char(c);
{c="\n"}
> clear_input in_char(c);
a<CR>
{c="a"}

© PrologIA
Aociation Prolog
R5-4 Reference Manual HERITAGE

in_char'(t)
Reads a non-blank character.
Reads all blank characters and then behaves like in_char(t).
Example:
>in_char'(x) in_char(y) in_char'(z) in_char(t);
ab c d
{x="a",y="b",z="c",t=" "}

next_char(t)
Attempts to unify the next input character with t without actually reading it.

next_char'(t)
Reads all blank characters, if any, and then behaves like next_char(t).
Example:
>next_char'(x) in_char(y);
abc
{x="a",y="a"}

inl(s)
inl(s, n)
Reads one line.
Reads all the end of the current line and unifies it as a character string with s.
n is unified with the rank of the read line in its unit. n is much more useful for
files and for EDIT windows. In the console or TTY windows, the lines are
divided into two groups; input and output lines. n then corresponds to the
rank within these groups.
Example:
> clear_input inl(s);
Maitre corbeau, sur un arbre perche
{s="Maitre corbeau, sur un arbre perche"}

in(t, c)
in(t, D, c)
Reads a Prolog term.
Reads the longest character sequence x which is a term or the beginning of a
term. If x is the expression of a term, unification of x with t is attempted. If x is
not a term, an error occurs. All blank characters following x are read. c unifies
with the first lexical unit read that does not belong to x. D is unified with
variable dictionary of the term, i.e. a list of pairs corresponding to t's
variables. Each pair contains the character string that is the original name of
the variable, and the relevant variable.
Example:
>in(t, c);
this is a term;
{t=this is a term, c=";"}
>in(t, D, c);
aa(x, bb(y_n1',x));
{t=aa(v129, bb(v163,v129)),
D=<"x", v129>.<"y_n1'",v163>.nil, c=";"}

© PrologIA
Aociation Prolog

HERITAGE Input and Output R5-5

Please note: in this case, it is essential to read one unit in advance because of
the operators.
in_integer(t)
First reads all blank characters, and then attempts to read an integer on the
current unit. If the object does not have integer syntax, nothing is read and
in_integer fails. Otherwise t is unified with the integer which has been read.
Example:
> in_integer(i) in_char(c) in_integer(j);
-123+456
{i=-123,c="+",j=456}
Warning: since integers and reals can be written on several lines using
"\<return>" (if the option for interpretation of '\' is active (see section U2.3.)),
if the object is written on several lines it is not possible to restore the lines
before the last line if the object is not an integer (in this case it is a real).
in_real(t)
First reads all blank characters, and then attempts to read a real on the current
unit. If the object does not have real syntax (defined by the current option),
nothing is read and in_real fails. Otherwise t is unified with the real that has
been read.
> in_real(x) in_char(c) in_real(y);
-123e+4,54.63d0
{x=-1.230000000000000e+06, c=",", y=5.463000000000000e+01}
Warning: since integers and reals can be written on several lines using
"\<return>" (if the option for interpretation of '\' is active (see section U2.3.)),
if the object is written on several lines it is not possible to restore the lines
before the last line if the object is not an integer (in this case it is a real).

in_double(t)
Identical with in_real(t).
in_string(t)
First reads all blank characters, and then attempts to read a Prolog string. If
the object does not have string syntax, nothing is read, and in_string fails.
Otherwise, t is unified with the read string.
Warning. this is a string type Prolog term (i.e. with quote marks) and not
"anything, considered as a string".
Example:
> in_string(s) in_char(c);
"Hello !";
{s="Hello !", c=";"}

in_ident(t)
First reads all blank characters, and then attempts to read a Prolog identifier. If
the object does not have identifier syntax (defined by the current option),
nothing is read, and in_ident fails. Otherwise, t is unified with the read
identifier. Example:
read(integer(n)) -> in_integer(n) !;
read(ident(i)) -> in_ident(i) !;

© PrologIA
Aociation Prolog
R5-6 Reference Manual HERITAGE

read(string(s)) -> in_string(s) !;


read(character(c)) -> in_char(c);;
>read(x1) read(x2) read(x3) read(x4) read(x5) read(x6) …;
aa := bb * 123 …
{x1=ident(aa),x2=character(":"),x3=character("="),
x4=ident(bb),x5=character("*"),x6=integer(123), … }

in_word(t1,t2)
Reads all blank characters, then reads the largest word, transforms it into a
string and tries to unify this string with t1. A word is either:

(1) a sequence of letters


(2) a sequence of digits
(3) any character which is not a blank, a letter, or a digit.
In (1), t2 is the identifier corresponding to t1 or nil if t2 is not already declared
in the dictionary.
In (2), t2 is the integer corresponding to t1 .
In (3), t2 = t1.
Example:
>in_word(x, y);
toto
{x="toto", y=nil}
>in_word(x, y);
insert
{x="insert", y=insert}
>in_word(x, y);
012345
{x="012345", y=12345}
>in_word(x, y);
+
{x="+", y="+"}

in_sentence(t1,t2)
Reads a sentence ending with ".", "?", "!" or any other character defined as a
terminator, and builds two lists out of it. t1 is the list of lexical units
constituting the sentence (words in the in_word sense), and t2 is the list of
corresponding atoms, as for in_word. The list of sentence terminators can be
modified by the predicates a d d _ s e n t e n c e _ t e r m i n a t o r / 1 and
remove_sentence_terminator/1.
>in_sentence(x, y);
this is a string.
{x="this"."is"."a"."string".".".nil,
y=nil.nil.nil.string.".".nil}
>in_sentence(x, y);
sum := 052345;.
{x="sum".":"."="."052345".";".".".nil,
y=nil.":"."=".52345.";".".".nil}

add_sentence_terminator(C)
Adds the character C to the list of sentence terminators (initially containing the
characters ".", "?", and "!").

© PrologIA
Aociation Prolog

HERITAGE Input and Output R5-7

remove_sentence_terminator(C)
Removes the character C from the list of sentence terminators. Causes a
failure if the list does not contain this character.

read_unit(t, u)
Reads a lexical unit.
Reads a lexical unit, unifies t with its type (identifier, number etc.) in the form
of a number, and u with its value.
Prolog II+'s lexical units are defined by the grammar in section 1.9. The
numbers given by t in read_unit correspond to the following notations from
this grammar:
value of t lexical category value of u
1 identifier the identifier
2 separator2 the corresponding string
3 variable the corresponding string
4 constant the constant
5 graphic_symbol the corresponding string
Example:
> read_unit(t1,u1) read_unit(t2,u2) read_unit(t3,u3)
read_unit(t4,u4);
x12 + :pi ,
{t1=3,u1="x12",t2=5,u2="+",t3=1,u3=pi,t4=2,u4=","}
> read_unit(t,u);
123
{t=4,u=123}

read_rule(t1, t2)
Reads a Prolog rule on the current input unit, and unifies t1 with the head and
t2 with the list of terms in the body.
Example:
> read_rule(t1,q1) read_rule(t2,q2);
tt(1,x) -> outl(x) fail;
tt(2,x) -> !;
{t1=tt(1,v118),q1=outl(v118).fail.nil,
t2=tt(1,v228),q2='!'.nil}
>

sscanf
The C function sscanf is accessible from Prolog via the callC primitive (see
section 6.6 of this manual).
Example:
> callC(sscanf("123","%f",<"R",y>));
{y=1.23000e+02}
> eq(f,"%x %o") callC(sscanf("12 12",f,<"I",x>,<"I",y>));
{x=18, y=10}
>

2"separator" is a syntactic separator: please see section 1.2 of this manual.

© PrologIA
Aociation Prolog
R5-8 Reference Manual HERITAGE

5.1.2 Modifying the input unit

The names for the input units can be Prolog strings or Prolog identifiers or integers.
Files and predefined windows can only be represented by strings.

input(u)
input(u,n)
The unit named u becomes the current input unit. If this unit is not one of the
open units, its descriptor is created and added to the stack of open input units.
If it is a new unit, a file is found and opened. A command file opened by input
can itself contain an input command. The new current unit is stacked above
the previous one. In the two argument version, n expresses the size of the
unit's buffer by the number of characters. It must be between 400 and 32K.
If n is not in this interval the buffer size will be the nearest value.

input_is(u)
Gives in u the name of the current input unit.

close_input
Closes the current unit (unless it is the console or a window) and removes its
descriptor from the top of the stack of units. The previous unit again becomes
the current unit.

close_input(u)
u is the name of a unit which must be included in the list of open input units.
Closes this unit (unless it is the console or a window) and removes its
descriptor from this list.

clear_input
Ignores characters remaining unread in the current input line.

5.2 Output

Prolog maintains a line pointer for each output unit, by means of the out, outm and
line primitives. It is reset by executing the line primitive. This pointer is used to
maintain within the system a representation of events on the unit's current line. In
particular, it can be used to find out how much space is left on the line (the line
length is defined by set_line_width) and then set a new carriage return.

Use of set_cursor does not affect this line pointer, and so Prolog's representation of
the line is no longer accurate. New carriage returns that are set (\<return>) may be
unwanted. To avoid this, it is recommended to use the outl and outml primitives with
set_cursor, instead of the out and out primitives. In this way, the pointer is
constantly reset, and management of presentation is left entirely to set_cursor. It
should be noted that the same behavior is obtained by making use of external rules
(C, Pascal, …) which manage screen presentation.

© PrologIA
Aociation Prolog

HERITAGE Input and Output R5-9

5.2.1 Output rules

beep
Generates a warning beep.

flush
Empties the current output unit's character buffer, by sending all the characters
waiting to be written to the associated physical unit.

out(t)
outl(t)
Writes the term t on the current unit. Any term written with out can be re-read
with in if the option for interpretation of «\» is active (see section 2.3. of the
user's manual). If a term is longer than the remaining length of the line, a
carriage return is inserted, in accordance with the following rules.

(1) Strings are cut in the required place, by insertion of a masked carriage
return (i.e. preceded by the character "\").

(2) Numbers are not cut, unless a single number is longer than a whole
line, in which case it is cut in the same way as a string.

(3) Identifiers are not cut, unless a single identifier is longer than a whole
line, in which case it is cut in the same way as a string.
The term is written in conformity with the following conventions:

(1) Lists are printed with period notation for Prolog II syntax and with
square brackets for Edinburgh syntax or if the option "standard
notation for reals" is active.

(2) If a string contains a non-printable character, the character is written in


the form of a printable escape sequence (please see outm).

(3) Any identifier which does not correspond to identifier syntax is written
with quote marks.

(4) The current execution context determines the possible abbreviations


for identifiers.

outl(t) is equivalent to the goal sequence out(t) line; when the term t is written,
the system goes to the next line.
Example:
>out(1.Peter."Hi!".nil);
1.Peter."Hi!".nil{}
>

© PrologIA
Aociation Prolog
R 5 - 10 Reference Manual HERITAGE

Please note: the braces printed after the term indicate that the goal
>out(1.Peter."Hi!".nil); has been successfully executed. One way of avoiding
this print-out is to make this execution fail artificially:
>out(1.Peter."Hi!".nil) line fail;
1.Peter."Hi!".nil
>

outm(s)
outml(s)
Writes the string s on the active output unit without the quote marks, and with
correct interpretation of formatting characters which s may contain (for
example: \n). A string longer than the remaining space on a line is truncated
by a "masked" carriage return. Characters corresponding to a non-printable
ISO 8859-1 code are sent to the current output unit without being
transformed.
Example:
>out(" \tHello! ") line fail;
"\tHello!"
>outm("\tHello!") line fail;
Hello!
>

outml(s) is equivalent to outm(s) line.

outm(s,n)
Writes the string s n times, with the same conventions as above.
Example:
>outm("-",40) line fail;
----------------------------------------
>

out_equ(t)
Writes the minimal system of equations for the term t . This rule is much
slower than out, but it factorizes the sub-trees and thus produces a more
compact representation, when this is possible.

line
Outputs a new line.

page
Goes to the next page. On the "console" unit, the screen is cleared and the
cursor is positioned at the top left hand corner of the screen. It has no effect in
the graphics environment.

paper
Writes a copy of console activity into a log file (default: prolog.log ).

© PrologIA
Aociation Prolog

HERITAGE Input and Output R 5 - 11

no_paper
Cancels paper. The log file is only closed at the end of the session. A
subsequent call to paper will add information at the end of the file.

set_cursor(n1,n2)
The cursor is positioned at (n1,n2) on the screen, where n1 is the column
coordinate and n2 is the line coordinate. (1,1) corresponds to the top left hand
corner of the screen. The following conditions must be fulfilled:
1 n1  line width, and 1  n2  lines on the screen.
It has no effect in the graphics environment.

set_line_cursor(n)
Positions the current character pointer at n on the current line. This provides a
type of tabulation. set_line_cursor does not work backwards from the current
character pointer. The first character position is 1.

sprintf
The C function sprintf is accessible from Prolog via the callC primitive (see
section 6.6 of this manual).
Example:
> callC(sprintf(<"",x,80>,"value: %ld",200));
{x="value: 200"}

To use the following primitives, it is necessary to first load the tree drawing module
(see section 5.3).

draw_equ(t)
Draws the minimal system of equations representing a finite or infinite tree t.
The tree-drawing module must be loaded in order to use this primitive.
> ... draw_equ(aa(bb(cc,dd),bb(cc,dd))) ...
aa
+--^--+
v1026 v1026

v1026 = bb
+^-+
cc dd
{}

draw_tree(t)
Draws the finite tree t on the screen (if the terminal has graphics facilities,
semi-graphic symbols are used). The tree-drawing module must be loaded in
order to use this primitive.
> ... draw_tree(aa(bb(cc,dd),bb(cc,dd))) ...
aa
+--^---+
bb bb
+^-+ +^-+
cc dd cc dd
{}

© PrologIA
Aociation Prolog
R 5 - 12 Reference Manual HERITAGE

draw_mode(x)
The following two primitives control the way trees are drawn. Depending on
the type of screen, some semi-graphic characters can be used to produce better
drawings. draw_mode(x) gives a character string x, which indicates the type of
screen used. The possible values for x depend on the machine: they are
"VT100", "GRAPHICS" and "TTY". "TTY" is for terminals without graphics
facilities, and is available on all machines. The tree-drawing module must be
loaded in order to use this primitive.

set_draw_mode(x)
Makes it possible to choose the type of screen to be used for tree drawing.
The values for x are the same as before. If you want to print trees on a
standard printer, the "TTY" mode must be used. The tree-drawing module
must be loaded in order to use this primitive.

5.2.2 Modifying the output unit

The names for the output units can be Prolog strings or Prolog identifiers or
integers. Files and predefined windows can only be represented by strings.

output(u)
output(u,n)
The unit called u becomes the current output unit. If the unit designated by u
is not already in the list of open output units, then the unit is allocated a
descriptor, and a file may be created with the name u. In the two argument
version, n expresses the size of the unit's buffer by the number of characters.
It must be between 400 and 32K. If n is not in this interval, the buffer size will
be the nearest value. In the one argument version the buffer size will be 400
characters.
This primitive can never be used to create a window or a memory file; to do
that please use the relevant primitives. If u is a character string ending with the
sign "+", the file with the same name apart from this sign is then opened in
append mode, i.e. if the file already exists on the disk, subsequent output will
be added to it.

output_is(u)
Gives in u the name of the current output unit.

close_output
The current unit is removed from the top of the stack of open output units. If
this corresponds to a file, the file is closed.

close_output(u)
u is the name of unit which must be included in the list of open output units.
If it is a file it is closed. The unit's descriptor is removed from this list and
deleted. This primitive can never be used to close a window; to do that please
use the relevant primitives

© PrologIA
Aociation Prolog

HERITAGE Input and Output R 5 - 13

line_width(n)
Returns in n the maximum current width of the current unit's lines, defined by
set_line_width.

set_line_width(n)
Is used to define the maximum line width in the current output unit. n
becomes the unit's new line width. The default line width is 80 characters. The
maximum possible width is 400 characters. If no carriage return is requested
before the maximum line length is reached, Prolog inserts one: either
<carriage return> is inserted between two lexical units, or the sequence
<\><carriage return> is inserted inside a unit.

echo
Activates the option which produces a display on the "console" unit of
characters written or read by another file type unit.

no_echo
Cancels the effect of echo.

5.3 Loading and adapting the drawing module

The Dessin module is not included in the initial state we supply. You can add it to
your Prolog system by loading the binary file:
>load("dessin.mo");

To load from the Prolog directory, enter the following command:


> getenv("PrologDir2",S)
conc_string(S,"dessin.mo",S1)
load(S1);

You can also recompile the source module:


>insert("dessin.m2");

This file creates a new module called Dessin containing the program for drawing
trees and equations. This makes the following rules available (see section 5.2.1):
draw_equ
draw_tree
draw_mode
set_draw_mode
gr_tree_click if graphic mode is active.

Since this is a drawing module, it is obviously necessary to incorporate certain


information about the semi-graphic capacities of the terminals used. To this end, a
"drawing mode" (draw_mode) is available for the management protocol of each
type of terminal.

© PrologIA
Aociation Prolog
R 5 - 14 Reference Manual HERITAGE

Some configurations are already defined: vt100, tty, etc. It is up to you to add to
dessin.m2 the configurations required by the terminals you use.

To define a new drawing mode:

1. Give it an internal name, which is an identifier (tty, vt100, etc.), an external


name, which is a character string ("TTY", "VT100", etc.) and associate the two
names by adding a specified fact:

termi(external_name,internal_name) —>;

Note that the end-user should only know the external name.

2. Add two new definitions of the en-graphique and hors-graphique rules which
control the terminal's transition from character mode to semi-graphic mode,
and vice versa.

3. Add a new config rule to define the character strings which, when in graphic
mode, display the graphics indicated.

Please note
In all cases, the "TTY" mode can be used to obtain basic drawings without having to
use any of the terminal's graphic possibilities. This can be useful for example if you
want to print tree diagrams on a standard printer.

5.4 Declaration of operators

The operators make it possible to write functional terms having one or two
arguments, without using brackets. The functional symbol is replaced by an
operator placed as follows:

- infixed for functional terms having two arguments;

- prefixed or suffixed for functional terms having one argument.

An operator is defined by a symbol, an order or precedence, and grouping rules. To


remove ambiguity from expressions containing several operators, the operators
having the lowest order of precedence are bracketed first. If two operators have the
same order of precedence, the grouping rules are used to determine the bracketing.
The syntax of expressions using operators and predefined operators is given in
section 1.9.2 of this manual.
Example:
/ binary operator, order of precedence 400, bracketed left first
- binary operator, order of precedence 500, bracketed left first
expression: 3 - 2 - 1 / 4 / 3
non-ambiguous expression: ((3 - 2) - ((1 / 4) / 3))
Prolog tree: sub(sub(3,2), div(div(1,4),3))

© PrologIA
Aociation Prolog

HERITAGE Input and Output R 5 - 15

Although notation with operators is lighter, it should be noted that if it is used


excessively it can lead to difficulties in understanding, when the trees are actually
represented by expressions containing little-known operators.

op(n,i1,s)
op(n,i1,s,i2)
Declares the operator s with precedence n(0 <= n <= 1200) and bracketing
type i1. s is an identifier, or a string representing a graphic symbol. In the 3-
argument form, s can be a list, and the declaration then applies to each list
element. The 3 argument version is also a compiling directive. This means
that an operator can also be declared in the middle of a source you are
compiling. The functional symbol represented by s is i2 if the latter has been
defined, otherwise it is the symbol s given. The associativity il is defined by
an identifier combining two or three letters f, x, y; with the following
conventions:
f represents the operator
x represents an expression with an order of precedence less than f
y represents an expression with an order of precedence less than or equal
to f.
The possible combinations are:
fx operator prefixed with operand of lesser precedence
fy operator prefixed with operand of lesser or equal precedence
xf operator postfixed with operand of lesser precedence
yf operator postfixed with operand of lesser or equal precedence
xfx operator infixed with operands of lesser precedence
yfx operator infixed on the left with an operand of the same precedence, with
left right bracketing
xfy operator infixed on the right with an operand of the same precedence,
with right left bracketing

When n is equal to 0, the effect of op is to delete the declaration existing for


the operator s.
When the arguments of op/3 are free variables, they are successively unified
with the definitions of the existing operators.

Example:
> insert;
op(900,fy,not) op(700,xfx,"=",eq);
not x -> x ! fail;
not x ->; ;
{}
> (not 1=2)3;
{}
> split(1=2,L);
{L=eq.1.2.nil}

3Remember that in Prolog II syntax, the operators must be bracketed at the first level of a rule
body.

© PrologIA
Aociation Prolog
R 5 - 16 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

6. The environment

6.1 How to leave Prolog


6.2 Automatic start-up of a Prolog program
6.3 Program editing
6.4 Date, time and measurements
6.5 Link to the system
6.6 Program debugger
6.7 Modification and display of the current state
6.8 Automatic space and stack management

This chapter describes the predefined rules which provide communication with the
operating system, and which function regardless of which particular system is used.
Those rules which depend on the implementation used are described in the user's
manual.

6.1 How to leave Prolog

exit(s)
exit
Leaves Prolog, and saves all the currently known programs, including those
which constitute the Prolog II+ supervisor. The current state is saved in a file
called s. The second form, exit, is equivalent to exit(prolog.po).
Note: it is possible to just save the modules you have created or modified
during the session (command save -see section 3.7) and leave Prolog using
the quit command.

quit(n)
quit
Leaves Prolog without saving anything. The value n is sent to the operating
system as a "termination status". Whatever the system, if n=0 the value sent
corresponds to "no error" (this value does not have to be nil).
The second form, quit, is equivalent to quit(0).

6.2 Automatic start-up of a Prolog program

If the binary state used to start Prolog contains modules that have an ini_module
rule, each of these rules is executed (in an order defined by Prolog), as soon as
initialization terminates. Prolog then attempts to execute the goal :to_begin.

The :to_begin rule is not defined in the initial state. If you want the program to start
automatically, you should add the following rule:

© PrologIA
Aociation Prolog
R6-2 Reference Manual HERITAGE

:to_begin —> xxxx ;

where xxxx is the initial goal to be executed from the application program. You must
then save this state. When you call Prolog later on with this new state, xxxx will be
executed immediately.

6.3 Program editing

Since Prolog II+ is an incremental compiler, it enables you to edit rules without
leaving Prolog, using an editor that we will call a host editor.

The host editor is called by the Prolog command edit.

There are several versions of this command, depending on what you want to do:

- modify one or several groups of rules

- edit and recompile a source module

- edit a text file of some kind.

There are some important things you should know about editing in Prolog:

- rules are deleted from the Prolog code space so that they can be written in the
text file used for editing. At the end of editing the file is reinserted.

- editing compiles, and therefore when non compiled facts are edited they will
be transformed into compiled rules.

- at any particular time there is only one copy of the rules; either as Prolog code
or as Prolog source.

- when a user interrupt occurs the code space will however be modified, in a
variety of ways depending on when the interruption occurs.

- when non visible rules are edited they are deleted, but are not provided in
source format!

6.3.1 Modifying groups of rules

This command is used to edit groups of rules, listed as arguments. When editing is
finished, these groups are re-inserted in place of the original groups. The groups
can belong to several different modules, in which case it is the reading/writing
context of the first group's module which is used.

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6-3

edit(ident/arity)
edit(l)
ident/arity represents the group of rules whose access is the identifier ident
and whose number of arguments is arity .
l is a sequence of ident/arity elements (may or may not end in nil).

When Prolog returns from a host editor call it may detect a syntax error in the rules
that you have just edited. If so it will display the number and contents of the line
containing the error, the corresponding diagnosis, and will ask you if you wish to
re-start the editing-compiling cycle, or abandon the attempt.

If you abandon the attempt the system brings you back to Prolog, and the non-
inserted rules are deleted.

By pressing the carriage-return key you can restart the host editor, and correct the
error. By pressing q <RETURN> you return to Prolog, and the non-inserted rules
are deleted.

Please note

It is possible that the text you have edited contains an error which Prolog
cannot detect immediately.

Remember that when the host editor is used, a file called PROEDIT.PRO
is created in the current directory, which contains the edited rules in their
final state. You will find yourself back in Prolog, without the edited rules
which have not been read. Save this program, and once you have left
Prolog, use a text editor to analyze the missing piece from
PROEDIT.PRO.

6.3.2 Editing and recompiling a source module

This function is used to modify and recompile the source text of a loaded module.
Editing will be carried out on the original form:

editm(m)
m is a string. Deletes all rules in the module m and starts editing of the
corresponding source file. The edited version is recompiled and replaces the
previous version.
If the source file cannot be found, editing is performed on a source created by
decompiling the module. This source file is called PROEDIT.Mx where x is
a number generated by Prolog having a different value for each module with a
different name.

Please note: any rules which may have been added to the module using
insert or assert during execution are executed before the module is
reloaded.

© PrologIA
Aociation Prolog
R6-4 Reference Manual HERITAGE

6.3.3 Editing any type of text file

This is performed by the command edit("file").

edit(s)
s is a string. Enables editing the file of name s.

6.4 Date, time and measurements


reset_chrono, chrono(x)
chrono unifies x with the time in seconds elapsed since the last reset_chrono.

reset_cpu_time, cpu_time(x)
cpu_time unifies x with the cpu time in milliseconds elapsed since the last
reset_cpu_time.

date(j,m,a,s)
Calculates the arguments j,m,a,s for the current date. The four arguments
correspond to the day of the month, the month, the year, and the number of the
day in the week (Sunday = 0, Monday = 1, ...).

date_string(s)
Calculates the current date in English and unifies the corresponding character
string with s.

date_stringF(s)
Calculates the current date in French and unifies the corresponding character
string with s.

week(n,s)
Returns in s the string corresponding to the day in the week whose rank is n,
and vice-versa.

month(n,s)
Returns in s the string corresponding to the month whose rank is n and vice
versa.

delay(n)
Generates a delay of n milliseconds

time(x)
Gives an absolute time in seconds. The origin of this time varies from one
machine to another.

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6-5

time(h,m,s)
Calculates arguments h, m, s of the current time, representing hours, minutes
and seconds.

6.5 Link to the system

sys_command
Executes an operating system command represented by the string s. When
the command called causes an error, sys_command generates a "SYSTEM
ERROR" and provides an error complement; the status returned by the
operating system.
On some systems (especially those running UNIX), this predicate may
consume a large amount of memory. This can be avoided by redefining it
with a coprocess (on these systems, refer to the chapter on coprocesses).

getenv(s,x)
Unifies x with the string representing the value of the environment system
variable whose name is defined in the string s. If the variable is not defined, x
is unified with an empty string.

set_import_dir(s)
Defines a reference directory that is consulted after the current directory, when
files have not been found by primitives manipulating files for reading, such as
input, insert, load. The character string s concatenated to a file name must
define a complete name the operating system can understand.

lkload(s,x)
This primitive is only available on certain operating systems, so please refer to
the User's Manual. When present, it enables dynamic linking and loading of
external programs.

ms_err(n,s)
Unifies s with the text of error number n. To do this, Prolog searches in the
error file err.txt which must consist of a sequence of lines in the following
format:
integer space character sequence constituting the text of the error.
You can add messages to this file, provided you comply with the indicated
format. We recommend you message numbers greater than 1000.

© PrologIA
Aociation Prolog
R6-6 Reference Manual HERITAGE

6.6 Program debugger


The Prolog debugger provides an interactive program trace without modifying
semantics, and without taking up memory space. It offers many useful features
enabling the user to position break points, trace the program step by step and jump
sections of it, print the state of the current proof, and view the backtracks.

When you have executed the program with the debugger enabled, the built-in
predicate statistics may help to configure the Prolog spaces.

Note: The optimized code only makes it possible to reconstruct an equivalent


representation of the source, and does not enable the debugger to view all the
information relating to this source. To obtain an exact representation of your
program, you must compile the rules without any optimizations, using the
appropriate option at Prolog start-up.

6.6.1 Trace mode

The debugger offers two operating modes.


• a trace mode displaying the execution,
• an interactive mode enabling you to take control during the execution and
intervene in it.

To begin with, before you plunge into the detail of the interactive mode commands,
the trace mode enables you to display all the information required to understand the
program.

The trace mode is a simple and quick way of understanding how a program
executes.

Each executed goal is displayed with its unified arguments on the rule chosen for
the current execution. The backtrackings are shown and the system specifies the
predicate where choices remained and the new rule's rank in the group.

If you load the example program menu.p2 and activate trace mode, the following
sequence shows how this information is presented:
> meal(e,Chapon_farci,d);
hors_d_oeuvre( Artichauts_Melanie)
main_course( Chapon_farci)
RECALL(2): main_course/ 1
main_course( Chapon_farci)
fish( Chapon_farci)
dessert( Sorbet_aux_poires)
{e=Artichauts_Melanie,d=Sorbet_aux_poires}
RECALL(2): dessert / 1
dessert( Fraises_chantilly)
{e=Artichauts_Melanie,d=Fraises_chantilly}
RECALL(3): dessert / 1
dessert( Melon_en_surprise)
{e=Artichauts_Melanie,d=Melon_en_surprise}

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6-7

To make the information provided by the trace easier to read (when executing
programs that write on the current output), it can be redirected into a file.

Activation, deactivation
Trace mode is activated by executing one of the built-in predicates trace/0 or
trace/1. It is deactivated by executing the built-in predicate no_trace/0.

trace
Activates the trace.

trace(f)
Activates the trace. It redirects all trace output into the file called f (Prolog
string). The file is closed when a predicate to close the debugger is executed.
If the debugging output was already redirected, the previous file is closed and
replaced by f.

no_trace
Deactivates the trace.

6.6.2 Interactive mode

Although the trace is simple to activate, it can rapidly produce a considerable flow of
information where it is easy to get lost. This is where the interactive mode becomes
extremely useful, because it enables you to go straight to the most important
information. Its advantages are:

• the commands for advancing in the code,


• definition of the information to produce,
• the additional commands for execution.

Interactive mode enables you to choose the information you want to extract from the
program, in the appropriate format, without modifying the program, and only in
designated sections of the code. Above all, it enables you to take control whenever
you want, to start actions.

6.6.2.1 Break points


In interactive mode, the debugger will display its welcome banner (DBG) and wait
for a command on each break point. To gain access to the command interpreter it is
important to define the break points properly. There are two types:
• fixed break points, which remain for as long as the debug mode is enabled
and provided they have not been deactivated by a command;

© PrologIA
Aociation Prolog
R6-8 Reference Manual HERITAGE

• temporary break points that are only valid during a command, which in fact
defines the next check point for the debugger.

When a break point is defined on a predicate the debugger stops as soon as the
current program calls this predicate. The Prolog machine will therefore stop at the
moment when the goal is to be erased, before unification with the head of the chosen
rule has taken place.

There are specific commands and built-in predicates to define fixed break points.
The temporary break points are defined implicitly by an advance command or when
the debugger is activated.

When the Prolog machine is running with the debugger enabled, a user interrupt
posts a temporary break point on the current goal and the interactive mode is re-
enabled. This means user interrupts are intercepted and do not produce an error.

See the debugger commands +, -, b and the predefined rules spy, no_spy,
show_spy.

6.6.2.2 Advancing in the code


When you advance in the code, you move from break point to break point.

There are three scales of advance. You will use different scales depending on how
"close" the error is and the type of information you want to extract from a section of
the program.

Starting from a break point, there are three ways of advancing (jumps):

1) You know where the problem is in a program, and you want to get there directly
and quickly.

Answer: (go to spy) goes to the next fixed break point, which can be
anywhere in the code.

2) You want to have a "close look" at the execution of the function, without going
down into the low levels of its "sub-programs".

Answer: (next) goes to the next goal of the same level or upper level. It
ignores the lower levels1, i.e. ignores the body of the current rule.

3) You want to see the whole execution of the function precisely, without omitting
any instructions.

Answer: (step) goes to the next goal.

1 Definition of a goal's level. Let's suppose a goal of the question is on level 0. If a goal is on
level n, the goals appearing in the body of its rule are all on the same level, equal to n+1.

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6-9

On our example of a menu, let's represent the possible advance jumps using next
and step:

meal ...

hors_d_oeuvre main_course dessert

step
next
meat

Note that on the specified facts step and next have the same effect.

The commands for advancing in the code enable you to define the next break point
and the information that must be obtained in the meantime. Each time you advance
you can choose whether or not to display information about the execution of the
program section.

See the debugger commands CR, n, N, g, t.

6.6.2.3 Ending execution


You have debugged part of the program and now need to end it. You can:

- (go to end) continue to the end of the program: by printing all the information, by
printing just the information concerning the fixed break points, or by leaving debug
mode and continuing normally.

- (abort) interrupt the program.

- (quit) quit Prolog.

See the debugger commands a, e, G, T, q.

6.6.2.4 Displaying information


We are now going to describe when and how information is displayed.

© PrologIA
Aociation Prolog
R 6 - 10 Reference Manual HERITAGE

When?

A backtracking is generated:

The information is displayed. It indicates that it is an alternative ( RECALL), the


number of the chosen new rule and the goal we are trying to erase again. The goal
to be retried is one of the goals to erase and so it can be used as a break point. For
example, on the following execution:
> main_course(Chapon_farci);
CALL: main_course( Chapon_farci)
DBG:
CALL: meat( Chapon_farci)
DBG:
RECALL(2): main_course( Chapon_farci)
DBG:
CALL: fish( Chapon_farci)
DBG:
{}

The backtracking information is:


RECALL(2): main_course( Chapon_farci)

The number of the rule to try again is written in brackets (2). A break point is
inserted on the new call to the goal
main_course( Chapon_farci)

On this other alternative we then have access to all the functions of the debugger.

Another example. If a fixed break point is placed on main_course/1, the


debugger stops on all its alternatives:
> meal(e,Chapon_farci,d);
CALL: meal( v147, Chapon_farci, v284)
DBG: +main_course/1 (adds the break point)
DBG: g (go to spy)
CALL: main_course( Chapon_farci)
DBG: g
RECALL(2): plat( Chapon_farci)
DBG: g
{e=Artichauts_Melanie,d=Sorbet_aux_poires}
{e=Artichauts_Melanie,d=Fraises_chantilly}
{e=Artichauts_Melanie,d=Melon_en_surprise}
CALL: main_course( Chapon_farci)
DBG: g
RECALL(2): plat( Chapon_farci)
DBG: g

An error is generated by the machine or by an external predicate:

The break points are not modified. The error message is displayed, even if the error
is recovered by a block, together with the resolution branch, when the error occurs.
For example, on the following execution:
> insert;
toto(x,y) -> block(x,titi(y)) outl(x);
titi(y) -> string_ident(y,z) outl(z);

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 11

;
{}
> debug toto(x,12);
CALL: toto( v156, 12)
DBG:
block
CALL: titi( 12)
DBG:
CALL: string_ident( 12, v360)
DBG:
BAD ARGUMENT TYPE
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ titi / 1, rule number 1
^^^^^^^^ toto / 2, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
CALL: outl( 253)
DBG:

The information about the error is:


BAD ARGUMENT TYPE
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ titi / 1, rule number 1
^^^^^^^^ toto / 2, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^

You can cancel display of this information about errors during a debugging session,
using the debugger command s.

This mechanism does not show up the errors block_exit produces in Prolog. The
predefined rule block_exit is treated as an ordinary predicate. To obtain a warning
about this type of error, simply put a break point on block_exit/1 and block_exit/2.

On a break point, i.e. when a goal is called:

Goals can be printed on two occasions, which we will call "before unification" and
"after unification". See the debugger commands p, P.

Goals can be printed before unification, i.e. the goal is displayed as it appears in the
current list of goals before it is unified with rule head chosen for its erasure.

They can be printed after unification, i.e. the goal is displayed after the rule has been
chosen and just before the next break point. Therefore we can obtain different
results from one execution to another for different advance jumps. For example, if
the advance jump in the debugger is a step for a specific goal, the Prolog machine
will have simply unified the goal with the rule head. However, if the jump is next the
Prolog machine will have executed the body of the rule where the unifications have
taken place, and the goal's arguments will not necessarily have the same values as
before.

Let's look at the value of the arguments for our example, using both types of
advance:
> meal(e,p,d);
CALL: meal( v156, v191, v226)
DBG: P1 (validates display after unification)

© PrologIA
Aociation Prolog
R 6 - 12 Reference Manual HERITAGE

DBG:
CALL: hors_d_oeuvre( v156)
DBG:
hors_d_oeuvre( Artichauts_Melanie)
CALL: main_course( v191)
DBG:
main_course( v191)
CALL: meat( v191)
DBG:
meat( Grillade_de_boeuf)
CALL: dessert( v226)
DBG: g (go to spy)
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Sorbet_aux_poires
}

> meal(e,p,d);
CALL: meal( v156, v191, v226)
DBG: P1
DBG:
CALL: hors_d_oeuvre( v156)
DBG:
hors_d_oeuvre( Artichauts_Melanie)
CALL: main_course( v191)
DBG: n (next)
main_course( Grillade_de_boeuf)
CALL: dessert( v226)
DBG: g
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Sorbet_aux_poires
}

How?

Presentation

You can define a margin (number of characters) for debugger display, to make the
debugging session easier to read and differentiate between messages from the
program and the debugger. All messages transmitted by the debugger will be
indented the defined number of characters from the margin when displayed.
> meal(e,p,d);
CALL: meal( v156, v191, v226)
DBG:
CALL: hors_d_oeuvre( v156)
DBG:
CALL: main_course( v191)
DBG: n (next)
CALL: dessert( v226)
DBG:
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Sorbet_aux_poires
}
RECALL(2): dessert(v190)
DBG:
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Fraises_chantilly
}
RECALL(3): dessert(v190)
DBG:
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Melon_en_surprise
}

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 13

RECALL(2): meat(v165)
DBG:
CALL: dessert( v226)
DBG:

Another alternative is to redirect the debugger's messages into a file. In this case,
only the prompt sequence will be displayed in the trace unit.

See the debugger command i, or the predefined rules debug(f) and debug(n,f).

Precision

You can configure the precision of the goal display, according to the amount of
information you want. There are three modes:

- The debugger prints the predicates without their arguments and specifies
their arity in the form identifier/arity.

- The debugger prints the predicates and their arguments in a functional


notation with an adjustable depth limit. Beyond a depth of 1,000 the whole
term is printed. When entire infinite trees are printed they are represented as
systems of equations. It is not possible to say a priori whether restricted
printing of an infinite tree is possible.

- The debugger prints the predicates and their arguments in the form of a
tree using the Dessin:draw_tree predicate. To use this mode the tree
drawing module must be loaded. The Dessin:draw_tree rule can be
modified to redefine what the debugger prints.

Details about the functional notation with a depth limit:

Each atom of the term to print is assigned a depth. Only atoms with a depth less
than the defined limit will be displayed.

The system counts recursively starting from the goal to display, and starts at 1. The
depth increments when the system goes from a term to a sub-term, as follows:

If a functional term f(a1, t2, …, as) appears in a term with depth n then the
functor f has a depth of n, and its arguments a1, …, as have the depth n+1.

If a tuple <t1, t2, …, ts> (t1 is not an identifier) appears in a term with depth
n then the atom <> has a depth of n and the arguments of tuple t1, t2, …, ts
have a depth of n+1.

If a list x.y appears in a term with depth n, then x has the depth n and y has
the depth n+1.

For example, this is how the depths of the atoms are defined for the following term:

element_of( 12, 1. 2. 3. 4. 5. nil, no)


1 2 2 3 4 5 6 7 2

© PrologIA
Aociation Prolog
R 6 - 14 Reference Manual HERITAGE

With a depth limit of 3, it will be printed: element_of( 12, [ 1, 2,…], no);

See the debugger command m.

Choosing the information

Parts of the program have already been proved and do not need to be verified. In
interactive mode you can use the next advance jump to avoid developing the body of
a predicate. The same possibility is available in trace mode (total trace or printing of
information between two break points).

For example, if main_course/1 does not need to be developed, we get:


> trace meal(e,p,d) !;
hors_d_oeuvre( Artichauts_Melanie)
main_course( Grillade_de_boeuf)
dessert( Sorbet_aux_poires)
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Sorbet_aux_poires
}

instead of:
> meal(e,p,d) !;
hors_d_oeuvre( Artichauts_Melanie)
main_course( v191)
meat( Grillade_de_boeuf)
dessert( Sorbet_aux_poires)
{e=Artichauts_Melanie,p=Grillade_de_boeuf,d=Sorbet_aux_poires
}

See the debugger commands >, <, j.

6.6.2.5 Additional information about execution


To obtain detailed information about a specific goal in the program that is executing,
we may want to know how far the execution has progressed, and which rule the
system is trying to erase.

On each break point, the debugger enables you to locate the goal called in relation to
the resolution tree and the rule base.

What is the current branch of the resolution tree?


^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ titi / 1, rule number 1
^^^^^^^^ toto / 2, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^

What is the position of the goal in the program?


---> meal / 3, rule number 1, goal number 3 in queue

In fact the current resolution branch is given by the state of the recursion stack.
Because the Prolog machine optimizes the terminal call, it is not possible to view the
rules in which the currently executing goal is the last in the rule body. For example:
> meal(e,p,d);

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 15

CALL: meal( v156, v191, v226)


DBG: s here the stack is empty, since meal is not installed yet.
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
DBG:
CALL: hors_d_oeuvre( v156)
DBG: s here it contains meal , since it is the calling goal.
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ meal / 3, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
DBG:
CALL: main_course( v191)
DBG: s here also, since main_course and hors_d_oeuvre have
the same depth.
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ meal / 3, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
DBG:
CALL: meat( v191)
DBG: s here main_course does not appear because meat is its
terminal call .
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^ meal / 3, rule number 1
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
DBG:
CALL: dessert( v226)
DBG: s here meal does not appear because dessert is its terminal
call.
^^^^^^^^^^^^^^^^TOP^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^BOTTOM^^^^^^^^^^^^^^^^
DBG:

Finally, to have access to the maximum amount of information, you can open a
Prolog session. This enables you to check for the program's side effects, restart
part of the program, start an additional program, verify the rule base, check the status
of the stacks, etc.

When the session opens, the command line prompt is displayed in the console and
you can enter any Prolog goal. When you close the session (e.g. by executing quit)
the debugger continues from where it was. It should be noted that the session's side
effects are kept: assignments, addition/suppression of rules, opening/closing of files,
etc.

For example, the execution of meal(e,Poulet,d) causes a failure, so we debug:


> meal(e,Poulet,d);
CALL: meal( v156, Poulet, v313)
DBG:
CALL: hors_d_oeuvre( v156)
DBG:
CALL: main_course( Poulet)
DBG:
CALL: meat( Poulet)
DBG:
RECALL(2): main_course( Poulet)
DBG:E why did meat(Poulet) fail?
we open a session,
> list(meat/1); the Prolog prompt is displayed,
meat(Grillade_de_boeuf) -> ;

© PrologIA
Aociation Prolog
R 6 - 16 Reference Manual HERITAGE

meat(Poulet_au_tilleul) -> ;

{} we consult the rule base,


> quit; we end the session,
Elapsed time: 19s
Goodbye...
DBG: w we're back in the debugger!
---> main_course / 1 , rule number 2, on backtracking
DBG: g
>

See the debugger commands s, w, E.

6.6.2.6 Configuration
As we have already seen, it is possible to define the debugger's behavior. The set of
behavior parameters is called the configuration.

Some configuration parameters can be specified when the debugger starts. They
will be valid during throughout the debugging session (i.e. for as long as the
debugger has not been disabled or reactivated with different parameters) unless a
command modifies them.

The behavior parameters are as follows:

upon activation or using the debugger command interpreter:


advancing in the code,
the moment when arguments are printed,

using the debugger command interpreter only:


presentation of the information, including:
a message indentation parameter,
a parameter to define precision or depth of display.
choice of information: on errors, between two break points, during the
trace.

There is a predefined standard configuration comprising the following: break on the


next goal, printing before unification, no indentation, printing of terms by out with a
depth of 4, printing of a message and the recursion stack on errors.

There are debugger tools enabling you to ascertain its configuration, and obtain
other information about the debugging:
the state of the options,
the list of active break points,
the list of predicates not developed in the trace,
the list of debugger commands.

See the debugger commands S, b, j, h and the predefined rule show_spy.

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 17

6.6.3 Activation of a debugging mode

The debugger is activated as soon as one of the built-in predicates trace/0, trace/1,
debug/0, debug/1 or debug/2 is executed. It is deactivated by executing one of the
built-in predicates no_trace/0 or no_debug/0.

A flag defines the configuration at the beginning. It is the sum of the values chosen
from:
1 break on the first call to a goal.
2 break on the first fixed break point.
8 Option to print after unification confirmed.
16 Option to print before unification confirmed.

A flag value of 0 corresponds to the predefined standard configuration.

debug(n) or
debug(n, f)
are the general predicates for activating the debugger. n must be a known
integer when the call is made. It specifies the starting configuration as it has
been defined above. An n value of 0 specifies the predefined standard
configuration. f is the name of the file containing the redirected debugger
display. The file is closed when a debugger deactivation predicate is executed.
If the debugger display was already redirected to a file, this file is closed and f
replaces it.

debug or
debug(f)
are the debugger's reactivation predicates. They do not modify the current
configuration. f is the name of the file that will contain the redirected
debugger display. The file is closed when a debugger deactivation predicate is
executed. If the debugger display was already redirected to a file, this file is
closed and f replaces it.

trace or
trace(f)
are the debugger's special predicates. They activate it in trace mode,
represented by the flag 19. f is the name of the file that will contain the
redirected debugger display. The file is closed when a debugger deactivation
predicate is executed. If the debugger display was already redirected to a file,
this file is closed and f replaces it.

no_trace or
no_debug
are the debugger's deactivation predicates. They function regardless of the
mode, and do not modify the current configuration.

© PrologIA
Aociation Prolog
R 6 - 18 Reference Manual HERITAGE

6.6.4 Management of break points

The break points are managed using the following predefined rules:

spy(i/a)
Places a break point on the rule with name i and arity a. The break point is
only taken into account if the debugger is activated with an appropriate mode.

no_spy(i/a)
Removes any break point placed on the rule with name i and arity a.

show_spy(l)
Unifies l with the list of primitives that have an active break point. The
primitives are shown in the normal way: i/a where i is its access identifier and
a is its arity.

6.6.5 Commands in interactive mode

At each break point, the debugger prints the prompt sequence "DBG:" indicating
that it is waiting for a user command. A carriage return, written CR in this section,
corresponds to the default command step in interactive mode. The other commands
end in a carriage return.

The following commands are available:

CR (step) Continues to the next call to a rule.

a (abort program) Generates a user interrupt.

b (breakpoints) Displays the active break points. See also the show_spy
predicate.

e (end debugging and go) Ends debugging mode and continues execution.

E (Execute) stacks a Prolog session.

f (fail) Causes a failure on the displayed goal.

g (go to spy) Continues to the next fixed break point without displaying
anything.

G integer
(Go to end) Continues to the end of the program. If integer is 0 it prints the
fixed break points only. If integer is not 0 it also prints the goals appearing in
the rule body of fixed break points.

h (help) Lists the commands available.

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 19

i integer
(indent) The value of integer defines the number of characters for the display
margin.

j
(jump) Gives the list of rules whose bodies are ignored in trace mode.

l integer
(length) The value of integer defines the length of the line for output.

m integer
(mode) The value of integer defines the mode for displaying Prolog goals:
0 Display in the form identifier/arity.
1 Display by the tree drawing program.
[2, 1000] Display with depth limited by integer.
> 1000 Display of the complete term.

n (next) Stops on the next goal that is not a sub-goal.

N (Next while tracing) Stops on the next goal that is not a sub-goal and prints
information about execution of the section of program, according to the
current options chosen. In this case the effect of the > command is ignored.

p boolean
(print before unification) Printing of goals before unification is activated if
boolean is 1, and deactivated if boolean is 0. If boolean is not mentioned it is
equivalent to 0.

P boolean
(Print after unification) Printing of goals after unification is activated if
boolean is 1, and deactivated if boolean is 0. If boolean is not mentioned it is
equivalent to 0.

q (quit) Quits Prolog and returns to the host system.

s (stack) Displays the Prolog stack of rules being executed.

s0 Cancels printing of the message and the Prolog stack when an error occurs. s
1 restores it.

S (State) Displays the current options.

t (trace to spy) Continues to the next fixed break point and prints the
information about execution of the section of program, according to the
current options chosen.

T (Trace to end) Continues to the end of the program and prints the execution
information according to the current options chosen.

w (where) Displays the position of the current goal in the program.

© PrologIA
Aociation Prolog
R 6 - 20 Reference Manual HERITAGE

+ ident/arity
Puts a break point on the group of rules with access identifier ident and arity
arity. See also the spy predicate.

- ident/arity
Removes all break points from the group of rules with access identifier ident
and arity arity. See also the no_spy predicate

-a Removes all break points in a single command.

> ident/arity
Indicates that the predicate with access identifier ident and arity arity must not
be developed in the trace.

< ident/arity
Cancels the effect of the opposite command (>) on the predicate with access
identifier ident and arity arity.

< a Cancels the effect of all the opposite commands (>) that have been applied to
predicates.

The fixed break points, predicates not to be developed in the trace, the display mode
and the margin definition are permanent. They are not modified by a specific or
default activation of the debugger. They can only be modified or removed
explicitly.

6.6.6 Example

Let's look at the example program about menus, supplied in the kit. The comments
about execution are shown in italics.

We verify the loaded rules and go into debug mode. Then we launch the goal
dif(d, Sorbet_aux_poires) balanced_meal( Truffes_sous_le_sel, p,
d).

User input is shown in bold. The lines entered by the user must end with a carriage
return, which is not shown here, except when there is an empty line, where it is
written CR.
> dictionary;
DICTIONARY CONTENT OF ""
balanced_meal / 3
calories / 2
dessert / 1
fish / 1
hors_d_oeuvre / 1
main_course / 1
meal / 3
meat / 1
smaller / 2
sumof / 4
value / 4

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 21

{}
> debug dif(d, Sorbet_aux_poires)
balanced_meal(Truffes_sous_le_sel,p,d);
CALL: dif( v254, Sorbet_aux_poires)
DBG: CR
CALL: balanced_meal( Truffes_sous_le_sel, v623, v743)
We add display after unification and indentation to the
default configuration.
DBG: P1
DBG: i5
We verify the current options.
DBG: S
Print after unification
Print before unification
Print mode = out, depth: 4
Errors are printed
Indentation= 5
We continue.
DBG: CR
CALL: meal( Truffes_sous_le_sel, v623, v743)
This is an important predicate. We put a fixed break point
on it and check the active fixed break points.
DBG: +meal/3
DBG: b
meal/3
We continue.
DBG: CR
meal( Truffes_sous_le_sel, v623, v743)
CALL: hors_d_oeuvre( Truffes_sous_le_sel)
DBG: CR
hors_d_oeuvre( Truffes_sous_le_sel)
CALL: main_course( v623)
This is an important predicate. We put a fixed break point
on it and check the active fixed break points.
DBG: +main_course/1
DBG: b
main_course/1
meal/3
We continue.
DBG: CR
main_course( v623)
CALL: meat( v623)
DBG: CR
meat( Grillade_de_boeuf)
CALL: dessert( v743)
DBG: CR
RECALL(2): dessert( v743)
DBG: CR
dessert( Fraises_chantilly)
CALL: value( Truffes_sous_le_sel, Grillade_de_boeuf,
Fraises_chantilly, v817)
We don't want to stop in this predicate, we just want to see
what is happening in it.
DBG: N
value( Truffes_sous_le_sel, Grillade_de_boeuf,
Fraises_chantilly, v817)
CALL: calories( Truffes_sous_le_sel, v828)
calories( Truffes_sous_le_sel, 212)

© PrologIA
Aociation Prolog
R 6 - 22 Reference Manual HERITAGE

CALL: calories( Grillade_de_boeuf, v833)


calories( Grillade_de_boeuf, 532)
CALL: calories( Fraises_chantilly, v838)
calories( Fraises_chantilly, 289)
CALL: sumof( 212, 532, 289, v817)
The arithmetical expressions were optimized when compiled.
add
add
sumof( 212, 532, 289, 1033)
CALL: smaller( 1033, 800)
DBG: N
inf
RECALL(3): dessert( v743)
DBG: CR
dessert( Melon_en_surprise)
CALL: value( Truffes_sous_le_sel, Grillade_de_boeuf,
Melon_en_surprise, v817)
We verify the predicate's position.
DBG: w
---> balanced_meal / 3 , rule number 1, goal number 2 in
queue
From now on we are not interested in the details of the
predicate. We cancel its development and check the list of
predicates in this case.
DBG: >value/4
DBG: j
value/4
We continue.
DBG: n
value( Truffes_sous_le_sel, Grillade_de_boeuf,
Melon_en_surprise, 866)
CALL: smaller( 866, 800)
DBG: >smaller/2
DBG: j
smaller/2
value/4
DBG: n
RECALL(2): dessert( v743)
We want to have the trace up to the next break point with
printing after unification only. We therefore deactivate
printing before unification.
DBG: p0
DBG: t
dessert( Fraises_chantilly)
value( Truffes_sous_le_sel, Poulet_au_tilleul,
Fraises_chantilly, 901)
RECALL(3): dessert( Melon_en_surprise)
value( Truffes_sous_le_sel, Poulet_au_tilleul,
Melon_en_surprise, 734)
smaller( 734, 800)
{d=Melon_en_surprise,p=Poulet_au_tilleul}
RECALL(2): main_course(v165)
DBG: p1
We have stopped on a fixed break point. We are interested in
all the important predicates (they have a fixed break point)
right up to the end.
DBG: +meat/1
DBG: +fish/1
DBG: b
fish/1

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 23

main_course/1
meal/3
meat/1
DBG: G
main_course( v623)
CALL: fish( v623)
fish( Bar_aux_algues)
{d=Fraises_chantilly,p=Bar_aux_algues}
{d=Melon_en_surprise,p=Bar_aux_algues}
RECALL(2): fish( v623)
fish( Chapon_farci)
{d=Fraises_chantilly,p=Chapon_farci}
{d=Melon_en_surprise,p=Chapon_farci}
>

6.7 Modification and display of the current state

alloc
alloc / 12
Describes the state of the Prolog stacks. The version with no argument writes
the current values on the current output. If the second version is used, the first
argument is unified with the space occupied, the second with the space
available, as follows:
1,2 : code space
3,4 : structure copy stack (heap)
5,6 : local stack (local environments and variables)
7,8 : restoration stack
9,10 : dictionary space
11,12 : none

edinburgh
This primitive is used to go into Edinburgh mode from Prolog II mode. It
loads the edinburg.mo module; and also changes the syntax, adds built-in
primitives, adds and modifies operators.

get_option(o,x)
Obtains the value of a behavior option in the session. o must be a character
string of one character representing the option. x is unified with a character
string of one character representing the option's value. The meaning of the
characters is defined by the conventions of the command line option -f (see
chapter U2.3). For example, to find out the real syntax chosen for the session:
> get_option("r",x);
{x="P"}

prologII
This primitive is used to go into Prolog II mode from Edinburgh mode. It
changes the syntax, modifies the operators, deletes the specific Edinburgh
built-in primitives.

© PrologIA
Aociation Prolog
R 6 - 24 Reference Manual HERITAGE

prologIIE
This primitive is used to go into Prolog II mode from Edinburgh mode. It
keeps the Edinburgh-specific predefined rules: changes the syntax and
modifies the operators.

state
Displays the current state of the stacks, and the name of the modules that are
in memory.

statistics
statistics/12
This primitve is used to display the maximum values reached in Prolog spaces
during a session. These values are only memorized in debug mode. If debug
has never been executed and statistics is called, the values displayed will be
meaningless. Arguments are the same that in alloc predicate.

set_options(o)
This primitive is used to change the options defined at start-up by the -f
command line option, without having to leave Prolog. o is a characer string.
In the example below, the user goes to edinburgh variable syntax and standard
reals syntax:
> set_options("vErS");

version(o)
This primitive gives you the current version of Prolog. For example, if the
current version is 3.1,
> version(o);
{o=301}

6.8 Automatic space and stack management


To function, a machine needs stacks to manage execution, and spaces to store the
program's structures.

The Prolog II+ system is a virtual machine. It has three stacks:


- the recursion stack (stack), containing the successive environments of the
calls in the current proof;

- the copy stack (heap), containing a copy of the current proof's structures;
- the restoration stack (trail), containing a record of the arguments' values,
for backtracking;

and two spaces for the internal structures:


- the code space, containing all the compiled rules and the static data for all
the modules;

© PrologIA
Aociation Prolog

HERITAGE The Environment R 6 - 25

- the dictionary space, containing all the identifiers and rule accesses created
during the session.

The Prolog II+ system comprises a garbage collection and packing mechanism for
the stacks and spaces, and a reallocation mechanism.

During operations that make use of the stacks or spaces (assert, insert, def_array,
non terminal recursivity …), these stacks or spaces may become saturated. The
garbage collection and packing mechanism is then activated automatically. If there
is still not enough free memory space, the reallocation mechanism is automatically
activated in turn. It's purpose is to increase the allocation to the relevant stack or
space by 25%. This is the default percentage, and it can be modified using a
command line option when Prolog starts (see U2.3).

You can explicitly request either of these two mechanisms on a stack or space, using
the gc and realloc predicates.

gc(x)
activates garbage collection and packing on the memory space denoted by x. x
can take one of the following values:
:code for the code space
:dictionary for the dictionary space,
:stacks for the stacks (they cannot be separated for this
operation)

N.B.: When code space garbage collection is activated, the system considers that all
the rules being used in the current execution must be conserved, even if they have
previously been deleted and are therefore inaccessible for a new execution.

N.B.: The garbage collector must determine which objects are unnecessary, so that
their space can be used again. The structures likely to be manipulated by an
external language, and where the garbage collector can function are the Prolog
identifiers. To avoid confusion, users must tell Prolog whether or not they are using
a particular identifier from the outside, so that Prolog knows whether an identifier is
still necessary, and so that the garbage collector does not delete it. This can be done
using the set_permanent_symbol and reset_permanent_symbol functions (cf.
Chapter 7 of this manual).

realloc R(x,y)
activates reallocation of the space denoted by x, with a size redefined by the
factor y. x can take the values :code, :dictionary, :stack, :heap, :trail,
depending on whether the space is in the code, the dictionary, the stack, the
heap or the trail. y is an integer indicating the percentage of increase (if it is
positive) or decrease (if it is negative) of the previous size.

© PrologIA
Aociation Prolog
R 6 - 26 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

7. Extending Prolog with other


languages.

7.1 Principles of the data transfer functions


7.2 Simple data transfer functions
7.3 Functions to transfer any type of term
7.4 Principle of the descriptor method
7.5 Shared data
7.6 Adding external functions
7.7 Adding external functions using direct calls

This chapter explains how to make links with external objects and how to add new
predefined rules written in C or a compatible language. The examples described in
this chapter can be found in the kit's expredef.c file. A Fortran equivalent is
provided in the kit's fprouser.eg file.

To extend Prolog with functions from other languages, you must have a
communication module to:

- create a link between the Prolog predicate and the external function,
- transform the data transferred between the Prolog structure and the
external structure.

Different methods can be used to carry out these two tasks.

- The link is defined in C. This is the descriptor method described in this


chapter.
- The link is defined in Prolog. This is the parasite method described in
appendix D.
- The data is transformed in Prolog. This is the descriptor method
concerning direct call functions, i.e. functions that do not need a C
interface to pass arguments,
- The data is transformed in C or Fortran; in the other cases.

To extend Prolog with certain types of data, which Prolog and C will then share, it is
sufficient to:
- create a link between the Prolog term and the external data item, using the
descriptor method.

© PrologIA
Aociation Prolog
R7-2 Reference Manual HERITAGE

We start this chapter with a description of the functions to communicate terms,


when the values of the terms are recovered and assigned in C or Fortran. These
functions are useful in many cases. We will then explain how to create the link with
external objects using the descriptor method. Finally, we will give details of the
possibilities offered by this method.

7.1 Principles of the data transfer functions

In sections 7.2 and 7.3 we are going to describe the transfer functions you can use
when a procedure in an external language needs to know the value of an argument in
the Prolog predicate linked to the procedure, or needs to assign it a value.

Below we define some principles that are common to all these functions.

Because languages differ in the way they pass an argument, one set of procedures is
provided for the C language, and another set for the FORTRAN language. The
FORTRAN routines have exactly the same arguments, but they are passed by their
address. Their names start with the letter "f" and do not contain a "_" sign. The
FORTRAN routines can also be used for PASCAL programs, by declaring all
arguments as var.

In every case a data item must be transmitted between Prolog and an external
language. Therefore, when the transfer function is called it is necessary to specify
the rank of the Prolog predicate's argument and the structure of the associated
external data item. Then, depending on the direction of transfer, either the Prolog
argument is "copied" into the external structure, or the term represented by the
external structure is constructed in the Prolog stacks and unified with the
associated predicate's argument.

On the other hand, it may be that the transfer cannot take place, in which case you
need to be informed. To do this, the transfer functions have an argument which
serves as an indicator. It is at zero when the function has been successful, strictly
positive when an error must be generated, and equal to -1 when a backtracking
must be generated.

Prolog's error management system requires that you leave the external program
immediately as soon as the *err flag - i.e. indicator - is not at zero. This is because
when the indicator is not at zero the situation is abnormal and requires a
backtracking or error in the Prolog program, which can only be performed once the
Prolog machine has been restarted, i.e. once the external program has terminated. It
may also be a more serious error, causing the Prolog machine to stop.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R7-3

7.2 Simple data transfer functions


The procedures described here can be used in simple operations, when the type of
data to transfer is known when the call is made, and this type corresponds to a type
in the other language; i.e. integers, reals and strings. For other cases, other more
general transfer functions are available, described in section 7.3.

For each type of data there is one procedure for transfers from Prolog to external
procedures, and another for transfers from external procedures to Prolog1.

7.2.1 Argument type test

The get_arg_type function is used to test the type and size of a Prolog argument, in
order to choose the appropriate transfer procedure to recover its value. This
function also enables you to obtain the size to allocate to recover a string. This
function does not return an error except when no argument exists with the defined
rank.
get_arg_type(no_arg, value, lgPtr, err)
int no_arg;
char *value;
int *lgPtr;
int *err;
integer*4 function fgetargtype(no_arg, value, lgPtr, err)
integer*4 no_arg,lgPtr,err;
character** value;

no_arg
This is an integer which gives the rank of the argument chosen in the Prolog
predicate. The first argument of the interface rule has the rank 1, the second
has the rank 2, and so on.

value
Address of a character type variable in which the "code" of the argument type
will be written. The returned characters have the following meanings:
"code" type
'I' integer
'R' real
'S' string
'N' identifier
'E' nil
'V' free variable
'D' list
'T' tuple
The type codes are the same as for the get_term, put_term procedures (see
section 7.2.1), except for the nil identifier whose code is 'E'.

1Additional procedures are available for string transfers. See Appendix E

© PrologIA
Aociation Prolog
R7-4 Reference Manual HERITAGE

lgPtr
Address of an integer variable in which the size in bytes occupied by a
constant will be written. When the argument is not a simple term, i.e. when it
is a list or tuple, the size is not specified.

err
The pointed variable is not 0 if an error occurs, otherwise it is equal to 0.

The function returns the value corresponding to *err.

7.2.2 Transferring simple data from Prolog to another language

The external program calls these functions to obtain the effective values of the
Prolog predicate.

If the effective argument type is not the expected one, or if there is no argument of
the required rank, the transfer function signals an error by assigning the err
indicator a non null value. If the value of an integer argument cannot be represented
in the associated external type, an error is signaled in the same way.

Warning. To ensure the error management system functions correctly,


you must leave the external program immediately if the variable
represented by err is not at zero.

Here are the available procedures for simple data types:

C Interface:
int get_integer(no_arg, value, err)
int no_arg;
long *value;
int *err;
int get_real(no_arg, value, err)
int no_arg;
float *value;
int *err;
int get_double(no_arg, value, err)
int no_arg;
double *value;
int *err;
int get_string(no_arg, value, err)
int no_arg;
char *value;
int *err;
int get_max_string(no_arg, lg_max, value, in_external_code,
err)
int no_arg;
int lg_max;
char *value;
int in_external_code;
int *err;

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R7-5

Fortran interface:
integer*4 function fgetinteger(no_arg, value, err)
integer*4 no_arg,value,err
integer*4 function fgetreal(no_arg, value, err)
integer*4 no_arg,err
real*4 value
integer*4 function fgetdouble(no_arg, value, err)
integer*4 no_arg,err
real*8 value
integer*4 function fgetstring(no_arg, lg, value, err)
integer*4 no_arg,lg,err
character** value
integer*4 function fgetmaxstring(no_arg, lg_max, lg, value,
in_external_code, err)
integer*4 no_arg,lg_max,lg,in_external_code,err
character** value

no_arg
This is an integer which gives the rank of the argument chosen in the Prolog
predicate. The first argument of the interface rule has the rank 1, the second
has the rank 2, and so on.

value
Address of the data item that must receive the value of the argument with rank
no_arg in the Prolog predicate.

lg
Integer used in Fortran functions manipulating strings, which must receive the
effective length of the character string.

lg_max
This is the size of the character zone.

in_external_code
This is a boolean, indicating whether the string must be encoded in external
character code (this is useful when the ISO character option is active and
characters are being used that are not present in the first half of the ISO set:
see Appendix E). If the value is 0, no transformation is performed on the
Prolog string.

err
The pointed variable is different from 0 if an error or a backtracking is
requested.

These functions return zero when an error has occurred or a non null value when no
error has occurred.

© PrologIA
Aociation Prolog
R7-6 Reference Manual HERITAGE

get_max_string copies the original character string from Prolog's working memory
into a zone that value points to, with a size of lg_max characters, defined in the
external program. A NULL character indicates the end of the string. An error is
generated if the size of the character zone defined by lg_max is insufficient to
recover the string.

get_string performs the same operation as get_max_string but does not test for
overflow. The size of the array value points to must therefore be sufficient to
contain the string. To prevent the risk of memory overwrite it is better to use
get_max_string.

7.2.3 Transferring simple data from an external language to Prolog

The external program calls these procedures in order to unify a value with an
argument in the associated Prolog predicate. If the unification fails, backtracking is
announced by the transfer procedure.

If the effective type of the argument is not the expected one, or if there is no
argument of the required rank, the transfer function signals an error by assigning
the err identifier a non null value.

Warning. To ensure the error management system functions correctly,


you must leave the external program immediately if the variable
represented by err is not at zero.

Here are the available procedures for simple data types:

C Interface:
int put_integer(no_arg, value, err)
int no_arg;
long value;
int *err;
int put_real(no_arg, value, err)
int no_arg;
float value;
int *err;
int put_double(no_arg, value, err)
int no_arg;
double value;
int *err;
int put_string(no_arg, value, err)
int no_arg;
char *value;
int *err;

Fortran Interface:
integer*4 function fputinteger(no_arg, value, err)
integer*4 no_arg,value,err
integer*4 function fputreal(no_arg, value, err)
integer*4 no_arg,err

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R7-7

real*4 value
integer*4 function fputdouble(no_arg, value, err)
integer*4 no_arg,err
real*8 value
integer*4 function fputstring(no_arg, lg, value, err)
integer*4 no_arg,lg,err
character** value

no_arg
This is an integer which gives the rank of the argument chosen in the Prolog
predicate. The first argument of the interface rule has the rank 1, the second
has the rank 2, and so on.

value
This is the value which will be unified with the argument having rank no_arg
in the associated Prolog predicate. For character string parameters, value is
the address of a string ending in zero and defined by the external program.
put_string copies this character string into Prolog's working memory and then
unifies the value with the argument in the interface rule.

err
The pointed variable is not 0 if an error or backtracking has been requested.

These functions return zero when an error is generated, or a non null value if there is
no error.

7.3 Functions to transfer any type of term


The terms we are dealing with in this section are terms that do not represent infinite
trees and can be any Prolog type. For example a list of tuples containing variables
is one such term.

To be able to transfer these terms, in particular Prolog-specific types of data, an


encoding system is required to identify this data outside Prolog.

To do this, Prolog gives you a choice between:


- character strings, which exist in all languages but require use of an
analyzer to identify the terms represented.

- a tree structure of items (type, value) encoded in arrays of data common to


all languages. This structure must be scanned to identify the terms
represented.

© PrologIA
Aociation Prolog
R7-8 Reference Manual HERITAGE

7.3.1 Using character strings

The functions described here are simple and easy to put into operation. They can be
used for instance the first time you create an interface between Prolog and other
languages.

They are much less efficient than the method using array structures, which is
described in the next section. They offer less possibilities for using the arguments,
and they are also restricted in their manipulation of variables. It is not possible for
several arguments in the predicate linked to the external procedure to use the same
free variable. The dictionary of variables is local for the communication procedure,
i.e. local for an argument and not for the rule.

C Interface:
get_strterm(no_arg, lg_max, value, in_external_code, err)
int no_arg;
int lg_max;
char *value;
int in_external_code;
int *err;

put_strterm(no_arg, value, in_external_code, err)


int no_arg;
char *value;
int in_external_code;
int *err;

Fortran Interface:
integer*4 function fgetstrterm(no_arg, lg_max, lg, value,
in_external_code, err)
integer*4 no_arg,lg_max,lg,in_external_code,err
character** value
integer*4 function fputstrterm(no_arg, lg, value,
in_external_code, err)
integer*4 no_arg,lg_max,in_external_code,err
character** value

no_arg
This is an integer which gives the rank of the argument chosen in the Prolog
predicate. The first argument of the interface rule has the rank 1, the second
has the rank 2, and so on. If there is no argument of this rank, an error is
signaled.

value
is the address of a zone of characters.

lg_max
is the size of this zone.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R7-9

in_external_code
is a boolean, indicating whether the string is (put_strterm), or must be
(get_strterm) in external character code (this is useful when the ISO character
option is active, and characters are being used that are not present in the first
half of the ISO set: see Appendix E).

err
indicates whether an error has occurred or not or whether a backtracking must
be generated.

When transferring from Prolog to the other language, the character zone value
points to must be big enough to contain the resulting string. Prolog transforms the
argument of rank no_arg (in the same way as the out predicate) into a string that
it copies to the value address. If the string to copy is greater than lg_max an error is
signaled.

When transferring from the other language to Prolog, Prolog analyzes the string
contained in value, constructs the Prolog term it represents (in the same way as the
in predicate), and unifies it with the argument of rank no_arg.

For example, in an external rule to unify the third argument with a list of 5 integers,
the following will be written:
put_strterm( 3, "[1,2,3,4,5]", 0, &err);

Below is a small example comprising a section in C to add into Prolog after the
external predicate declaration is added and a section in Prolog which tests it. We
assume that the link between the Prolog predicate and the C function has been
declared.
int test_ccom()
{ int err; char s[80];
get_strterm(1,80,s,1,&err);
if (err) return err;
fprintf(stderr,">>>>%s\n",s);
put_strterm(2,s,1,&err);
if (err) return err;
return 0;
}

> test_ccom(term(1.2.x,"string",[]),z);
>>>>term(1.2.v64,"string",nil)
{z=term(1.2.v150,"string",nil)}
>

7.3.2 Using array structures

The two term transfer functions described here, get_term and put_term, are the most
general functions for transferring data.

Since the functions for transferring simple terms use data types, this interface can
also be used when the type of the argument to process is not known in advance.

© PrologIA
Aociation Prolog
R 7 - 10 Reference Manual HERITAGE

When transferring data from the other language to Prolog, the aim is to unify the
proposed term with the argument of the associated Prolog predicate. If unification
fails, the transfer function signals a backtracking.

These interface procedures transform Prolog's structures into structures of arrays,


which are easy to manipulate in typed algorithmic languages such as Pascal or C.
The resulting structures can be retained during successive executions, and can be
written or loaded from a file. To do this, Prolog's terms are split into four arrays:

Two arrays for constants;

- one array containing characters for the strings,


- one array containing doubles numbers.

Two arrays to code the type and value of a term and its sub-terms;
- one character array for the types (or "tags") of terms/sub-terms.
- one array of long integers for the values of terms/sub-terms. The meaning
of each item is given by the content of the item with the same index in the type
array.

The term corresponding to the no_arg argument is coded in the first box of both the
type array and the value array:
tag_tab[0], val_tab[0]

7.3.2.1 Description of how a term is coded


A term is represented by a tag and an integer value which is interpreted according to
the tag.

term: (tag, value)


Integer: 'I' value of the integer. If the integer coming from Prolog
is too big to be encoded, an error is signaled.
Real number: 'R' index in the double number array real_tab.
Real number: 'X' index in the double number array real_tab.
String: 'S' index i in the character array str_tab.

Indicates the first character in the string. The string


ends with a NULL {chr(0)} character.
Ident: 'N' integer which represents a particular identifier
exclusively

» This representation is unique for as long as the


identifier is declared as used (see
set_permanent_symbol). Otherwise the garbage
collector can delete it.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 11

term: (tag, value)


variable: 'V' a free variable number.

This is a unique number for a given state of the machine


(see Section 7.3). If two numbers are different, then we
are dealing with two distinct free variables (i.e. they are
not linked to each other). In a single external procedure
call, these numbers remain coherent for different calls of
the procedures get_term and put_term. There is no link
connecting these two numbers between two activations
or two states.
You can create new variables by calling put_term with
unused numbers. We strongly advise you to create
numbers in order of increasing size in relation to the
numbers which have already been used. Prolog
increases the number attributed by 1 each time.
Sequence: 'D' an index in the term/sub-term arrays relating to a sub-
term sequence.

The indicated sequence finishes with 'E' or 'F' depending


on the circumstances.
Tuple: 'T' an index in the term/sub-term arrays tag_tab and
val_tab.

Points to a sequence of terms whose first element is an


integer representing the number of arguments n in the
tuple, followed by n sub-terms representing the
arguments.
term: (tag, value)
End list: 'E' undefined

Indicates the end of a sequence which ends with nil.


This marker can be the first element in a sequence
indicated by 'D'.
End sequence: 'F' undefined

Indicates the end of a sequence which does not end with


nil. The term which follows this marker is the last
element in the sequence. This marker cannot be the first
element in a sequence indicated by 'D'.

There are two equivalent representations of the term 1.2.3.nil; one is in vectorised
form, the second is a pointed pair (a pair here is represented by three entries).
Prolog always produces data in the first form, which is more compact, while the
second is useful for the construction of lists whose length is unknown when
construction begins.

© PrologIA
Aociation Prolog
R 7 - 12 Reference Manual HERITAGE

The pair ('N',0) represents the identifier nil. (in the array below, "-" represents
undefined values)

compact form pointed pair form


00 'D' 1 'D' 1 term: 1.2.3.nil

01 'I' 1 'I' 1
02 'I' 2 'F' -
03 'I' 3 'D' 4
04 'E' - 'I' 2
05 'F' -
06 'D' 7
07 'I' 3
08 'F' -
09 'N' 0

Example:

How to code the term 1.2.(3."Hi!".x).father(x,y).nil


index tag_tab val_tab (32 bits)
00 'D' 1 sequence type argument
* coding of argument's sub-terms
01 'I' 1
02 'I' 2 ...
03 'D' 10 relating to: (3."Hi!".x)
04 'T' 6 relating to: father(x,y)
05 'E' - nil
* start of sub-term: father(x,y)
06 'I' 3
07 'N' <integer representing father>
08 'V' 0 x
09 'V' 1 y
start of sub-term: (3."Hi!".x)
10 'I' 3
11 'S' 0 reference for 1st element. of str_tab
12 'F' -
13 'V' 0 x
14 - -

Character array Real array


index character index real
00 'H' 00 -
01 'i' 01 -
02 '!'
03 null (0)
04 -

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 13

7.3.2.2 Identifiers
In the array structures an identifier is encoded by a key (normally an integer) in the
Prolog dictionary. When the data is transformed by the interface functions
(get_term, put_term), conversion functions between the key and the identifier
representation (character string) may be necessary.

The pro_symbol function, starting from a character string, constructs the


corresponding Prolog identifier which, for instance, may then be used in a term sent
to Prolog using the put_term procedure. The character string must have identifier
syntax. If the given character string does not contain any prefix (it is an abbreviated
notation), the identifier created will depend on the current Prolog context (For more
details see Chapter 3). If an error occurs, the function returns the value 0.
long pro_symbol(str)
char *str;
integer*8 function fprosymbol(lg, str)
integer*4 lg
character** str

The symbol_string function or its Fortran equivalent , is used to represent a Prolog


identifier as a string. This identifier will have been obtained using one of the term
communication functions, e.g. get_term. The function's arguments are the key
symbol, the address of a memory area str where the string can be copied, and the
maximum length of the copied character string lgmax. The string obtained is the
identifier's notation according to the current context, if possible the abbreviated
notation. The function will give the effective length of the string in the output
parameter lg. The function returns 0 if everything is OK, or a positive integer
corresponding to an error number if an error occurs.
NB: key must correspond to a valid symbol.
int symbol_string(key, str, lg, lg_max)
long key;
char *str;
int *lg;
int lg_max;
integer*4 function fsymbolstring(key, str, lg, lg_max)
integer*4 key,lg_max,lg
character** str

The character chosen to separate the prefix and suffix in the complete representation
of an identifier can be modified in Prolog. The following function is therefore used
to ascertain the character currently used:
char prefix_limit();
character*1 function fprefixlimit();

The functions set_permanent_symbol and reset_permanent_symbol or their


Fortran equivalent, are used when the Prolog garbage collector is activated on a
dictionary, to tell it that an identifier is respectively used or not used by an external
procedure.
NB: key must correspond to a valid symbol.

© PrologIA
Aociation Prolog
R 7 - 14 Reference Manual HERITAGE

set_permanent_symbol(key)
long key;
reset_permanent_symbol(key)
long key;
integer*4 function fsetpermanentsymbol(key)
integer*4 key
integer*4 function fresetpermanentsymbol(key)
integer*4 key

7.3.2.3 Description of the transfer functions


When the call is made, the parameters are:

- The number of the argument no_arg.

- The size of the arrays: tab_size, str_tab_size, real_tab_size.

- The arrays used to encode the term: tag_tab, val_tab, str_tab, real_tab. When
an array is not referenced (for example if it has neither strings, nor reals), it can
be replaced by NULL. An error is indicated when one of the arrays is not big
enough to encode the term.

- An integer which indicates the last box used to code the term in the arrays:
tag_tab and val_tab: max_used.

- A boolean which indicates whether an error has occurred in the interface


procedures. This boolean must be tested for each call, and you must leave the
external procedure immediately if it is true: error_found.
int get_term(no_arg, tab_size, str_tab_size, real_tab_size,
tag_tab, val_tab, str_tab, real_tab, max_used,
err );
int no_arg;
int tab_size, str_tab_size, real_tab_size;
char tag_tab[];
long val_tab[];
char str_tab[];
double real_array[];
int * max_used;
int *err;

int put_term(no_arg, tab_size, str_tab_size, real_tab_size,


tag_tab, val_tab, str_tab, real_tab, max_used,
err );
int no_arg;
int tab_size, str_tab_size, real_tab_size;
char tag_tab[];
long val_tab[];
char str_tab[];
double real_array[];
int max_used;
int *err;
integer*4 function fgetterm(no_arg, tabsize, strtabsize,
realtabsize,
tagtab, valtab, strtab, realtab, maxused,

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 15

err );
integer*4 function fputterm(no_arg, tabsize, strtabsize,
realtabsize,
tagtab, valtab, strtab, realtab, maxused,
err );

Examples of how to use these interface procedures can be found in the "expredef.c"
kit's file or the "fprouser.eg" kit's file.

7.4 Principle of the descriptor method

The descriptor method is used to define Prolog relay objects and their link with an
external object. It can be used for external functions and shared data. In this
method the objects and links are declared in C.

First we will determine the elements that need to be described in C to create this
definition, and then we will describe the two ways of declaring them: statically or
dynamically.

7.4.1 Descriptive elements

To be able to create the link, it is necessary to know:

- the external object; in a language such as C this is expressed by its address


and type.
- the Prolog object, i.e. its name, its type and its size or arity, depending on
whether its is an array or a predicate.

You must define the following items:

name
Identifies the Prolog term associated with the external object. It is a pointer to
a C type string containing the representation of a complete Prolog identifier.
In the case of a SYMBOL_ARRAY object it has a different meaning, since it only
represents the module that the array's identifiers belong to. It therefore
contains the representation of these symbols' prefix.

type
Defines the type of the declared external object. The possible values are as
follows:
I N T _ A R R A Y for an integer array, C H A R _ A R R A Y for a character array,
STRING_ARRAY for a string array SINGLE_FLOAT_ARRAY for an array of single
precision reals, DOUBLE_ARRAY for an array of double precision reals,
SYMBOL_ARRAY for an identifier array, C_FUNCTION or C_FUNCTION_PROTECTED
for an external function, C _ F U N C T I O N _ B A C K T R A C K or
C_FUNCTION_BACKTRACK_PROTECTED for a non-determinist external function,
DIRECT_C_FUNCTION for a direct-call external function. For data arrays, it is

© PrologIA
Aociation Prolog
R 7 - 16 Reference Manual HERITAGE

possible to add the constant OFFSET_ZERO_BASED to enable Prolog to index


them starting from zero.

size
In the case of an external function, defines the rule's arity. In the case of a
shared data item, defines the size of the array. Has no meaning in the case of
SYMBOL_ARRAY.

adresse
Defines the effective address of the declared C object (or of a sub-array of
descriptors in the case of SYMBOL_ARRAY).

7.4.2 Static declaration

The external objects and associated Prolog objects can be declared statically by
descriptor tables that Prolog scans at initialization time. When you load Prolog
these tables will create the necessary links and declarations. The Prolog objects
created in this way, and their links with the external object, are permanent
throughout the session. They are not deleted by the predefined rules kill_module,
kill_array, suppress etc.

An external descriptor (see proext.h file) is a structure consisting of four fields


containing the necessary items that we have identified above:
typedef struct
{
char *name;
int type;
int size;
POINTER adresse;
} EXTERNAL_DESCRIPTOR;

To add these objects to Prolog, the Prolog machine must be extended by one or
more external modules containing the declaration of these descriptors. A descriptor
must be assigned to a descriptor table, which the general array PRO_EXTERNAL
must point to. The prolink linking program automatically constructs this
PRO_EXTERNAL array in the prodesc module and then reconstructs the Prolog
machine.

PRO_EXTERNAL is an array of descriptor table addresses. It must end with a null


adress (0). Its initial version in the kit it contains the table of the prouser file.
EXTERNAL_DESCRIPTOR *PRO_EXTERNAL[] = {
prouser_desc,
0 };

Descriptor table
A descriptor table is an array of descriptors ending in a descriptor containing 0 in
the name field. For example:
EXTERNAL_DESCRIPTOR sample_desc[] =

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 17

{
{":term_vars", C_FUNCTION, 2, (POINTER) term_vars},
{":qsort", DIRECT_C_FUNCTION, 1, (POINTER) quicksort},
{":enumerate", C_FUNCTION_BACKTRACK,3,(POINTER)enumerate},
{ 0, 0, 0, 0}
};

You can create as many tables as you like. Normally you should create one for each
external file.

7.4.3 Dynamic declaration

The PRO_BIND function enables you to create associations of Prolog-C objects


dynamically. The Prolog runnable must know the external objects (i.e. the Prolog
machine must be extended by external modules containing these objects). However
the Prolog object and the link with it are created when the PRO_BIND function is
executed.

In the same way as a static declaration, the Prolog objects created in this way and
their link with the external object are permanent throughout the session. Once the
declaration has been made, you cannot cancel its effect.

The PRO_BIND function has 4 arguments. Each argument represents a necessary


item that we have already identified:
int PRO_BIND(name, type, size, adresse)
char *name;
int type, size;
void *adresse;

For example, it is possible to create a zone of shared data dynamically. As soon as


the PRO_BIND function has been called Prolog knows the array.

The following example allocates a zone of 1000 reals shared by Prolog and C, and
accessible in Prolog using the name mymodule:data.
#include <malloc.h>
#include "proext.h"
...
double *t;
t = (double *) malloc( 1000*sizeof(double));
PRO_BIND( "mymodule:data"
, DOUBLE_ARRAY
, 1000
, (POINTER) t);

Once this sequence has been executed, the following Prolog program executes
without errors, and references the data zone t[4]:
assign(mymodule:data(5), 1.5e );

In the following sections we describe the different types of object that can be
accessed using the descriptor method. The examples are described with static
declarations, but obviously they can also be declared dynamically.

© PrologIA
Aociation Prolog
R 7 - 18 Reference Manual HERITAGE

7.5 Shared data


Prolog and C can share any type of data, provided both languages can manipulate it.
The suitable data types are integers, reals, characters, character strings and
identifiers.

Prolog can be extended by one or more zones of shared data. These data zones are
treated as arrays and processed as arrays by both languages.

The shared data is defined by declaring a descriptor whose type field will have one
of the following values: INT_ARRAY , SINGLE_FLOAT_ARRAY , DOUBLE_ARRAY,
CHAR_ARRAY, STRING_ARRAY, SYMBOL_ARRAY. In addition, OFFSET_ZERO_BASED can be
added to any of these values.

The name field will be Prolog's representation of the array. The def_array primitive
must not be used to define this array. The size field indicates the number of items
in the array.

The adresse field is the address of the memory zone reserved for this array in C.
Depending on the object's type, it will be:

INT_ARRAY
the address of a static integer zone (int type in C).

CHAR_ARRAY
the address of a character zone2 (1 byte per character).

STRING_ARRAY
the address of an array of pointers to strings3 ending with the null character.
It can be declared in the form: char *tab[size];

Warning. There is no overflow test on the size of the strings the interface
manipulates. Don't forget to allocate the space for the strings, and to
initialize the pointer array.

SINGLE_FLOAT_ARRAY
the address of a zone of IEEE 32 bit reals.

DOUBLE_ARRAY
the address of a zone of IEEE 64 bit reals.

2Are you sure about the character encoding mode? See appendix E.

3Are you sure about the string encoding mode? See appendix E.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 19

SYMBOL_ARRAY
the address of a sub-table of associations (identifier string, internal
representation). The programmer initializes the string part, and Prolog
initializes the international representation part.
For this type of descriptor, the name field defines the default prefix for the
table's symbols (i.e. if the string id_name corresponds to an abbreviated name,
this is the default prefix to be used).
This type of object makes it possible to construct automatically a table of the
internal values of the Prolog identifiers we want to manipulate. All the table's
identifiers are permanent (see set_permanent_symbol) be default.

7.5.1 Example of a shared data zone

Here, we declare two arrays shared by C and Prolog. The first is an array of 100
integers, called com in C and :com in Prolog. The second is an array of 3 strings of
no more than 10 characters, called m:str in Prolog, and str in C.
#include "proext.h"
int com[100];
char *str[3] =
{
"0123456789",
" ",
" "
};

EXTERNAL_DESCRIPTOR my_desc_table1 [] =
{{":com", INT_ARRAY+OFFSET_ZERO_BASED, 100, (POINTER)com},
{"m:str", STRING_ARRAY, 3, (POINTER) str },
{ 0, 0, 0, 0 }
};

Supposing these declarations are contained in a file called table.c, it can be linked to
Prolog once it has been compiled, by executing prolink to link it to table's object
module and the descriptor descTable1. (See User's Manual section 2.8).

When it is loaded, Prolog will automatically create a link with the C array. It will be
possible to modify and consult this array by means of the standard Prolog
commands assign and val. It should be noted that for shared data declared with
OFFSET_ZERO_BASED the Prolog indices start at 0, for the other arrays they start at 1,
and that the C indices start at 0. The following commands in C and Prolog have
exactly the same effect and work on the same memory zone:
Prolog C
assign(:com[4], 100); com[4] = 100;
val(:com[4],_x) outl(_x); printf("%ld\n",com[4]);
val(m:str[1],_x) outm(_x); printf("%s",str[0]);
assign(m:str[2],"abc"); strcpy(str[1],"abc");

© PrologIA
Aociation Prolog
R 7 - 20 Reference Manual HERITAGE

7.6 Adding external functions


External functions are defined by declaring a descriptor. There are two types of
external function:

- functions that carry out one process and stop. The value of the
descriptor's type field will then be C_FUNCTION or DIRECT_C_FUNCTION.
We will describe DIRECT_C_FUNCTION type objects in section 7.7.

- non-determinist functions that can carry out several different processes


and therefore return several possible results. The value of the
descriptor's type field will then be C_FUNCTION_BACKTRACK.

C_FUNCTION_PROTECTED and C_FUNCTION_BACKTRACK_PROTECTED are other types of


object that can be declared by descriptors. These types identify the same objects as
the C_FUNCTION and C_FUNCTION_BACKTRACK but only their "visibility" changes. The
PROTECTED object types will be hidden in the debug mode.

C_FUNCTION
By declaring this type of object you automatically create a Prolog relay rule
called name with an arity of size. This Prolog rule will be executed by calling
the C function whose address is in the adresse field. The rule's arguments
can be accessed from the C function using the standard data transfer functions
get_... and put_... . The C function adresse points to must be declared as the
int type and is called by Prolog without any parameters. It must return the
termination condition (-1 for FAIL, 0 for SUCCESS, > 0 for ERROR).
This is a simpler way of constructing external predefined rules than by
directly using parasites (/?n) and the relay procedure user_rule (see Appendix
D).

C_FUNCTION_BACKTRACK
By declaring this type of object you automatically create a Prolog relay rule
called name with an arity of size. This Prolog rule will be executed by calling
the C function whose address is in the adresse field. The rule's arguments
can be accessed from the C function using the standard data transfer functions
get_... and put_... . The function must be declared as the int type. It is called
by Prolog with a single long type parameter indicating the number of the
current call. It must return the termination condition (FAIL for a failure,
SUCCESS for a success, > 0 for an error,
SUCCESS_END_OF_C_BACKTRACK to indicate the success of the last
call, or FAIL_END_OF_C_BACKTRACK to indicate failure of the last call).
In the event of a cut, an additional call to this function will be made using the
conventional value CUT_OF_C_BACKTRACK as the argument. This aim
of this call is not to find another solution, but to signal that there will not be
any more calls, and in this way make it possible to terminate the processes in
progress (e.g. freeing of allocated memory, closing files, etc.). During a call
to this function, an integer value can be stored in Prolog's space using the
function store_C_backtrack_data(long ptr), or can be recovered by the return

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 21

of the function long restore_C_backtrack_data(void). Makes it possible to


construct non-determinist predefined rules in an external language.

7.6.1 Example of how to define a built-in predicate

When linked to Prolog, the following file automatically produces two new built-in
predicates: sys:reverse(s1,s2) that unifies s2 with the inverted string s1; and
sys:enumerate(x,b,e) that unifies x in succession with the integers between b and e.
If you want to use the abbreviated name, you must add the name in the closed
context "sys" by executing the following command:
> add_implicit("sys","reverse")
add_implicit("sys","enumerate");

#include "proext.h"
#include <stdio.h>
#include <string.h>
#define MAX_STRING 512

int reverse();

EXTERNAL_DESCRIPTOR descTable2[] =
{{"sys:reverse", C_FUNCTION, 2, (POINTER) reverse},
{"sys:enumerate", C_FUNCTION_BACKTRACK, 3,
(POINTER) enumerate},
{ 0, 0, 0, 0 }
};

reverse()
{
int err, i, j, lg;
char c1, c[MAX_STRING];
if ( ! get_string(1,c,&err) )
return err;
lg = strlen(c);
for (i=0; i<lg/2; i++)
{
j = lg -1 -i;
c1 = c[i];
c[i] = c[j];
c[j] = c1;
}
if ( ! put_string(2,c,&err) )
return err;
return 0;
}

typedef struct {
int direction, current, start, end;
} enumRecord, *EnumMemory;

int enumerate(call)
long call;
{
EnumMemory mem;
int err;
if (call==CUT_OF_C_BACKTRACK) /* cut */

© PrologIA
Aociation Prolog
R 7 - 22 Reference Manual HERITAGE

{
mem = (EnumMemory) restore_C_backtrack_data();
free(mem);
return;
}

if (call==1) /*first call */


{
/* mem will constitute the predicate's memory from one
call to the next */

mem = (EnumMemory) malloc(sizeof(enumRecord));

get_integer(2, &mem->start, &err);


if (err) { free(mem); return 253;}
get_integer(3, &mem->end, &err);
if (err) { free(mem); return 253;}

mem->direction = (mem->start > mem->end) ? -1 : 1;


mem->current = mem->start;

store_C_backtrack_data(mem);
}

/* the memorized data address is recovered */


if (call != 1)
mem = (EnumMemory) restore_C_backtrack_data();

/* instanciation of the predicate's first argument*/


put_integer(1,mem->current,&err);

if (mem->current == mem->end)
{
/* it's finished, it must be freed */
free(mem);
return END_OF_C_BACKTRACK;
}
else
/* the counter is incremented */
mem->current += mem->direction;

return err;
}

The above file must now be compiled, linked (see User's Manual section 2.8), and
the new Prolog must be activated to obtain:
Prolog II+, ..
...
>sys:reverse("0123456",x);
{x="6543210"}
>sys:enumerate(x,-2,2);
{x=-2}
{x=-1}
{x=0}
{x=1}
{x=2}
>

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 23

7.7 Adding external functions using direct calls


Unlike the other external functions that can be accessed using the descriptor
method, direct call external functions do not have a C interface to pass the
parameters. This type of C function can be written with its parameters, as if it were
to be called by a standard C program. In particular it can be a function in a library
whose sources you do not have control over. Indeed, in this type of function, the
transformation of the data (Prolog -> C and C -> Prolog) will be carried out in
Prolog by means of the predefined rule callC.

This method therefore makes it possible to transfer types of data common to both
languages, i.e. integers, reals, character strings and homogeneous arrays of these
data types.

A direct call external function is declared by declaring a descriptor whose type field
has the value DIRECT_C_FUNCTION.

DIRECT_C_FUNCTION
By declaring this type of object you automatically create a Prolog relay rule
called name with an arity of size that can only be executed using the callC
primitive. The execution of callC consists in calling the C function pointed by
the descriptor's adresse field.
This C function must not have more than 20 arguments. If the descriptor's
size field has the value -1, the type and number of arguments vary depending
on the call. For example it is possible to call sprintf (see section 5.2 of this
manual).

7.7.1 CallC primitive

When the call is made, the predefined primitive callC determines the way in which
the arguments are passed to the C function, their type and the type of the return
value, according to the effective arguments of the Prolog predicate, and in
compliance with the various conventions described in the next section. This makes
it possible to call functions with varying types and numbers of arguments.

callC(t1)
callC(t1,t2)
t1 is a term representing the call to the Prolog predicate with its parameters in
compliance with the chosen conventions. t2 is a term representing the result.
If t2 is nil the function's result is ignored. The single argument version
callC(t1) is equivalent to callC(t1,nil).
This function makes it possible to call functions you have described with a
DIRECT_C_FUNCTION descriptor, as well as the sprintf and sscanf functions
which are pre-declared.

© PrologIA
Aociation Prolog
R 7 - 24 Reference Manual HERITAGE

If you are using a system that allows implementation of the lkload primitive, it
is possible to call functions existing in the Prolog environment without
declaring them. The callC primitive then creates the link dynamically when
the first call is made. To do this the runnable file prolog must be in the
current directory.

Examples:
> callC(sscanf("123","%lf",<"R",y>));
{y=1.230000000000000e+02}
> eq(x,"123") callC(sscanf(x,"%2f",<"R",y>));
{x="123", y=1.200000000000000e+01}
> eq(f,"%x %o") callC(sscanf("12 12",f,<"I",x>,<"I",y>));
{x=18, y=10}
> callC(sprintf(<"",x,80>,"value: %ld",200));
{x="valeur: 200"}

7.7.2 Prolog conventions for data transfer

Our aim here is to be able to express in Prolog all the information needed to call a C
function, concerning its arguments and return value. We will therefore examine:
- the way in which the arguments are passed,
- the type of the function's arguments and return value,
- the initial value of the arguments,
- the resulting value of the arguments and the function,
- other technical information connected with the object's type.

The most crucial aspect here is not the passage of data, but rather the role of the data
, i.e. whether it is input and/or output data.

In Prolog, once data has been assigned a value this value cannot change (except by
backtracking, but when comparing it with C this can be regarded as another
execution). If a Prolog procedure had to accept a value as input and a result as
output, it would have to use two data items. This is the fundamental difference
between Prolog and C, and so it is important to know whether a data item (initialized
or not) has to change value during execution of the C function. In the rest of this
section, we will therefore differentiate between an argument with a return value and
an argument without a return value. From this it will be deduced automatically
whether the data is passing by address or by value.

The following data can be passed as a parameter:


1. a long integer with or without return value,
2. a double precision real with or without return value,
3. a character string with or without return value,
4. an array of integers, character strings or double precision reals, with or
without a return value.

The result of the function can be:


1. a long integer,
2. a double precision real.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 25

Now let's take a look at the conventions. To illustrate them with examples, we will
assume that a link has been declared between the predicate prologRelay and the
function functionC.

7.7.2.1 Convention for parameters without a return value


In this case there is no need to specify the data type. Prolog already knows it
because the data item already has a value.

An integer, real or string is represented by the Prolog data item itself.


Homogeneous arrays of integers, reals or strings are represented by a Prolog
list (possibly ending in nil) of integers, reals or strings.
Example:
:prologRelay(180, 3.14e0, "pi", 2.3.5.7.11.13.17.nil,
"b"."a"."ba".nil)
is equivalent to the following C instructions:
{ long arg1 = 180L; double arg2 = 3.14;
char arg3[] = {'p','i','\0'};
long arg4[] = {2,3,5,7,11,11,13,17};
char *arg5[] = {"b","a","ba"};
functionC(arg1,arg2,arg3,arg4,arg5); }

Strings and arrays are always passed by their address in accordance with the normal
C convention. In any case Prolog makes a copy of the arguments in an intermediate
zone whose size can be configured on the command line (see Chapter 2 of the
User's Manual).

7.7.2.2 Convention for the function's return


It is necessary to know the type of the function's return and to have available a
Prolog term that will be unified with its value. The convention is as follows:

The term representing the result must be a pair:


< result_type, result_variable >
- where result_type is a string indicating the return's type: "I" for an integer,
"R" or "X" for a real .
- where result_variable will be unified with the value returned by the function
(integer or real).

7.7.2.3 Convention for parameters with a return value


Two Prolog data items are required for a C data item with an expected return value.
The first must be known when the call is made and is used to transmit the initial
value to the C function. The second will be unified with the new value obtained
from the C function.

We differentiate between the types of data: simple types and types requiring
allocation of a memory zone.

© PrologIA
Aociation Prolog
R 7 - 26 Reference Manual HERITAGE

Note. Some conventions with return values specify memory zone sizes to
allocate, for storage of the results of the called C functions. Therefore it
is very important to ensure that the zones are sufficient for the expected
results. You must also ensure that the argument types are consistent with
the declarations made in C.

The convention for simple data types, i.e. integers and reals, is as follows:

The effective argument of the Prolog predicate is a pair:


< initial_value, result_variable >
- where initial_value is the initial value of the zone whose address is passed as a
parameter of the C function. If the value can be anything, you can enter "I"
(integer) or "R" (real) as the initial value.
- where result_variable will be unified with the new value of the argument
returned by the function (integer or real).
Example:
:prologRelay(<180,x>, <3.14e0,y>)
is equivalent to the following C instructions:
{ long arg1 = 180L; double arg2 = 3.14;
functionC(&arg1,&arg2); }

followed by the assignments to variables x and y of the new values for arg1
and arg2.

The convention for data requiring a memory zone depends on the data type:

For a character string, you must have a character zone, whose size you must
define, big enough to contain the initial string first and then the result string.

The effective argument of the Prolog predicate is a triple:


< initial_value, result_variable, max_result_size >
- where max_result_size is an integer specifying the size of the zone to allocate
for the operation, whose address is transmitted to the C function,
- where initial_value is the initial value copied into the zone allocated for the
operation,
- where result_variable will be unified with the result (Prolog string).
Example:
:prologRelay(<"pi",x,100>)
is equivalent to the following C instructions:
{ char arg1[100];
strcpy(arg1,"pi");
functionC(arg1); }

followed by assignment to the variable x of the new value of arg1.

For an array of integers or of reals, you must have a zone of integers or reals
acting as an array. You must define the number of items in it, and it must be big
enough to contain the input array items first, and then the output array items.

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 27

The effective argument of the Prolog predicate is a quadruple:


< initial_value, result_variable, result_size, array_size >
- where array_size is an integer specifying the number of items in the zone to
allocate for the operation, whose address is transmitted to the C function.
- where result_size indicates the number of valid array items to take into
account for the return.
- where initial_value is the Prolog list of the initial values of the array's items,
ending in nil. The type of these items determines the parameter's type.
- where result_variable will be unified with the result (Prolog list of integers or
reals, ending in nil).
Example:
:prologRelay(<2.4.6.8.12,x,1,5>, <0e0.nil,y,5,5>)
is equivalent to the following C instructions:
{ long arg1[]={2,4,5,6,8,12}; double arg2[5];
arg2[0] = 0.0;
functionC(arg1,arg2); }

followed by the assignments to variables x and y of the new values for arg1
and arg2.

For an array of character strings, you must have a zone of pointers to represent
the array. You must define the number of items in this zone. You may also need to
define a character zone to store all the characters in all the array's strings, and define
its size also.

The effective argument of the Prolog predicate is a quadruple:


< initial_value, result_variable, max_nbr_of_characters, array_size >
- where array_size is an integer specifying the number of items in the zone to
allocate for the operation, whose address is transmitted to the C function. The
end of the array must be indicated by the NULL pointer after the last item.
- where initial_value is a Prolog list of strings the array points to as input,
ending in nil ("".nil is the minimum).
- where max_nbr_of_characters is an integer enabling you to let Prolog
manage (i.e. allocate and clear) the output string character buffer.
If you, the user, are managing the output string space(s), the value of
max_nbr_of_characters must be 0.
If you let Prolog allocate and then clear a character buffer,
max_nbr_of_characters must not be null. In this case it indicates the total
maximum number of characters necessary to store all the characters in all the
array's strings. The value of the array's first item (character string pointer) will
be the address of this space (where the first input string is copied).
- where result_variable will be unified with the result, a Prolog list of strings,
ending in nil.

Example:
:prologRelay(<"once"."upon"."a"."time",x,100,5>)
is equivalent to the following C instructions:
{ char * arg1[5]; char buffer[100];

© PrologIA
Aociation Prolog
R 7 - 28 Reference Manual HERITAGE

strcpy(buffer,"once"); arg1[0] = buffer;


arg1[1] = "upon"; arg1[2] = "a"; arg1[3] = "time";
functionC(arg1); }

followed by the assignment to the variable x of the new values for arg1.

7.7.3 Example: a simple way to call a C function

Below we show examples with different types of arguments, using user-declared


functions and a system function.
#include <stdio.h>
#include <string.h>
#include "proext.h"

#define REAL double


#define INTEGER long

static REAL complete_example(ii1,io1,ri1,ro1,si1,so1,tii1,


tri1,tio1,tro1,tsi1,tso1,reserved)
/*-------------------------------------------------------*/
INTEGER ii1,*io1;
REAL ri1,*ro1;
char *si1;
char *so1;
REAL *tri1;
REAL *tro1;
INTEGER *tio1,*tii1;
char **tsi1,**tso1;
int reserved;
{
int i;

printf("ii1= %d\n",ii1); /*integer in input*/


printf("io1= %d\n",*io1); /*integer in output*/
printf("ri1= %g\n",ri1); /*real in input*/
printf("ro1= %g\n",*ro1); /*real in output*/
printf("si1= %s\n",si1); /*string in input*/
printf("so1= %s\n",so1); /*string in output*/
for (i=0;i<2;i++) /*integer array*/
printf("tii1[%d]= %d\n",i,tii1[i]); /*in input*/
for (i=0;i<2;i++) /*real array*/
printf("tri1[%d]= %g\n",i,tri1[i]); /*in input*/
for (i=0;i<3;i++) /*integer array*/
printf("tio1[%d]= %d\n",i,tio1[i]); /*in output*/
for (i=0;tsi1[i];i++) /*string array*/
printf("tsi1[%d]= %s\n",i,tsi1[i]); /*in input*/
for (i=0;i<3;i++) /*real array*/
printf("tro1[%d]= %g\n",i,tro1[i]); /*in output*/
*io1 = 3333; /*integer in output*/
*ro1 = - 8888.; /*real in output*/
strcpy(so1,"bonjour"); /*string in output*/
for (i=0;i<10;i++) /*integer array*/
tio1[i] = i+200; /*in output*/
for (i=0;i<10;i++) /*real array*/
tro1[i] = (float) i +200.; /*in output*/
for (i=0;tso1[i];i++) /*string array*/
printf("strin(%d)=%s\n",i,tso1[i]);/*in output*/
if(reserved) /*space for strings reserved by prolog */

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 29

{
strcpy(tso1[0],"Zone1"); /*first pointer(tso1[0])*/
/*initialized by Prolog */
tso1[1] = tso1[0]+6; /*others pointers initialized*/
/*by the user */
strcpy(tso1[1],"Zone2");
tso1[2] = NULL; /*end of array */
}
else /*space for strings reserved by the user */
{
tso1[0] = "Zone1";
tso1[1] = (char *) malloc(10);
strcpy(tso1[1],"Zone2");
tso1[2] = NULL;
}
return 1234.; /*returned value */
}

static REAL average(tab,n)/*


----------------------------*/
INTEGER *tab,n;
{
INTEGER i,sum=0;
for (i=0;i<n;i++) sum += tab[i]; return (sum/n);
}

static mystrcmp(a1,a2)/*
------------------------*/
char **a1,**a2;
{
return strcmp(*a1,*a2);
}

static quicksort(tab_in,tab_out)/*
-------------------------------*/
char **tab_in, **tab_out;
{
int i,nbr;

for (nbr=0;tab_in[nbr];nbr++)
tab_out[nbr] = tab_in[nbr];
tab_out[nbr] = NULL;
qsort(tab_out,nbr,sizeof(char *),mystrcmp);
}

static reverse(str)/*
------------------------*/
char *str;
{
char c;
INTEGER i,len;

len = strlen(str);
for (i=0;i<len/2;i++)
{
c = str[i];
str[i] = str[len - (i+1)];
str[len - (i+1) ] = c;
}
}

© PrologIA
Aociation Prolog
R 7 - 30 Reference Manual HERITAGE

EXTERNAL_DESCRIPTOR calld_desc[] =
{
{":complete_example", DIRECT_C_FUNCTION, 13, (POINTER)
complete_example},
{":average", DIRECT_C_FUNCTION, -1, (POINTER) average},
{":reverse", DIRECT_C_FUNCTION, 1, (POINTER) reverse},
{":qsort", DIRECT_C_FUNCTION, 2, (POINTER) quicksort},
{0, 0, 0, 0}
};

Let's assume the above file is called callc.c. We must now compile it, create the
links (see the User's Manual Chapter 2.8), and then activate the new Prolog to
obtain:
Prolog II+, ..
...
> eq(r_eserved,30)
callC(complete_example
(
11, /*integer in input */
<155,i>, /* integer in output with initialization*/
+13.0e0, /* real in input*/
<+222.0e0,r>,/* real in output with initialization*/
"str_input", /* string in input*/
<"ee",s,10>, /* string in output with initialization*/
123.456.nil, /*array of integers in input */
14.0e0.15.0e0.nil, /*array of reals in input */
<11.22.33,w,5,20>, /*array of integers in output
/*with initialization*/
<+44.0e0.+55.0e0.+66.0e0,t1,5,20>, /*array of reals in
output with initialization*/
"list_str_in1"."list_str_in2".nil, /*array of STRINGS*/
/*in input */
<"list_str_out1"."list_str_out2"."list_str_out3".nil,
T_S,r_eserved,5>,
r_eserved /*integer in input */
),
<"R",m>) /*result */
;

ii1= 11
io1= 155
ri1= 13
ro1= 222
si1= str_input
so1= ee
tii1[0]= 123
tii1[1]= 456
tri1[0]= 14
tri1[1]= 15
tio1[0]= 11
tio1[1]= 22
tio1[2]= 33
tsi1[0]= list_str_in1
tsi1[1]= list_str_in2
tro1[0]= 44
tro1[1]= 55
tro1[2]= 66
strin(0)=list_str_out1
strin(1)=list_str_out2
{r_eserved=30,i=3333,

© PrologIA
Aociation Prolog

HERITAGE Extending Prolog with other languages R 7 - 31

r=-8.888000000000000e+03,
s="bonjour",
w=200.201.202.203.204.nil,
t1=2.000000000000e+02.2.010000000000e+02.2.020000000000e+02.
2.030000000000e+02.2.040000000000e+02.nil,
T_S="Zone1" ."Zone2".nil,
m=1.234000000000e+03
}
> callC(average(1.3.5.nil,3),<"R",x>);
{x=3.000000000000e+00}
> callC(reverse(<"abcde",s,20>));
{s="edcba"}
> callC(reverse(<"abcdef",s,20>));
{s="fedcba"}
> callC(qsort("qqq"."zzz"."aaa"."iii".nil,<"".nil,s,0,50>));
/*0 because strings not created (already exist)*/
{s="aaa"."iii"."qqq"."zzz".nil}

© PrologIA
Aociation Prolog
R 7 - 32 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

8. How to launch a Prolog


goal with a C program

8.1 Basic theory


8.2 Initializing Prolog
8.3 Stacking a Prolog goal
8.4 Programming
8.5 Simple method for calling a Prolog goal
8.6 Other functions

This chapter assumes that the reader is fully conversant with Chapter 7. If this is
not yet the case, this chapter can be skipped.

The Prolog machine can be used as a sub-program of another program. It will be


easier to understand how it is manipulated, using a procedural language, if we
present Prolog as a machine which goes through a series of states (or stopping
points). A set of procedures is used to transfer the Prolog machine from the current
state to a new state.

A C program can only be called by a predefined rule, apart from when the Prolog
machine is at a stopping point. This rule can either stack a new goal or cause an
error.

When the Prolog machine is at a stopping point, a C program can do the following:
stack a new goal, reactivate the machine up to the next stopping point to get another
solution, or cause abandonment of the current goal and a return to the previous state.

8 . 1 Basic theory
When a Prolog machine is in a "normal state", this means that it is executing a
series of goals (see Chapter 2 of this manual). This process is sometimes called the
Prolog clock. When the machine is in this situation, we refer to it as being active.

When the Prolog machine is activated, it already has an initial sequence of goals to
execute. The execution process (choice of a rule, unification of the head, etc ...) will
last for as long as the current sequence of goals is not empty. When this sequence
is empty, the machine reaches a stopping point.

In this section, we define the various states the Prolog machine can be in when it is
not active, from the point of view of a C programmer (or a Pascal programmer,
etc...). These states are called stopping points. We also describe the procedures
which make the machine pass from one stopping point to another.

© PrologIA
Aociation Prolog
R8-2 Reference Manual HERITAGE

The possible states of the machine at a stopping point are:

0. Machine not initialized. In fact, this is not the state of the machine, but rather
the situation we are in before it has been initialized (space allocation, etc ...).
The ProStart(…) procedure, which is called once per session, takes us to the
next state:

1. Nothing to execute (NO_GOAL). The machine has been initialized, but the
sequence of goals to execute is empty.
The machine also arrives at this state during normal functioning, when there
are no more possible ways of executing the current goal sequence, i.e. when
all the solutions to the current problem have already been obtained. When in
this state, any activation of the machine (using next_solution()) immediately
brings it back to the same NO_GOAL state.

2. Goal ready to be executed. This is a preliminary stage in the machine's


activation. The procedure new_goal() has just installed the goal sequence
exec(_b, _x); the calling program must now unify _b with the goal or list of
goals to be executed using the standard routines (put_integer, put_term,
etc…).

3. Prolog execution, in a predefined rule. When an external rule is being


executed, the relevant C program (or Pascal etc…) takes control of the
execution, and the Prolog machine "seems" to have stopped. However, this
situation differs from the previous states since it does not correspond to a
stopping point. This is because the Prolog machine has not stopped in the
normal way, at the beginning or end of an execution. On the contrary, it is
right in the middle of an execution, waiting for an external procedure to end.

4. Solution found (SOLUTION_EXISTS). This is the most frequent stopping


point: the current goal sequence has just been executed. The calling program
can recover the solutions using the argument _x from the call exec(_b,_x).
The Prolog machine has memorized all the choice points of the current
execution. From this state, it is possible to call the procedure next_solution()
to relaunch the machine in order to obtain the other solutions.
Therefore, the most frequent sequence of states will be:

NO_GOAL  «Goal ready»  SOLUTION_EXISTS  …


… SOLUTION_EXISTS  NO_GOAL

5. Error encountered (ERROR). The machine is put in this state when an error
has made its normal functioning abort. An activation (by next_solution() )
will transfer it to the NO_GOAL state.

In any of the states 1 to 4 above, the procedure new_goal() can be called to install a
new problem above the current one. The latter is retained in exactly the same state,
so that subsequently it will be possible to continue to obtain its solutions.

© PrologIA
Aociation Prolog

HERITAGE How to launch a Prolog goal with a C program R8-3

In the same way, in states 2 to 5 we can call the procedure kill_goal(), which causes
abandonment of the current problem and a return to the previous problem, which is
in exactly the same state as when new_goal() was called.

The functions which activate the Prolog machine (i.e. which transfer it to another
state) are:

ProStart(..)
Function used to initialize the Prolog machine. This function must be called
once before any other call concerning Prolog. Initializes the machine in state
1.

ProFinal(..)
Function making it possible to terminate and clear the Prolog machine and
environment. It has an integer argument that specifies Prolog’s termination
status.

new_goal()
Memorizes the current state of the machine, and transfers it to state 2 (goal
ready to be executed). State 2 is initialized with the call exec(_b,_s) whose
variables must be instantiated by the calling program AFTER the new_goal
call.
This procedure stacks the activations of goals _b up to a depth which is only
limited by the size of the Prolog stacks.

kill_goal()
Returns to exactly the same state the machine was in before the last new_goal
call. new_goal and kill_goal function as parentheses bracketing the execution
of a new Prolog goal.

next_solution()
This is an activation function of the machine, which transfers it to the next
stopping point (1, 4, or 5). The value of the function is the new state of the
Prolog machine: SOLUTION_EXISTS (0), NO_GOAL (-1), ERROR (>0).

© PrologIA
Aociation Prolog
R8-4 Reference Manual HERITAGE

The following diagram defines the possible transitions for any Prolog state, apart
from the non-initialized state:

8 . 2 Initializing Prolog
When an application starts up, Prolog is in a non-initialized state. The ProStart
function initializes Prolog with a configuration (stack sizes, input file,…), defined in
the character string passed as the parameter. This string represents the Prolog start-
up options (stack sizes, input file, etc.). The function returns 0 if everything is OK,
or a non null positive number corresponding to an error number if an error has
occurred and initialization has not taken place.

It is illegal to call any procedure except ProStart in this non-initialized state.

The types of the function and of its argument must be as shown:

© PrologIA
Aociation Prolog

HERITAGE How to launch a Prolog goal with a C program R8-5

int ProStart(params)
char *params;

When you have finished using Prolog, the ProFinal function enables you to clear
the structures and terminate Prolog. The function has no return value, but instead an
argument that specifies Prolog’s termination status and determines a message
printed by ProFinal . This message must be defined in the Prolog error file. The
status value must be 0 for a normal termination, or a strictly positive number for an
error status. This error status could be for example the error returned by one of the
following functions: new_goal, next_solution or kill_goal.

When ProFinal has been executed, Prolog is once more in a non-initialized state.

The function’s types and argument must be as described.


ProFinal(status)
int status;

Here is an example:
my_prolog_initialization()
{
int err;
if ((err = ProStart("-c 400 -f cM prolog.po")) == 0)
fprintf(stderr,"initialization succeeded");
else
{ fprintf(stderr,"initialization failed, bye!");
exit(err);}
}

my_prolog_termination(condition)
int condition;
{
if (my_error(condition))
{ my_error_message(condition);
ProFinal(0);
}
else
ProFinal(condition);
}

Use of the Prolog machine is started and terminated by calling the ProStart and
ProFinal functions.

© PrologIA
Aociation Prolog
R8-6 Reference Manual HERITAGE

8 . 3 Stacking a Prolog goal


A goal _b is stacked by means of a call to a linking rule exec(_b,_s), which ensures
that the current goal is retained and that the machine stops at a precise state. This
rule has two arguments: the first is a term representing the goal _b to be executed,
the second is the term which will be obtained as a solution (this is generally a list of
the interesting variables of the goal _b).

When new_goal has been called, the call exec(_b,_s) is ready to be executed. The
standard routines can be used to instantiate the arguments (put_term(1,..) to
instantiate _b, and put_term(2,..) to define the variables corresponding to the
interesting solution).

A call to the function next_solution transfers the machine to one of the states 1,4 or
5. The value returned by this function is the state which has been reached:
NO_GOAL (-1), ERROR (>0), or SOLUTION_EXISTS (0).

The linking rule is equivalent to:

exec(_b,_s) ->
block(_e,_b)
condition(_e,_k)
stopping_point1(_k,_s)
fail ;
exec(_b,_s) -> stopping_point2(NO_GOAL,nil);

condition(_e,SOLUTION_EXISTS) -> free(_e) !;


condition(_e,_e) -> integer(_e) !;
condition(_e,BLOCK_EXIT_WITHOUT_BLOCK) ->;

stopping_point1(K,S) -> stop;

stopping_point2(K,S)-> stop stopping_point2(NO_GOAL,[]);

Everything happens as if the user were in the rule stopping_point. Because of the
way exec is written, the value of the first argument (obtained by get_integer(1,..))
also contains the state which has been reached. If this state is
SOLUTION_EXISTS, the second argument (obtained by get_term(2,..)) contains
the term defining the interesting solution.

© PrologIA
Aociation Prolog

HERITAGE How to launch a Prolog goal with a C program R8-7

8 . 4 Programming
The file proext.h contains the declarations for the interface procedures and
structures. An #include from this file must be placed at the start of the modules
using these procedures.

Here is an example of a C program which prints all the solutions of enum(i,-2,8),


and which can be written in prouser.c exactly as it is, replacing the
EXTERNAL_DESCRIPTOR declaration.
#define MAX_TAB 10
example()
{
int err;
long i;
P_SYMBOL pro_symbol();
char tags[MAX_TAB];
int vals[MAX_TAB];
int n = 0;
/* initialization of the goal */
new_goal();
tags[0] = 'T'; vals[0] = 1;

tags[1] = 'I'; vals[1] = 4;


tags[2] = 'N'; vals[2] = pro_symbol("sys:enum");
tags[3] = 'V'; vals[3] = 0; /* i */
tags[4] = 'I'; vals[4] = -2;
tags[5] = 'I'; vals[5] = 8;
put_term(1, MAX_TAB,0,0, tags,vals, 0,0, 5, &err);
if (err) goto error;
/* interesting solution created */
tags[0] = 'V'; vals[0] = 0;
put_term(2, MAX_TAB,0,0, tags,vals, 0,0, 0, &err);
if (err) goto error;
/* printing solutions */
n = 1;
while ((err = next_solution()) == SOLUTION_EXISTS)
{
get_integer(2, &i, &err); /*value of i*/
if (err) goto error;
printf("solution %d : %ld\n", n++,i);
}
if (err > 0)
goto error;
kill_goal();
return 0;
error:
printf("error %d at the %d ith step\n",err,n);
kill_goal();
return err;
}

EXTERNAL_DESCRIPTOR prouser_desc[] =
{{":example", C_FUNCTION, 0, (POINTER)example},
{0,0,0,0}};

© PrologIA
Aociation Prolog
R8-8 Reference Manual HERITAGE

There is another example of how to use Prolog as a sub-program in the princip.c


file, which is Prolog's main module.

8 . 5 Simple method for calling a Prolog goal


There is another simpler method for installing a Prolog goal from an external
language and recovering its solutions.

Installation of a Prolog goal is simplified by the new_pattern, function, which is


equivalent to new_goal, put_term for the goal, and put_term for the result. However
this function is less efficient in this area because it uses the Prolog parser.

Recovery of the solution's values is simplified by the get_formats function, which is


equivalent to get_term and the processing of the different arrays.

This method consists in specifying the structure of the goal's arguments and their
interesting values when the goal is installed, so that they can be named when a
solution is obtained, instead of having to perform an algorithmic search for the
required sub-terms of the solution.

The called goal's arguments can be any term (except infinite) and the values to
extract are simple terms such as integers, reals, doubles, identifiers, or strings.

8.5.1. Description
int new_pattern(char * goal)
is a function with a single argument; a character string representing a Prolog
term that is the goal to execute, and where the interesting results are
represented by formats. The function returns 0 if everything is OK, or an
error number if an error occurs.
The following formats are accepted:
%d for integers
%s for character strings
%f for single reals
%F for double reals
%i for identifiers in the form of an integer
%I for identifiers in the form of a character string

Here is an example of new_pattern calls:


error = new_pattern(":test(<%i,x,y>,%d,0)");
error = new_pattern("sys:enum(%d,-2,10)");

© PrologIA
Aociation Prolog

HERITAGE How to launch a Prolog goal with a C program R8-9

int get_formats(int no, void *p, …)


is a function with a variable number of arguments, where:
no, the 1st argument, is an integer indicating the rank of the value to recover
(rank of the format concerned, in the string transmitted to new_pattern). If it
has the value 0, this means that all the values are to be recovered.
The number of subsequent arguments depends on the number of values to be
recovered and their type. If you are expecting a character string (format %s or
%I), two arguments are required. The first must be a pointer to a memory
area in which Prolog can store the string; the second must be an integer
indicating the maximum size of the string. If you are expecting something
else, the required argument is the address of the C variable where the required
value will be memorized. The function returns 0 if everything is OK, or an
error number if an error occurs.
Here are the types of C variables associated with each format:
format C type type of passage
%d long address
%s char *, int value
%f float address
%F double address
%i long address
%I char *, int value

Here is an example of a get_formats call:


long i;
error = new_pattern("sys:enum(%d,-2,10)");
error = get_formats(0, &i);

The get_formats function will load the integer i with the value associated with
the first format (the integer -2 in our example). It should be noted that this
call is exactly equivalent to:
error = get_formats(1, &i);

8.5.2. Example
Here is an example of how to use the new_pattern and get_formats functions:

test_rules(recovery, "recovery", 1.2e0)->;


test_rules(of the, "of strings", 4444.2e0)->;
test_rules(idents, "of", 0.2e0)->;
test_rules(Prolog, "characters", 1.2e0)->;

int example2()
{
int error;
long i;
char s[100];
float f;

© PrologIA
Aociation Prolog
R 8 - 10 Reference Manual HERITAGE

error = new_pattern("test_rules(%i,%s,%f)");
if (error) return error;
while (next_solution() == SOLUTION_EXISTS)
{
error = get_formats(0, &i, s, 100, &f);
if (error) goto error;
printf("%d %s %f\n",i,s,f);
}

kill_goal();
return 0;
error:
printf("error\n");
kill_goal();
return error;
}

8 . 6 Other functions
ConnectDescriptors( EXTERNAL_DESCRIPTOR * paD[] )
This routine is used to declare the descriptor array paD in the application
code. The array is written in the same way as a direct C extension and must
be persistent throughout the whole of the Prolog session that uses it (e.g.
qualified as static if it is positioned as a local variable). The declaration must
be made before the start of the session (before the call of ProStart() ).
If the argument is NULL, the descriptors will be deleted in the next session.
If the routine is called several times, the last array will be taken. The routine
returns 0 if it succeeds, -1 if it fails (session already started).

ConnectInString( InStringFunction * pfIS )


This routine allows to redefine the function to read in the console. This is
done by declaring a text input function pfIS() to which Prolog must submit all
input (predicates). Before such a function is installed, an empty string is
returned for each input request (therefore making the request impossible).
Replacement and deletion of this function operate in the same way as the
previous function. This routine returns the previous function that was
installed.
The format of the input function is imposed. Its first argument is the address
of a buffer ready to receive the text (therefore allocated), its second argument
is the maximum capacity of this buffer. The function's return code is ignored.
If an error occurs it must return an empty string in the buffer.
Internally, the function can perform any operation, even a blocking operation
(by processing events) necessary to obtain the text to return.

© PrologIA
Aociation Prolog

HERITAGE How to launch a Prolog goal with a C program R 8 - 11

ConnectOutString( OutStringFunction * pfOS )


This routine allows to redefine the function to write in the console. This is
done by declaring a text output function pfOS() to which Prolog will submit
all output (predicates, messages). Before such a function is installed, no
output can be visible. Replacement and deletion of this function operate as in
the previous function. This routine returns the previous function that was
installed.
The format of the output function is imposed. Its only argument is the
address of a buffer containing the text to print. The function's return code is
ignored: no error is expected.
Internally, the function can perform any operation, even a blocking operation
(by processing the events) necessary to display the text. However it should be
noted that Prolog can emit empty lines, and therefore filtering may be
necessary, if message boxes are used for example.

get_error_complement( int lgmax, char *str, int in_external_code )


This routine allows to get a string representing the term corresponding to the
error complement built by the execution of a goal. It must be called before the
kill_goal() function. The variable str (string) must have been allocated before
and must have a length greater or equal to the integer lgmax passed in the first
parameter. If the boolean in_external_code is not null, that means we want to
obtain the string in external character code.

© PrologIA
Aociation Prolog

HERITAGE
Aociation Prolog

HERITAGE

9. Interruptions

9.1 Concepts
9.2 Description of the interfaces
9.3 Complete example

In this chapter we describe how to link Prolog programs to asynchronous events


such as physical interruptions. When an interruption occurs the current Prolog
program is automatically suspended, and the interruption handling function is
activated as soon as the Prolog machine enters a state in which cross-calls can be
performed (i.e. at the next inference). When the function ends, the suspended proof
continues as normal. It is possible to communicate between the two environments
by means of static data (fact base, arrays, assignments).

This mechanism therefore makes it possible to suspend the current execution, and
stack the activation of a new Prolog machine which will process the interruption.

9.1 Concepts
The Prolog machine has a vector of external event bits. The first eight bits (0 to 7)
are reserved for events defined by the user. Each bit must be associated with a C
function to construct the arguments and call a Prolog goal. This C function is
installed by the user by calling the pro_signal procedure.

Interruption of a Prolog program can only be processed in certain specific states


such as the end of unification, or inside a built-in predicate. This interruption must
therefore be memorized until the Prolog machine is in a suitable state to process it.
This is done by the send_prolog_interrupt procedure, which must be called by the
interruption handler to inform Prolog of this event.

To link a Prolog program to a given asynchronous event, the following operations


must therefore be performed:

1. Choose a bit (0 to 7) and represent it with a mask (e.g. myEvent = (1 <<


number of bit)).

2. Write a function (e.g. myHandler) which will be used to activate the Prolog
program handling the interruption.

3. In the Prolog environment, associate the event myEvent with the function that
processes it by calling the function:
pro_signal(myEvent,myHandler).

© PrologIA
Aociation Prolog
R9-2 Reference Manual HERITAGE

4. In the routine called at interruption, send the event to Prolog by calling the
function:
send_prolog_interrupt(myEvent ).

An example of a sequence of events and processes can be represented by the


following diagram:
pro_signal(myEvent,myHandler)

P
myHandler()
R
{
O
new_goal();...
C
next_solution();
E
kill_goal();
S
} Prolog machine
S

I
N
new_goal() next_solution() kill_goal()
T
E (*myHandler)()
R
R
U
P
T
I reset myEvent flag
O
prolog_event_handler(myEvent)
N

asynchronous user
interruption
Prolog machine ...
myAsynchronousHandler()
{
send_prolog_interrupt(myEvent); set myEvent flag
}

9.2 Description of the interfaces

The functions defined here are used to link Prolog II+ with interruption procedures.
The prototypes for these functions are given at the end of this chapter.

pro_signal(event_mask,event_handler)
Associates the event event_mask with the activation function event_handler.
This function returns -1L if there is an error (in particular if a function is
already associated with event_mask), NULL otherwise. If the second
argument is NULL the activation function associated with the first argument is
deleted, and its value is returned as the function result. The event_mask
argument must be one of the following values: 1, 2, 4, 8, 16, 32, 64, 128.

© PrologIA
Aociation Prolog

HERITAGE Interruptions R9-3

When the event_handler function is called and its result n is greater than 0 the
corresponding Prolog error is activated.

send_prolog_interrupt(event_mask)
Activates the process associated with the interruption event_mask, as soon as
this is allowed by the Prolog machine.

Conventions for the call to the activation function event_handler.

This function must return an integer which is interpreted as a Prolog error code if
this integer is positive.

When several interruptions are on stand-by, they are processed in the order defined
by the bit numbers (bit 0 first).

We recommend not to use the functions get/put_strterm if the time factor is critical,
since these functions are relatively slow to execute.

Prototypes of interface functions


long pro_signal(event_mask,event_handler)
unsigned short event_mask;
int (*event_handler)();
void send_prolog_interrupt(event_mask)
unsigned short event_mask;

9.3 Complete example


In this section we describe an example constructed for the UNIX system which uses
the system primitive kill to send signals to the Prolog task from the Shell.

To implement this example, follow the steps described below:

1. Write the Prolog extension to react to the SIGUSR11 signal: 30 and associate
with it the rule message in the file test.c.
#include <signal.h>
#include "proext.h"
#define MYEVENT 8

extern long pro_signal();


extern void send_prolog_interrupt();
extern P_SYMBOL pro_symbol();

static int my_P_Handler()


{
int err=0;

1This is an asynchronous signal which can be generated from outside Prolog from another UNIX
process. UNIX is a multi-task system, in which all executing programs are processes.

© PrologIA
Aociation Prolog
R9-4 Reference Manual HERITAGE

new_goal();
put_strterm(1,":message",&err);
if (!err)
err = next_solution();
kill_goal();
return err>0 ? err : 0 ;
}

static void my_C_signal_handler()


{
send_prolog_interrupt(MYEVENT);
}
/* This call can be placed in the main program to
perform initialization automatically. The descriptor array
is then no longer necessary */
static long install_handler()
{
pro_signal(MYEVENT,my_P_Handler);
signal(SIGUSR1,my_C_signal_handler);
return 0;
}

EXTERNAL_DESCRIPTOR testTable[] =
{{":install_handler", C_FUNCTION, 0, (POINTER)
install_handler},
{ 0, 0, 0, 0 }
};

2. Compile test.c and link with Prolog1. In Prolog add the interruption handling
program.
$ cc -c test.c2
$ prolink test.o testTable
$ prolog
...
> insert;
message -> val(counter,n) outl(n);
count(N) -> val(mod(N+1,1000000),N1) assign(counter,N1)
count(N1);
;
> install_handler count(0);

3. Connect up to another console, determine the Prolog process identification


number (pid) with the command ps, and send the signal 30 to Prolog. Each
time the signal is sent the current value of the counter is printed on the Prolog
console.
shell$ ps -ax > install_handler
count(0);
....2525...Prolog

1Please refer to section 2.8 of the User's Manual for instructions on how to compile and link in
Prolog, using your system.

2This command creates the object module compiled from test.c.

© PrologIA
Aociation Prolog

HERITAGE Interruptions R9-5

shell$ kill -30 25251 64790


shell$ kill -30 2525 301267

1 This command transmits the SIGUSR1 signal (which Prolog must react to) to the Prolog
process.

© PrologIA
Aociation Prolog
R9-6 Reference Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

10. Edinburgh extensions

10.1 Syntax
10.2 Control
10.3 Manipulation of rules
10.4 Predefined data operations
10.5 Input and output
10.6 The environment
10.7 Translation of DCG

This chapter describes the additional rules made available when the Edinburgh
module is loaded.

It is organized in the same way as the reference manual, and describes the features
specific to Edinburgh mode for each topic.

A certain number of predefined rules are identical to the Prolog II+ predefined
rules, but with different names.

All the Prolog II+ functionalities are available in Edinburgh syntax.

IMPORTANT: In this chapter, all atoms given in the argument position have an
empty prefix (""). The examples shown are written assuming the option
corresponding to "all atoms in the argument position not explicitly prefixed have an
empty prefix" is active. This option is described in appendix A. If it is not active,
you must bear in mind that atoms whose abbreviated representation is already
known to the system must be explicitly prefixed with the empty prefix, otherwise the
sys prefix will be used by default (at least in the user context). This applies in
particular to the following atoms: debug, string, fail (used in the predicate
set_prolog_flag/2), true, false (used for example in the predicate write_term/2), and
input, output, read, write (used for stream_property/2 or open/4).

10.1 Syntax

10.1.1 General information

The Edinburgh syntax is accepted as input in one of the following cases:

1) when Prolog II + is activated:


a) if you use the option -E (equivalent to -m edinburg.mo)
b) If you use a binary state saved when the Edinburgh syntax was active,

2) on the Prolog II+ command line

©PrologIA
Aociation Prolog
R 10 - 2 Reference Manual HERITAGE

a) if the edinburg.mo file is loaded (by the load or reload predicate).


b) if the edinburgh goal is keyed in,

The exact syntax is described in Chapter 1 using the E variant of the syntactic rules.
The main differences compared to the Edinburgh syntax described in the ISO/IEC
standard are described in appendix A.

When the first term encountered on the command line or in a directive is a list, it is
interpreted as a list of files to be consulted. user is equivalent to "console".

10.1.2 Operators

In Edinburgh syntax, the following operators are predefined:

operator precedence type constructed term


:- 1200 xfx sys:':-'(T1,T2)
:- 1200 fx sys:':-'(T1)
?- 1200 fx sys:'?-'(T1)
--> 1200 xfx sys:'-->'(T1,T2)
; 1100 xfy sys:';'(T1,T2)
-> 1050 xfy sys:'->'(T1,T2)
, 1001 xfy sys:','(T1,T2)
\+ 900 fy sys:not(T1)
is 700 xfx sys:is(T1,T2)
= 700 xfx sys:'='(T1,T2)
< 700 xfx sys:'<'(T1,T2)
> 700 xfx sys:'>'(T1,T2)
>= 700 xfx sys:'>='(T1,T2)
=< 700 xfx sys:'=<'(T1,T2)
@< 700 xfx sys:'@<'(T1,T2)
@> 700 xfx sys:'@>'(T1,T2)
@>= 700 xfx sys:'@>='(T1,T2)
@=< 700 xfx sys:'@=<'(T1,T2)
\= 700 xfx sys:'\='(T1,T2)
== 700 xfx sys:'=='(T1,T2)
=\= 700 xfx sys:'=\='(T1,T2)
\== 700 xfx sys:'\=='(T1,T2)
=.. 700 xfx sys:'=..'(T1,T2)
=:= 700 xfx sys:'=:='(T1,T2)
+ 500 yfx sys:'+'(T1,T2)
- 500 yfx sys:'-'(T1,T2)
/\ 500 yfx sys:'/\'(T1,T2)
\/ 500 yfx sys:'\/'(T1,T2)
mod 400 yfx sys:mod(T1,T2)
rem 400 yfx sys:rem(T1,T2)

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 3

operator precedence type constructed term


* 400 yfx sys:'*'(T1,T2)
/ 400 yfx sys:'/'(T1,T2)
<< 400 yfx sys:'<<'(T1,T2)
>> 400 yfx sys:'>>'(T1,T2)
// 400 yfx sys:'//'(T1,T2)
\ 200 fy sys:'\'(T1,T2)
** 200 xfx sys:'**'(T1,T2)
+1 200 fy sys:'+'(T1)
-1 200 fy sys:'-'(T1)
^ 200 xfy sys:'^'(T1,T2)

current_op(P,M,O)
Unifies the arguments P, M and O with the precedence, the type of parenthesis
and the operator respectively. Example:
?- current_op(1200,M,O).
{M=fx,O=?-}
{M=fx,O=:-}
{M=xfx,O=:-}
{M=xfx,O=-->}

10.2 control

\+ X or \+(X)
Equivalent to not(X).

X=Y or =(X,Y)
Succeeds if X can be unified with Y, fails otherwise. Defined by the rule:
X = X.

X \= Y or \=(X,Y)
Succeeds if X cannot be unified with Y, fails otherwise. Examples:
?- 1 \= 1.
?- X \= 1.
?- X \= Y.
?- 1 \= 1.0.
{}

X -> Y or ->(X,Y)
"If-then". Is defined by the rule (the parentheses are just to make it more
legible):
(X -> Y) :- X,!,Y.

X,Y
Propositional "and". X is executed, then Y.

©PrologIA
Aociation Prolog
R 10 - 4 Reference Manual HERITAGE

X;Y
Propositional "or". Is defined by the following rules (Please note: in
Prolog II the cut is transparent):
X;Y :- X.
X;Y :- Y.

call(X)
Is defined by the rule:
call(X) :- X.

catch(G,C,R)
Starts execution of goal G. Succeeds in two cases:
- execution of G succeeds with a "throw" interruption,
- a "throw" interruption occurs whose argument unifies with the
argument C and execution of goal R succeeds. If unification fails, the
interruption spreads via the block/block_exit mechanism.
Examples:
reconsult(user).
foo(X) :- Y is X*2, throw(test(Y)).
bar(X) :- X=Y, throw(Y).
coo(X) :- throw(X).
car(X) :- X=1, throw(X).
g :- catch(p, B, write(h2)), coo(c).
p.
p :- throw(b). .
{}
?- catch(foo(5),test(Y),true).
{Y=10}
?- catch(bar(3),Z,true).
{Z=3}
?- catch(true,C,write(foo)), throw(bla).
-> bla([]) 'block_exit' NO 'block' CORRESPONDENT

?- catch(coo(X),Y,true).
{}
?- catch(car(X),Y,true).
{X=1,Y=1}
?- catch(g, C, write(h1)).
h1{C=c}

fail_if(X)
Equivalent to call to not(call(X)).
?- fail_if(true).
?- fail_if(4=5).
{}

once(G)
Executes goal G in the first way possible. Defined by the rule:
once(G) :- G, ! .

throw(X)
Equivalent to a call to block_exit(X1) , where X1 is a copy of the term X
(renaming of variables).

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 5

true
Always executes successfully.

unify_with_occurs_check(X, Y)
Attempts to unify terms X and Y with a check for non production of infinite
trees. Fails if the unification fails or if it generates an infinite tree. Examples:
?- unify_with_occurs_check(1,1).
{}
?- unify_with_occurs_check(1,2).
?- unify_with_occurs_check(X,1).
{X=1}
?- unify_with_occurs_check(X,a(X)).
?- unify_with_occurs_check(X,[1|X]).
?- unify_with_occurs_check(X,[X|1]).
?-

10.3 Manipulation of rules


abolish(P)
Behaves like suppress(P) where P is an identifier or a term in the form
identifier/arity.

assert(X)
assertz(X)
Adds the rule or fact X at the end of a group of rules. Please refer to the
description of assert in Prolog II.
Warning. In Edinburgh syntax, the comma is both a separator and an
operator, and the argument must therefore be bracketed in these rules:
?- assert(a).
{}
?- assert((a :- b,c)).
{}

asserta(X)
Adds the rule or fact X at the beginning of a group of rules. Please refer to
the description of asserta in Prolog II.

clause(T,Q)
T must not be a free variable. Unifies T and Q with the head and body
respectively of all clauses whose access is defined by T. Behaves like rule
except that an empty body is represented by true, and a non-empty body is
represented by a structure with the node ','.

consult(F)
reconsult(F)
Equivalent to insert and reinsert respectively. If F is an identifier, the string
corresponding to its abbreviation is taken as the file name (i.e. the prefix is
ignored). If the value of F is user or "user", it reads on the current reading
unit.

©PrologIA
Aociation Prolog
R 10 - 6 Reference Manual HERITAGE

listing
listing(X)
Equivalent to list and list(X).

retract(X)
Same behavior as retract with two arguments. X must be a fact or rule whose
head predicate is instantiated.
retract((T:- true)) is equivalent to retract(T),
retract(T) is equivalent to retract(T,[]), if T does not unify with :- (T1,T2),
retract((T :- Q)) is equivalent to retract(T,Q).

retractall(X)
Retracts all rules whose heads unify with X (without unification of X or
backtracking). X must have the pattern of a rule head, otherwise the predicate
will have no effect. Always results in a success.

10.4 Predefined data operations

10.4.1 type testing rules

atom(X)
Succeeds if X is an identifier, fails otherwise. Equivalent to ident(X).

atomic(X)
Succeeds if X is a constant, fails otherwise.

compound(X)
Succeeds if X is a list or tuple, fails otherwise.

float(X)
Is equivalent to real(X).

nonvar(X)
Is equivalent to bound(X).

number(X)
Succeeds if X is an integer or a real, and fails otherwise.

var(X)
Succeeds if X is a free variable and fails otherwise. Is equivalent to free(X).

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 7

10.4.2 Arithmetic operations

An expression is evaluated using the predefined rule val. Certain expressions can
be used directly in Edinburgh syntax as terms to erase.

The following terms can be erased with using the val predicate.

X =:= Y or =:=(X,Y)
Is equivalent to val(eql(X,Y),1).

X =\= Y or =\= (X,Y)


Is equivalent to val('=\='(X,Y),1).

X < Y or <(X,Y)
X =< Y or =<(X,Y)
X > Y or >(X,Y)
X >= Y or >=(X,Y)
Are equivalent respectively to:
val('<'(X,Y),1)
val('=<'(X,Y),1)
val('>'(X,Y),1)
val('>='(X,Y),1)

X is Y or is(X,Y)
Is equivalent to val(Y,X).

The following functions are specific to Edinburgh mode. They are evaluated by the
predefined rules val, tval and is. They must be applied to integer or real number
arguments.

\X or \(X)
value (\X) = value ('~'(X)) = bit by bit complement of X.
The value of X must be an integer. The result is an integer.

X // Y or //(X,Y)
value (//(X, Y)) = integer division of value (X) by value (Y).
The result is an integer.

log(t)
value (log(t)) = value (ln(t)) = Napierian logarithm(value(t)).
The result is a real.

truncate(t)
value (truncate(t)) = value (trunc(t)) = the value of t is converted into an
integer.
The result is an integer.

©PrologIA
Aociation Prolog
R 10 - 8 Reference Manual HERITAGE

10.4.3 Composition and decomposition of objects

X =.. Y or =..(X,Y)
If X is instantiated, Y is unified with a list in which the first element is the
functor of X, and the subsequent elements are possible arguments in their
order.
If X is free, Y must be instantiated with a list in which the first element is
atomic. X is then unified with a term constructed using the first element in the
list as functor, and the other elements as arguments.
An atomic element is a list constituted by this single element. Examples:
?- '=..'(foo(a,b),[foo,a,b]).
{}
?- '=..'(X,[foo,a,b]).
{X=foo(a,b)}
?- '=..'(foo(a,b),L).
{L=[foo,a,b]}
?- '=..'(foo(X,b),[foo,a,Y]).
{X=a,Y=b}
?- '=..'(1,[1]).
{}
?- '=..'(foo(a,b),[foo,b,a]).
?- '=..'(f(X),[f,u(X)]).
{X=_714, _714=u(_714)}

arg(N,T,X)
X returns the Nth element of the term T. N is an integer, and T a tuple or
pointed pair. Both must be known when the rule is made.
If T is a pointed pair, then if;
N=1, X is unified with the first element of the pair.
N=2, X is unified with the second element of the pair.
If N is an integer, and T is a tuple whose size is M>1, then if:
0<N<M, X is unified with argument N+1 of the tuple T.
(i.e. with argument N of T=f(a1,...,an,...,aM)).
Fails otherwise.
Example :
?- arg(1,eq(john,fred), X).
{X=john}
?- arg(0,eq(john,fred), Y).
?-

atom_chars(A,L)
Associates the list L of characters with the identifier A it constitutes and vice-
versa. The prefix of identifier A is ignored (as input) or equal to "" (as
output). Examples:
?- atom_chars('',L).
{L=[]}
?- atom_chars('''', L).
{L=['''']}
?- atom_chars('ant',L).
{L=[a,n,t]}
?- atom_chars(Str, ['s', 'o', 'p']).
{Str=sop}

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 9

atom_codes(A,L)
Associates the list L of internal codes (ISO codes or host machine codes) with
the identifier A it constitutes and vice-versa. The prefix of identifier A is
ignored (as input) or equal to "" (as output).

atom_concat(A1,A2,A3)
Manipulates identifiers in the same way as conc_string manipulates character
strings. The prefixes of identifiers A1, A2, A3 are ignored (as input) or equal
to "" (as output). Examples:
?- atom_concat('hello',' world',S3).
{S3='hello world'}
?- atom_concat(T,' world','small world').
{T=small}
?- atom_concat(T1,T2,'hello').
{T1='',T2=hello}
{T1=h,T2=ello}
{T1=he,T2=llo}
{T1=hel,T2=lo}
{T1=hell,T2=o}
{T1=hello,T2=''}

atom_length(A,N)
Unifies N with the length of identifier A. The prefix of identifier A is ignored.
Examples:
?- atom_length('enchanted evening',N).
{N=17}
?- atom_length('',N).
{N=0}

functor(T,F,N)
Associates tree T with its functor F and arity N, and vice versa.
?- functor(foo(a,b,c),X,Y).
{X=foo,Y=3}
?- functor(X,foo,3).
{X=foo(_515,_516,_517)}
?- functor(X,foo,0).
{X=foo}
?- functor(foo(a),foo,2).
?- functor(foo(a),fo,1).
?- functor(1,X,Y).
{X=1,Y=0}
?- functor(X,1.1,0).
{X=1.1}
?- functor([_|_],'.',2).
{}
?- functor([],[],0).
{}

name(X,L)
If X is an identifier or number, L is unified with the list of internal codes (ISO
codes or host machine codes) of the characters constituting the representation
of identifier X.
If L is a list of the internal codes of an identifier's letters, X is instantiated with
the identifier determined by the current prefixing conventions.

©PrologIA
Aociation Prolog
R 10 - 10 Reference Manual HERITAGE

?-name(abc:def,L).
{L=[97,98,99,58,100,101,102]}
?- name(123,L).
{L=[49,50,51]}
?- name(X,[65,66|4]).
?- name("asd",X).
?- name(Y,X).
?- name(ab:'cd',L).
{L=[97,98,58,99,100]}
?- name(ab:' %',L).
{L=[97,98,58,39,32,37,39]}
?- name(I,[97,98,58,99,100]).
{I=ab:cd}
?- name(M,[97,98,58,39,32,37,39]).
{M=ab:' %'}
?-

number_chars(N,L)
Associates the list L of characters with the number N it constitutes.
Conversely, considers L as input and associates the number N with it (printed
in decimal form). Examples:
?- number_chars(33, L).
{L=['3','3']}
?- number_chars(33.0, L).
{L=['3','3','.','0']}
?- number_chars(X, ['3', '.', '3', 'E', '+', '0']).
{X=3.3}
?- number_chars(3.3, ['3', '.', '3', 'E', '+', '0']).
{}
?- number_chars(A, ['-', '2', '5']).
{A=-25}
?- number_chars(A, [' ', '3']).
{A=3}
?- number_chars(A, ['0', 'x', 'f']).
{A=15}
?- number_chars(A, ['0', '''', 'a']).
{A=97}
?- number_chars(A, ['4', '.', '2']).
{A=4.2}
?- number_chars(A, ['4', '2', '.', '0', 'e', '-', '1']).
{A=4.2}

number_codes(N,L)
Same description as number_chars/2 but L is a list of internal codes (ISO
codes or host machine codes).

phrase(X,Y)
phrase(X,Y,Z)
Attempts to split the list Y into a sentence of the grammar and a remainder. X
must be a grammar rule head, Y and Z can be free variables or lists.
Enumerates the possible solutions and unifies the remainder with Z. The two-
argument version phrase(X,Y) is equivalent to phrase(X,Y,[]).
Note: If Y or Z are character strings, they are first transformed into lists of
characters before the call is performed: phrase(sum(X),"1+2+3") is
automatically transformed in the call phrase(sum(X), ["1","+","2","+","3"]).

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 11

sub_atom(A1,N1,N2,N3,A2)
Results in a success if identifier A1, which must be known when the call is
made, can be seen as the concatenation of three parts such that N1 is the
length of the first part, N2 the length of the second part, which is simply the
identifier A2, and N3 the length of the third part. The prefixes of identifiers
A1 and A2 are ignored (as input) or equal to "" (as output). Examples:
?- sub_atom(abracadabra, 0, 5, A, S2).
{A=6,S2=abrac}
?- sub_atom(abracadabra, _, 5, 0, S2).
{S2=dabra}
?- sub_atom(abracadabra, 3, L, 3, S2).
{L=5,S2=acada}
?- sub_atom(abracadabra, B, 2, A, ab).
{B=0,A=9}
{B=7,A=2}
?- sub_atom('Banana', 3, 2, A, S2).
{A=1,S2=an}
?- sub_atom('charity', B, 3, A, S2).
{B=0,A=4,S2=cha}
{B=1,A=3,S2=har}
{B=2,A=2,S2=ari}
{B=3,A=1,S2=rit}
{B=4,A=0,S2=ity}
?- sub_atom('ab', Start, Length, A, Sub_atom).
{Start=0,Length=0,A=2,Sub_atom=''}
{Start=0,Length=1,A=1,Sub_atom=a}
{Start=0,Length=2,A=0,Sub_atom=ab}
{Start=1,Length=0,A=1,Sub_atom=''}
{Start=1,Length=1,A=0,Sub_atom=b}
{Start=2,Length=0,A=0,Sub_atom=''}

10.4.4 Comparing any terms

X == Y or ==(X,Y)
Succeeds if X is formally equal to Y, fails otherwise. Examples:
?- 1 == 1.
{}
?- X == X.
{}
?- 1 == 2.
?- X == 1.
?- X == Y.
?- _ == 1.
?- _ == _.
?-

X \== Y or \== (X,Y)


Succeeds if X is not formally equal to Y, fails otherwise. Examples:
?- 1 \== 1.
?- 1 \== 2.
{}
?- X \== 1.
{}
?- _ \== _.
{}
?-

©PrologIA
Aociation Prolog
R 10 - 12 Reference Manual HERITAGE

X @< Y
Compares terms X and Y, and succeeds if X precedes Y. Fails otherwise.

X @> Y
Compares terms X and Y and succeeds if Y precedes X. Fails otherwise

X @>= Y
Compares terms X and Y and succeeds if Y precedes or is formally equal to X.
Fails otherwise.

X @=< Y
Compares terms X and Y and succeeds if X precedes or is formally equal to Y.
Fails otherwise. Some examples:
?- 1.0 @< 1.
{}
?- @<(aardvark,zebra).
{}
?- @<(short,short).
?- short @< shorter.
{}
?- @<(foo(a),foo(b)).
{}
?- @<(foo(a,b),north(a)).
?- @<(X,X).
?- Y @< X.
{}
?- @<(_,_).
{}
?- @<(foo(X,a),foo(Y,b)).
{}
?- "foo" @> foo.
{}
?- [1,2,3] @> [1,1,3,4].
{}
?- [1,2] @> <>(1,2).
?- [1,2] @> <>(X).
{}

10.5 Input and output

10.5.1 Introduction

When an input/output unit opens (predicates open/3 and open/4), an output


argument is unified with a constant (in this case a negative integer). This argument
must be a free variable when the call is made. The constant is used in the predicates
to denote the access channel to the unit. A start-up option makes it possible to
associate the unit with an identifier, called an "alias". In the program sources this
will be a clearer and more global way of denoting the channel number.

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 13

close(C,O), close(C)
Closes the unit associated with channel C. If argument O exists, it must be a
list of options taken from among:
force(true): if a unit closing error occurs it will be generated.
force(false): if a unit closing error occurs it will be ignored.

open(S,M,C,O), open(S,M,C)
Opens the unit whose name is the atom S in mode M, and returns the
associated channel C. If argument O exists, it must be a list of options taken
from among:
- alias(A) where A must be an identifier and will indicate an alias to be
used as the unit's name in the predicates.
- eof_action(A) which indicates the action to perform on an end of file
according to the value of A:
- error: an error is generated (default).
- eof_code: a special code determined by the reading predicate
is returned upon each attempt to access the file (see reading
predicates).
- reset: the same code as for eof_code is returned and reading
of the end of file is canceled. The value of the end_of_stream
property remains at. This is useful for terminals.
- lg_buffer(L) where L must be an integer and indicates the size of the
buffer associated to the unit.
- reposition(B) where B can take the value true or false and indicates
whether the reading (or writing) index can be re-positioned (call to the
primitive set_stream_position/2). Default: true.
- type(T) where T denotes the unit type.
Channel C associated with the unit must be a free variable when the call is
made, and is unified with a negative integer value (transparent for the user).
Example:
?- open(bfile,write,X,[alias(bfile),type(binary)]).
{X=-7}

set_stream_position(C,N)
Positions the reading or writing cursor of the unit associated with channel C at
the Nth byte. N must be an integer and the unit must be a disk file.

stream_property(C,P)
Succeeds if the unit associated with channel C has the property P. C can be a
free variable, in which case all channels possessing property P will be unified
with C. P can either be free or indicate one of the following properties:
- alias(A) where A will be unified with the unit's alias.
- file_name(S) where S will be unified with the unit's name.
- input which will be true if the unit is an input unit.
- mode(M) where M will be unified with the unit opening mode.
- output which will be true if the unit is an output unit.

©PrologIA
Aociation Prolog
R 10 - 14 Reference Manual HERITAGE

- position(P) where P will be unified with the position of the unit's


cursor.
- type(T) where T will be unified with unit's type.
- reposition(B) where B will be unified with the value :true or :false
depending on which option is chosen when the unit is opened.
- eof_action(A) where A will be unified with the action to perform on an
end of file.
- end_of_stream(E) where E will be unified with:
- not if you are not on an end of file
- at if you are at an end of file
- past if you have gone past the end of file (reading has been
attempted after an end of file was indicated)
C cannot be an alias because it can also be used as output.
Examples
?- stream_property(S,P).
{S=-6,P=file_name(foo)}
{S=-7,P=file_name(bfoo)}
{S=-6,P=mode(append)}
{S=-7,P=mode(read)}
{S=-6,P=alias(momo)}
{S=-7,P=alias(bfile)}
{S=-6,P=type(text)}
{S=-7,P=type(binary)}
{S=-7,P=input}
{S=-6,P=output}
{S=-6,P=position(69)}
{S=-7,P=position(4)}
{S=-6,P=reposition(:true)}
{S=-7,P=reposition(false)}
{S=-6,P=eof_action(error)}
{S=-7,P=eof_action(eof_code)}
{S=-6,P=end_of_stream(:not)}
{S=-7,P=end_of_stream(:not)}
?- stream_property(S,type(text)).
{S=-6}
?- stream_property(-7,type(B)).
{B=binary}

10.5.2 Input

10.5.2.1 Interpreting character strings


If a text is positioned as an argument, and is written between double quotes, the
parser may interpret it in several different ways depending on the option chosen
(on the command line or by executing the predicate set_prolog_flag/2):
- as a true character string (true type).
- as an atom: this will be equivalent to writing between single quotes.
- as a list made up of the characters (atoms prefixed by the empty prefix)
constituting the string.
- as a list made up of the codes of the characters constituting the string.

Examples:
?- set_prolog_flag(double_quotes,string), read(R).

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 15

"hello world".
{R="hello world"}
?- set_prolog_flag(double_quotes,chars), read(R).
"hello world".
{R=[h,e,l,l,o,' ',w,o,r,l,d]}
?- set_prolog_flag(double_quotes,codes), read(R).
"hello world".
{R=[104,101,108,108,111,32,119,111,114,108,100]}
?- set_prolog_flag(double_quotes,atom), read(R).
"hello world".
{R='hello world'}
?-

10.5.2.2 Predicates
If the argument denoting the input unit is an input argument, you can use either the
channel number or the alias associated with the unit. Otherwise (i.e. the predicate
current_input/1), the channel number will be returned.

Most input predicates can be used either on the unit specified in the argument
(channel number, alias), or on the current input unit, in which case the argument
indicating the unit is absent.

The behavior of reading predicates when an end of file is detected complies with the
eof_action option chosen when the reading unit was opened.

at_end_of_stream(C), at_end_of_stream
Succeeds if reading on channel C has already indicated an end of file, fails
otherwise. Unlike the eof predicate, this predicate does not attempt to read
channel C again. Instead it just examines the status of the previous reading.

current_input(C)
C is unified with the channel associated with the current input unit. Warning:
C will not be an alias.

get(C,X), get(X)
X is unified with the integer equal to the internal code (ISO code or host
machine code) of the first non blank character read on the input unit
associated with channel C. If an end of file is reached and if unit has been
opened with eof_action(eof_code) option X is unified with -1.

get_byte(C,X), get_byte(B)
X is unified with the first byte (integer >= 0) read on the input unit associated
with channel C. This unit must be the :binary type. If an end of file is
reached and if unit has been opened with eof_action(eof_code) option X is
unified with -1.

get_char(C,X), get_char(X)
X is unified with the first character read on the input unit associated with
channel C. If an end of file is reached and if unit has been opened with
eof_action(eof_code) option X is unified with end_of_file.

©PrologIA
Aociation Prolog
R 10 - 16 Reference Manual HERITAGE

get_code(C,X), get_code(X)
X is unified with the integer equal to the internal code (ISO code or host
machine code) of the first character read on the input unit associated with
channel C. If an end of file is reached and if unit has been opened with
eof_action(eof_code) option X is unified with -1.

get0(X)
Identical to get_code/1.

peek_byte(C,X), peek_byte(X)
Attempts to unify X with the first byte (integer >= 0) input on the unit
associated with channel C. This unit must be the :binary type. The byte is
not read. Therefore this predicate does not modify the unit's properties
position and end_of_stream. If an end of file is reached and if the unit has
been opened with eof_action(eof_code) option X is unified with -1.

peek_char(C,X), peek_char(X)
Attempts to unify X with the first character input on the unit associated with
channel C. The character is not read. Therefore this predicate does not
modify the unit's properties position and end_of_stream. If an end of file is
reached and if the unit has been opened with eof_action(eof_code) option X is
unified with end_of_file.

peek_code(C,X), peek_code(X)
Attempts to unify X with the integer equal to the internal code (ISO code or
host machine code) of the first character input on the unit associated with
channel C. The character is not read. Therefore this predicate does not
modify the unit's properties position and end_of_stream. If an end of file is
reached and if unit has been opened with eof_action(eof_code) option X is
unified with -1.

read(C,X), read(X)
Reads the next term on the unit associated with channel C, followed by the
first subsequent non blank character. Equivalent to in(X,_) on unit C. If an
end of file is reached and if unit has been opened with eof_action(eof_code)
option X is unified with end_of_file.
> read(X).
[1,2].
{X=[1,2]}

read_line(C,S,N), read_line(S,N), read_line(S)


Similar to the predicate inl(S,N) on the unit associated with channel C.

read_term(C,X,O), read_term(X,O)
Similar to the read predicate, but in addition you can obtain the following list
of options:
- variables(L_V) where L_V will be the list of variables of term X.

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 17

- variable_names(L_VN) where L_VN will be the dictionary of


variables of term X, and will be made up of items in the pattern:
"variable name" = variable.
- singletons(L_S) where L_S will be the dictionary of singleton
variables (only appearing once) in the term X, and will be made up of
items in the pattern "variable name" = variable.
Example:
?- read_term(T,[variables(L_V),variable_names(L_VN),
singletons(S)]).
aa(X,[Y,X,Y,Z],<>(Z,U)).
{T=aa(_940,[_969,_940,_969,_1042],_1042(_1208)),
L_V=[_940,_969,_1042,_1208],
L_VN=["X" = _940,"Y" = _969,"Z" = _1042,
"U" = _1208],
S=["U" = _1208]}

see(F)
Is equivalent to input(F). If F is an identifier, the string corresponding to its
abbreviation is taken as the file name (i.e. the prefix is ignored).

seeing(F)
Is equivalent to input_is(F). If F is an identifier, the string corresponding to
its abbreviation is taken as the file name (i.e. the prefix is ignored).

seen
Is equivalent to close_input.

set_input(C)
Redirects current input to the unit associated with channel C.

10.5.3 Output

If the argument denoting the output unit is an input argument, you can use either the
channel number or the alias associated with this unit. Otherwise, (i.e. the predicate
current_output/1), it is the channel number that will be returned.

Most of the output predicates can be used either on the unit specified in the
argument (channel number, alias), or on the current output unit, in which case the
argument indicating the unit is absent.

current_output(C)
C is unified with the channel associated with the current output unit.
Warning: C will not be an alias.

flush_output(C), flush_output
Equivalent to the predicate flush/0 for the output unit associated with channel
C.

©PrologIA
Aociation Prolog
R 10 - 18 Reference Manual HERITAGE

nl(C), nl
Equivalent to line/0 for the output unit associated with channel C.

put(X)
Equivalent to put_code/1.

put_byte(C,X), put_byte(X)
The byte X (integer >= 0) is sent to the output unit associated with channel C.
This unit must be the :binary type.

put_char(C,X), put_char(X)
The character X is sent to the output unit associated with channel C.

put_code(C,X), put_code(X)
The internal code of character X is sent to the output unit associated with
channel C.

set_output(C)
Redirects the current output to the unit associated with channel C.

tab(N)
Sends N blanks to the current output unit.

tell(F)
Is equivalent to output(F). If F is an identifier, the string corresponding to its
abbreviation is taken as the file name (i.e. the prefix is ignored).

telling(F)
Is equivalent to output_is(F). If F is an identifier, the string corresponding to
its abbreviation is taken as the file name (i.e. the prefix is ignored).

told
Is equivalent to close_output.

write(C,X), write(X)
Is equivalent to w r i t e _ t e r m with the options [ q u o t e d ( f a l s e ) ,
numbervars(true), ignore_ops(false)].

writeq(C,X), writeq(X)
Is equivalent to write_term with the options [quoted(true), numbervars(true),
ignore_ops(false)].

write_canonical(C,X), write_canonical(X)
Is equivalent to w r i t e _ t e r m with the options [ q u o t e d ( t r u e ) ,
numbervars(false), ignore_ops(true)].

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 19

write_term(C,X,O), write_term(X,O)
Writes the term X on the output unit associated with channel C, taking account
of the list of options O selected from the following:
- quoted(true) or quoted(false): indicates whether or not the string and
identifier constants in X must be written in quoted form.
- ignore_ops(true) or ignore_ops(false): indicates whether or not the
current operator declarations should be ignored.
- numbervars(true) or numbervars(false): indicates whether or not the
terms in the form '$VAR'(N), (where N is a positive integer) must be
written as a variable consisting of an upper-case letter followed by an
integer. The letter is the (i+1)th letter of the alphabet, and the integer is
j, such that:
i = N modulo 26
j = N / 26 (integer division).
If an option is not specified, its default value is :false.
Examples:
?- write_term(['quoted atom', "string", 1+2,
'$VAR'(35)],[]).
[quoted atom,string,1 + 2,'$VAR'(35)]{}
?- write_term(['quoted atom', "string", 1+2,
'$VAR'(35)],[quoted(:true),numbervars(true),
ignore_ops(true)]).
['quoted atom',"string",+(1,2),J1]{}
?-

10.6 The environment

A number of global parameters called "status variables" can be modified or


consulted. They are:
- the debugger status :
status variable name: debug
possible values: on or off .
- Prolog's behavior when a rule is called but not defined:
status variable name: unknown
possible values: error (generates an error), warning (generates a warning) or
fail (failure).
- interpretation of double quotes in the argument position:
status variable name: double_quotes
possible values: chars (list of characters), codes (list of character codes), atom
(atom) or string (real strings).
- the possibility of character conversion:
status variable name: char_conversion
Only possible value at present: off (disabled).
- confirmation that integer arithmetic is not bounded
status variable name: bounded
Non modifiable value: false.
- maximum number of arguments in a rule or structure:

©PrologIA
Aociation Prolog
R 10 - 20 Reference Manual HERITAGE

status variable name: max_arity


Non modifiable value: 8388607.
- the definition of integer division and its remainder:
status variable name: integer_rounding_function
Non modifiable value: toward_zero.

current_prolog_flag(X,Y)
Gives information about the current values of the environment status variables.
The status variables max_integer and min_integer always cause a failure
because integer arithmetic is not bounded. For example: We want to know
the values of all the status variables:
?- current_prolog_flag(F, V).
{F=bounded,V=false}
{F=integer_rounding_function,V=toward_zero}
{F=char_conversion,V=off}
{F=max_arity,V=8388607}
{F=:debug,V=off}
{F=unknown,V=warning}
{F=double_quotes,V=:string}

halt(X), halt
Equivalent to quit(X) and quit respectively

set_prolog_flag(X,Y)
Sets the environment status variable X to the value Y. This predicate is also a
compiling directive, i.e. the environment variables may be modified in the
middle of a source you are compiling. Examples:
?- consult.
set_prolog_flag(double_quotes, codes).
foo :- myrule("abc").
.
{}
?- set_prolog_flag(debug, on).
{}

10.7 Translation of DCG1


In insertion mode, Prolog transforms rules of the form shown below into Prolog II+
rules.

A --> B.

Where A is a term and B is a sequence of terms. For each term in the sequence B:

- If it is a list, it is interpreted as a sequence of terminal symbols.

1Definite Clause Grammar, extension of context-free grammars and sub-set of metamorphosis


grammars.

©PrologIA
Aociation Prolog

HERITAGE Edinburgh extensions R 10 - 21

- If it is a character string, it is transformed into a list of characters which is


therefore also considered as a list of terminal symbols.

- If it is a term between braces, it is interpreted as a call to a rule to be performed.

- Otherwise the term is considered to be a non-terminal symbol representing a


rewriting rule.

The predefined rule phrase/2 or phrase/3 is used to analyze or synthesize the


grammatical strings defined by this grammar (see section 10.2).

To translate the grammar rule into a Prolog rule, Prolog will call the predicate
:term_expansion/2 if it has been defined. If not it will use its own transformation
program. It is thus possible to perform automatic transformations of terms having
the form (A --> B). To define a transformation program, the following rule must be
defined:

term_expansion(X,Y)
When this rule is called, X is the term Prolog has just read and Y is a free
variable. X has the form (A --> B).
After the call, Y must represent the Prolog rule, which must be associated with
rewriting rule X (i.e. the Prolog rule that will be asserted).

Here are two examples of compilation and interrogation of a DCG grammar.

Example 1
?- [user].
sum(Z) --> digit(Z).
sum(X+Y) --> digit(X), "+", sum(Y).
digit(1) --> "1".
...
digit(9) --> "9".
.
{}
?- list.
sum(_53,_54,_55) :-
digit(_53,_54,_55).
sum(_57 + _58,_54,_55) :-
digit(_57,_54,["+" | _59]),
sum(_58,_59,_55).

digit(1,["1"|_54],_54).
...
digit(9,["9"|_54],_54).
{}
?- phrase(sum(Z),"1+2+3").
{Z=1 + (2 + 3)}
?- phrase(sum(1+(2+9)),L).
{L=["1","+","2","+","9"]}

Example 2
?- [user].
sum(Z) --> digit(Z).

©PrologIA
Aociation Prolog
R 10 - 22 Reference Manual HERITAGE

sum(Z) --> digit(X), "+", sum(Y),{Z is X+Y}.


digit(N) --> [C],{string_integer(C,N)}.

list3 --> elt, elt, elt.


elt --> [a].
elt --> [b].
elt --> [c]. .
{}
?- phrase(sum(Z),"1+2+3").
{Z=6}
?- phrase(list3,L).
{L=[a,a,a]}
{L=[a,a,b]}
{L=[a,a,c]}
...
{L=[c,c,c]}

©PrologIA
Aociation Prolog

HERITAGE

Appendix A
Differences between Prolog II+ and
the standard

A.1. General level


A.2 Functionalities not implemented
A.3 Restricted functionalities

A.1 General level

Range of the cut in a meta-call

In Prolog II+ the cut in a meta-call has a greater range than in the standard. For
example this means that there are the following differences in operation, compared
to the standard:
?- insert.
a(1).
a(2).
.
?- call( (Z=!, a(X), Z) ).
{Z=!,X=1} /* a single solution instead of 2 */

The character strings

Prolog II+ has an extra option compared to the standard definition, making it
possible to classify "in double quotes" in a type of its own which is the "character
string" type. This option is active by default at Prolog start-up.

Identifier prefixing

In Prolog II+, when identifiers are read they are always assigned a prefix in
accordance with the current context, whether they are positioned as
arguments(functors) or goals (rule head or body). However we also make it
possible to automatically assign non-prefixed identifiers the empty prefix ("") when
they are positioned as arguments. To do this, simply start Prolog with "-f a0"
option.

For example, when the system reads call(nl) in this mode it will call a rule that is
doubtless not defined (:nl), whereas call(sys:nl) will print a line feed. .

To remove this possibility, execute:

©PrologIA
Aociation Prolog
A-2 Appendix A HERITAGE

?- set_options("a1").

Logical view and immediate view

In the mechanism for dynamic modification of a group of rules (assert, retract,


suppress), the standard defines the so-called "logical" view. In this view, everything
happens as if the execution of a group of rules was performed on a copy of the
group, and therefore ignores any modifications undergone during the execution.
Another possible view is the "immediate" view, which immediately takes into
account any modification of a group.

Prolog II+ uses the immediate view.

The only times when the behavior may be different from an immediate process is
when a rule is suppressed in a group where there still remain alternatives to execute.
The enumeration of all the possibilities is then quite complex. The complexity
depends on whether or not the group of rules in question is indexed, on the position
of the modified rule in relation to the rule of the same group that is being executed,
on the type of the goals' first argument (variable, constant, etc.).

The tuples

The tuple type is not defined in the Prolog standard. To define an equivalence, we
can say that the term f(a1, a2, ..., an) where f is an atom, is equivalent to the tuple
<>(f, a1, a2, ..., an), except when n=0 (f is not equivalent to <>(f) ).

A.2 Functionalities not implemented

The directives char_conversion/2 and current_char_conversion/2 have not been


implemented.

A.3 Restricted functionalities


The multifile/1 directive is equivalent to the discontiguous/1 directive. The file
concept is not taken into account by the compiling process.

Only the :off value is taken into account for the second parameter of the compiling
directive and primitive set_prolog_flag/2 when the value of the first parameter is
:char_conversion.

©PrologIA
Aociation Prolog

HERITAGE A. Differences between Prolog II+ and the standard A-3

©PrologIA
Aociation Prolog

HERITAGE
Aociation Prolog

HERITAGE

Appendix B
List of predefined directives and
predicates

a : constants (identifier, integer, real, or string)


b : 0 or 1
c : string of one character
d : double precision real
f : identifier or string
h : stream or alias
i : identifier
l : list
m : integer or real
n : integer
r : real (single or double precision)
s : string
t : term
u : unit: "console", file name or window name (string or identifier)
v : variable

+ : the argument must be instantiated (even not completely)


- : the argument must be a variable (instantiated if success)
? : any argument, it will be instantiated if success
@: any argument, it will remain unaltered

B.1 Compiler directives

discontiguous( +i /+n) discontiguous(foo/2)


dynamic( +i /+n) dynamic(aa/2)
ensure_loaded( +u) ensure_loaded("myfile")
include( +u) include("myfile")
initialization( +t) initialization(write(end))
module( +s) module("Interface")
module( +s, +l) module("room",["",["table","glass"]])
module( +s, +l1, +l2) module("lex",["",["uncle","son"]],["1"])
module( +t, +l1, +l2, +s) module(lexicon,[],["sys"],"lex")
multifile( +i /+n) multifile (foo/2)
omodule( +s) omodule("Interface")
op( +n, +i1, +i2) op(900,fy,not)
set_alias(+i, +a) set_alias(foo,122)
set_prolog_flag( +i1, +i2) set_prolog_flag(unknown,warning)

©PrologIA
Aociation Prolog
B-2 Reference manual HERITAGE

B.2 Predicates
A
abolish( @t) abolish(myrule/2)
abs( +m) val(abs(-1.5e0),1.5e)
add( +m1, +m2) val(add(2.3E0,3.1E1),3.33E1)
add_implicit( +s1, +s2) add_implicit("sys","outml")
add_tlv( -v, ?t, +i) add_tlv(V, 33, foo)
alloc
alloc( ?n1, ?n2, ?n3, ?n4, ?n5, ?n6, ?n7, ?n8, ?n9, ?n10, ?n11, ?n12)
arg( +n, +t1, ?t2) arg(0,<>(aa,bb),aa)
arg2( +n, +t1, ?t2) arg2(2,<>(aa,bb),bb)
assert( +t) assert(brother(jean,paul))
assert( +t1, +t2) assert(pp(X),[qq(X),rr(X)])
assert''( +t1, +t2) assert''(pp(X),[qq(X),rr(X)])
asserta( +t) asserta(brother(jean,paul))
asserta( +t1, +t2) asserta(pp(X),[qq(X),rr(X)])
assertn( +t1, +t2, +n) assertn(pp(x),[qq(X),rr(X)],2)
assertz( +t1, +t2) assertz(pp(x),[qq(X),rr(X)])
assertz( +t) assertz(brother(X,Y):-son(X,Z),son(Y,Z))
assign( +i, @t) assign(fo,term(3,[1,2,x],tab[5],"str"))
at_end_of_stream
at_end_of_stream( +h) at_end_of_stream(alias1)
atan( +m) val(atan(1),X)
atom( @t) atom(foo)
atom_chars( +i, ?l) atom_chars(foo,X)
atom_chars( -i, +l) atom_chars(X,["a","b"])
atom_codes( +i, ?l) atom_codes(foo,X)
atom_codes( -i, +l) atom_codes(X,[65,66])
atom_concat( ?i1, ?i2, +i) atom_concat(X,Y,foo)
atom_concat( +i1, +i2, -l) atom_concat(fo1,fo2,X)
atom_length( +i, ?n) atom_length(foo,X)
atomic( @T) atomic(1)

B
bagof( ?v, +t, ?l) bagof(X,frere(X,Y),L)
beep
block( ?t1, +t2) block(edit,call_editor)
block( ?t1, ?t2, +t3) block(edit,_info,call_editor)
block_exit( @t) block_exit(edit)
block_exit( @t1, @t2) block_exit(edit, "this error")
bound( @t) bound(X)

C
call( +t) call(outml("Hello"))
callC( +t1) callC(sscanf("12.","%f",<>("R",X)))
callC( +t1, ?t2) callC(open("myfile"),<>("I",X))
catch( +t1, ?t2, +t3) catch(foo(5),test(Y),outml("Hello"))

©PrologIA
Aociation Prolog

HERITAGE B. List of predefined directives and predicates B-3

char_code( +c, ?n) char_code("A",65)


char_code( -c, +n) char_code(X,65)
chrono( ?v)
clause( +t1, ?t2) clause(brother(X,Y),Q)
clear_input
close( +h) close(alias1)
close( +h, +l) close(alias1, force(true))
close_context_dictionary( +s) close_context_dictionary("data")
close_input
close_input( +u) close_input("myfile")
close_output
close_output( +u) close_output("myfile")
compound( @t) compound([1,2])
conc_list_string( +l, ?s) conc_list_string(["ab","cd"],"abcd")
conc_string( ?s1, ?s2, +s3), conc_string("ab",X,"abcd")
conc_string( +s1, +s2, -s3) conc_string("ab","cd",X)
consult( +f) consult("prog1.p2E")
copy_term( @t1, ?t2) copy_term([1,2,<>("zz",X),Z], K)
copy_term_with_constraints(@t1, ?t2)
dif(X,3) copy_term_with_constraints(
[1,2,<>(X),Z], K)
cos( +m) val(cos(+3.14e0),X)
cpu_time( ?v)
current_context( ?t) current_context(X)
current_context( ?t, ?l1, ?l2, ?s) current_context(X,Y,Z,D)
current_file( ?u) current_file(X)
current_file( ?u , ?i1, ?i2) current_file(X,T,M)
current_input( ?n) current_input(X)
current_op( ?n, ?i, ?f) current_op(200,xfx,Y)
current_output( ?n) current_output(X)
current_predicate( ?i/ ?n) current_predicate(:to_begin/0)
current_prolog_flag( ?i1, ?i2) current_prolog_flag (unknown,X)

D
date( ?v1, ?v2, ?v3, ?v4) date(J,M,A,S)
date_string( ?v)
date_stringF( ?v)
debug
debug( +u) debug("echodebug.dat")
debug( +n) debug(3)
debug( +n, +u) debug(3, "echodebug.dat")
def_array( +i, +n) def_array(stack,100)
default( +t1, +t2) default(man(X),eq(x,[]))
delay( +n) delay(5000)
dictionary
dictionary( ?l)
dictionary( +s, ?l) dictionary("sys",X)
dif( ?t1, ?t2) dif(X,toto)

©PrologIA
Aociation Prolog
B-4 Reference manual HERITAGE

div( +m1, +m2) val(div(8.0e,3),X)


dot( @t) dot([1,X])
double( +m) val(double(1),1e0)
draw_equ( @t) draw_equ(aa(bb(cc),bb(cc)))
draw_mode( ?s)
draw_tree( @t) draw_tree(aa(bb(cc),bb(cc,dd)))

E
echo
edinburgh
edit( +i/+n) edit(hors_d_oeuvre/1)
edit( +l) edit([meat/1,fish/1])
edit( +s) edit("file.dat")
editm( +s) editm("my_module")
enum( ?v, +n) enum(X,10)
enum( ?v, +n1, +n2) enum(X,10,20)
eof
eol
eq( ?t1, ?t2) eq(X,father(john,mary))
eql( +a1, +a2) val(eql(3,3),1)
equations( +t1, ?t2, ?l) equations(X,T,l)
exit
exit( +s) exit("myfile.psv")
exp( +m) val(exp(+1.0e0),X)

FGH
fail
fail_if( +t) fail_if(fail)
fasserta( +t) fasserta(town("Marseille",13))
fassertz( +t) fassertz(town("Marignane",13))
file_dictionary( +s, ?l) file_dictionary("foo.mo",X)
find_pattern( +s1, +s2, ?n) find_pattern("abcdef","de",4)
findall( ?V, +T, ?L) findall (X,brother(X,Y),L)
float( +m) val(float(5),+5.0e0)
flush
flush_output
flush_output( +h) flush_output(alias1)
free( @t) free(X)
freeze( -v, +t) freeze(X,list(X))
freplace( +t, +n, +t') freplace(old(X,Y),1,"010180")
freplace( +i/+a, +n1, +n2, +t) freplace(old/2,10,2,"011293")
fretract( +t) fretract(town(X,83))
fretractall( @t) fretractall(town(X,83))
functor( -t, +i, +n) functor(X,aa,2)
functor( +t, ?i, ?n) functor(aa(bb(X),bb(cc)),aa,X)
gc( +i) gc(:dictionary)
gensymbol( -v) gensymbol(X)
get( ?n) char_code(";",C), get(C)

©PrologIA
Aociation Prolog

HERITAGE B. List of predefined directives and predicates B-5

get( +h, ?n) get(alias1,C)


get_byte( ?n)
get_byte( +h, ?n) get_byte(alias1, C)
get_char( ?c)
get_char( +h, ?c) get_char(alias1, C)
get_code( ?n) char_code(";",C), get_code(C)
get_code( +h, ?n) get_code(alias1, C)
get_option( +c, ?c) get_option("r", C)
get_tlv( -v, ?l) get_tlv(V, L)
get0( ?n) get0(X)
getenv( +s1, ?s2) getenv("PrologEdit",X)
halt
halt( +n) halt(1)
hidden( +i/+n) hidden(my_rule/0)
hidden( +s) hidden("private")
hidden_debug( +i/+n) hidden_debug(my_rule/0)
hidden_debug( +s) hidden_debug("private")
hidden_rule( +i/+n) hidden_rule(my_rule/0)
hidden_rule( +s) hidden_rule("private")

IK
ident( @t) ident(toto)
if( +b, +a1, +a2) val(if(inf(1,5),add(1,1),3),2)
import_dir( ?s)
in( ?t , ?c) in(X,C)
in( ?t , ?l, ?c) in(X,D,C)
in_char( ?c) in_char(X)
in_char'( ?c) in_char'(X)
in_double( ?d) in_double(X)
in_ident( ?i) in_ident(X)
in_integer( ?n) in_integer(X)
in_real( ?r) in_real(X)
in_sentence( ?t1, ?t2) in_sentence(X,Y)
in_string( ?s) in_string(X)
in_word( ?s, ?a) in_word(X,Y)
include( +s) include("myfile")
index( +i/+n) index(database/1)
inf( +a1, +a2) val(inf("to","zou"),1)
infe( +a1, +a2) val(infe("to","zou"),1)
infinite
infinite_flag val(infinite_flag,X)
init_fassert( +i/+a, +l) init_fassert(town/2,[[1,2],1,2])
inl( ?v) inl(X)
inl( ?v1, ?v2) inl(X,Y)
input( +u) input("console")
input( +u , +n) input("myfile", 1000)
input_is( ?u) input_is("console")
insert

©PrologIA
Aociation Prolog
B-6 Reference manual HERITAGE

insert( +s) insert("mutant.p2")


insertz
insertz( +s) insert("mutant.p2")
integer( @t) integer(3)
is( ?t1, @t2) X is 1+2
is_array( +i, ?v) is_array(tab,X)
keysort( +l, ?l) keysort([43,31,52,12], L)
keysort( +l, ?l, +i) keysort([43,31,52,12], L, mycompar)
kill_array( +i) kill_array(tab1)
kill_module( +s) kill_module("lex")

L
line
line_width( ?n) line_width(X)
list
list( +i/+n) list(foo/2)
list( +i/+n, n) list(foo/2,4)
list( +s) list("mymodule")
list_of( ?v, +l1, +t, ?l2) list_of(X,[],data(X),L)
list_string( +l, ?s) list_string(["a","b"],X)
list_tuple( +l, ?t) list_tuple([aa,bb,cc],x)
listing
listing( +s) listing("mymodule")
lkload( +s1, +s2) lkload("my_file","my_table")
ln( +m) val(ln(1.0e0),0.0e0)
log( +m) val(log(1.0e0),0.0e0)
load( +s) load("myfile")
load( +s, +l) load("myfile", [<>("aa","bb")])

MN
member( ?t, ?l) member(1,[1,2,3,4])
memory_file( +s) memory_file("non-terminal")
memory_file( +s, +n) memory_file("lexical",32000)
mod( +n1, +n2) val(mod(7,3),1)
month( ?i, ?s) month(5,"may")
ms_err( +i, ?s) ms_err(104,X)
mul( +m1, +m2) val(mul(add(3.1e0,0.077d0),5),X)
name( +f, ?l) name(toto,X)
name( -f, +l) name(X,[116,111,116,111])
new_tlv( -v, ?t, +i) new_tlv(V, 33, foo)
next_char( ?c) next_char(",")
next_char'( ?c) next_char'(X)
nil
nl
nl( +h) nl(alias1)
no_debug
no_echo
no_index( +i/+a) no_index(foo/2)

©PrologIA
Aociation Prolog

HERITAGE B. List of predefined directives and predicates B-7

no_infinite
no_paper
no_spy( +i/+n) no_spy(foo/2)
no_trace
nonvar( @t) nonvar([1|X])
not( @t) not(true)
not_defined( ?l)
number( @t) number(10)
number_chars( +n, ?l) number_chars(123,X)
number_chars( -n, +l) number_chars(X,["1","2","3"])
number_codes( +n, ?l) number_codes(123,X)
number_codes(- n, +l) number_codes(X,[49,50,51])

OPQ
once( +t) once(out(foo))
op( ?n, ?i1, ?i2) op(900,fy,not)
op( +n, +i1, +i2, +i3) op(700,xfx,"=",eq)
open( +s, +i, -v) open("file",:read,X)
open( +s, +i, -v, +l) open("file",:read,X,[alias(alias1))
or( +t1, +t2) or(eq(X,3),outl(X).fail)
out( @t) out([a,b])
out_equ( @t) out_equ(aa(bb))
outl( @t) outl([a,b])
outm( +s) outm("bonjour")
outm( +s, +n) outm("_",30)
outml( +s) outml("The cat and the dog")
output( +s) output("myfile.pro")
output( +u , +n) output ("myfile", 1000)
output_is( ?s) output_is("myfile.pro")
page
paper
peek_byte( ?n)
peek_byte( +h, ?n) peek_byte(alias1,X)
peek_char( ?c)
peek_char( h, ?c) peek_char(alias1,X)
peek_code( ?n)
peek_code( +h, ?n) peek_code(alias1,X)
phrase( ?t1, ?t2) phrase(somme(X),"1+2+3")
phrase( ?t1, ?t2 , ?t3) phrase(somme(X),"1+2+3",Y)
predefined( +t) predefined(outm("Ok"))
prefix_limit( ?c) prefix_limit(X)
prologII
prologIIE
put( +n) char_code("!",C), put(C)
put_byte( +n) put_byte(12)
put_byte( +h, +n) put_byte(alias1,12)
put_char( +c) put_char("e")
put_char( +h, +c) put_char(alias1,"e")

©PrologIA
Aociation Prolog
B-8 Reference manual HERITAGE

put_code( +n) put_code(12)


put_code( +h, +n) put_code(alias1,12)
quit
quit( +n) quit(1)

R
rad( +m) val(rad(+90.0e0),X)
read( ?t) read(X)
read( +h, ?t) read(alias1,X)
read_rule( ?v1, ?v2) read_rule(T,Q)
read_term( ?t, +l) read_term(X,[variables(L)])
read_term( +h, ?t, +l) read_term(alias1,X,[variables(L)])
read_unit( ?v1, ?v2) read_unit(_type,_valeur)
real( @t) real(-5.9e0)
realloc( +i, +n) realloc(:code,50)
reconsult( +f) reconsult("prog1.p2E")
recv_double( +n1, ?v2) recv_double(5,D)
recv_integer( +n1, ?v2) recv_integer(5,N)
recv_real( +n1, ?v2) recv_real(5,R)
recv_string( +n1, ?v2) recv_string(5,S)
redef_array( +i, +n) redef_array(foo,1000)
reinsert
reinsert( +u) reinsert("prog.p2")
reload( +s) reload("myfile")
reload( +s, +l) reload("myfile", [<>("aa","bb")])
remove_implicit( +s1, +s2) remove_implicit("sys","outml")
remove_sentence_terminator(+c) remove_sentence_terminator(";")
repeat
reset_chrono
reset_cpu_time
retract( +t1, ?t2) retract(father(john,X),Y)
retract( +t) retract(brother(X,Y):- true)
retractall( @T) retractall(father(john,X))
rule( +t1, ?t2) rule(father(john,x),Y)
rule( +n, +t1, ?t2) rule(r,father(john,X),Y)
rule( +n, +i, +t1, ?t2) rule(5,father,T,Q)
rule_nb( +i/+n, ?v) rule_nb(foo/2,X)

S
save( +l, +s) save(["aa","bb"], "myfile")
save_state( +s) save_state("myfile")
see( +f) see(filei)
seeing( +f) seeing(filei)
seen
send_double( +n, +d) send_double(5,12d0)
send_integer( +n1, +n2) send_integer(5,1000)
send_real( +n, +r) send_real(5,3.14e0)
send_string( +n, +s) send_string(5,"error")

©PrologIA
Aociation Prolog

HERITAGE B. List of predefined directives and predicates B-9

set_context( +s) set_context("user")


set_context( +s1, +l1, +l2, +s2) set_context("user",[],["sys"],"")
set_cursor( +n1, +n2) set_cursor(1,24)
set_draw_mode( +s) set_draw_mode("TTY")
set_import_dir( +s) set_import_dir("/home/user/")
set_input( +h) set_input(alias1)
set_line_cursor( +n) set_line_cursor(10)
set_line_width( +n) set_line_width(132)
set_options( +s) set_options("vEw2")
set_output( +h) set_output(alias1)
set_prefix_limit( +c) set_prefix_limit("$")
set_prolog_flag( +i1, +i2) set_prolog_flag(unknown,warning)
set_stream_position( +h, +n) set_stream_position(alias1,200)
setarg( +n, +t1, @t2) setarg(3,[1,2,3,4,5],[1,2,3])
setof( ?v, +t, ?l) setof (X,frere(X,Y),L)
show_spy( ?v)
sin( +m) val(sin(+3.14e0),X)
sort( +l, ?l) sort([43,31,52,12], L)
sort( +l, ?l, +i) sort([43,31,52,12], L, mycompar)
split( @t, ?l) split(father(john),[father,john])
split( +s, ?l) split("abc",["a","b","c"])
spy( +i/+n) spy(foo/2)
sqrt( +m) val(sqrt(+9.0e0),+3.0e0)
state
statistics
statistics( ?n1, ?n2, ?n3, ?n4, ?n5, ?n6, ?n7, ?n8, ?n9, ?n10, ?n11, ?n12)
stream_property( +h, ?l) stream_property(alias1,alias(X))
string( @t) string("abc")
string_double( +s, ?d) string_double(1d0,X)
string_double( -s, +d) string_double(X,1.2345678d15)
string_ident( ?s1, ?s2, +i) string_ident(X,"john",john)
string_ident( +s1, +s2, -i) string_ident("user","john",X)
string_ident( +s, ?i) string_ident("john",X)
string_ident( -s, +i) string_ident(X,john)
string_integer( +s, ?n) string_integer("123",X)
string_integer( -s, +n) string_integer(X,123)
string_real( +s, ?r) string_real("+12.E15",X)
string_real( -s, +r) string_real(X,+1.2E16)
string_term( +s, ?t) string_term("err(500,X)",X)
string_term( -s, +t) string_term(X,err(500,V60))
string_term( +s, ?t1, ?t2), string_term("err(500,X) ss",X,Y)
string_term( -s, +t1, ?t2) string_term(X,err(1),Y)
string_term( +s, ?t1, ?t2, +n), string_term("err(500,X) ss",X,Y,1000)
string_term( -s, +t1, ?t2, +n) string_term(X,err(1),Y,1000)
sub( +m1, +m2) val(sub(2d1,1e0),X)
sub_atom( +i1, ?n1, ?n2, ?n3, ?i2) sub_atom(abracadabra,0,5,X,Y)
substring( +s1, +n1, +n2, ?s2) substring("abcdef",4,2,X)
sup( +a1, +a2) val(sup("to","zou"),0)

©PrologIA
Aociation Prolog
B - 10 Reference manual HERITAGE

supe( +a1, +a2) val(sup("zou","zou"),1)


suppress( +i/+n) suppress(foo/2)
suppress( +i/+n, +n) suppress(foo/2,5)
sys_command( +s) sys_command("showusers")

TUVW
tab( +n) tab(10)
tan( +m) val(tan(-3.14e0),X)
tassign( +i, @t) tassign(aa,term(3,[1,X],tab[5],"str"))
tassign( +i[+n], @t) tassign(tab[1],123)
tell( +f) tell(file)
telling( +f) telling(file)
term_cmp( @t1, @t2, ?n) term_cmp(1,"foo",X)
term_cmpv(@t1, @t2, ?n) term_cmpv(1,"foo",X)
term_vars(@t1, ?l) term_vars(one(2.X,Y,Y),L)
throw( @t) throw(12)
time( ?n)
time( ?n1, ?n2, ?n3)
told
trace
trace( +s) trace("debug.dat")
true
trunc( +m) val(trunc(+3.8e0),3)
truncate( +m) val(truncate(+3.8e0),3)
tuple( @t) tuple(ff(a))
tval( @t1, ?t2) tval(1+2*3+pile[1],X)
unify_tlv( -v, ?t2) unify_tlv(V, 22)
unify_with_occurs_check( ?t1, ?t2) unify_with_occurs_check(X,1)
val( @t1, ?t 2) val(3,3)
var( @t) var(X)
var_time( -v, ?n) var_time(X,Y)
version( ?n) version(X)
week( ?n, ?s) week(0,"sunday")
write( @t) write("Hello world!")
write( +h, @t) write(alias1,"Hello world!")
write_canonical( @t) write_canonical ("Hello world!")
write_canonical( +h, @t) write_canonical (alias1,"Hello world!")
write_term( @t , +l) write_term("foo",[quoted(:true)])
write_term( +h, @t , +l) write_term (alias1,"f",[quoted(:false)])
writeq( @t) writeq(foo(1,2,3)
writeq( +h, @t) writeq(alias1,foo(1,2,3)

Autres
\( +n) val(\(4),X)
~( +n) val(~(4),X)
+m1 * +m2 val(-3.14e0 * 0.5e,X)
+m1 + +m2 val(1+2,X)

©PrologIA
Aociation Prolog

HERITAGE B. List of predefined directives and predicates B - 11

+t1 , +t2 write("ca va"),nl


+t1 ; +t2 integer(X);real(X)
- +m -2
+m1 - +m2 val(1-2,X)
+t1 --> +t2 phrase --> gn, gv.
+t1 -> +t2 string(X) -> see(X)
+m1 / +m2 val(3/4,X)
+m1 // +m2 Y is 3 // 4
+n1 /\ +n2 val(4 '/\' 8,X)
+a1 < +a2 val(1 '<' 2,X)
+n1 << +n2 val(1 '<<'4,X)
?t1 = ?t2 1 = X
+t1 =.. ?t2 toto(1,2) =.. X
-t1 =.. +t2 Y =.. [toto,X]
+a1 =< +a2 val(1 '=<' 1,X)
@t1 == @t2 func(X) == func(Y)
+t1 =:= +t2 tab[I] =:= I
+t1 =\= +t2 (1+2) =\= (2*3)
@t1 \= @t2 1 \= 2
+a1 > +a2 val(2 '>' 1,X)
+a1 >= +a2 val(2 '>=' 1,X)
n1 >> +n2 val(1024 '>>' 2,X)
+n1 \/ +n2 val(14 '\/' 687,X)
@t1 \== @t2 func(1,X) \== func(1,2)
+a1 @=< +a2
+a1 @> +a2
+a1 @>= +a2
+a1 @< +a2
\+( @T) \+(fail)

©PrologIA
Aociation Prolog
B - 12 Reference manual HERITAGE

©PrologIA
Aociation Prolog

HERITAGE

Appendix C.
Some examples of Prolog II+
programs

C.1 Grammars
C.2 Formal derivation
C.3 Mutants
C.4 Database consultation by evaluating a logic formula
C.5 A brain teaser
C.6 Construction of a path
C.7 Infinite trees

C.1 Grammars
Describing the problem

The grammar of a language is a set of rules which determines whether or not a


sequence of words, constructed from an alphabet, belongs to the language. If it
does belong, it is possible to show the structure underlying the analyzed sentence.

Context-free languages are an important category: for example, below is the


grammar defining the set of all arithmetical expressions which can be constructed
using integers and the operators +, - and * with their usual properties.

(0) <expression> ::= <sum>

(1) <sum> ::= <product> <rest of sum>

(2) <product> ::= <primary> <rest of product>

<primary>
(3) ::= <number>
(4) ::= ( <expression> )

<rest of sum>
(5) ::= <op add> <product> <rest of sum>
(6) ::= <empty>

<rest of product>
(7) ::= <op mul> <primary> <rest of product>
(8) ::= <empty>

© PrologIA
Aociation Prolog
C - 2 Reference Manual HERITAGE

(9) <op mul> ::= *

<op add>
(10) ::= +
(11) ::= -

<number>
(12) ::= 0
(13) ::= 1
(14) ::= 2
(...)

(22) <empty> ::=

An example of the decomposition of the expression 2 * 3 + 6 is given in figure C.1


(the names of the non-terminals have been abbreviated).

C..1.1 Representation of grammars in Prolog

How can Prolog be used to construct this analyzer? Let's suppose that the input
string is a graph: the first peak in the graph is placed at the beginning of the
sentence, and a peak is added at the end of each word in the sentence. Thus, each
word labels the arc joining the two nodes on each side of it. In our example, we
obtain:
2 * 3 + 6
• -----> • -----> • -----> • -----> • -----> •
a b c d e f

<expr>
|
|
<sum>
__/ \__
___/ \__
/ \
<prod> <r-o-s->
/ \ / | \
/ \ / | \
<prim> <r-o-p> <op-a> <prod> <r-o-s>
| / | \ | / \ |
| / | \ | / \ |
<nb> <op-m> <prim> <r-o-p> | <prim> <r-o-p> |
| | | | | | | |
| | | | | | | |
| | <nb> <empty> | <nb> <empty> <empty>
| | | | |
| | | | |
2 * 3 + 6
Figure C.1

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 3

The rules of the grammar can therefore be seen as instructions which allow this
graph to be completed. A rule such as (21) is to be interpreted as: "if there is an arc
labeled "9" between node x and node y of the graph, add an arc labeled "number"
between x and y".

A rule such as (1) gives the following: "if there is an arc labeled product between
nodes x and y and an arc labeled rest of sum between nodes y and z, add an arc
labeled expression between x and z". To analyze a sentence using these
conventions, we search for an arc labeled expression between the first and the last
peak of the associated graph. If we succeed, the sentence will be accepted, if not it
will be rejected.

Let's now write the corresponding Prolog program: each non-terminal symbol N in
the grammar is associated with a predicate of the same name N(<x,y>); which will
be interpreted as: "there is an arc labeled N between the nodes x and y of the graph".

For rule (1), this gives the following clause:


sum(<x,y>) -> product(<x,z>) rest_of_sum(<z,y>) ;

Going back to the graph, it can be represented simply by the list of words
constituting the input sentence:
• peak a
/ \
2 • peak b
/ \
* • peak c
/ \
3 • peak d
/ \
+ • peak e
/ \
6 nil peak f

Each peak in the graph corresponds to a subtree of the tree in figure C.1. If we use
this representation for N(<x,y>), x represents the input string before the execution
of N, and y represents the string remaining to be analysed after N has been
executed. Moreover, this representation makes it possible to express terminal rules
such as (12) and (13) etc, in the form:
number(<x,y>) -> word(n,<x,y>) integer(n) ;

which uses the standard rule:


word(a,<a.x,x>) -> ;

and the predefined rule integer. Finally, recognizing whether or not a sentence
belongs to the language defined by our grammar is equivalent to executing:
expression(<p,nil>)

where p represents the input sentence in the form of a list.

© PrologIA
Aociation Prolog
C - 4 Reference Manual HERITAGE

C.1.2 Displaying the underlying structure

We have now reached the point where we know how to translate a grammar into a
set of rules telling us whether or not a sentence belongs to a language. We can go
further, and complete the set of relations to give the tree constructed by parsing ,
e.g. for the previous example:
add
/ \
mul 6
/ \
2 3

To do this, we only need to add an argument to the predicates associated with the
non-terminals of the grammar. This argument will express the way in which a
sentence is constructed from sub-sentences. We therefore obtain:
number(n,<x,y>) -> word(n,<x,y>) ;
primary(n,<x,y>) -> number(n,<x,y>) ;

Finally, our starting rule becomes:


expression(e,<x,y>) ->
product(p,<x,z>) rest_of_sum(p,e,<z,y>) ;

where e represents the tree associated with the expression analyzed. Here is the
complete program:
" grammar of expressions "

expression(e,<x,y>) -> sum(e,<x,y>) ;

sum(e,<x,y>) ->
product(p,<x,z>) rest_of_sum(p,e,<z,y>) ;

product(p,<x,y>) ->
primary(f,<x,z>) rest_of_product(f,p,<z,y>) ;

primary(n,<x,y>) ->
word(n,<x,y>) integer(n) ;
primary(e,<x,y>) ->
word("(",<x,z>)
expression(e,<z,t>)
word(")",<t,y>) ;

rest_of_sum(p,e,<x,y>) ->
word(o,<x,z>)
op_add(o,o_a)
product(p',<z,t>)
rest_of_sum(<o_a,p,p'>,e,<t,y>) ;
rest_of_sum(e,e,<x,x>) -> ;

rest_of_product(f,p,<x,y>) ->
word(o,<x,z>)
op_mul(o,o_m)
primary(f',<z,t>)
rest_of_product(<o_m,f,f'>,p,<t,y>) ;
rest_of_product(f,f,<x,x>) -> ;

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 5

word(a,<a.x,x>) -> ;

op_add("+",add) -> ;
op_add("-",sub) -> ;

op_mul("*",mul) -> ;

" reading "

read(l) -> in_sentence(s,l);

" running the program "

run ->
outm("the expression ")
read(p)
analyze(p,e)
val(e,f)
outm(" evaluates to ")
outl(f);

analyze(p,e) -> expression(e,<p,nil>) ! ;


analyze(p,e) -> outm("... is incorrect") deadend ;

We use the predicate read which reads a sentence ending with "." and transforms it
into a list of words. For example:
>read(p) ;
12+(23-4)*5+210-34-43.
{ p=12."+"."(".23."-".4.")"."*".5."+".210."-".34."-".
43.nil}

The predicate expression constructs a syntax tree from the sentence which it has
read (if it belongs to the language). We can now communicate this tree to the
predefined rule val which calculates and prints out its value. All this is done by:
>run;
The expression 12+(23-4)*5+210-34-43.
evaluates to 240

C.2 Formal differentiation


In mathematics, differentiation is an operation which, given one algebraic
expression, derives another algebraic expression from it, called the derivative.
Expressions are constructed with numbers, the operators +, -, *, function symbols
such as sin, cos, ... and a certain number of unknowns. Differentiation concerns
these unknowns. In our example, the numbers will always be integers; we will only
use one unknown: x, and the only unary function symbols will be sin and cos. The
first part of the program is the parsing grammar for these expressions: it is an
extended version of that given in the previous example. Here it is:
" grammar of expressions "

expression(e,<x,y>) -> sum(e,<x,y>) ;

© PrologIA
Aociation Prolog
C - 6 Reference Manual HERITAGE

sum(e,<x,y>) ->
product(p,<x,z>) rest_of_sum(p,e,<z,y>);

product(p,<x,y>) ->
factor(f,<x,z>) rest_of_product(f,p,<z,y>);

factor(f,<x,y>) ->
primary(p,<x,z>) rest_of_factor(p,f,<z,y>);

primary(n,<x,y>) -> word(n,<x,y>) integer(n);


primary("x",<x,y>) -> word("x",<x,y>);
primary(<o_u,p>,<x,y>) ->
word(o,<x,z>)
op_un(o,o_u)
primary(p,<z,y>);
primary(e,<x,y>) ->
word("(",<x,z>)
expression(e,<z,t>)
word(")",<t,y>);

rest_of_sum(p,e,<x,y>) ->
word(o,<x,z>)
op_add(o,o_a)
product(p',<z,t>)
rest_of_sum(<o_a,p,p'>,e,<t,y>);
rest_of_sum(e,e,<x,x>) ->;

rest_of_product(f,p,<x,y>) ->
word(o,<x,z>)
op_mul(o,o_m)
factor(f',<z,t>)
rest_of_product(<o_m,f,f'>,p,<t,y>);
rest_of_product(f,f,<x,x>) ->;

rest_of_factor(p,f,<x,y>) ->
word(o,<x,z>)
op_exp(o,o_e)
primary(p',<z,t>)
rest_of_factor(<o_e,p,p'>,f,<t,y>);
rest_of_factor(f,f,<x,x>) ->;

word(a,<a.x,x>) ->;

op_add("+",plus) ->;
op_add("-",minus) ->;

op_mul("*",mult) ->;

op_exp("E",exp) ->;

op_un("-",minus) ->;
op_un(sin,sin) ->;
op_un(cos,cos) ->;

" differentiation rules "

derivative(x,x,1) -> ;
derivative(n,x,0) -> integer(n) ;
derivative(plus(u,v),x,plus(u',v')) ->
derivative(u,x,u')
derivative(v,x,v');

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 7

derivative(minus(u,v),x,minus(u',v')) ->
derivative(u,x,u')
derivative(v,x,v');
derivative(mult(u,v),x,plus(mult(u,v'),mult(v,u'))) ->
derivative(u,x,u')
derivative(v,x,v');
derivative(exp(u,n),x,mult(n,mult(u',exp(u,minus(n,1))))) ->
derivative(u,x,u');
derivative(minus(u),x,minus(u')) -> derivative(u,x,u');
derivative(sin(u),x,mult(u',cos(u))) -> derivative(u,x,u');
derivative(cos(u),x,minus(mult(u',sin(u)))) ->
derivative(u,x,u');

" simplification rules "

simplify(<o_b,x,y>,u) ->
simplify(x,x')
simplify(y,y')
simp(o_b,x',y',u);
simplify(<o_u,x>,u) ->
simplify(x,x')
simp(o_u,x',u);
simplify(x,x) ;

simp(plus,0,x,x) -> ;
simp(plus,x,0,x) -> ;
simp(minus,x,0,x) -> ;
simp(minus,0,x,y) -> simp(minus,x,y);
simp(mult,0,x,0) -> ;
simp(mult,x,0,0) -> ;
simp(mult,1,x,x) -> ;
simp(mult,x,1,x) -> ;
simp(exp,x,0,1) -> ;
simp(mult,minus(x),y,u) ->
simp(mult,x,y,v)
simp(minus,v,u);
simp(mult,x,minus(y),u) ->
simp(mult,x,y,v)
simp(minus,v,u);
simp(exp,x,1,x) -> ;
simp(exp,0,x,0) -> ;
simp(exp,1,x,1) -> ;
simp(o_b,x,y,u) ->
dif(o_b,exp)
integer(x)
integer(y)
evalCst(<o_b,x,y>,u);
simp(o_b,x,<o_b,u,v>,t) -> simp(o_b,x,u,z) simp(o_b,z,v,t);
simp(o_b,x,y,<o_b,x,y>) ->;
simp(minus,0,0) -> ;
simp(minus,minus(x),x) -> ;
simp(sin,0,0) -> ;
simp(cos,0,1) -> ;
simp(o_u,x,<o_u,x>) -> ;

evalCst(plus(x,y),u) -> val(x+y,u);


evalCst(minus(x,y),u) -> val(x-y,u);
evalCst(mult(x,y),u) -> val(x*y,u);

© PrologIA
Aociation Prolog
C - 8 Reference Manual HERITAGE

"reading"

read(nil) -> next_char'(".") ! in_char'(".");


read(a.b) -> in_ident(a) ! read(b);
read("+".b) -> next_char'("+") ! in_char'("+") read(b);
read("-".b) -> next_char'("-") ! in_char'("-") read(b);
read(a.b) -> in_integer(a) ! read(b);
read(a.b) -> in_char'(a) read(b);

"writing"

write(<o_b,x,y>) ->
!
op_bin(o,o_b)
outm("(")
write(x)
outm(o)
write(y)
outm(")");
write(minus(x)) -> ! outm("-") write(x);
write(<o_u,x>) -> ! op_un(o,o_u) out(o) write(x);
write(x) -> string(x) ! outm(x) ;
write(x) -> out(x);

op_bin(o,o_b) -> op_add(o,o_b);


op_bin(o,o_b) -> op_mul(o,o_b);
op_bin(o,o_b) -> op_exp(o,o_b);

" running the program "

run ->
outm("the expression ")
read(p)
analyze(p,e)
derivative(e,"x",e')
simplify(e',f)
outm("has for derivative ")
write(f)
line
!;

analyze(p,e) -> expression(e,<p,".".nil>) !;


analyze(p,e) -> outm(" ... is incorrect ") fail ;

Here, for example, is the result of analysis of an expression.


$ prolog
> insert("deriv.p2");
{}
> read(p) expression(e, <p, nil>);
3*x^2+6*x+5.
{p=3."*"."x"."^".2."+".6."*"."x"."+".5.".".nil,
e=plus(plus(mult(3,exp("x",2)),mult(6,"x")),5)}

Next we define the differentiation relation derivative(f,x,f') which means: f' is the
derivative of f with respect to x.

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 9

Since this relation gives one rule for each operator or function symbol, it can be
expressed quite naturally. For example, the derivative of the preceding expression is
given by:
> read(p) expression(e, <p, nil>) derivee(e, "x", e');
3*x2^+6*x+5.
...,
e'=plus(plus(plus(mult(3,mult(2,mult(1,exp("x",minus(2,1)))))
,
mult(exp("x",2),0)),plus(mult(6,1),mult("x",0))),0)}

Clearly, the result is still far from simple! We have therefore added a (very
incomplete) simplification program, which produces a more condensed result. This
is accomplished by the predicate run. Here is an example of its use:
>run;
the expression 3*x^2+6*x+5.
has the derivative ((6*x)+6)

>run;
the expression cos(-3*x^2+2).
has the derivative ((6*x)*sin(-(3*(x^2))+2))

C.3 Mutants
In this example we are breeding mutants, hybrid offspring of animal names. The
animals are known by their names (in French), represented as character strings.
Two animals give birth to a mutant if the end of the name of the first animal is
identical to the beginning of the name of the second.The interesting aspect of this
program is that the same relation append is used in two different ways: firstly to
join together two lists, and secondly to break up a list into two sublists.

On the next page are the results produced by the following set of animals: alligator,
tortue, caribou, ours, cheval, vache, lapin, pintade, hibou, bouquetin and chèvre.
>pretty_mutant;
alligatortue
caribours
caribouquetin
chevalligator
chevalapin
vacheval
vachevre
lapintade
hibours
hibouquetin
>

© PrologIA
Aociation Prolog
C - 10 Reference Manual HERITAGE

Here is the program:


"MUTANTS"

mutant(z) ->
animal(x)
animal(y)
append(a,b,x)
dif(b,nil)
append(b,c,y)
dif(c,nil)
append(x,c,z);

append(nil,y,y) ->;
append(e.x,y,e.z) -> append(x,y,z);

pretty_mutant(x) -> mutant(y) list_string(y,x);

animal("a"."l"."l"."i"."g"."a"."t"."o"."r".nil) ->;
animal("t"."o"."r"."t"."u"."e".nil) ->;
animal("c"."a"."r"."i"."b"."o"."u".nil) ->;
animal("o"."u"."r"."s".nil) ->;
animal("c"."h"."e"."v"."a"."l".nil) ->;
animal("v"."a"."c"."h"."e".nil) ->;
animal("l"."a"."p"."i"."n".nil) ->;
animal("p"."i"."n"."t"."a"."d"."e".nil) ->;
animal("h"."i"."b"."o"."u".nil) ->;
animal("b"."o"."u"."q"."u"."e"."t"."i"."n".nil) ->;
animal("c"."h"."e"."v"."r"."e".nil) ->;

C.4 Data base consultation by evaluating a logic


formula
In this example, we have created a data base containing individuals identified by
name, age, birthplace, and the fact that they do or do not wear glasses. All this
information is contained in assertions such as:
individu(candide,20,constantinople,no) -> ;

which indicates that the individual named Candide is 20 years old, that he was born
in Constantinople and that he doesn't wear glasses. In addition, elementary relations
(atomic formulas) can be defined from this data.

The program evaluates a logical formula which is made up of atomic formulas, the
connectors "and" and "or" and existential and universal quantifiers which apply to
typed variables. A typed variable is one that has a specific domain of values. The
type of question we can ask is:
"what are the values of x belonging to the domain D for which the property P
is true?"

this is translated by the formula :


element(x,set(x,D,P)).

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 11

For example, the question: (1) What city does mimosa live in ? is translated by the
formula:
element(x,set(x,city,lives_in(mimosa,x)))) ,

in the same way: (2) Does olive wear glasses ? is translated by:
element(x,set(x,boolean,glasses(olive,x))))

and finally: (3) What are the cities having at least one inhabitant less than 20 years
old who wears glasses ? corresponds to:
element(x,set(x,city,exist(y,name,and(lives_in(y,x),
and(years_old(y,a),
and(inferior(a,20),
glasses(y,yes)))))))).

These three questions have already been entered and can now be activated by
respond_to_all which writes the question in natural language followed by the
answers. The result is as follows (the answers computed by the machine are
preceded by " -->"):
>respond_to_all;
which city does mimosa live in ?
--> aspres_sur_buech
does olive wear glasses?
--> no
what are the cities having at least one inhabitant at least
20 years old who wears glasses ?
--> aspres_sur_buech
--> severac_le_chateau

Here is the complete program:


"(1) database"

individu(candide,20,constantinople,no) -> ;
individu(cunegonde,20,constantinople,yes) -> ;
individu(gontran,94,aspres_sur_buech,no) -> ;
individu(casimir,2,severac_le_chateau,yes) -> ;
individu(clementine,1,cucugnan,no) -> ;
individu(popeye,99,aspres_sur_buech,yes) -> ;
individu(olive,99,aspres_sur_buech,no) -> ;
individu(mimosa,1,aspres_sur_buech,yes) -> ;
individu(bip,15,pampelune,no) -> ;
individu(ignace,114,loyola,yes) -> ;
individu(balthazar,87,jerusalem,no) -> ;
individu(gaspard,96,smyrna,yes) -> ;
individu(melchior,34,kartoum,no) -> ;

"(2) definition of types"

type(x,name) -> name(x);


type(x,age) -> age(x);
type(x,city) -> city(x);
type(x,boolean) -> boolean(x);

© PrologIA
Aociation Prolog
C - 12 Reference Manual HERITAGE

name(candide) -> ;
name(cunegonde) -> ;
name(gontran) -> ;
name(casimir) -> ;
name(clementine) -> ;
name(popeye) -> ;
name(olive) -> ;
name(mimosa) -> ;
name(bip) -> ;
name(ignace) -> ;
name(balthazar) -> ;
name(gaspard) -> ;
name(melchior) -> ;

age(20) -> ;
age(94) -> ;
age(2) -> ;
age(1) -> ;
age(99) -> ;
age(15) -> ;
age(114) -> ;
age(87) -> ;
age(96) -> ;
age(34) -> ;

city(constantinople) -> ;
city(aspres_sur_buech) -> ;
city(severac_le_chateau) -> ;
city(cucugnan) -> ;
city(pampelune) -> ;
city(loyola) -> ;
city(jerusalem) -> ;
city(smyrna) -> ;
city(kartoum) -> ;

boolean(yes) -> ;
boolean(no) -> ;

"(3) list of the atomic formulas"

atomic(lives_in(x,y)) -> ;
atomic(years_old(x,y)) -> ;
atomic(glasses(x,y)) -> ;
atomic(older_than(x,y)) -> ;
atomic(inferior(x,y)) -> ;
atomic(different(x,y)) -> ;

"(4) evaluation of the atomic formulas"

lives_in(x,y) -> individu(x,a,y,b);

years_old(x,y) -> individu(x,y,v,b);

older_than(x,y) ->
individu(x,a,v,b)
individu(y,a',v',b')
val(inf(a',a),1);

glasses(x,y) -> individu(x,a,v,y);

inferior(x,y) -> val(inf(x,y),1);

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 13

different(x,y) -> dif(x,y);

"(5) evaluation of the formulas"

true(p) ->
atomic(p)
p;

true(no(p)) ->
no(true(p));

true(and(p,q)) ->
true(p)
true(q);

true(or(p,q)) ->
true(p) ;
true(or(p,q)) ->
true(q) ;

true(exist(x,t,p)) ->
type(x,t)
true(p);

true(all(x,t,p)) ->
no(true(exist(x,t,no(p))));

"(6) useful definitions"

no(p) ->
p
!
fail;
no(p) -> ;

"(7) calculation of responses"

respond_to_all ->
question(i,q)
element(y,q)
line
outm("---> ")
out(y)
line;

element(x,set(x,t,p)) ->
type(x,t)
true(p);

"(8) list of questions"

question(1,set(x,city,lives_in(mimosa,x))) ->
outm("(1) what city does mimosa live in ?");

question(2,set(x,boolean,glasses(olive,x))) ->
outm("(2) does olive wear glasses ?");

© PrologIA
Aociation Prolog
C - 14 Reference Manual HERITAGE

question(3,set(x,city,exist(y,name,and(lives_in(y,x),
and(years_old(y,a),and(inferior(a,20),glasses(y,yes))))))) ->
outm("(3) what are the cities having at least one
inhabitant")
outm("at least 20 years of age who wears glasses ?");

C.5 A brain-teaser
In this example, we have designed a program which solves a well-known
cryptarithmetic problem: how to replace each of the letters s,e,n,d,m,o,r,y by a
different digit, so that:
SEND
+ MORE
------
MONEY

If we were using conventional programming, we would have to consider two


problems simultaneously: the problem of addition and the fact that two different
letters are replaced by two different digits. With the postponed evaluation provided
by dif, these two problems can be clearly separated: the different predicate postpones
all the occurrences of dif. We then only have to program addition. The dif
eventually comes into play as we approach the solution to the problem. The
program is not only clearer, it is also more efficient . Here is the solution:
>pretty_solution;

9567
+1085
-----
10652
{}

and here is the program:


" resolution of SEND+MORE=MONEY "

solution(s.e.n.d.m.o.r.y) ->
different(s.e.n.d.m.o.r.y.nil)
sum(r1,0,0,m,0)
sum(r2,s,m,o,r1)
sum(r3,e,o,n,r2)
sum(r4,n,r,e,r3)
sum( 0,d,e,y,r4);

sum(x,0,0,x,0) -> ! remainder(x);


sum(r,x,y,z,r') ->
remainder(r)
digit(x)
digit(y)
val(add(r,add(x,y)),t)
val(div(t,10),r')
val(mod(t,10),z);

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 15

digit(0) -> ;
digit(1) -> ;
digit(2) -> ;
digit(3) -> ;
digit(4) -> ;
digit(5) -> ;
digit(6) -> ;
digit(7) -> ;
digit(8) -> ;
digit(9) -> ;

remainder(1) -> ;
remainder(0) -> ;

different(nil) -> ;
different(x.l) -> out_of(x,l) different(l);

out_of(x,nil) -> ;
out_of(x,a.l) -> dif(x,a) out_of(x,l);

pretty_solution -> solution(s) pretty_output(s) ;

pretty_output(s.e.n.d.m.o.r.y) ->
outm(" ") out(s) out(e) out(n) out(d) line
outm("+") out(m) out(o) out(r) out(e) line
outm("-----") line
out(m) out(o) out(n) out(e) out(y) line;

C.6 Constructing a path


This program lists paths without loops using the predicate freeze. Remember that
freeze postpones the execution of the literal it is applied to, for as long as a certain
variable has not been assigned a value. It is used here to create a good path, i.e. a
path which does not pass twice through the same place.

In order to do that, a possible path is calculated by the predicate path. The


postponed predicate good_list will automatically reject the path being constructed as
soon as the program attempts to adjoin a node which has already appeared. Here is
a list of paths without loops passing through Marseille, London and Los Angeles:
>good_path(l);
{l=Marseille.nil}
{l=London.nil}
{l=LosAngeles.nil}
{l=Marseille.London.nil}
{l=Marseille.London.LosAngeles.nil}
{l=Marseille.LosAngeles.nil}
{l=Marseille.LosAngeles.London.nil}
{l=London.Marseille.nil}
{l=London.Marseille.LosAngeles.nil}
{l=London.LosAngeles.nil}
{l=London.LosAngeles.Marseille.nil}

© PrologIA
Aociation Prolog
C - 16 Reference Manual HERITAGE

{l=LosAngeles.Marseille.nil}
{l=LosAngeles.Marseille.London.nil}
{l=LosAngeles.London.nil}
{l=LosAngeles.London.Marseille.nil}
>

And here is the program:


"paths without loops"

good_path(l) -> good_list(l) path(l);

path(x.nil) -> town(x);


path(x.x'.l) -> route(x,x') path(x'.l);

route(x,x') -> town(x) town(x');

town(Marseille) -> ;
town(London) -> ;
town(LosAngeles) -> ;

"lists without repetitions"

good_list(l) -> freeze(l,good_list'(l));

good_list'(nil) -> ;
good_list'(x.l) -> out_of(x,l) good_list(l);

out_of(x,l) -> freeze(l,out_of'(x,l));

out_of'(x,nil) -> ;
out_of'(x,x'.l) -> dif(x,x') out_of(x,l);

C.7 Infinite trees


Finite state automata are a good example of objects which can be represented by
infinite (rational) trees. The program presented here computes a minimal automaton
which accepts certain strings and rejects others. All these strings are made from a's
and b's. The predefined rule draw_equ(x) is used both to draw the automaton and to
minimize its size i.e. the number of its states.
> infinite;
> accepts(s,"a"."b".nil) accepts(s,"b"."a".nil)
rejects(s,"a".nil) rejects(s,"b".nil)
rejects(s,"a"."a".nil) rejects(s,"b"."b".nil)
rejects(s,"a"."a"."b".nil) rejects(s,"b"."b"."a".nil)
Peano_integer(n)
automaton_of_size(s,n)
!
draw_equ(s)
fail;

© PrologIA
Aociation Prolog

HERITAGE C.Some examples of Prolog II+ programs C - 17

x = final
/ \
aa bb
| |
y z
y = non_final
/ \
aa bb
| |
z x
z = non_final
/ \
aa bb
| |
x y

The term fail causes backtracking, to avoid the final print-out. Here is the complete
program behind all this. It must be noted that the goals accepts(s,x) and rejects(s,x)
are achieved in a completely deterministic way. This is why, to obtain the minimal
automaton, it is not necessary to have Peano_integer(n) as the first goal in the
sequence of preceding goals (to be executed).
"Acceptance"

accepts(s,nil) -> final_state(s);


accepts(s,e.x) -> arrow(s,e,s') accepts(s',x);

rejects(s,nil) -> non_final_state(s);


rejects(s,e.x) -> arrow(s,e,s') rejects(s',x);

final_state(<final,aa(s1),bb(s2)>) -> ;

non_final_state(<non_final,aa(s1),bb(s2)>) -> ;

arrow(<f,aa(s1),bb(s2)>,"a",s1) -> ;
arrow(<f,aa(s1),bb(s2)>,"b",s2) -> ;

"Computing an automaton of a given size"

automaton_of_size(s,n) -> automata_of_size(s.nil,n,nil);

automata_of_size(nil,0,l) -> ;
automata_of_size(s.l,n,l') ->
element_of(s,l')
automata_of_size(l,n,l');
automata_of_size(s.l,suc(n),l') ->
not_element_of(s,l')
arrow(s,"a",s1)
arrow(s,"b",s2)
automata_of_size(s1.s2.l,n,s.l');

element_of(s,s.l) -> ;
element_of(s,s'.l) -> dif(s,s') element_of(s,l);

not_element_of(s,nil) -> ;
not_element_of(s,s'.l) -> dif(s,s') not_element_of(s,l);

© PrologIA
Aociation Prolog
C - 18 Reference Manual HERITAGE

"Enumeration of Peano integers"

Peano_integer(0) -> ;
Peano_integer(suc(n)) -> Peano_integer(n);

© PrologIA
Aociation Prolog

HERITAGE

Appendix D
Adding predefined rules
(parasite method)

D.1 General description


D.2 Prolog rule to create the interface
D.3 Calling the external program
D.4 How to cause backtracking or send back an error

This chapter explains how to add new predefined rules to the standard set, and
describes the interface procedures. The method described is the only one working
in 16 bits mode on PC. Otherwise, a simpler method using descriptors can also be
used for the compiler (see Chapter 7 of the Reference Manual).

The external procedure may either cause backtracking, send back an error which
will then be processed by the block mechanism, or display a message defined by the
user.

The user module prouser acts as a link between Prolog and user routines written in
C. The user module fprouser links Prolog and user routines written in Fortran. It
is thus possible to use simultanesously predefined rules written in both languages.
The corresponding source files are included in the distribution volume.

D.1 General description

Remember that there are two ways of calling an external function defined in C from
Prolog:

1. Using the descriptor method (see Reference Manual section 7.6). This is
direct calling, in which the Prolog calling rule is automatically generated.

2. Using a parasite via a linking procedure defined in the user module supplied
in the kit.

When Prolog is started without specifying the initial state, the standard initial state
(file initial.po) is loaded. To add new predefined rules written in another language,
using the parasite method described here, you must:

1. Define Prolog's call to these rules in Prolog, and include it in an initial state
(in the descriptor method this step is performed automatically).

2. Define the external program in C, Fortran or any another compatible language,


and include it in the prolog Machine.

©PrologIA
Aociation Prolog
D-2 Reference Manual HERITAGE

Two links are necessary using this method:

- one between the Prolog program and the prouser module

- another between this module and the external procedure.

prolog my_rule(...) -> /?300;

switch(nb) {
...
case 300:
prouser.c my_rule(...);
break;
...}

another C module my_rule(...)


{
...
}

Let's use an example to explain the method. The first step when adding a new
predefined rule, is to decide which module to define it in. We could use a module
specially reserved for this purpose, called "Interface" for example. In the example
below, we define a new predefined rule in just such a module.

The two main steps are:

1. Define the calling rule in the "Interface" module.


module("Interface");
my_rule(x,y,z) -> /?300;
end_module("Interface");

This can be done either in a seperate source module, or directly on the Prolog
command line. You can save this module using the command:
save( ["Interface"], "Interface.mo");

This module can now be reloaded in any initial state, using the command load.
You can also directly create a new initial state using the command:
exit("new_state.po");.

In what follows, we will assume that a new initial state has been created.
new_state.po is a file containing an initial state enlarged by the calling rule
compiled by Prolog.

2. Create a new prolog Machine containing the external program.

©PrologIA
Aociation Prolog

HERITAGE D. Adding predefined rules D-3

- Write the external program using the communication procedures described in


section 7.1 of the Reference Manual, and compile it with the appropriate
compiler.

- Up-date the prouser user module (see Section D.3.) and compile it.

- Re-link the new modules with the modules constituting Prolog (see section 2.7
of the User's Manual for the exact commands to be used on your machine).

The new prolog Machine can now be used, with the initial state enlarged by the new
predefined rule.

D.2 Prolog rule to create the interface

When you call an external procedure from Prolog, the rule used has to satisfy the
following conditions:

- the rule head must be an identifier followed by arguments which are free
variables

- the rule body must contain a parasite represented by a number preceded by /?.

For example, the linking rule for find_pattern is:


sys:find_pattern(s1,s2,n) -> /?201;

The number selects the relevant external procedure (see the user_rule procedure in
the prouser.c module). For each number there is a call to a corresponding external
procedure in the C function user_rule and the Fortran function fuserrule.
Please note
Numbers less than 250 are reserved for the system (this is not checked). Numbers
greater than 250 are available to the user. We recommend using numbers between
250 and 9999 for C routines whose call is in the prouser module, numbers between
10000 and 20000 for Fortran routines (or other Fortran type languages) whose call
is in the fprouser module, and numbers greater than 20000 for 16 bits mode
routines for DOS/WINDOWS3 whose call is in the prowuser module.

D.3 Calling the external program

An external program can only be called from Prolog using the parasite method, if
the associated number and call command have been added to the user_rule
procedure in the prouser C module (or the fuserrule procedure in the fprouser
Fortran module).

Here is an extract from the text of the C function user_rule:


user_rule(nb, err, err_nb)
int nb, *err, *err_nb;
{

©PrologIA
Aociation Prolog
D-4 Reference Manual HERITAGE

*err = FALSE;
*err_nb = 0;

switch (class(num))
{
case FORTRAN_FUNCTION:
fuserrule_(&num, err, err_nb);
break;
case REAL_MODE_FUNCTION:
real_mode_user_rule(num, err, err_nb);
break;
case NORMAL_FUNCTION:
switch (nb)
{
case 201:
find_pattern(err, err_nb);
break;
...
/* add procedure calls here */
default:
*err = TRUE;
*err_nb = 500;
}
}
}

Normal termination of the external program (which is expressed by a success in


Prolog) occurs when the value of the err_nb parameter in the C function user_rule
is zero.

Depending on the nature of the external program, you can either insert it directly
into the prouser module, or write it in a separate file.

If you have written the external rules in modules other than prouser or fprouser,
you will have to compile these modules and add their names to the prolink linking
program.

As supplied to you, the prouser module establishes the call links between the
Prolog compiler and the external procedure find_pattern. This is given as an
example of how to write external rules.

Warning: The external program called find_pattern given as an example,


puts into operation the predefined rule find_pattern(s1,s2,n). If it is
modified carelessly, this may cause the rule to function incorrectly.

D.4 How to cause backtracking or send back an error


To send back an error from an external procedure, the procedure must set the
parameter err_nb of the user_rule procedure.

©PrologIA
Aociation Prolog

HERITAGE D. Adding predefined rules D-5

Important note:
From version 4.1 onwards, the err parameter has no meaning, and Prolog ignores it.
However bottom-up compatibility between the versions is still guaranteed.

If err_nb is set to a value greater than zero, a command equivalent to the Prolog
command block_exit(err_nb) is executed. To associate a message with it, add the
corresponding line in the err.txt file, in the following form
Number Text_describing_the_error

The predefined rule ms_err gives access to the message associated with a given
number in the Interface world. Error numbers less than 1000 are reserved for
Prolog, and numbers greater than 1000 are available to the user. Below is a list of
some of the error messages concerning external modules:
500 ERROR IN USER PREDEFINED RULE
501 WRONG ARGUMENT NB IN USER MODULE
502 VALUE OUT OF RANGE IN USER MODULE
503 STRING TOO LONG IN USER MODULE
520 GET-TERM : VALUE ARRAY NOT BIG ENOUGH TO CODE THE TERM
521 GET-TERM : STRING ARRAY NOT BIG ENOUGH TO CODE THE TERM
522 GET-TERM : REAL ARRAY NOT BIG ENOUGH TO CODE THE TERM
523 PUT-TERM : VALUE ARRAY INDEX OUT OF RANGE
Indicates that a value outside the possible indexes for the val_tab array corresponds
to a 'T' or 'D' type tag .
524 PUT-TERM : STRING ARRAY INDEX OUT OF RANGE
Indicates that a value outside the possible indexes for the string array corresponds
to an 'S' type tag .
525 PUT-TERM : REAL ARRAY INDEX OUT OF RANGE
Indicates that a value outside the possible indexes for the real array corresponds to
an 'R' type tag .
526 PUT-TERM : WRONG TUPLE CODING
A tuple index refers to a sequence whose first element is not an integer.
527 PUT-TERM : INVALID TYPE IN TAG ARRAY
528 PUT-TERM : PROLOG ARGUMENT IS NOT A FREE VARIABLE

Backtracking is caused when you return to Prolog with err_nb set to a negative
integer.

©PrologIA
Aociation Prolog
D-6 Reference Manual HERITAGE

©PrologIA
Aociation Prolog

HERITAGE

Appendix E
Prolog II+ characters

E.1. Presentation
E.2. ISO set: advantages and disadvantages
E.3. Host set: advantages and disadvantages
E.4 Remarks
E.5 Conventions

E.1. Presentation
Two sets of characters can be used in Prolog II+ :

• a set defined by the ISO code 8859-1.

• the host machine set.

The set is chosen at the start of the Prolog session, and this choice remains valid
until the end of the session (see User's Manual section 2.3).

There are two sets of characters, and therefore there are two internal coding modes
for these characters:

• One mode in which whatever host system is used, the internal coding is the same:
ISO 8859-1.

• A second mode in which the internal coding used is that of the host system.

Provided we are only handling characters, there is no problem. But if we want to


handle character codes, only the ISO set guarantees that the same code will be used
on all machines. For example, when using the ISO set char_code("é",x) has the
same value on Macintosh and PC, which is not the case if the host set is used.

To have two internal coding modes we must also have two types of binary file:

• Files that contain strings encoded according to the ISO code.

• Files than contain strings encoded with with host system characters.

When saving is performed, the coding chosen for the session is memorized in the
file that is created: a warning message will be displayed when a file is loaded if the
coding memorized in the binary file is not the same as the coding chosen for the
current session.

©PrologIA
Aociation Prolog
E - 2 Reference Manual HERITAGE

In addition, in ISO mode, since Prolog handles data (characters) which may not
exist on the host machine, these data must be associated with an external
representation1 (character sequence) in order to be displayed. There are two modes
for representation of accented characters not belongning to the host set:

• One mode in which they are represented by an accent_escape sequence (see


R1.31) which is very easy to read.

• Another mode in which they are represented by an octal sequence.

This mode is chosen at the start of the Prolog session, and remains valid throughout
the session (see User's Manual section 2.3).

From now on, we will distinguish between an internal representation (binary string),
which is a value in memory, and display of this data (print string), i.e. its
representation in character form on an input or output channel.

E.2. ISO set: advantages and disadvantages


The ISO set has the advantage that it guarantees module portability (sources or
binary versions) between machines. It also enables characters to be handled which
are not necessarily on the host machine (e.g. UNIX machines that use the 7 bit
ASCII set), in particular accented characters.

The disadvantage of using ISO with an extremely open language such as Prolog
which performs many data transfer and sharing operations, is the difference in
internal coding of certain data (strings) between Prolog and the external
environment. This means that a transformation has to be performed for each
external communication. In fact, the user does not always need to do this,
depending on the operation that will be performed on these data. The data may be
required:

• in ISO code.

• in host code as data (binary string).

• in host code as representations (print string).

For instance, string-handling procedures that don't need to know their meaning,
such as find_pattern which compares them, or substring which splits them,
operate independently of any particular code and thus do not need these
transformations. However, procedures that call the host system will need them.

1 The display function is an external representation (outside Prolog) and must therefore be
encoded by the host system. Prolog only handles data, i.e. the ISO codes. It is the input/output
that makes the transformation between graphic representation and internal coding.

©PrologIA
Aociation Prolog

HERITAGE E. Prolog II+ characters E - 3

To sum up, this set is satisfactory provided that procedures to transform strings
between the ISO coding and the host coding are available, and that the type of
coding assumed in Prolog communication procedures is known.

E.3. Host set: advantages and disadvantages


The advantage of the host machine set is to simplify the transition from
representation of strings in the host language to coding of the strings in Prolog II+.
It is not necessary to transform data between Prolog and the external environment.

The disadvantage of this choice is that the ASCII set is relatively restricted, and that
extended characters are not standardized on all machines, thus making the programs
non portable.

E.4. Remarks
•If the same coding is used as that of the host machine, the data element and its
representation merge, whereas if ISO coding is used the data element and its
representation may be different and the external representation may take up more
bytes in memory than the data element.

•The first half of the ISO code table is identical to the US ASCII table. If a Prolog
program does not contain extended characters, there is no point in performing
transformations between ISO and host sets.

•If the user wishes to use characters not existing on the host machine, not only must
the ISO mode be chosen, but also, for communications purposes they must be either
be transmitted in ISO or in printable form (print string).

•The ISO mode without accent_escape is like the host mode in that it reduces the
number of characters that can create ambiguity if they are preceded by the '\'
character. This mode can therefore be used in programs that contain numerous '\'
characters, to avoid having to mask them (useful for Edinburgh programs which
frequently handle identifiers or graphic_symbol contain '\' characters).

E.5. ISO mode conventions


Data shared between Prolog and external languages described in
EXTERNAL_DESCRIPTOR, must be coded in ISO.

The PRO_BIND function, used to create shared data zones dynamically, references
data which must be encoded in ISO. However its first argument which is the Prolog
name for the data zone is a host string.

©PrologIA
Aociation Prolog
E - 4 Reference Manual HERITAGE

String transfer by pipe - between Prolog and co-processes - are considered as


input/output and must therefore be host strings in printable form. The relevant
functions are send_string and receive_string.

For data transfers between Prolog and external languages or vice versa, the
following conventions apply:

get_string, put_string, get_term, put_term:


send and receive ISO strings

get_O_string, put_O_string:
have the same arguments as get_string and put_string respectively, and
function in the same way, but send and receive host strings in printable form.

Finally, here are four string translation procedures:

bin_str_iso_to_host(source,dest)2

bin_str_host_to_iso(source,dest)2
convert an ISO string into a host string and vice versa, by assimilating strings
to data (binary string). The lengths are conserved, there may be non printable
characters and the characters in the input string not existing in the output set
are replaced by '?'.

print_str_iso_to_host(source,dest)2

print_str_host_to_iso(source,dest)2
convert an ISO string into a host string and vice versa, when the host string is
the representation (printable string) of the ISO string. The lengths of the two
strings is not necessarily the same, and a character can be represented by a
four character string.

2source is the address of a memory zone containing the reference string terminated by the null
character. dest is the address of the memory zone into which Prolog will copy the resulting
string. It is up to the user to reserve the necessary space.

©PrologIA
Aociation Prolog

HERITAGE

Appendix F
Table ISO 8859-1

0 1 2 3 4 5 6 7
SP 0 @ P p
0 `
1 ! 1 A Q a q
2 " 2 B R b r
3 # 3 C S c s
4 $ 4 D T d t
5 % 5 E U e u
6 & 6 F V f v
7 ' 7 G W g w
8 ( 8 H X h x
9 ) 9 I Y i y
A * : J Z j z
B + ; K [ k {
C , < L \ l |
D - = M ] m }
E . > N ^ n ~
F / ? O _ o

8 9 A B C D E F
NBSP ° À –
D à
0
1 ¡ ± ’
A Ñ á ñ
2 ¢ 2 Â Ò â ò
3 £ 3 Ã Ó ã ó
4  ´ Ä Ô ä ô
5 µ °
A Õ °a õ
Y-
6 ¶ Æ Ö æ ö
7 § · Ç ç ÷
8 ¨ , È Ø è ø
9 ı É Ù é ù
©
A ^
ª º E U’ ê ú
B » Ë ^ ë û
« U
C ¬ 1/4 Ì Ü `i ü
D SHY 1/2 I’ Y’ í y’
^
E ® 3/4 I î
F – ¿ Ï ß ï ÿ

©PrologIA
Aociation Prolog
F - 2 Reference Manual HERITAGE

©PrologIA
Aociation Prolog

HERITAGE

PROLOG II+

Windows
USER'S MANUAL

© PrologIA
Aociation Prolog
2 Windows 3 User's Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 3

Contents

Contents.............................................................................................................3

Foreword............................................................................................................7

1. Installation Guide ...............................................................................U 1 - 1


1.0 Foreword ..................................................................................U 1 - 1
1.1 Necessary equipment and software...........................................U 1 - 1
1.1.1 To start Prolog ............................................................ U 1 - 1
1.1.2 To add extensions (standard 32 bit method)................ U 1 - 1
1.1.3 To add extensions in 16 bit code................................. U 1 - 2
1.1.4 To create and distribute applications............................ U 1 - 2
1.2 Contents of the installation kit...................................................U 1 - 2
1.2.1 Essential files for use of Prolog .................................. U 1 - 2
1.2.2 Additional files for use of Prolog................................ U 1 - 3
1.2.3 Files to add standard extensions (32 bits) ................... U 1 - 4
1.2.4 Files for the 16 bit extensions
(reserved for Windows 3) ........................................... U 1 - 5
1.2.4.1 The method for 16 bit extensions.................... U 1 - 5
1.2.4.2 Files for the 16 bits extensions........................ U 1 - 5
1.2.4.3 Examples provided.......................................... U 1 - 6
1.2.5 Example files............................................................... U 1 - 6
1.2.6 File suffix conventions................................................ U 1 - 7
1.3 Installation procedure................................................................U 1 - 7
1.4 Modification of the execution environment...............................U 1 - 8

2. Using Windows Prolog II+.................................................................U 2 - 1


2.1 Starting and leaving Prolog.......................................................U 2 - 1
2.1.1 Abbreviations, default files .......................................... U 2 - 2
2.1.2 Leaving Prolog............................................................ U 2 - 2
2.2 Spaces and default sizes............................................................U 2 - 2
2.3 Command line syntax ...............................................................U 2 - 3
2.4 Creating and executing a program...........................................U 2 - 10
2.5 Program interruption...............................................................U 2 - 11
2.6 Construction and start-up of Prolog with graphics..................U 2 - 11
2.7 Compiling and editing links....................................................U 2 - 11

© PrologIA
Aociation Prolog
4 Windows 3 User's Manual HERITAGE

3. Special features of the Windows version ......................................... U 3 - 1


3.1 Boundary values of arithmetical constants................................ U 3 - 1
3.2 Characters in the Prolog II+ syntax ......................................... U 3 - 1
3.3 How to customize an application.............................................. U 3 - 2
3.4 Modifying the Support............................................................. U 3 - 3
3.5 Extensions in 16 bit mode (reserved for Windows 3) .............. U 3 - 4
3.6. Using Prolog as a DLL............................................................ U 3 - 6

4. Communication with an application using


the DDE protocol.............................................................................. U 4 - 1
4.1 Overview of the DDE protocol................................................. U 4 - 1
4.1.1 The three identification levels of the DDE protocol ..... U 4 - 2
4.1.2 The possibilities offered by the Prolog DDE protocol. U 4 - 3
4.2 Using Prolog II+ simply as a DDE server............................... U 4 - 4
4.2.1 Initializing the Prolog II+ Server.................................U 4 - 4
4.2.2 Transmitting a request to Prolog II+ ...........................U 4 - 5
4.2.3 Executing a Prolog goal and recovering the solutions.. U 4 - 5
4.2.4 Diagram of the Prolog II+ Server................................U 4 - 7
4.2.5 Examples.....................................................................U 4 - 7
4.3 Programming a Client or Server application program in ......................
Prolog II+................................................................................ U 4 - 8
4.3.1 Programming a DDE Client application program........ U 4 - 8
4.3.2 Programming a DDE Server application program ..... U 4 - 11

5. Graphics Primitives............................................................................ U 5 - 1
5.1 Description of the graphics system .......................................... U 5 - 2
5.1.1 Events..........................................................................U 5 - 2
5.1.2 Graphics objects..........................................................U 5 - 2
5.1.3 Configuration of Prolog II+ graphics at start-up......... U 5 - 5
5.1.4 Conventions used in this chapter ................................. U 5 - 6
5.2 Window management primitives .............................................. U 5 - 7
5.2.1 Creation and deletion of a window...............................U 5 - 7
5.2.2 Configuration and manipulation of a window.............. U 5 - 9
5.2.3 Refreshing of graphics units......................................U 5 - 12
5.3 Elementary primitives for management of objects attached to ..............
a window................................................................................ U 5 - 12
5.3.1 Creation and deletion of objects................................. U 5 - 12
5.3.2 Configuration of objects............................................U 5 - 16
5.3.3 Event management.....................................................U 5 - 19

© PrologIA
Aociation Prolog

HERITAGE Introduction 5

5.4 Specific primitives for menu management...............................U 5 - 21


5.4.1 Saving and loading the menu bar............................... U 5 - 21
5.4.2 Description of a menu............................................... U 5 - 22
5.5 Drawing and writing mode......................................................U 5 - 25
5.6 Drawing and positioning.........................................................U 5 - 28
5.7 Mouse position in a graphics unit...........................................U 5 - 32
5.8 Special user input primitives ...................................................U 5 - 34
5.8.1 Button simulation...................................................... U 5 - 34
5.8.2 Display of messages with confirmation..................... U 5 - 35
5.8.3 Text editing ............................................................... U 5 - 35
5.8.4 Choice boxes............................................................. U 5 - 37
5.8.5 Choosing files........................................................... U 5 - 39
5.8.6 Choosing a node of a tree.......................................... U 5 - 40
5.9 Rules to manage structured objects.........................................U 5 - 40
5.10 Sending events to Prolog from an external object....................U 5 - 47

© PrologIA
Aociation Prolog
6 Windows 3 User's Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE Introduction 7

Foreword

Prolog II+ documentation is contained in two manuals:

- the Reference Manual gives a precise description of the language and its uses,
which applies to all implementations of Prolog II+.

- the User's Manual describes everything which applies to a specific machine or


operating system. There is a user's manual for each machine and this one concerns
the Windows version .

The user's manual explains how to carry out, on your machine, the functions
described in the reference manual.

The first chapter describes how to install Prolog on your machine.

The second chapter concerns Prolog start-up, saved state management and the file
name structure.

The third chapter describes the features which are specific to this particular version,
i.e. everything that has been added or removed in comparison with the basic version,
and also the boundary values for constants.

The fourth chapter describes how to communicate with an application, using DDE
protocol.

The last chapter describes the library of graphics primitives, which is specific to
each implementation.

In the examples given in this manual, computer output appears in "tele-type


characters" and user input appears in "italic tele-type characters".

© PrologIA
Aociation Prolog
8 Windows 3 User's Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

1. Installation Guide

1.0 Foreword
1.1 Necessary equipment and software
1.2 Contents of the installation kit
1.3 Installation procedure
1.4 Modification of the execution environment

This chapter describes how to install the Prolog II+ compiler as an application in
the Windows environment. We recommend you read the whole chapter before
installing the system.

1.0 Foreword
Prolog II+ for Windows is now a true 32 bit application running on Windows NT,
Windows 3.1 extended with the Win32s kit, and Windows 95.

If you are using Windows 3, Prolog II+ still makes it possible to add 16 bit
extensions in C, which are now located in a separate DLL, and therefore only
require the standard 16 bit SDK.

1.1 Necessary equipment and software

1.1.1 To start Prolog

The minimum configuration is a 386 PC computer with 4 Mb of memory, equipped


with Windows version 3.1 plus the Win32s kit. In fact the standard system now
would instead be Windows 95 or Windows NT.

1.1.2 To add extensions (standard 32 bit method)

If you are using 32 bit code you can use all the different resources for adding
Prolog extensions. The recommended development tool is "MicroSoft Visual C++
version 2.xx". You can also use any other compatible SDK.

© PrologIA
Aociation Prolog
U1-2 Windows User's Manual HERITAGE

1.1.3 To add extensions in 16 bit code

Only Windows 3 users can add extensions in 16 bit code, since Windows NT and
Windows 95 do not recognize the extension DLL. The only method available here
is the parasite method described in the appendix. The extension code is placed in a
DLL that Prolog loads automatically. To construct this DLL we provide a static
library containing the communication functions (get_integer etc.). It is compiled
with the "CL version 8.00" of the "MicroSoft Visual C++ version 1". You can use
any other compatible SDK.

This DLL has access to the whole of the Windows 16 bit API.

1.1.4 To create and distribute applications

To create and distribute applications, you must order the following kit:

Run Time Prolog II+ for Windows. For Windows 3, you must also redistribute
the Win32s kit.

1.2 Contents of the installation kit

Note about Windows 3

If you are using Windows 3, the first thing to do is install the supplied Win32s kit.
It has its own autonomous installation procedure, and must be redistributed "as is"
to your own customers who are use Windows 3. The "FreeCall" set supplied with
this kit will enable you to check it functions correctly.

The kit to install Prolog II+ on Windows consists of one volume containing the
following files:

1.2.1 Essential files for use of Prolog

err.txt
File containing error messages in English, consulted by Prolog when the
ms_err rule is called, if the -r option has not been used to choose a different
one. To obtain messages in French, choose the file called fr_err.txt.

fonts.usr
File defining the fonts that Prolog II+ uses in the graphics environment. The
user can modify this file before start-up, to define fonts called :ft(1), :ft(2) etc.
These fonts will be used for example by the gr_font predicate.

initial.po
File containing the supervisor's saved code.

© PrologIA
Aociation Prolog

HERITAGE Installation Guide U1-3

prolog.exe
Runnable file for the Prolog II+ development version.

1.2.2 Additional files for use of Prolog

customiz.dl_
DLL containing Prolog II+ customization resources, automatically recognized
if renamed as customiz.dll.

dde.mo
Prolog object module which must be loaded to write a client or a server
application using DDE protocol.

dessin.m2, dessin.mo
Source and object files containing the tree drawing module.

edinburg.mo
A Prolog object module which is loaded automatically when the Edinburgh
syntax is selected. It contains all built-in predicates specific to the Edinburgh
syntax.

fr_err.txt
File containing the error messages in French.

graphic.mo
Prolog object module containing all graphics primitives. This file must be
loaded to start Prolog's graphics environment.

graphstr.mo
Prolog object module which is loaded automatically by graphic environment
according to selected configuration when starting.

obdialog.mo
Prolog object module which must be loaded to use the primitive for
management of structured graphics objects: gr_dialog. Automatically loaded
by loading graphic.mo file.

prolog2.pre
Text file containing the Prolog II+ command line. Assuming this file exists,
the options it specifies replace the default options. This file is first searched
for in the current directory, and then in the directory defined in PrologDir2
environment variable. It can be edited using any text editor.

tools
Directory of tools as:

© PrologIA
Aociation Prolog
U1-4 Windows User's Manual HERITAGE

dbgbase.mo
Object module which must be reloaded, and which provides more detailed
error messages about Prolog II syntax built-in predicates.

dbgedin.mo
Object module which must be reloaded, and which provides more detailed
error messages about Edinburgh syntax built-in predicates. Can be loaded
instead of edinburg.mo.

dbggraph.mo
Object module which must be reloaded, and which provides more detailed
error messages about graphics built-in predicates. Can be loaded instead
of graphic.mo.

int_edit.mo
Prolog object module which must be reloaded (reload predicate) to be able
to use the integrated editor instead of host editor defined in PrologEdit
environment variable.

1.2.3 Files to add standard extensions (32 bits)

All the files listed below are used to reconstruct Prolog II+. The object files and the
library are essential, and constitute the final runnable: prolog32.exe.

princip.c, princip.obj
Source and object files containing the way to run the initial goal of Prolog.

proentry.c, proentry.obj
Source and object files containing the main program (WinMain). The
proentry.obj file can be replaced by a user program that uses Prolog as a sub-
program.

proext.h
C source file containing declarations of macros and structures, to be included
in user modules written in C.

prolink.bat
Command file to re-edit the Prolog II+ links to construct the runnable file. It
can be modified by the user.

prolog.def
Module description file used when linking. You must add to it the names of
any Callbacks you want to export (see SDK Windows).

prolog.lib
Library file containing the Prolog functions.

© PrologIA
Aociation Prolog

HERITAGE Installation Guide U1-5

prolog.res
Compiled file of Prolog resources.

prouser.c, prouser.obj
Source and object files for the C external interface.

use_win.h
Source file that must be included in user modules written in C, to ensure they
are compatible with the Support.

1.2.4 Files for the 16 bit extensions (reserved for Windows 3)

1.2.4.1 The method for 16 bit extensions


The 16 bit extensions are located in a DLL that can be generated using the
Windows 3 standard SDK, without modifying the 32 bit runnable. This DLL is
loaded automatically whenever an extension rule located in the reserved range is
called, and is unloaded when Prolog has terminated. It must be positioned in
compliance with the following rules:

The DLL must be in the same place as Prolog's 32 bit runnable, and it must have
the same name except for the last character, which is replaced by '-', and the
suffix which is ".DLL".

Example: c:\prolog\prolog.exe corresponds to c:\prolog\prolo-.dll

When using communication primitives with Prolog, it is useful to know that when
pointers are passed they are converted, but the pointed data is not copied. The
operation is therefore relatively efficient.

1.2.4.2 Files for the 16 bits extensions


usermpty.c
Empty extension file to be filled with your functions, which can also appear in
a separate source or static libraries. This file also provides the standard
functions for initializing and terminating the DLL, making it possible to place
your functions in it.

callpro.h
File providing the prototypes for the communication primitives to include.

callpros.lib, callprol.lib
Static library providing the link code to Prolog, available in a Small model
(callpros) and a Large model (callprol). One of the two versions must be
linked to your code.

© PrologIA
Aociation Prolog
U1-6 Windows User's Manual HERITAGE

callpro.def
File defining the DLL's standard module used by the linker. You may need to
modify this file's parameters and add your own exports. The rank numbers
do not matter, since the connection functions are recognized by their name.

userdll.mak
Example of a makefile for the DLL, to be adapted.

1.2.4.3 Examples provided


You must copy the DLLs of extensions provided as examples into the directory
containing the runnable and rename them so they will be recognized. Only one can
therefore be used at a time:

tutorial.c, tutorial.mak, tutorial.p2 -> tutorial.dll


Brief tutorial describing the mandatory rules to obey.

userfunc.c, userfunc.mak, userfunc.p2 -> userfunc.dll


Large example providing various rules making use of most of the
communication primitives.

userxtrn.c, userxtrn.mak, userxtrn.p2 -> userxtrn.dll,


An example which connects up a second 16 bit DLL and makes use of the
Windows API. It is the 16 bit version of the external object example, as
supplied in 32 bits. The sources for the loaded DLL are grouped in a sub-
directory.

1.2.5 Example files

The examples are located in the sub-directory examples in the Prolog Kit.

The following examples of Prolog programming are described in the Appendix:

automat.p2 infinite trees


database.p2 formula evaluation
deriv.p2 formal differentiation
grammar.p2 grammars
menu.p2 composition of a menu
money.p2 a puzzle
mutant.p2 mutants
path.p2 construction of a path

Other examples:
Other examples using graphic environment are given, and also self documented
sample files to add external predicates.

© PrologIA
Aociation Prolog

HERITAGE Installation Guide U1-7

1.2.6 File suffix conventions

The following conventions are used to indicate the type of file and its meaning:

.c The file contains sources written in C.

.obj The file contains object files.

.d2 The file contains only Prolog II+ macros definitions.

.m2 The file contains a Prolog II+ source module written in Prolog II
syntax.

.m2E The file contains a Prolog II+ source module written in Edinburgh
syntax.

.mo The file contains the code for a compiled Prolog module (be careful,
these files are not compatible with the system link editor, only Prolog
can use them).

.po Same as above, but these files contain a complete state (files saved
using the command exit). These are the only files that can be used as
the initial state for Prolog start-up.

.p2 This is a source file containing Prolog II+ rules written in Prolog II
syntax. It is loaded with the insert command when the current syntax
is Prolog II syntax.

.p2E This is a source file containing Prolog II+ rules written in Edinburgh
syntax. It is loaded with the consult command when the current
syntax is Edinburgh syntax.

.pex This is a source file containing Prolog commands. It must be used


with the input command.

.txt This file contains text of any type.

The files whose names end in .p2 contain the source texts for the programs given
as examples in the Appendix.

1.3 Installation procedure

The Prolog II+ distribution volume was generated by compressing a tree structure.
As soon as you are in the directory in which you wish to place the files, the loading
command can be executed as indicated in the information sheet accompanying the
distribution kit.

© PrologIA
Aociation Prolog
U1-8 Windows User's Manual HERITAGE

We recommend you create a directory reserved for Prolog, called for example
c:\prolog, and install the kit's files in it. You must then define the environment
variable used by Prolog to access these files (see section 1.4).

1.4 Modification of the execution environment

The most convenient way to use Prolog is to define the following variables in your
execution environment (autoexec.bat):

PrologDir2
This is the path used by Prolog if the following files have not been defined in
the current directory: initial.po, edinburg.mo, err.txt. The variable
concatenated to the file name must specify its complete path.

PrologEdit
Name of your command file that will start the text editor to be used by Prolog
(using the edit and editm predicates) when editing with a host machine editor.
The following command must be comprehensible for the command
interpreter:
%PrologEdit% file-name
There is no default value for this variable.
Note: In Windows3 your command file must also create at the end a file
called file.end in a directory defined by the environment variable called TEMP,
to indicate the end of editing. For example, if you want to use the DOS editor
edlin, you must write the following command file (myedit.bat):
rem begin
edlin %1
echo >> file.end
rem end

However, if you want to use the built-in editor instead of an external editor,
you must execute the following predicate:
> reload("int_edit.mo");

© PrologIA
Aociation Prolog

HERITAGE Installation Guide U1-9

© PrologIA
Aociation Prolog

HERITAGE
Aociation Prolog

HERITAGE

2. Using Windows Prolog II+

2.1 Starting and leaving Prolog


2.2 Spaces and default sizes
2.3 Command line syntax
2.4 Creating and executing a program
2.5 Program interruption
2.6 Construction and start-up of Prolog with graphics
2.7 Compiling and editing links

Prolog II+ is the compiler for an advanced version of the Prolog language. The
Windows Prolog II+ compiler enables you to load, execute, extend or interactively
modify a Prolog program.

The compiler starts with an initial state. When you leave Prolog using the command
exit, the current state of the progam is saved in a binary code file, which can be used
later as a new initial state. The initial.po file we supply is a new initial state; i.e. it
contains just a supervisor and predefined rules.

This chapter describes how to start the Windows Prolog II+ compiler, create a
program and then leave the system.

This chapter also explains how to use the other runnables in the Prolog II+ kit.

2.1 Starting and leaving Prolog

To begin a session, launch the prolog.exe Windows runnable by any convenient


means; using the Program Manager, from a shell...

To end a session, type one of these Prolog goals: quit or exit. You can also use the
Quit option in the main menu.

© PrologIA
Aociation Prolog
U2-2 Windows User's Manual HERITAGE

2.1.1 Abbreviations, default files

If no file name is given for the initial state file, the default file name is initial.po.
Below are two examples

win prolog

This command starts the compiler with an initial state initial.po, which is sought,
first using the current directory, and then using the path indicated by the
environment variable PrologDir2. An error occurs if such a file does not already
exist. The Prolog command exit saves the state of the program in the file called
prolog.po in the current directory.

win prolog myfile.po

This command starts the compiler with the initial state myfile.po. An error occurs if
such a file does not already exist.

When it starts, Prolog creates the Application window and the Console window. It
then displays its title line with some information about its configuration, and loads
the binary start-up state.

Once loading is over, Prolog waits for a command. It displays a prompt and waits
for a sequence of goals that it can execute. Prolog will function in this way until the
session is terminated using quit or exit.

2.1.2 Leaving Prolog

If you use the predefined rule quit or a menu to leave Prolog, no state will be saved.

If you use the predefined rule exit to leave Prolog, the current state is saved under
the name prolog.po.

If you use the predefined rule exit("file_name") to leave Prolog, this file-name will
always be used for the resulting saved state.

2.2 Spaces and default sizes

Prolog's work space is divided into different spaces, to which is added the name
dictionary space, designed as an independent external module. By default, the sizes
of these spaces are read in the initial binary file, unless the command line option is
used which enables the method for determining these values to be changed. Here
are the most important spaces:

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U2-3

code space
This is the space where the initial state and the code generated by the compiler
are loaded. The default size is 500 Kb. There is no limit on module size,
except that the total of all the module sizes must be less than the total space
for the code.
When rules (thus modules) are deleted, the space is automatically collected for
the rules which are not being used.

dictionary space
Dictionary of Prolog identifiers. Default size: 200Kb.

recursion stack space (stack)


Contains the local variables for the proof which is running. Default size:
100Kb. Space in this stack is not consumed during terminal recursion (please
refer to the Reference Manual; Chapter 2 -Control of program execution for
more details).

copy stack space (heap)


The Prolog II+ compiler uses a structure copying technique, making it
possible to introduce a highly effective garbage collector. The default size is
100Kb.

restoration stack space (trail)


This stack memorizes the values to be restored for backtrackings during the
current program execution. Default size: 50 Kb. The garbage collector
provides space recovery in this stack, if an overflow occurs.

space for direct calls to C


This is a work space for encoding arguments for direct calls to C functions or
procedures by the callC primitive. Default size: 1 Kb.

These default sizes can be modified, using the options on the command line or in
the prolog2.pre file.

2.3 Command line syntax

All the syntactic descriptions in this manual use square brackets [ ] for optional
elements, and curly brackets {} for elements which can be repeated any number of
times - including zero.

It is possible to store the Prolog start-up command by including it in a prolog2.pre


options file which can be placed in the current directory or in Prolog's installation
directory. If such a file exists, Prolog will process all of its options that are not
already on the command line (which therefore has priority). Only the first line is
read. All the other lines are ignored, as is the first word (program name).

© PrologIA
Aociation Prolog
U2-4 Windows User's Manual HERITAGE

The syntax of the Prolog command is


win (in MS-DOS) prolog [ parameters] [ initial_state]

The file name initial_state, written in host system syntax, denotes the state file which
is to be used to start the Prolog session. If nothing is specified, initial.po is the
default name which will be used for this file.

The parameters can be specified in any order. They modify the compiler's default
sizes and options. The list of possible parameters is as follows:
[-H] [-c n] [-C file] [-d n] [-E] [-f fv{fv}] [-h n] [-i file] [-
j file] {-m file} [-M n] [-o file] [-P parameter] [-q n] [-Q] [-r
file] [-R n] [-s n] [-t n]

Meaning of the parameters:

-H
(Help) This command line help facility displays the default configuration.

-c integer
(code) Defines the amount of space used (in Kb) for rules, static variables
and Prolog arrays.

-C file
(Compile) Compiles the source file called file, generates an object file and
leaves Prolog. The name of the object file is determined following these rules
If the option -o is simultaneously used, the name used in this option is
used;
If the source file does not contain any module, the name empty.mo is used;
If the source file contains only one module, this name of module suffixed
with .mo is used (if this module is the empty one, the name user.mo is
used;
If the source file contains several modules, the name of the source file
suffixed with .mo. is used.

-d integer
(dict.) Defines the amount of space used, in Kb, for the dictionary.

-E
(Edinburgh) activates Prolog in Edinburgh mode (see Chapter 10 of the
Reference Manual) and is equivalent to the -m edinburg.mo option.
It changes the syntax and loads the new predefined rules specific to the
Edinburgh mode. The Edinburgh mode assumes that the variable syntax is
not the Prolog syntax, and that the real number syntax is the standard syntax.
So when this option is used it modifies the values of the s, v, and r flags which
will have the respective values E, E or U, and S. This option is the last to be
processed. Therefore, if the flags s and r are specified by the -f option they
will be ignored, as will the v flag defined at P.

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U2-5

-f fv{fv}
(flags) Defines the values of various behavior options. A sequence of
character pairs defining the values of various default options. The default
option values are equivalent to the following parameter:
-f a1A0cIe0g1G0i1o1rPsSuWvPw1zU
fv{fv} is a sequence of character pairs where in each pair, the first character
defines the option, the second its value. The available options are as follows:

option possible values


a 0,1
A 0,1,c,C,d,D,h,H,s,S,t,T
c I,M
e 0,1
g 0,1
G 0,1,c,C,d,D,s,S
i 0,1
o 0,1
r P,S
s A,C,I,S
u E,F,W
v E,P,U
w 0,1,2
z U,D

a: (atoms)
Determines whether the empty prefix ("") must be automatically
assigned to non-prefixed atoms when they are positioned as
arguments:

0 These atoms will not be prefixed (assigned to the empty


prefix).

1 These atoms will be prefixed in accordance with the current


context.

A: (reallocation)
Determines whether reallocation of the relevant space must be
prohibited or permitted:
1 All reallocations are prohibited

0 All reallocations are permitted


c Reallocation of the code is prohibited (C means it is
permitted).

d Reallocation of the dictionary is prohibited (D means it is


permitted).

© PrologIA
Aociation Prolog
U2-6 Windows User's Manual HERITAGE

h Reallocation of the heap (copy stack) is prohibited (H means


it is permitted).
s Reallocation of the stack (recursion stack) is prohibited (S
means it is permitted).
t Reallocation of the trail (recursion stack) is prohibited (T
means it is permitted).

c: (character coding)
Determines the type of internal character coding:

I coding according to the ISO set 8859-1.

M coding according to the host machine set.

e: (escape mode)
Determines the mode for printing accented characters not belonging
to the host machine set. This flag only has a meaning in the ISO
coding mode. The possible values are:

0 the character is written as in a format_escape -\octal code-


(see R1.29). A useful feature of this option is that it reduces
the set of characters creating ambiguity when the "\" is written
(see R1-7).

1 the character is written as an accent_escape sequence (see


R1.29-R1.31).

g: (garbage collection information)


If the value is 1 (default value), a message is printed each time
garbage collection is performed, otherwise the message is not printed.

G: (garbage collector)
Determines whether gargabe collection in the relevant space must be
prohibited or permitted:
1 All garbage collection is prohibited.

0 All garbage collection is permitted.


c Garbage collection in the code is prohibited (C means it is
permitted).
d Garbage collection in the dictionary is prohibited (D means it
is permitted).
s Garbage collection in the stacks is prohibited (S means it is
permitted).

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U2-7

i: (interprets reading of the special character '\')


If the value is 1 (default), the character(s) following the '\' are
interpreted in a special way (e.g. the sequence \t signifies the
tabulation character). If the value is 0, the character '\' loses its status
as a special character. It is no longer possible to combine it with a
format_escape or accent_escape to represent another character,
regardless of the value of the e option.

o: (optimization)
Determines whether or not the generated code (arithmetical
instructions, comparison instructions, type tests, block, val, assign...)
is optimized. When optimization is selected, and a rule is decompiled
(for example using rule), arithmetical operations may produce a
sequence of terms which is different from the original sequence. In
the same way, when decompiling a rule using the block predicate, an
equivalent term will be shown instead of the original one. Also, the
debugger may not display certain arithmetical operations, or certain
type tests, or arguments of predicates such as val, assign and block.
The possible values are:
0 (no optimization) The program appears in its original form
when rule or the debugger are used.
1 (optimization) This is the default value. It applies to any
code produced by insert, module or assert.

r: (reals)
Determines the syntax used for reals.
P Prolog II notation. It allows simultaneous use with infixed
list notation.
S Standard notation. Reals are written in abbreviated form, and
the lists are written in square bracket notation, e.g. [1, 2, 3].

s: (string)
This option only takes effect in Edinburgh mode. The value defines
the syntactical interpretation of the lexical unit string described in
section 1.4 of the Reference Manual.

A (Atom) The unit represents an identifier. It will be prefixed in


accordance with the current reading context.
C (Character) The unit represents a list of single letter
identifiers. They will be prefixed in accordance with the
current reading context.
I (Integer) The unit represents a list of integers equal to the
respective codes (Machine or ISO depending on the chosen
option) of each character in the string.
S (String) The unit represents a Prolog character string.

© PrologIA
Aociation Prolog
U2-8 Windows User's Manual HERITAGE

u: (undefined)
Defines the result of an attempt to execute a non-defined rule. The
possible values are:
E (Error) The goal is printed, and the system stops.
F (Fail) Same behavior as the interpreter: failure.
W (Warning) A message is printed and the goal fails.

v: (variables)
Determines the syntax used for variables and identifiers.
E (Edinburgh) Edinburgh notation
P (Prolog II+) Prolog II+ notation

U (Underlined variables) Variables are only denoted by


alphanumeric sequences starting with "_". This is the basic
syntax (see Reference Manual, Chapter 1).

w: (warning)
Defines the warning for certain surprising configurations. Does not
function on messages resulting from the uW option when a called
predicate is not defined.
0 no message is given.
1 during execution, warning is given when the following
primitives are erased:
- block_exit/1 or block_exit/2 with a free variable instead of
the error number,
- load/2 or reload/2 with a demand for replacement of a non-
existent prefix,
- save/2 or kill_module/1 for a non-existent module,
- suppress/1 or suppress/2 for a non-existent rule,
- kill_array/1 for an undefined array.
2 gives the same warnings as in mode 1, and in addition
indicates:
- during compiling, the non anonymous variables which only
have one occurrence in the rule (likely to be caused by a
typing error).

z: (reading Prolog sizes)


Determines how the Prolog space sizes are defined.

U the sizes of the spaces are read in the initial binary file

D default sizes defined in chapter 3.

-h integer
(heap) Defines the amount of space, in Kb, reserved for the copy stack.

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U2-9

-i file
(Input) Defines the name of the file which the current reading unit is directed
to at start-up. By default reading is performed at the console.

-j file
Defines the name of log file created by the Prolog paper primitive (default:
"prolog.log").

-m file
(Module) Loads at start-up, after the binary state, the Prolog object module
whose name is file. If the file is not found in the current directory, the system
looks for it in the directory defined by the PrologDir2 environment variable.
If several of these options (up to 20) are used, they are processed in order of
appearance.

-M integer
Maximum response time in milliseconds for a DDE exchange, after which an
error is signaled.

-o file
(Output) Defines the name of the file which the current output unit is directed
to at start-up. By default writing is performed at the "console". The Prolog
title line still appears in the console.

-P parameter
Passes a parameter on the command line. This parameter can be recovered
from Prolog in the predefined table of character strings tab_user_param. If
an empty string is returned this means there are no more parameters to
recover. A maximum of 20 parameters can be transmitted on the command
line. Example:
prolog -P 1 -P foo
> val(tab_user_param[1], V);
{V = "1"}
> val(tab_user_param[2], V);
{V = "foo"}
> val(tab_user_param[3], V);
{V = ""}

-q integer
Defines the amount of space, in Kb, reserved for encoding the arguments of
direct calls to C procedures.

-Q
Starts Prolog in an iconic state (Quiet).

-r file
Defines the name of the error file used by Prolog (default: "err.txt"). To
obtain error messages in French, choose the file called fr_err.txt.

© PrologIA
Aociation Prolog
U 2 - 10 Windows User's Manual HERITAGE

-R integer
(Realloc) Defines the percentage size increase for automatic reallocation
(default 25).

-s integer
(stack) Defines the amount of space, in Kb, reserved for the recursion and
local variables stack.

-t integer
(trail) Defines the amount of space, in Kb, reserved for the restoration stack,
(variables restored after backtracking).

2.4 Creating and executing a program

Here is a complete example of the creation and execution of a program which


defines a small database, and starts with the basic state. $ represents the system
prompt, > represents Prolog's. For the sake of simplicity, the rule insert is used
directly without calling the editor.
$ win prolog (on DOS)
PROLOG II+ ...
... PrologIA Prolog is started with the initial
state. The only rules (or programs)
present in memory are the built-in
predicates.
>insert;
father(Jean,Marie) ->;
father(Jean,Pierre) ->;
; Here the user program is compiled.
It is now known by Prolog.
{}
>father(x,y); Execution of this program is started.

{x=Jean, y=Marie}
{x=Jean, y=Pierre}
>exit; A new binary start-up state is saved,
containing the user program.
Bye......
$

The prolog.po file has now been created, and contains a new state (built-in
predicates and your program). To start with the previous state, start Prolog again by
entering the name of the corresponding file:
$ win prolog prolog.po
PROLOG II+ ...
... PrologIA Prolog now knows the built-in
predicates and your program.
>father(Jean,y); You can start an execution.
{y=Marie}
{y=Pierre}
>quit; You now leave Prolog without
saving.
Bye......

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U 2 - 11

To save the state with another file name, use the command exit("file-name").

2.5 Program interruption

A Prolog program can be interrupted at any moment by pressing the Ctrl+Pause


command. The interruption is processed by the Prolog error mangement system
and corresponds to error 16. It can therefore be recovered by a program using the
predefined rule block (see reference manual). If the error is not recovered, Prolog
command level is reached and the message: USER INTERRUPT is displayed.

2.6 Construction and start-up of Prolog with graphics

For the first execution, run Prolog with graphic module:


C:\> win prolog -m graphic.mo

After choosing options in the control panel, you should save current state to avoid
doing it again every time you run Prolog:
> save_state("myini.po");

For following executions, you just have to run:


C:\> win prolog myini.po

2.7 Compiling and editing links


To add an extension to Prolog, you can either use the prouser.c file or create one or
more other modules. You must then recompile the module(s) and link it/them with
the Prolog library to reconstruct the prolog.exe file. This is performed by the
prolink.bat program.

prolink.bat

The prolink.bat program is used to reconstruct a Prolog runnable file that has been
modified or to which modules have been added that may contain descriptors for
external data. The prolink command has the form:
prolink ['object_modules_list'] ['descriptors_list']

object_modules_list
is a series of names of compiled object modules. These modules must be
included in the final runnable.

© PrologIA
Aociation Prolog
U 2 - 12 Windows User's Manual HERITAGE

descriptors_list
is a series of names of descriptor arrays (see Chapter 7 of the Reference
Manual) located in the object modules given as the first argument. If no
descriptor arrays have been created, the second argument can be left out.

© PrologIA
Aociation Prolog

HERITAGE Using Windows Prolog II+ U 2 - 13

© PrologIA
Aociation Prolog

HERITAGE
Aociation Prolog

HERITAGE

3. Special features of
the Windows version

3.1 Boundary values of arithmetical constants


3.2 Characters in Prolog II+ syntax
3.3 How to customize an application
3.4 Modifying the main program
3.5 Extensions in 16 bit mode
3.6. Using Prolog in a DLL form

3.1 Boundary values of arithmetical constants


Boolean values are represented by the integers 0 and 1.

Theoretically there is no limit on the values of integers manipulated in Prolog. The


values of integers used in communication with external languages are limited
between -2 147 483 648 and 2 147 483 647 (231-1); this corresponds to the long
int type in C.

The reals manipulated in Prolog correspond to the double type in C (IEEE 64 bits).
The range of values for doubles is from -1.79e308 to +1.79e308; their biggest
negative value is -2.2e-308 and the smallest positive value is +2.2e-308. Some
communication functions only accept single precision reals. The range of values for
single precision reals is from -3.4e38 to +3.4e38; their biggest negative value is
-1.2e-38 and their smallest positive value is +1.2e-38. This corresponds to the float
type in C (IEEE 32 bits).

3.2 Characters in the Prolog II+ syntax

Throughout the first chapter of the Reference Manual, the syntax described applies
more especially to the ISO set. This chapter describes a part of the syntax relating
to characters, adapted for the Windows systems. It is valid for each Prolog session
which uses the host machine's character set.

It should be noted that whereas MS-DOS uses the OEM character set, Windows
uses the ANSI set, which is virtually identical to the ISO set. So when files written
in MS-DOS containing accented characters are displayed in a window, these
characters may be replaced by black rectangles. We therefore recommend you
create text files with an editor in Windows.

© PrologIA
Aociation Prolog
U3-2 Windows User's Manual HERITAGE

big_letter = "A" | … | "Z" ;


letter = big_letter | "a" | … | "z";

digit = "0" | … | "9" ;


alpha = letter | digit | "_";
separator = "(" | ")" | "[" | "]" | "{" | "}" | "|" | "," ;
separatorP= ";" | "." | "<" | ">" ;
special_char = "%" | "'" | """ | "_" | "!" | "`" |;
special_charE = ";" ;
graphic_c = graphic_char | "\", graphic_char ;
E
graphic_char = "." | "<" | ">" ;
graphic_char = "#" | "$" | "&" | "*" | "+" | "-" | ":"
| "/" | "=" | "?" | "\" | "@" | "^" | "~"
| NBSP … ¿ |  | ÷ ;

character = letter | digit | separator |


graphic_char|special_char ;
string_char = character - ( """ | "\") | """"
| "\", format_escape ;

format_escape = "b" | "f" | "n" | "r" | "t" | "\"


| newline
| octal_digit, octal_digit, octal_digit
| ("x" | "X"), hex_digit, hex_digit ;

3.3 How to customize an application

At initialization time, the system searches for the DLL customiz.dll and loads it if it
exists in the directory which contains the executable file of Prolog. This DLL does
not contain any executable code. The purpose of this DLL is to support User
resources. The user resources will therefore be linked to this module using a
provided makefile.

The system will search for the following resources at initialization time, and if they
exist they replace the corresponding original resources:

10
is an icon resource that will be used instead of Prolog's "Column" icon to
represent the application's main window. You can also use it to represent the
application in the Application Manager window: just search for it in the
customiz.dll module instead of prolog.exe.

1, in a STRINGTABLE resource
is a character string resource that will be used as the initial title of Prolog's
main window instead of "Prolog II+". Caution, remember that in a resource
the final '\0' character must be explicit.

© PrologIA
Aociation Prolog

HERITAGE Special features of the Windows version U3-3

100
is a dialog box description resource, that can be written either by hand or
using the SDK Dialog Editor. If it is found, the "About Prolog" item in the
Application menu disappears and the "About the Application" item is enabled,
causing this "About Box" to open. It can represent whatever you like but only
one button will be recognized, and it must have the identifier 1 (IDOK).

Other user resources can be supplied, but they will not be generated automatically.
Please follow the standard Windows procedure. Two important points must always
be borne in mind:

- Your dialog function must also be exported by the Application, so make sure you
declare it in the prolog.def module,

- Your resource will be located in the customiz.dll module, not in prolog.exe.


Therefore, in all the primitives that handle your resources (DialogBox(), etc.) you
must use the hUserDLL handle provided in the prouser.c module, instead of the
Instance handle.

In the case of Windows 3 and to use resources via 16 bit extensions, it is more
suitable to link these resources directly to the extension DLL.

The userrsc.rc module supplied in the kit is an example of a customization resource


script. It was compiled and included in the file customiz.dl_ supplied in the Prolog
kit. This DLL must be renamed customiz.dll to have a demonstration of this
example.

The compilation of a customization DLL with the 16 bits SDK is a particular


procedure described in a commented section of the file userrsc.rc.

3.4 Modifying the Support

The proentry.c file contains the source for the main routine of Prolog as an
application. The routine is commented in detail and calls the following functions:
- InitializeProlog (hInstance, hPrevInstance, lpCmdLine, nCmdShow) which
will perform the initializations required to start Prolog. This function returns
0 if the initializations succeed, or an error number if an error has occurred. Its
parameters are those of the WinMain function application. It replaces the
ProStart function mentioned in Chapter 8 of the reference manual.

© PrologIA
Aociation Prolog
U3-4 Windows User's Manual HERITAGE

- StartPrologMainGoal() which will start the Prolog main goal, by calling the
promain() function from the princip.c file, whose source is already provided.
This function returns 0 if everything is OK, or an error number if an error has
occurred. The call to the StartPrologMainGoal function is not obligatory in
order to use the Prolog machine. It can be replaced by calling a user
procedure that installs its own goal and thus uses Prolog as a runtime.
However, if you feel intuitively that this procedure's task will be too long, it
must be started as described in the file, to avoid paralyzing the machine.

- TerminateProlog() which will perform the tasks required to terminate


Prolog. It replaces the ProFinal function mentioned in Chapter 8 of the
reference manual.

This file also provides the function Prolog uses to distribute each Windows
message that has been read.

3.5 Extensions in 16 bit mode (reserved for Windows 3)

In the 16 bit environment, some of the functionalities cannot be accessed. It does


not allow direct calling of C functions (via the callC predicate), the creation of
shared data zones, the use of descriptors or the use of new_pattern function and
get_formats fonction.

External procedures can only be added using the parasite method described in
Appendix D.

In the parasite linking method, a user module acts as a link between Prolog and the
user routines written in C. The parasite numbers from 20000 to 29999 are reserved
for C routines linked to this interface. This module can be developed like a standard
Windows 3 Application. Switching and control transfer are very rapid and
everything happens as if the extension was directly linked to the 32 bit application.

Complete example : adding a rule in 16 bit mode

Here is a complete example describing all the operations needed to create a new
built-in predicate, implemented by an external routine in 16 bit code.

Let us suppose that you are programming in C and that you want to add a built-in
predicate roots(a,b,c,x,y) to calculate the two real roots x and y of the equation
ax2 + bx + c = 0, if they exist, and which causes backtracking if not.
Here is the step-by-step sequence you should follow:

0. Copy the files proext.h, libentry.obj, usermpty.c, callpro.h, callpro.def,


callproS.lib, userdll.mak into your current directory. Rename usermpty.c as
roots.c. Adapt userdll.mak by assigning the SourceName macro to roots.

1. Add the following code to roots.c:

© PrologIA
Aociation Prolog

HERITAGE Special features of the Windows version U3-5

#include <math.h>
then
real_roots(perr_nb)
int *perr_nb;
{
float a, b, c, d, x1;
if ( !get_real(1, &a, perr_nb)
|| !get_real(2, &b, perr_nb)
|| !get_real(3, &c, perr_nb))
return;
if ( a == 0.)
*perr_nb = -1; /*backtrack*/
else if ( (d = b * b - 4 * a * c) < 0.)
*perr_nb = -1; /*backtrack*/
else
{
x1 = (-b + sqrt(d)) / (2 * a);
if ( ! put_real(4, x1, perr_nb) )
return;
put_real(5, -b/a - x1, perr_nb);
}
}

2. Modify the user_rule function of the roots.c file by adding the call to the new
external program. For example, give the new rule the number 20001:
user_rule(nb, err, err_nb)
int nb, *err, *err_nb;
{
*err = *err_nb = 0;

switch (nb)
{
...
case 20001:
real_roots(err_nb);
break;
...
}
}

3. Compile and edit the links:


$ nmake -f userdll.mak

4. Rename the roots.dll file as prolo-.dll and copy it into the same place as the
Prolog runnable:
$ copy roots.dll c:\prolog\prolo-.dll

5. Start a Prolog session:


$ win prolog
PROLOG II+, ...
... PrologIA
>

6. Insert the call to the external rule in the module "":


> insert;
roots(a,b,c,x,y) -> /?20001;
;
{}

© PrologIA
Aociation Prolog
U3-6 Windows User's Manual HERITAGE

>

7. Try out the new rule:


> roots(1.0e,-8.0e,15.0e,x,y);
{x=5.0e0, y=3.0e0}
> roots(+2.0e,+4.0e,+8.0e,x,y);
>

3.6. Using Prolog as a DLL


Prolog II+ is also available in the form of a 32 bit DLL (file prolog.dll) without any
environment: graphics, input/output. This DLL can be used by any Windows 32 bit
application which can also run in Windows 3 extended with API Win32s. The
Prolog DLL exports the routines described below, as well as the standard routines
described in the chapter dealing with C extensions of Prolog.

It should be noted that all these routines are exported by the DLL using the cdecl
protocol. Use of the import library (file prodll.lib) and the definition of prototypes
(file exportsw.h ) will enable you to avoid any problems in this area.

ConnectDescriptors( EXTERNAL_DESCRIPTOR * paD[] )


This routine is used to declare the descriptor array paD in the application
code. The array is written in the same way as a direct C extension and must
be persistent throughout the whole of the Prolog session that uses it (e.g.
qualified as static if it is positioned as a local variable). The declaration must
be made before the start of the session (before the call of ProStart() ).
If the argument is NULL, the descriptors will be deleted in the next session.
If the routine is called several times, the last array will be taken. The routine
returns 0 if it succeeds, -1 if it fails (session already started).
The example provided with the DLL uses a function declared in this way.

ConnectUserRule( UserRuleFunction * pfUR )


This routine is used to declare a routing function belonging to the user pfUR()
for C extensions using the parasite method. This function will play the part of
the user_rule() function in the prouser.c module. The format of this function
(the UserRuleFunction type defined in the prototypes) is imposed: it is the
same as the user_rule() function.
If the argument is NULL the currently installed routing function is deleted.
As a precaution it is necessary to delete the current function before installing
the new one. The routine returns 0 if it succeeds, -1 if it fails (replacement
refused).
The range of parasite numbers that can be installed in this way is the range
corresponding to ordinary extensions: 1 to 9999.
The mechanisms relating to the other ranges of numbers remain unchanged.
For example you can call an external function written in 16 bit mode in the
same way as the standard development version (16 bit DLL).

© PrologIA
Aociation Prolog

HERITAGE Special features of the Windows version U3-7

ConnectInString( InStringFunction * pfIS )


This routine is used to complete the DLL by adding inputs to it. This is done
by declaring a text input function pfIS() to which Prolog must submit all input
(predicates). Before such a function is installed, an empty string is returned
for each input request (therefore making the request impossible).
Replacement and deletion of this function operate in the same way as the
previous function.
The format of this function (InStringFunction type defined in the prototype
file) is imposed. Its first argument is the address of a buffer ready to receive
the text (therefore allocated), its second argument is the maximum capacity of
this buffer. The function's return code is ignored. If an error occurs it must
return an empty string in the buffer.
Internally, the function can perform any operation, even a blocking operation
(by processing events) necessary to obtain the text to return.

ConnectOutString( OutStringFunction * pfOS )


This routine is used to complete the DLL by adding outputs to it. This is
done by declaring a text output function pfOS() to which Prolog will submit
all output (predicates, messages). Before such a function is installed, no
output can be visible. Replacement and deletion of this function operate as in
the previous function.
The format of this function (OutStringFunction type defined in the prototype
file) is imposed. Its only argument is the address of a buffer containing the
text to print. The function's return code is ignored: no error is expected.
Internally, the function can perform any operation, even a blocking operation
(by processing the events) necessary to display the text. However it should be
noted that Prolog can emit empty lines, and therefore filtering may be
necessary, if message boxes are used for example.

InterruptProlog( )
This routine with no argument is used to activate a user interrupt in the Prolog
session currently being executed. It can be called at any time. The example
provided with the DLL shows how to use it to stop execution of the Prolog
predicate enum.

© PrologIA
Aociation Prolog
U3-8 Windows User's Manual HERITAGE

© PrologIA
Aociation Prolog

HERITAGE

4. Communication with an application


using the DDE protocol

4.1 Overview of the DDE protocol


4.2 Using Prolog II+ simply as a DDE server
4.3 Programming a Client or Server application program in Prolog II+

The Prolog II+ environment supports the DDE protocol and ensures portability
between Windows 32 and OS/2-PM. These new functionalities enable you to carry
out two types of operation.

- You can launch Prolog goals and recover the results from an external Client
application program, without writing any interface code.

- By loading a specific Prolog module, you can obtain a complete set of primitives
enabling you to write a DDE Client or Server application without any C extension.

4.1 Overview of the DDE protocol

This is just a very brief presentation of the DDE protocol. For more detailed
information, please refer to the chosen host system's documentation.

The DDE is a one-direction communication protocol between two application


programs called Client and Server. The communication is initiated by the Client
within the platform.

© PrologIA
Aociation Prolog
U4-2 Windows User's Manual HERITAGE

4.1.1 The three identification levels of the DDE protocol

The DDE protocol is based on identification of three levels of exchange, usually


called "Service", "Topic" and "Item". Each identifier is a text string which is
normally case sensitive and limited to approximately 255 characters. In theory it is
unique in the context fixed by the identifier of the previous level.

Service identifies a logical Server. In practice it is usually the generic name of the
Server application itself ("EXCEL", "WORD", "CLOCK", etc.). However there is
nothing to stop the Server declaring several Services, if it is capable of managing
them.

Topic indicates a topic of conversation. It is the underlying basis for opening a


DDE exchange. In practice the Topic usually depends on a specific Server, and so
the Topic and Service are implicitly linked (e.g. who else could edit the "Excel
Spreadsheet called EXAMPLE.XLS"?). However there is nothing to stop a Server
from accepting any given Topic.

The name of Item indicates a given specific object relatively to a conversation taking
place on a given Topic. Therefore in practice it is often a specific "paragraph" of the
open "document" (e.g. range "E7-K9" of the above-mentioned spreadsheet).
However it can be any entity subordinate to the Topic and compatible with the DDE
operations to be performed on it (e.g. a "Reset" signal obviously accessed for a
"Poke" operation, in a conversation on the Topic "Time" with "CLOCK").

Independently of these identifiers, a DDE exchange is characterized by the choice of


a data format. This format can be private or public and is implicitly negotiated
when the conversation is opened. It is assumed that the Client has inquired about the
formats the Server supports for the Topic in question and has chosen the richest
format that it also is capable of supporting.

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U4-3

The DDE Formalism


Logic Server
Logic Client = its Service

"Service"
TEXT only
for Prolog
(currently) "Topic 1"
Some Data
One-Way Conversation (+ Format)
"Topic 2"
Execute( Order)
"Item 1"
RequestData
HotLinkData "Item 2"
WarmLinkData
PokeData( Data) Some Other
"Item z" Data
Data for RequestData,
else Boolean ACK

"Topic n"

4.1.2 The possibilities offered by the Prolog DDE protocol

To comply with the standard programming model for Prolog II+, the general DDE
protocol has been adapted as follows:

- All exchanges take place by means of calls to primitives or else automatic calls to
goals by the system. From now on these goals will be called "callback goals". A
primitive's return value corresponds to the end of a transaction and provides the
associated status.

- The communication parameters are presented to the DDE protocol in a standard


form in Prolog II+: the text strings themselves for the identifier strings (Service,
Topic, Item) and an opaque integer for the conversation identifiers. An internal
data base performs the conversion and checks the consistency of the parameters
the user supplies.

- The capacities of the Prolog DDE are limited to "Standard Text String" data.

- When the potential Client does not specify the Service or the Topic, there should
be a negotiation stage where the Server describes what it has on offer. This sub-
protocol cannot be implemented in the form of an extendable skeleton in Prolog.
It has therefore been decided that Prolog will only accept "Wild
Connections" with a specified Topic.

© PrologIA
Aociation Prolog
U4-4 Windows User's Manual HERITAGE

- The callback goals participate in system mechanisms and therefore cause the
classic problems one would expect. This means they must be debugged in a
simulation context before they are connected, instead of "on site". Similarly the
processes they generate must be of a "reasonable" duration (to be judged
intuitively by users).

- Transmission of a data item is signaled on the basis of the Topic. Distribution to


each Client concerned by this Topic is carried out internally.

4.2 Using Prolog II+ simply as a DDE server

To use Prolog II+ as a DDE Server you must have a Client application program
capable of formulating requests that can be configured in the "Pure Text" format.
There are several ways of testing this out:

- you already have such an application program, even if it seems too big to be used
in this way,

- you can use a "Sample DDE Client" supplied with the Software Development Kit
for the host platform (e.g. the SDK from MicroSoft for Windows),

- you use another Prolog II+ programmed as a DDE Client.

4.2.1 Initializing the Prolog II+ Server

To validate the DDE Service you must call the following primitive:

ddePublishExternalEvent( _bActivate)
Activates the Service (_bActivate is 1) or deactivates it (_bActivate is 0).
Deactivation of the Service prevents any future connection, but does not
dismiss any Clients already connected. However they will be dismissed
correctly if Prolog II+ terminates prematurely.

Once Prolog II+ is validated it publishes a Service (or application name) entitled
Prolog2 under which it recognizes the Topic ExternalEvent. If a "Wild
Connection" has no Service but specifies this Topic it will also be accepted. Any
number of Clients can connect up (each using its own method) within the system's
limits.

It should be noted that when connection or any subsequent operation takes place the
Prolog II+ console does not react in any way, except in the case of an explicit
writing operation.

Once the Client has connected it is free to use standard DDE requests using the
semantics described below.

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U4-5

4.2.2 Transmitting a request to Prolog II+

There are two ways of doing this:

- You can send a Poke request to an Item called "anytext" without any additional
data (it will be ignored if present). An extern_event( "anytext", 0, 0) event is
placed in the Prolog II+ event queue, which can be read by the graphic module's
get_event/3 predicate.

- You can send an Execute request (the Item parameter does not exist) with a
prolog_goal. The transmitted goal is placed in Prolog II+'s execution queue and
will be launched in an asynchronous manner by the machine. When the request
succeeds this means the transmission has succeeded, not the transmitted
goal. Here we do not consider the recovery of solutions.

Any Prolog error messages are shown in the current output unit (by default the
console), and are not transmitted to the Client. The unification of the transmitted
goal's variables does not produce any trace. Only explicit writing will be visible.

Limit. The prolog_goal data item is limited to 32,767 characters and must take the
form of a unique goal (not a sequence or list of goals), complying with the current
syntax, otherwise an error is generated.

Examples: answers from the Prolog II+ console to some requests:

- Poke request on the Item "Lily was here" with the data item "You won't see me":
> get_event( 0, x, y);
{ x=extern_event( "Lily was here", 0, 0), y=0 }
>

- Execute request with the data item "please( "answer me")":


-> please/1 : CALL TO UNDEFINED RULE
>

- Execute request with the data item "enum( i, 15)":


> (nothing visible happens)

- Execute request with the data item "outml( "Hello ")":


Hello
> (but no display of {} )

4.2.3 Executing a Prolog goal and recovering the solutions

The data item transmitted by the Execute request accepts a second syntax, which can
be described as follows:

prolog_goal, Index, identifier where:


prolog_goal obeys the constraints described above,
Index is the number based on 1 of the argument of prolog_goal to recover,

© PrologIA
Aociation Prolog
U4-6 Windows User's Manual HERITAGE

identifier has the syntax of an abbreviated Prolog identifier (no prefix) and will
designate the solution.

When the goal executes the value assigned to the designated argument will be
converted into a character string and associated with its identifier. If the goal fails or
generates an error, the value assigned to the solution will be "*Failure" or "*Error
nnn" respectively, where nnn is the Prolog error code. The Client can recover the
solution(s) in two ways:

- By sending a Request request to the Identifier Item after execution of the goal.
The returned value is that of the last current solution of the goal the identifier is
associated with, in the previously described conditions. The problem is that there
is no method of automatic synchronization making it possible to find out whether
the goal has been executed. If it has not been executed the request fails, unless
the identifier used already contains the solution for another goal launched
beforehand. The second problem is that only the last solution is recovered.

- By sending a HotLink or Advise request to the Identifier Item before execution of


the goal. When the goal associated with the identifier is executed, each solution
(in the previous sense) is transmitted to the Client as an update of the Item. The
advantage of this method is that synchronization is semi-implicit; and so it is very
suitable for a Client with an event-driven structure. It should be noted that if the
Client wants to differentiate between the last solution and the others, the called
goal must be encapsulated so as to transmit a solution that can be differentiated.
When the Client has obtained satisfaction it can cancel the link (Unadvise
request).

Remarks

- If the Prolog II+ Server is requested by several Clients, the transmitted goals are
stocked in chronological order, and their only link with their author is the
specified identifier. This characteristic makes it possible to share data between
Clients, with or without their consent. When an application is based on several
application programs, it is advisable to choose with care the identifiers used.

- If one of the Clients transmits the goal quit or any goal that has a side effect,
Prolog II+ executes it without considering the interests of the other Clients. For
example, a tool that periodically attempts to connect with Prolog II+ to launch a
Execute( quit) request on it would constitute a veritable anti-Prolog vaccine.

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U4-7

4.2.4 Diagram of the Prolog II+ Server

This diagram should be compared with the more general diagram given above.

Logic Server:
Logic Client The "PROLOG" DDE Service Automatic Service

"Prolog2"

One-Way Conversation (TEXT)


"ExternalEvent"
Execute( "Goal, Arg, Number") Goals
Queue
RequestData "LastResultNumber"

HotLinkData "AnyResultNumber"
Execute
PokeData() "Anything"
Data for RequestData, ExternEvent( "Anything")
else Boolean ACK
Events
Queue

get_event()

4.2.5 Examples

- The Execute request with the data item 'eq(production, x), 2, my_var' succeeds
and associates the value of x (here production) with the identifier my_var in the
interface.

- The Execute request with the data item 'eq(production, x), 1, my_atom' succeeds.

- The Request request for the Item my_var succeeds and returns production

- The Request request for the Item my_atom' succeeds and returns production (1st
argument).

- The Execute request with the data item 'arg2( X, Y, Z), 3, my_arg' succeeds, but
the message:
-> <v33> : BAD ARGUMENT TYPE
is displayed in the Prolog II+ console

- The Request request for the Item my_arg succeeds and returns *Error 253

- The request Advise (or HotLinkData) for the Item enumerate succeeds.

© PrologIA
Aociation Prolog
U4-8 Windows User's Manual HERITAGE

- The Execute request with the data item 'enum( i, 5), 1, enumerate ' succeeds and
the Client receives 1, 2, 3, 4, 5 in succession.

- The Request request for the Item enumerate succeeds and returns 5.

4.3 Programming a Client or Server application program in


Prolog II+

In both cases you must load the "dde.mo" module, which installs the DDE
primitives. To cancel installation call the following primitive:

ddeCleanup/0
Terminates all the conversations and Services in progress and removes all the
Prolog primitives relating to the DDE. This primitive is not the right way to
end the DDE activity of a Client or Server application program. It should only
be used afterwards.

Depending on the performance of the system and application programs, time-out


problems may occur, generating a Prolog error. Although the general time-out
period of 3 seconds is already ample, it can be increased using the -M tttt command
line option, where tttt is the duration in milliseconds. This value should be
determined by testing. Its boundary values are 200 and 15,000 ms.

The following sections examine the two modes separately, but there is nothing to
stop an application from being a Client and Server simultaneously, in different
conversations. However when writing it you must take great care with management
of conversation numbers and with the DDE identifiers used. The following primitive
will be of great assistance in this task:

ddeRememberDatabase( _xData)
Enumerates the current Services and conversations and unifies them with the
argument _xData. It has the following format:
dde_I_serve(_tService) for Services (therefore the Server only),
dde_I_am_Client(_hConversation, _tTopic) or
dde_I_am_Server(_hConversation, _tTopic,) for the conversations.

4.3.1 Programming a DDE Client application program

DDE transactions are initiated by the Client, but some of them also take the form of
asynchronous notifications from the Server. The system assumes the Client takes
account of them and adapts its behavior accordingly. Similarly, the system assumes
the Client knows how to use the Server it wants to use. It may also be necessary for
the Client to start the required Server application program.

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U4-9

Connection and disconnection primitives

ddeDeclareAsClient( _xService, _tTopic, _hConversation)


Attempts to open a conversation on the Topic specified by the character string
_tTopic with the logic Server specified by the character string _xService or
any other server if _xService is nil. If the conversation is opened, the
_hConversation argument unifies with a unique value (opaque integer)
identifying this conversation for any subsequent operation. If no server is
found an error is signaled. If there are several candidate servers, the first
answer will be selected.

ddeEndConversation( _hConversation)
Ends the conversation designated by_hConversation by dismissing the
Server. If _hConversation is a free variable, ends by enumerating
(backtracking) all the current conversations by unifying _hConversation with
the relevant conversation. If the designated conversation does not exist, the
unification fails. Use of this primitive is natural for the Client.

Request transmission primitive

ddeTransmitRequest( _hConversation, _xRequest)


This primitive makes the request _xRequest to the Server linked to the
conversation _hConversation in a synchronous manner. The termination
status of this primitive (success or error) is linked to that of the request. The
system recognizes the following requests:

- ddeRequestData(_tItem, _xValue) makes a standard Request requested for


the data item named by the string _tItem, and attempts to unify the
resulting Prolog text string with the value of _xValue.
- ddeWarmLinkData(_tItem, ddeOpen) or
ddeWarmLinkData(_tItem, ddeClose): makes a standard Advise request for
the data item named by the string _tItem, requesting a subscription
advising it if this data item is modified (warm link), or canceling this
subscription.
- ddeHotLinkData(_tItem, ddeOpen) or
ddeHotLinkData(_tItem, ddeClose): makes a standard Advise request for the
data item named by the string _tItem, requesting a subscription providing
automatic update of this data item (hot link) or canceling this
subscription.
- ddePokeData(_tItem, _xData): makes a standard Poke request for the item
named by the string _tItem, therefore sending the Server the data item
_xData, which is either a text string or nil (simple signal without attached
data).
- ddeExecute(_xArgument): makes a standard Execute request to the Server,
sending it a text command contained in the string _xArgument.

© PrologIA
Aociation Prolog
U 4 - 10 Windows User's Manual HERITAGE

Callback goals

The callback goals (predefined names) are in the global module and have the prefix
"". The user writes them and the system calls them. They are therefore subject to
constraints depending on the system programming. The following rules should be
borne in mind:

- Callback goals can perform backtracking, but the transmitted request will be
validated (assuming it requires validation) if there is at least one solution.

- Callback goals should not execute abnormally large processes (to be judged by the
user), and certainly not processes interacting with the user including modal
stages. There is a risk of a time-out, or even of a defensive reaction from the
system.

- This means that the callback goals cannot be debugged on site. They must be
debugged using a simulator.

:ddeCbServerClosing( _hConversation)
Indicates that the Server has prematurely terminated the conversation
_hConversation for whatever reason. The termination status of its processing
does not affect the result transmitted to the server. The value of
_hConversation must from now on be considered invalid and recyclable
(therefore ddeEndConversation( _hConversation) will fail if it is attempted).

:ddeCbServerUpdate( _hConversation, _tItem, _xArgument)


Following an Advise request, advises of a change in the value of the item the
Client had subscribed to for the conversation _hConversation. This Item is
designated by the character string _tItem. The new value is either transmitted
in _xArgument (hot link) or available for a future ddeRequestData request
(warm link). In the latter case _xArgument is nil. This goal's termination status
has no significance and no effect on the result transmitted to the server.

Example

The following scenario describes in Prolog a dialog with a clock Server.


> load( "dde.mo") ;
{}
> insert; % Minimum code required to follow the dialog
ddeCbServerUpdate( _hC, "Now", "24:00:00") ->
ddeTransmitRequest( _hC, ddeExecute,
"Close") ! ;
ddeCbServerUpdate( _, "Now", _tTime) ->
outm( "\tIt is ") outml( _tTime) ;
ddeCbServerClosing( _) ->
outml( "\t\tEnd !") ;
;
{}
> ddeDeclareAsClient( "Time", nil, _hC);
{ _hC=1 }
> ddeTransmitRequest( 1, ddeRequestData("Now", _t));

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U 4 - 11

{ _t="15:20:33" }
> ddeTransmitRequest( 1, ddePokeData("Now", "23:59:30"));
{}
> ddeTransmitRequest( 1, ddeHotLinkData("Now", ddeOpen));
{}
It is 23:59:55
It is 23:59:56
It is 23:59:57
It is 23:59:58
It is 23:59:59
End !
> ddeEndConversation( 1); % Failure, number 1 is out-of date
>

4.3.2 Programming a DDE Server application program

There are more restrictions on this mode, because a Server must be at the complete
disposal of Clients, and also avoid any conflicts of interest with other Servers. So
the first and most important step is to formally define all the commands it can
receive, and give them appropriate names. The instructions on how to use it must be
very comprehensive.

Declaration primitive

ddeDeclareAsServer( <_nMode, _tService> )


Declares the DDE Service named by the character string _tService (if the
value of _nMode is ddeOpen ) or deletes it (if _nMode's value is ddeClose).
If _tService is a free variable and the value of _nMode is ddeClose, terminates
each declared Service (backtracking) and unifies it with _tService. When a
Service is deleted all the Clients connected to it are abruptly dismissed. This
should be avoided by first terminating all the relevant conversations.

Connection and disconnection primitives

ddeAcceptClient( _tService, _tTopic, _hConversation)


Accepts the Client's request during connection. This primitive must be called
during execution of the callback goal ddeCbClientWantsServer/2. The
arguments _tService and _tTopic are character strings transmitted by this
callback goal. Provided no system problem arises, the argument
_hConversation will be unified with a unique integer value identifying this
conversation for any subsequent operations.

ddeEndConversation( _hConversation)
Terminates the _hConversation by dismissing the Client. If _hConversation
is a free variable this primitive terminates all the current conversations by
enumeration and unifies _hConversation with the relevant conversations. Use
of this primitive is natural for the Client. Although the Server can use this
primitive it is not recommended. It would only be necessary to use if a
problem arises.

© PrologIA
Aociation Prolog
U 4 - 12 Windows User's Manual HERITAGE

Primitive for transmitting data to the Clients

ddeTransmitData( _tTopic, _tItem, _xNewValue)


- Must be called when requested by a Client, and therefore during execution
of the callback goal ddeCbClientRequest/2 for a ddeRequestData request, to
transmit _xNewValue, the new value of the Item _tItem.
- The call can be initiated by the Server to transmit either the new value
_xNewValue of the Item _tItem (hot link) or to advise Clients who have
subscribed to the modified Item (warm link). In the latter case the
_xNewValue argument is ignored. The decision to advise on the basis of the
_tTopic Topic instead of to each Client concerned is imposed by
implementation constraints. The internal data base ensures the notifications
are distributed correctly.

Callback goals

Same remarks as for the Client mode

:ddeCbClientWantsServer( _xService, _tTopic)


Advises that a Client has requested connection for the Topic designated by the
character string _tTopic, with the logic Server designated by the character
string _xService, unless the value of _xService is nil which means the Client
has no preference. To establish this conversation the Server must execute this
goal, and during this operation execute the primitive ddeAcceptClient/3.
Otherwise (error or failure) the Client is expelled. In theory the Client should
not have to insist, and so if the Server rejects the request, this is a definitive
rejection.

:ddeCbClientRequest( _hConversation, _xRequest)


Advises the Client's _xRequest request in the conditions linked to the
conversation _hConversation, and waits for the answer in synchronous
manner. This goal's termination status determines that of the request. A
Prolog error will have the same effect here as a failure. The system
recognizes the following requests:

- ddeRequestData(_xArgument): advises a standard Request request for the


data item named by the string _xArgument, and waits for the Server to
execute the primitive ddeTransmitData/3 that passes its new value during
execution of the goal,
- ddeWarmLinkData(_tItem, ddeOpen) or
ddeWarmLinkData(_tItem, ddeClose): advises a standard Advise request for
the data item named by the character string _tItem, requesting a
subscription for advising on this data item (warm link) or cancellation of
this subscription. The system assumes that the Server records this
information to modify its subsequent behavior,

© PrologIA
Aociation Prolog

HERITAGE Communication with an application, using DDE protocol U 4 - 13

- ddeHotLinkData(_tItem, ddeOpen) or
ddeHotLinkData(_tItem, ddeClose): advises a standard Advise request for
the data item named by the string _tItem, requesting a subscription to
automatic update of this data item (hot link) or cancellation of this
subscription. The system assumes that Server records this information to
modify its subsequent behavior,
- ddePokeData(_tItem, _xValue): advises a standard Poke request for the Item
named by the string _tItem, therefore sending the data item _xValue
(Prolog text string) to the Server, or else a simple signal without any
attached data. In this case the value of _xValue is nil,
- ddeExecute(_xArgument): advises a standard Execute request to the Server
passing it a pre-agreed text message contained in the string _xArgument,
that the system assumes the Server understands and executes in a
synchronous manner. Its status must determine whether or not the
message succeeds,
- ddeClose: advises of the disconnection of the Client. The internal data base
is automatically updated and the system assumes that the Server updates
its own data, if any. This notification takes place after the event, and the
goal's termination status has no effect.

Example

Let's imagine that the Server is the fridge in a restaurant. It has to manage the stock
of different dishes, eaten in a random manner. It has to communicate the quantity of
each dish that is available and subtract the quantity eaten. It must warn the
restaurant when stocks run low and then be able to produce on request a list of the
dishes to be restocked. Finally, its must be able to record a delivery.

We define the name of the Service: Fridge.

We define the names of the Topics:


Boss, reserved for the restaurant manager,
Waiter, for the waiters in the restaurant.

The items will be the names of the dishes associated with an available quantity, in an
internal data base. An item called "Rupture" that only the Boss can access enables
him to obtain the list of dishes with a stock of less than 5. The boss can interrogate
it using Request and/or subscribe to it. He will then receive the up-to-date list each
time a dish is eaten in the restaurant. Only the boss is authorized to supply the
Fridge with an Execute request passing a list of figures. He also has access to all
the authorized operations for the waiters in the restaurant.

The program for this example is given in the file called ddefrigo.p2 of the kit. You
will notice that it is much bigger than the previous one. To use it in an interesting
way, it is best to have several Client application programs (approximately 3) that can
(easily) use random DDE Identifiers. If other Prolog instances are used as Clients,
a file called ddecligo.p2 in the kit provides simplified commands adapted for this
example. In all cases, launch the to_begin rule to start these programs. They then
list their instructions for use.

© PrologIA
Aociation Prolog
U 4 - 14 Windows User's Manual HERITAGE

We suggest the following manipulations:

- First of all fill the fridge, initially empty. For example the boss launches an
Execute request for the string : "4 Rabbit, 15 Chicken, 7 Apple Crumble, end" ,

- Try to connect a second boss, especially if the first one is already subscribed to
Rupture,

- Try to obtain a dish that is not available, e.g. Poke request of "dish name, -1",

- Check that the boss is advised when stocks dwindle,

- ...

© PrologIA
Aociation Prolog

HERITAGE

5. Graphics Primitives

5.1 Description of the graphics system


5.2 Window management primitives
5.3 Elementary primitives for management of objects attached to a window
5.4 Specific primitives for menu management
5.5 Drawing and writing mode
5.6 Drawing and positioning
5.7 Mouse position in a graphics area
5.8 Special user input primitives
5.9 Rules to manage structured objects
5.10 Sending events to Prolog from an external object

The Prolog II+ system comprises an asynchronous event management system.


This system enables the environment (windows, menus, etc.) to function, without
obliging you to reorganize the program in the form of an event management loop.
Most events - such as re-sizing of a window, scrolling in text windows, etc - are
managed automatically. You can associate Prolog procedures with certain events,
such as menu selection or refreshing of a graphics window. Events such as mouse
clicking or keyboard input can be tested by a program, so that the program can be
made to react accordingly.

The Prolog II+ graphics primitives also enable you to create panels, which act as
supports for other types of graphics object. The primitives to create and manipulate
objects only act upon Prolog objects. All these objects must be created by means of
Prolog predicates only, without using external tools (e.g. a screen generator).
However, the event management primitives can also manipulate events affecting
objects outside Prolog.

The descriptions of the different environments have been grouped in a single


document, to highlight the differences that still exist between these environments.

A  sign in the margin indicates a primitive or feature that is specific to Macintosh.

A s sign indicates new primitives now available under Window3, OS/2-PM and
Motif1 . These primitives are not yet implemented on Macintosh.

If you want to port your programs to other configurations, you should not use these
marked rules, which are specific to a machine or environment.

1 Prolog II+ graphics under the Motif environment were developed in collaboration with
Digital Equipment Corporation.
Aociation Prolog
U5-2 Windows User's Manual HERITAGE

5.1 Description of the graphics system


This chapter describes a library of primitives which are used to create graphics
interfaces. It assumes you are used to manipulating multi-window environments
and their tool boxes, and that you are familiar with the characteristics of the host
machine's graphics environment. The general graphic display characteristics, the
behavior of windows and graphics objects, and manipulation of the mouse are all
specific to the host machine. For all information concerning these topics, please
refer to the corresponding manual.

From the point of view of Prolog, all the graphics effects produced must be
considered as side effects. In particular, a drawn object is never erased in
backtracking. Similarly, the position of the writing point is a global variable.

5.1.1 Events

Events are caused by physical interruptions generated by the keyboard or mouse.


They are processed at one set of levels (operating system, graphics system, etc.) and
then distributed to another set of levels (…final user). We are interested in the
events that reach Prolog.

Some Prolog graphics objects are sensitive to events, and transmit them to the
Prolog programmer who can choose between three different processes:
- immediate processing by attaching a Prolog program to the object;
- automatic addition to the Prolog events queue, for subsequent processing;
- nothing.

5.1.2 Graphics objects

First, let's look at the main graphics objects; windows. Windows may or may not
have a frame, a title bar and menus. They can be re-sized, given icons and made
invisible. Text windows can have horizontal or vertical scroll bars, and their
contents can be saved.

There are four types of window, with different characteristics and functions.

EDIT windows
These are text windows for text editing. Their contents can be modified
directly using the keyboard, the mouse and the menus, and also by program
using Prolog input/output. The writing point is at the end of the text. The
reading point is initially at the top of the window, and is then at the last read
position. It should be noted that when reading is requested, Prolog copies a
whole line into a buffer.
These windows have limited capacity. Manipulations that increase the size of
the text beyond this limit will be ignored.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U5-3

FRAMEPANEL windows
These windows are empty. Their only function is to receive objects. They do
not have a drawable or editable part.

GRAPHICS windows
These windows are for drawings. They are affected by keyboard and mouse
actions, and can receive objects. Standard methods can be used to insert text
into them. By default, the bitmap image is not saved and so refreshing is not
guaranteed. They can receive a bitmap to enable automatic redrawing.
To maintain compatibility, the MODAL type still exists, as a sub-set of the
GRAPHICS type, and denotes GRAPHICS windows that have the MODAL
attribute. This attribute gives the window input focus, which restricts user
events to this window only and makes input in this window mandatory.
By convention, primitives which only have an effect in a GRAPHICS window
have the prefix gr_.

TTY windows
These are text windows operating in write and read modes, always at the end
of the window. They produce a trace or listing and function like terminals, i.e.
everything displayed is non modifiable and input is in line mode, so that
provided the input line has not been finished it can be modified.
These windows have a limited capacity. If necessary, automatic truncation is
performed at the top of the window.

Let's now look at the other objects. They are designed to be placed on a window,
called the parent window. They move with their parent and cannot exist once it has
been deleted. Their size and position are defined by coordinates relating to the top
inner left-hand corner of the parent.

What happens if the size of the parent window changes?

To determine the behavior of an object when the size of its parent changes, we can
define the attachment of the object to an edge of the parent window:
When an object is attached to one edge of the parent, this means that the
distance (defined when the attachment is created) between the edge and the
object is constant regardless of the changes in the parent's size.

Please note that:


- an object is always attached in two directions (a minimum of one edge for
each direction). The default values are the top edge and the left-hand edge.
- an object whose size is not fixed by the system can be attached to two
sides for a single direction. This means that the object will be re-sized at
the same time as its parent.

© PrologIA
Aociation Prolog
U5-4 Windows User's Manual HERITAGE

The following objects must have a parent:

Check button:
Two-state button. When activated it changes state and generates an event .

Push button:
Push button which generates an event when activated.

Radio button:
Exclusive two-state choice button. Radio buttons are organized in groups,
only one of which can be selected at a time. In particular, as soon as a button
in the group is activated it generates an event, and deselects the previously
selected button. When created, by default the first button in the group is
selected.

Drawing area:
Graphics zone designed for drawing, sensitive to keyboard and mouse
actions. It can contain text, entered by means of the normal writing methods.
By default the bitmap image is not saved, but the zone can be equipped with a
bitmap to provide automatic redrawing. The primitives prefixed by gr_ take
effect in this zone if it has been defined beforehand as the current graphics
zone (see gr_window).

Editfield:
Single or multi-line editing field. It generates an event when a character is
typed or when input focus is lost or obtained.

Label:
Non editable text zone, not affected by events. Is used only to display a text
whose redrawing is managed automatically.

Listbox:
List of items written in a rectangle, with a vertical scroll bar. Each item can
take two values: selected or not selected. Each time an item in the list box is
selected, an event is generated.

Popup menu:
Pulldown menu:
A menu groups a series of vertically arranged items. An item can either be a
terminal or a menu, in which case it is called a hierarchical menu. When a
terminal item is selected in the menu, an event is generated and the menu
disappears. There are two separate types of menu which differ because of the
way they are activated and the characteristics of the windows they can be
attached to.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U5-5

A popup menu can be attached to any window unit. A popup menu is


activated when the mouse cursor is in the window, either by pressing the
mouse's menu button on a multi-button mouse, or by pressing the option key
and the mouse button on a single-button mouse. The menu is displayed
under the mouse cursor.
One or more pulldown menus can be attached to any window unit that has a
title bar (not suitable for frame windows). The menu title is then inserted in
the window menu bar and the menu is activated by clicking on its title. The
list of items is then pulled down beneath. It should be noted that the menu
title is not a menu item.

Scrollbar:
Scroll bar with a scroll box (rectangle that moves in the bar) whose position
represents a location comprised in the range represented by the scroll bar. It
can be used as a gauge. Each time the scroll bar is activated, it generates an
event.

5.1.3 Configuration of Prolog II+ graphics at start-up.

When Prolog starts, it has a menu bar and three predefined windows, one of which
is visible.
The visible window is the TTY type console window, which is by default the
current reading and writing unit. The reading and writing units can be
changed by the input and output primitives respectively.

The other two windows are:


- the GRAPHICS type "graphic" window. By default, it is the current
graphics unit, i.e. the unit in which primitives prefixed by gr_ can be applied.
The graphics unit can be changed using the gr_window primitive.
- the TTY type "trace" window, used in debug or trace mode.

The menu bar has the following predefined menus:


- the File menu is used to create editing windows and leave Prolog.
- the Windows menu is used to display or hide existing windows.
- the Control menu is used to generate user interrupts, to get into debug mode,
and to rapidly execute certain Prolog built-in predicates.
- the Tools menu is used to activate a number of tools.
- various host system menus.

Below is a list of some very basic graphics primitives.

init_screen
initializes graphics mode. This predicate is automatically started when the
graphic.mo module is loaded.

© PrologIA
Aociation Prolog
U5-6 Windows User's Manual HERITAGE

end_screen
de-installs graphics mode, i.e. it closes the windows, cancels the menus and
suppresses access to the graphics predicates.

get_screen(x,y)
get_screen(x,y,N)
x and y are unified with the width and height of the screenr espectively, in
pixels. In the three argument version, N is unfied with 1 if the screen only has
two colors (black and white), or otherwise with a higher number.

graphic_system(s)
Unifies s with a character string that varies depending on the host graphics
system:"M" for Motif, "W" for Windows3, "P" for Presentation Manager.

The file int_edit.mo enables you to use the built-in editor by means of the edit and
editm predicates, instead of the editor defined by the environment variable
PrologEdit. To do this, you must execute the following goals:
> reload("int_edit.mo");
> exit("initial.po"); (if you want to avoid having to repeat the
previous command the next time Prolog starts).

5.1.4 Conventions used in this chapter

In all the following rules, x and y stand for horizontal (x) and vertical (y)
coordinates. The direction of the x's positive axis is to the right. The direction of
the y's positive axis is downwards. Remember that the default origin (i.e. x=0, y=0)
coincides with the top inside left-hand corner of the reference element. The
reference element is the current graphics window for drawing, the parent window for
an object which is not a window, and the screen for a window.

The x and y oordinates can be expressed by integers or real numbers.

Variables starting with r will represent trees defining a rectangle. These trees must
have one of the following forms:
<x1,y1>.<x2,y2> or <x1,y1,x2,y2>
where x1,y1 are the coordinates of the top left-hand corner, and x2,y2 are those of
the bottom right-hand corner.

The term boolean will refer to an integer that takes the values 0 or 1 and is used as a
truth value for a property (object visibility etc.).

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U5-7

You can name an object using a string, and this identification can be used for all the
primitives used to create and manage objects. You can also allow Prolog to assign
the object a default identification (this will be an integer) when it is created (leaving
one free variable). This identification can be used subsequently for all the object
management primitives. Or else, for objects that are not windows you can name
them using an identifier that will be valid for all the primitives affecting these
objects.

5.2 Window management primitives

5.2.1 Creation and deletion of a window

new_window(s,t)
s new_window(s,t,s')
new_window(s,t,v,r)
s new_window(s,t,v,s',r)
new_window(s,t,v,x1,y1,x2,y2)
s new_window(s,t,v,s',x1,y1,x2,y2)
These rules create a new window, and a new I/O unit called s of type t. The
name must not have been used already for existing units, and it can be a
string. If s is a free variable when the call is made, it will be unified with a
window identification provided by Prolog.
The character string s' is displayed in title bar of the window. If s' is not
specified, s is displayed.
v is a boolean (1 or 0) indicating whether or not the window is visible. By
default the window is visible.
x1,y1 are the new coordinates of the top inside left-hand corner of the window,
in relation to the screen.
x2,y2 are the coordinates of the bottom inside right-hand corner of the new
window. The origin is the top left-hand corner of the screen.
t has the form type, or type.attributes_list where type determines the type of
window and therefore the type of operations that can be applied to it.
The possible values for type are:
"EDIT" or :edit
to create an EDIT window.
s "FRAMEPANEL" or :framepanel
to create a FRAMEPANEL window.
"GRAPHICS" or :graphics
to create a GRAPHICS window.
"MODAL" or :modal
to create a GRAPHICS window with the MODAL attribute.
"TTY" or :tty
to create a TTY window.

© PrologIA
Aociation Prolog
U5-8 Windows User's Manual HERITAGE

The possible values for an attributes_list attribute are:


<"DISTANCE", n> or < :distance, n>
n is an integer denoting a portion of the drawable part of the window
reserved for button creation. This zone is located at the top of the window
across its whole width and with a height equal to n% of the total height.
This attribute is valid for all window types, but is only useful for
FRAMEPANEL windows.
 <"FONT", n > or < :font, n >
Defines the number n of the character font used in a text window. The
host system determines the font associated with n.
 <"FONTSIZE", n > or < :fontsize, n >
Defines the size of the font used in a text window.
<"MODAL", b> or < :modal, b>
b is a boolean indicating whether the window is modal or not. The default
value is 0. This attribute is valid for any window type. If the window is
modal, it stays above all other windows, and all events outside the window
are de-activated (except user interrupt). External events are re-activated
when the window is killed. Modal windows can be stacked.
s <"NO_RESIZE", b> or < :no_resize, b>
b is a boolean indicating whether window re-sizing using the mouse (or
a predefined key combination on some machines) is authorized or not.
The default value is 0. Whatever value b takes, a window can always be
re-sized by a program.
<"SHAPE", n> or < :shape, n>
n is an integer determining the window shape. The standard shapes are
0 (window with title bar, menu bar and scroll bars) and 1 (frame
window). By default, modal graphics windows have attribute 1, and
other window types have the attribute 0. This attribute is valid for any
window type. It should be noted that the GRAPHICS and
FRAMEPANEL windows do not have scroll bars.
 <"SAVE", r > or < :save, r >
This attribute is only valid for a graphics or modal window. It defines
in this window the rectangle r associated with a refreshment bitmap (for
color machines, a large rectangle may require considerable memory
space).
<"SAVE", b > or < :save, b >
b is a boolean indicating whether or not a refreshment bitmap is
associated with the window. The default value is b = 0.
 If b =1, a refreshment bitmap the same size as the window is created
Example of a graphics window with automatic saving:
> new_window("query","GRAPHICS".<"SAVE",1>.nil);
The following two goals are equivalent:
> new_window("fen","MODAL");
> new_window("fen","GRAPHICS".<"MODAL",1>.nil);

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U5-9

create_window(s,t,s',r1)
create_window(s,t,v,s',r1)
create_window(s,t,v,s',r1,r2)
Similar to new_window, but can be used to define a coordinate system with a
scale.
r1 has the form <x1,y1,x2,y2> where x1,y1,x2,y2 are reals indicating the
coordinates of the drawable section of the window in a screen [0,1] *
[0,1].
r2 has the form <x1,y1,x2,y2> where x1,y1,x2,y2 are integers defining a
user's local coordinate system. This parameter is only to be specified for
GRAPHICS and FRAMEPANEL windows. If parameter r2 is not
specified, the graphics coordinates in the window will be given in pixels.
For example, if a window is created by the following call:
> create_window("mywindow", "GRAPHICS", 1, "mywindow",
<0.1E0,0.1E0,0.6E0,0.7E0>, <0,0,100,100>);

whatever the screen size, a rectangle drawn by gr_rect(1,0,0,100,100) will fill


it, gr_moveto(50,50) will position it at the center, etc..
Another example:
> create_window("ww","GRAPHICS",1,"mywindow",
<1e-1,1e-1,5e-1,5e-1);

kill_window(s)
Deletes the window s, which must not be a predefined window (i.e. it must
have been created by new_window or create_window). If the deleted window
was the current input or output, the previously active input or output unit
becomes active again. If the deleted window was the current graphics window,
the predefined "graphic" window becomes the current graphics unit. For
more information please refer to the kill_object predicate.

5.2.2 Configuration and manipulation of a window

clear_window(s)
Erases the contents of the window s. It does not modify any of the window's
objects or delete events linked to the window that are in the Prolog queue. It
is valid for any type of window (but has no effect on a FRAMEPANEL
window).

file_window(s1)
file_window(s1,s2)
Create an EDIT window called s2 if it does not exist already, initialized with
the text contained in the file called s1. file_window(s1) is equivalent to
file_window(s1,s1).

© PrologIA
Aociation Prolog
U 5 - 10 Windows User's Manual HERITAGE

front_window(s)
Unifies s with the name of the Prolog window that is on top and has the input
focus.

get_window(s,v)
get_window(s,v,x1,y1,x2,y2)
s get_window(s,t,v,x1,y1,x2,y2)
Gives information about the type, attributes, visibility and coordinates of
window s. The two argument version just gives information about visibility.
By backtracking, unifies the parameters s,t,v,x1,y1,x2,y2 in sucession with the
values corresponding to each window. Please refer to the
new_window(s,t,v,x1,y1,x2,y2) primitive for the meaning of the parameters.
The type and attributes are given in identifier form. The value of the :distance
attribute is now given in pixels, instead of a percentage of the drawable part as
previously.

gr_window(s)
The graphics window s becomes the current graphics unit.

gr_window_is(s)
Unifies s with the name of the current graphics unit.

 option+ close box


When you click in the close box of a window, the corresponding unit closes
and its name is removed from the menu containing the window names, unless
it is a predefined window. However it is possible to make a window invisible
without closing it, by pressing the option key when you click the close box.

 print_window(s)
 print_window(s,f,t)
Prints the contents of text window s with the font f of size t. The same
conventions apply as for gr_text(f,t,l) (See 5.5. Drawing and writing mode).
The one argument version prints the window with its current font.

 gr_print(s)
 gr_print(s,_rx,_ry,x0,y0)
 gr_print(s,r1,r2)
Prints the contents of the graphics window s. The zone to print can be
specified by means of the third version. It is the contents of rectangle r1, and
the result on paper is located in rectangle r2. Any reductions and translations
are automatically performed. The single argument version prints the window
without modifying the format.
The 5 argument version is used to specify the reduction according to the X
and Y axes, in the form of two numbers _rx and _ry between 0e0 and 1e0.
The position of the printing origin on paper can be entered in x0 and y0.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 11

> gr_print("graphic",0.5e0,0.5e0,0,0);

will print the "graphic" window, reduced by a quarter (each dimension is


reduced by half).

reset_window(s)
Repositions the cursor at the beginning of the EDIT window called s. The
rule fails is s is not an EDIT window created by new _w indow or
create_window. The point of writing is still the end of the text.

save_window(s1)
save_window(s1, s2)
Saves the contents of the text window s1 in the file called s2. The one
argument version is equivalent to save_window(s1,s1).

set_window(s,b)
This rule enables you to modify the attributes and visibility of a window. s
identifies the window, b can either be an attribute (see new_window) or a
boolean indicating whether the window will be visible (1) or invisible (0).
The possible attributes for graphics and modal windows are as follows:
<"SAVE", v > when v is a boolean
This predicate can also be used with this attribute for a drawing area.
It's identification is then s.
If v =1, the system creates a refreshment bitmap for the size of the
object.
 <"SAVE", r > where r is a rectangle.
For a text window:
 <"FONT", n >
 <"FONTSIZE", n >

Example:
> set_window("console",<"FONTSIZE",12>);

set_window(s,b,x1,y1,x2,y2)
This rule is used to modify the visibility, size and position of windows.
s window name (character string or integer), such as "console", "graphic"
or "trace" for the predefined windows.
b boolean flag indicating whether the window will be visible (1) or
invisible (0).
x1,y1 new coordinates of the top inside left-hand corner of the window, in
relation to the screen.
x2,y2 new coordinates of the bottom inside right-hand corner of the window.
The origin is the top left-hand corner of the screen.
Example:
> set_window("graphic",1,50,50,300,300);

© PrologIA
Aociation Prolog
U 5 - 12 Windows User's Manual HERITAGE

5.2.3 Refreshing of graphics units

GRAPHICS windows or drawing areas can be refreshed automatically by


associating them with an auxiliary bitmap (see the new_window or set_window or
new_drawing_area primitives).

If this method is not used, a graphics units coroutine is available which is activated
whenever these units require graphics refreshing. This coroutine is:
exec(:gr_update(u))

where u represents the name of the unit. The :gr_update rule is not defined in the
standard environment, and is not started if the user does not define it. By writing a
:gr_update/1 rule, the user can therefore define the refreshing of the graphics units,
without using an auxiliary bitmap.

5.3 Elementary primitives for management of objects attached to a


window
We have used the term elementary becuase these primitives are used to perform
basic operations such as creation, configuration and querying of an object. They
also manipulate very simple elements, such as an object, an object attribute or an
event that has occurred on an object.

These primitives are not sufficient to manipulate and configure menus completely.
The menu primitives that do this are described in 5.4.

5.3.1 Creation and deletion of objects

An object can be identified either by a string or a Prolog II+ identifier. Its


identification may not be specified (free variable when the creating predicate was
called). In this case, Prolog assigns it a default identification; a Prolog identifier
obn where n is an integer.

Some objects require a title or a text. This is determined by a Prolog character


string, which may be empty.

An integer constant is used to specify the visibility of an object when it is created:


0 = invisible, 1 = visible.

You can modify the default attachments of objects by adding the attributes
:top_attach, :left_attach, :bottom_attach, :right_attach to the list of creation
options. Use the :top_attach and/or :bottom_attach attributes to modify the vertical
attachment, and the :left_attach and/or :right_attach attributes to redefine the
horizontal attachment.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 13

A Prolog program can be linked to the events (if any) occurring on the created
object. As soon as the events take place, the current Prolog program is suspended
and the predicate associated with the object is started. The predicate's first argument
is the identification of the object, and a possible second argument may be additional
information (character typed, etc). When the predicate terminates, the suspended
proof carries on as normal. In this way it is possible to manage graphics screen
input "live".
It is also possible to delay the processing of entered data or events, by simply
specifying sys:get_event instead of the predicate. The event will be put into the
Prolog events queue (it can be monitored using get_event or cleared using
clear_events).
It is also quite possible to do nothing. Simply specify nil to replace the predicate,
and the object's events will be ignored.

s kill_object(o)
Deletes object o. Is valid for any object.

s new_check_button(o,p,v,s,b,<x1,y1,x2,y2>)
Creates a check button identified by o, containing a text s. The button and text
will be written in a rectangle with coordinates x1, y1, x2, y2 in the parent
window p. Visibility is determined by the value of v.
x2 and y2 must be free. They are unified with the coordinates of the bottom
inside right-hand corner of the object when it has been created.
b can be nil, sys:get_event or a rule identifier. In this last case, each time the
button is activated, the goal b(o) is started.

s new_drawing_area(o,p,v,<x1,y1,x2,y2>,r2,l)
s new_drawing_area(o,p,v,<x1,y1,x2,y2>,l)
Creates a graphics area identified by o. It is drawn in a rectangle whose
coordinates are x1, y1, x2, y2 in the parent window p. Its visibility will depend
on the value of v. r2 has the same meaning as in the create_window
predicate (local coordinate system). l is a possibly empty (nil) list of options
formed by the identifiers:
:no_border if you don't want a border around the area.
:save to have a save bitmap.
:top_attach, :left_attach, :right_attach, :bottom_attach

s new_push_button(o,p,v,s,b,<x1,y1,x2,y2>)
s new_push_button(o,p,v,s,b,<x1,y1,x2,y2>,l)
Creates a push button identified by o, containing a text s, whose coordinates
are x1, y1, x2, y2 in the parent window p. Visibility is determined by the value
of v.
If x2 and y2 are free they are unified with the coordinates of the bottom right-
hand corner of the object, when it has been created.

© PrologIA
Aociation Prolog
U 5 - 14 Windows User's Manual HERITAGE

b can be nil, sys:get_event or a rule identifier. In this last case, each time the
button is activated, the goal b(o) is started. l is a possibly empty (nil) list of
options formed from the identifiers:
:buttonD is used to define it as the "default button", i.e.any carriage
returns not detected by another object will activate this button. These buttons
are designed so that there is one for each window. If this is not the case,
behavior is not guaranteed, and depends on the host system.
:top_attach, :left_attach, :right_attach, :bottom_attach

s new_radio_button(o,g,p,v,s,b,<x1,y1,x2,y2>)
Creates a radio button identified by o, containing a text s. g is a Prolog
identifier representing the group comprising the button. The button and text
are written in a rectangle with coordinates x1, y1, x2, y2 in the parent window
p. Visibility is determined by the value of v.
x2 and y2 must be free. They are unified with the coordinates of the bottom
inside right-hand corner of the object when it has been created.
b can be nil, sys:get_event or a rule identifier. In this last case, each time the
button is activated, the goal b(o) is started.

s new_edit_field(o,p,v,b,<x1, y1, x2, y2>,l)


Creates an editing field identified by o, with coordinates x1, y1, x2, y2 in the
parent window p. Visibility is determined by the value of v.
b can be nil, sys:get_event or a rule identifier. In the latter case, each time a
character is typed in the editing field, the goal b(o,c) is started, where c is the
character and each time input focus is lost or obtained the goal b(o) is started.
l is a list of options, which may possibly be empty (nil), formed by the
following identifiers:
:multiple if the field can comprise several lines.
:hscroll to have a horizontal scroll bar.
:vscroll to have a vertical scroll bar.
<chars_nb,n> if the field is restricted to n characters (n is an integer).
:top_attach, :left_attach, :right_attach, :bottom_attach
By default, the editfield is single line with no scroll bar, and the number of
characters is limited to 1024.

s new_label(o,p,v,s,<x1,y1,x2,y2>,l)
Creates a label identified by o, containing a text s, written in a rectangle with
coordinates x1, y1, x2, y2 in the parent window p. Visibility will be determined
by the value of v.
If x2 and y2 are free they are unified with the coordinates of the bottom inside
right-hand corner of the object, when it has been created.
l is a list of options, which may possibly be empty (nil), formed by the
following identifiers:
:left for left-aligned text in the rectangle.
:right for right-aligned text in the rectangle.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 15

:no_border for text with no border.


:top_attach, :left_attach, :right_attach, :bottom_attach
By default, the text is bordered and centered, and its alignment depends on the
host graphics system.

s new_listbox(o,p,v,b,<x1, y1, x2, y2>,l)


Creates a list box identified by o, with coordinates x1, y1, x2, y2 in the parent
window p. Visibility is determined by the value of v. List box items must be
defined using the set_attribute primitive.
b can be nil, sys:get_event or a rule identifier. In this last case, each time a
selection is made in the list box, the goal b(o,n,m) is started, where n is the
numer of the affected item and m the modifier used.
l is a list of options, which may possibly be empty (nil), formed by the
following identifiers:
:multiple if the selection can comprise several items.
:hscroll if a horizontal scrollbar is required.
:top_attach, :left_attach, :right_attach, :bottom_attach
By default, the list box is in single selection mode (maximum of 1 item
selected), and has a vertical scrollbar which can be invisible if the number of
items in the box is insufficient.

s new_popup_menu(o,p)
Creates a popup menu support identified by o, attached to the window p. No
item is created. To create an item use the set_menu primitive.
Note: it is not necessary to create a popup menu support before using the
set_menu primitive. If set_menu is used with the name of a window, it refers
to that window's popup menu. If the menu does not exist, set_menu creates it,
but its identification is not known.

If we suppose that mygraph is the identification for a graphics window, the


series of goals shown below creates a popup menu consisting of a list of
items: "doLine", "doRect", "doOval". The procedures doLine/1, doRect/1,
doOval/1 are attached to each item respectively.
> new_popup_menu(popgraph,mygraph);
> set_menu(popgraph,nil,doLine.doRect.nil);
> set_menu(mygraph,"new".nil,doOval);

s new_pulldown_menu(o,p,s)
Creates a pulldown menu identified by o, with the name s (character string),
and attached to the window p. Its items will then be created by the set_menu
primitive. Is not valid for frame shaped windows.
The sequence of goals below creates a customized titled popup menu
consisting of the list of items: "myColor", "myMode", "myFont", "myPen".
The procedures myColor/1, myMode/1, myFont/1, myPen/1 are attached to
each item respectively.
> new_pulldown_menu(mymenu,mygraph,"custom");

© PrologIA
Aociation Prolog
U 5 - 16 Windows User's Manual HERITAGE

> set_menu(mymenu,nil,myColor.myMode.myFont.miPen.nil);
> set_menu(mymenu,"miPen".nil,myPen);

s new_scrollbar(o,p,v,b,<x1,y1,x2,y2>,l)
Creates a scrollbar identified by o, with coordinates x1, y1, x2, y2 in the
parent window p. Visibility is determined by the value of v.
If x2 and y2 are free they are unified with the coordinates of the bottom inside
right-hand corner of the object, when it has been created.
b can be nil, sys:get_event or a rule identifier. In this last case, each time the
scrollbar is activated, the goal b(o,n) is started.
l is a list of options, which may possibly be empty (nil), formed by the
following identifiers:
:vscroll for a vertical scrollbar.
:hscroll for a horizontal scrollbar.
:top_attach, :left_attach, :right_attach, :bottom_attach
The default orientation is determined by the coordinates, given that the length
of a bar is greater than its width.

5.3.2 Configuration of objects

s get_attribute(o,a,v)
Supplies information about the state or properties of objects.
o is the object identification.
a is the attribute identification.
v will be unified with the value of the queried attribute.
The possible attributes are the same as for the set_attribute primitive, except
for the focus and customColor attributes. The following attributes which are
added are properties of non-modifiable creation:
:parent: v is unified with the identification of the parent of object o.
:type: v is unified with an identifier representing the type of the object o. The
possible values are: :graphics, :tty, :edit, :framepanel, :label,
:push_button, :check_button, :radio_button, :scrollbar, :edit_field,
:popup_menu, :pulldown_menu, :listbox
:fontheight: v is the height in pixels of the font used by the object. The font
height is the height of the rectangle containing the characters (including
the line space).
:group: v is unified with the identifier of radio button group o.
:items_nb: v is unified with the number of items in the list box o.

s set_attribute(o,a,v)
Is used to modify or specify the configuration of objects .
o is the object identification.
a is the attribute identification.
v is the attribute value.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 17

The possible attributes are determined by the type of object. The general
attributes are as follows:
:activity: indicates whether the object or menu item reacts to events or not. v's
value is 1 or 0 respectively. Is not valid for labels.
:background: concerns the background color of the object. v is an integer or
identifier and complies with the same conventions as those applying in the
gr_color2 primitve (see 5.5. Drawing and writing mode).
:bottom_right: concerns the position of the outside bottom right-hand corner
of the object. v has the form <p1, p2> where p1 is the abscissa and p2 is
the ordinate. It resizes the object. Is not valid for menus.
:cursor: concerns the mouse pointer shape when it is inside window o. v is
one of the following identifiers: :default, :wait, :cross. For set_attribute,
if the value of o is nil, the definition is valid for all the windows.
:customColor: defines the user color for object o. v has the form <_r, _g,
_b> where _r, _g _b are integers or reals and represent the color in red,
green and blue components, as defined in the gr_color3 primitive (see
5.5. Drawing and writing mode). This attribute is not valid for the
get_attribute primitve.
:focus: gives the input focus to the object o. v is ignored. This attribute is not
valid for the get_attribute primitive.
:font: concerns the font used by the object. v is an identifier that has the same
meaning as in the gr_font primitive (see 5.5. Drawing and writing mode).
The font defines the style and the size. The size can be obtained using the
get_attribute primitive with the fontheight attribute.
:foreground: concerns the color for drawing an object (text or drawing). v is
an integer or identifier and complies with the same conventions as in the
gr_color2 primitve (see 5.5. Drawing and writing mode).
:predicate: v is the Prolog predicate attached to the object. It is not valid for
labels (they are not sensitive) or menus and their items (please refer to the
set_menu primitive for more information).
Note: it can be used for graphics units. It then corresponds to the
predicate that must be started when an expose event occurs (it is
necessary to redraw part of the unit) and the unit does not have a bitmap.
The default value assigned is gr_update.
Note: take care not to confuse this predicate with the predicate that starts
on a click event. This predicate is linked to an area of the unit (please
refer to the gr_sensitive predicate for more details), and cannot be
modified by set_attribute.
:protected allows to disable close option in the default menu of a window.
:rank: concerns the numbering of the objects in their parent. v is the local
rank of the object in its parent. This number is unique for any given
parent, and it is implicitly the creation order number. This attribute is not
valid for windows.
:state: concerns the state of the selected or unselected object. The value of v is
1 or 0 respectively. Is only valid for check buttons and radio buttons.

© PrologIA
Aociation Prolog
U 5 - 18 Windows User's Manual HERITAGE

:text: concerns the text of an editing field, a title bar, the label of a button type
object or label. In general, v is a character string. For an editing field, v
can take the form <s, 1> signifying that the character string s must be
added (append mode) to the content of the editing field.
:text_selection: concerns selection in an editing field. v has the form <p1,
p2> where p1 is the index of the first selected character (starts at 0), p2 is
the index folowing the last selected character, and p2 >= p1.
:top_left: concerns the position of the top left-hand corner of the object. v has
the form <p1, p2> where p1 is the abscissa, and p2 is the ordinate. It
moves the object. Is not valid for menus.
:user_field: concerns the user field, which Prolog does not manage at all. v is
an integer. The programmer can use it for example as a global variable
associated with the object.
:visibility: concerns the visibility of the object. The value of v is 0 if the object
is invisible, 1 if it is visible, or 2 if the object is an iconized window. Is
not valid for menus.
:width_height: v has the form <p1, p2> where p1 is the width of the object
and p2 is its height. Is not valid for menus.
The following attributes are specific to listbox:
:items: concerns the list of list box items. v is a list of Prolog strings that
describes all the list box items by their text, in the same order.
:selected_items: concerns the list of selected items in a list box. v is the list of
ranks of the selected items. If more than one rank is given for a list box
in simple selection mode, the last selection will be taken into account.
:state(i): concerns the state of a selected or unselected list box item. v has the
value 1 or 0 respectively. i is an integer for the number of the relevant
item in the list box. The first list box item is represented by the integer 1.
:text(i): concerns the text of a list box item. i is an integer for the number of
the relevant item in the list box. The first list box item is represented by
the integer 1. v can have different values, determined by the following
circumstances:
– Query on the text of an item. v is a character string. If the item does
not exist, v is the empty string.
– Modification of an item's text. i is an existing item number, and v is a
non empty character string.
– Deletion of the item. i is an existing item number, v is the character
string.
– Creation of the item. i is a non-existent item number and v is a
possibly empty character string.
– Insertion of the item. v has the form <p1, 1> where p1 is any
character string for the text of the item created at the position denoted
by i.
:toplist: v is the number of the first visible item in the list box.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 19

The following attributes are specific to the scrollbar:


:scrollb_page: concerns the magnitude of scroll box movement when a jump
is requested (click between the arrow and the scroll box). v is an integer.
:scrollb_pos: v denotes the scroll box position in the scrollbar. v is one of the
integer values in the range of the scrollbar. Zero is at the top of the
vertical bars, and to the left of the horizontal bars.
:scrollb_range: concerns the range of scrollbar values. v is an integer. If it is
positive, the values will be between 0 and v. If it is negative, the values
will be between v and –v.
:scrollb_step: v is an integer denoting the magnitude of scrollbox movement
when a scroll arrow is activated. The minimum and default magnitude is
1. To obtain the new position, v must be deducted from or added to the
current position.

s get_local_object(p, n, o)
Unifies o with the identification of the object whose parent is p and has a local
rank of n in p.

s get_objects(p,l_o)
Unifies l_o with the list of objects whose parent is p.

5.3.3 Event management

s get_event(b,e,o)
Tests whether an event whose type is defined by e concerning object o is
present in the Prolog events queue. If it is present, the first corresponding
event (the oldest one) is read and therefore deleted from the queue, and the
system attemps to unify the arguments. Otherwise get_event acts according to
the value of b, which must be known when the call is made.
If the value of b is 0, get_event does not block, and generates backtracking.
If the value of b is 1, get_event blocks. The system waits for the event, reads it
and finally attempts unification.
o is either the identification of an object, or a free variable. In the latter case,
all the objects are concerned.
e is either a free variable, in which case all events are concerned, or has the
form:
:char(c): for editing fields and GRAPHICS windows, where c is the character
code.
:click: for a button (push, check or radio) or a scrollbar. No result is
transmitted, only a success or a failure.
:click(i,m): for the menus or list boxes, where i is the number of the selected
item and m specifies the state of the main modification keys. m is the
sum of the following values:
1 if the SHIFT key is pressed,

© PrologIA
Aociation Prolog
U 5 - 20 Windows User's Manual HERITAGE

2 if the CONTROL key is pressed,


32 for a DOUBLE-CLICK
Note: a double mouse click on an item will generate the following
sequence of events: :click(i,0) :click(i,32).
:click_down(x,y,m): for GRAPHICS and FRAMEPANEL windows and
drawing areas, where x,y are the click coordinates in relation to the
window. m specifies the state of the main modification keys.
:click_up(x,y,m): for GRAPHICS units (windows or drawing areas), where x,y
are the click coordinates in relation to the window. m specifies the state
of the main modification keys.
Note: a double mouse click in a graphics unit will generate the
following sequence of events: :click_down(x,y,0) :click_up(x,y,0)
:click_down(x,y,32) :click_up(x,y,0).
:focus_in: for the editing fields. No result is transmitted, just a success or
failure.
:focus_out: for the editing fields. No result is transmitted, just a success or
failure.
:update: for GRAPHICS units (windows or drawing areas) which do not have
a bitmap and still have the default predicate sys:get_event linked to the
unit.

s peek_event(b,e,o)
Same method and values as the get_event(b,e,o) primitive, but just consults the
event queue without modifying it. The event e for object o is not deleted from
the queue.

s clear_events(e,o)
Clears all events defined by e concerning the object o without any unification.
This predicate never fails. e complies with the same conventions as for
get_event(b,e,o).

5.4 Specific primitives for menu management

The set_menu primitive described in this section defines or redefines hierarchical


menus.

All menus are attached to a window, whether they are popup or pulldown. A special
support for general application menus does exist however, called the Prolog menu
bar.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 21

5.4.1 Saving and loading the menu bar

Prolog's general menu bar is identified by :prolog. To obtain the list of


identifications for its menus execute sys:get_objects(:prolog,l).

clear_menubar
Calls save_menubar and then erases the standard menu bar. This primitive is
used to redefine the menu bar completely.

clear_menubar(w)
Clears the menu bar in window w.

s restore_sysmenus(s,f,e)
Adds the "File" and "Edit" system menus to the menu bar of window s and
unifies their names with f and e. The variable remains free if the menu does
not exist.

 save_menubar
Memorizes the current menu bar. This rule can only be called once.

 restore_menubar
Restores the menu bar saved using save_menubar.

 add_stdmenu(s)
This primitive is used to reinsert one or more standard menus following a call
to clear_menubar. s must be one of the following strings:
"apple" : to insert the Apple menu
"file" : to insert the File menu
"edit" : to insert the Edit menu
"find" : to insert the Find menu
"control" : to insert the Control menu
"window" : to insert the Window menu

5.4.2 Description of a menu

set_menu(u,p,v)
This primitive is used to define or redefine the value v of the item indicated by
p in the menu called u.
The meanings of each argument are as follows:

u (unit) Represents the relevant menu. 0 for a menu in the menu bar,
the identification of a window for the popup menu associated with it, or the
identification of a menu (popup or pulldown).

© PrologIA
Aociation Prolog
U 5 - 22 Windows User's Manual HERITAGE

c (path) List of strings indicating a selection path in the menu u. The


corresponding element in the path is replaced by v. If the hierarchy did not
already exist, it is created. If the list is nil, the whole of the menu is replaced.
Warning: the title of a pulldown menu is not an item, and should not be
included in the path.

v (value) Tree describing the value which replaces the item at the
position indicated by p, in the menu u. This value can either be a leaf, or a
hierarchy.

Leaf type value


A leaf is represented by:
<"Item Name",Identifier,n>
The string "Item Name" replaces the text of the item indicated by the path. If
the string is an empty string, the denoted item is suppressed. A '&' character
in the “Item Name” string will not be displayed in the item’s text, and will
denote the character that follows it as a keyboard abbreviation to activate the
item.
Identifier is the access identifier of a rule with arity 1 attached to the item.
n is a boolean indicating whether or not the item is checked.
The following simplified forms can be used for v instead of this triplet:
nil to indicate a horizontal separation line.
Identifier for <"Identifier",Identifer,0>
<"Item Name",Identifier> for
<"Item Name",Identifier,0>

When the menu is selected, the current program is suspended, and the goal
Identifier(u) is immediately activated. If the goal terminates without any
errors, the program continues as normal, otherwise the error is propagated by
the block_exit mechanism.
Example: let us suppose that an editing window "menu.p2" is open:
> set_menu( 0
, ["Control","Compile the window"]
,<"Compile the window",compiling_win>)
set_menu( "menu.p2"
, ["Compile"]
,<"Compile",compiling_win>);
{}
>
insert;
compiling_win(0) -> front_window(u) reinsert(u);
compiling_win(u) -> string(u) reinsert(u);;
{}
>

Hierarchy type value


A hierarchy is represented by a two argument tuple with the following
structure:

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 23

<"Item Name", list_of_values>


Each value itself represents a leaf or a hierarchy. A simplified form can be
used:
list_of_values
In this case, the item name is indicated at the end of the path. This is the same
as inserting the hierarchy under the indicated item.
Example:
> set_menu("graphic",[], [ <"File", [quit]>
, <"Do", [goal1,<"Stop",goal2>]>
, <"Size", [ <"1",size1>
, <"2",size2,1>
, <"3",size3>
]>
] );
insert;
size1(u) -> gr_window(u) gr_text(1,10,nil);
size2(u) -> gr_window(u) gr_text(1,12,nil);
...

File
Do
Size 1
2
3

File
Do goal1
Size Stop

When set_menu is used for the menu bar, i.e. with u equal to 0, the menu
created on the bar is a pulldown menu. The title of the pulldown menu is
represented by the first string in the path p, or if the value of p is null, the first
string whose value is v. This menu's identification is a string; the title string
when the menu is created. Subsequent modifications of the title do not
modify the menu's identification. This identification can be useful for other
primitives, such as kill_object, get_attribute…
Example:
> set_menu(0,"new".nil,<"colors",black.grey.white.nil>);
The identification of the menu created by this call is "new", and its title is
"colors".
> set_menu(0,nil,colors.black.grey.white.nil);
The identification of the menu created by this call is "colors", and its title is
"colors".
> set_menu(0,"colors"."black"."white"."else".nil,else);
The identification of the menu created by this call is "colors", and its title is
"colors".

© PrologIA
Aociation Prolog
U 5 - 24 Windows User's Manual HERITAGE

In the primitives below, the first and second arguments comply with the same
conventions as for set_menu :

check_item(u,p,v)
This primitive checks an item or removes the check, depending on the value of
v: 0 = not checked, 1 = checked with the standard checking mark.
 If v is an integer greater than 1, the host machine character whose code v is
used as the checking mark.
Example:
> check_item(0,"Windows"."trace".nil,1);

 command_menu(u,p,v)
v is the code of the character used with the command key ( ) as a keyboard
equivalent to activate the item specified by the first two arguments.
Example of how to create the keyboard equivalent T to activate the Prolog
trace.
> char_code("T",n)
command_menu(0,"Control"."trace".nil,n);
s The character used as a keyboard abbreviation is a character belonging
to the menu item’s text. It is denoted when the menu or item is defined.

enable_menu(u,p,v)
Is used to deactivate (v =0) or reactivate (v =1) a menu or item. The following
example deactivates the whole editing menu.
> enable_menu(0,"Edit".nil,0);

 style_menu(u,p,v)
Specifies the style of a menu. v is an integer in which each bit represents one
of the styles specified in the order defined in the gr_text primitive.
The example below puts the trace item of the Windows menu in underlined
italics (bits 1 and 2 positioned):
> style_menu(0,"Windows"."trace".nil,6);

5.5 Drawing and writing mode

The set of primitives described in this section affect the properties of the current
graphics unit (which can be either a GRAPHICS window or a drawing area).

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 25

gr_color3(r,g,b)
Defines the color of the current graphics unit in components: r red, g green, b
blue. If the values are reals, they correspond to percentages of intensity for
each component. They must be between 0e0 and 1e0, and can be ported from
one machine to another. If the values are integers, they must be between 0 and
65535. This color is memorized as the customColor of the current graphics
unit.

 gr_color(d,c)
Defines the color of the background (if d= 0) or of the pen (if d=1) in the
current graphics unit. The argument p is an integer representing one of the
following 8 colors: 33:black, 30:white, 205:red, 341:green, 409:blue 273:cyan,
137:magenta, 69:yellow.

s gr_color1(d,c)
Defines the color of the background (if d= 0) or of the pen (if d=1) in the
current graphics unit. The argument c represents a color, using the same
conventions as the gr_color2 primitive.

gr_color2(b,p)
Defines the color of the background b and of the pen p in the current graphics
unit. The arguments b and p are integers or identifiers representing one of the
following colors:

0 :white
1 :red
2 :green
3 :blue
4 :pink
5 :orange
6 :brown
7 :magenta
8 :purple
9 :cyan
10 :yellow
11 :lightGrey
12 :darkGrey
13 :black
14 :defaultColor (system color)
15 :customColor (user color defined by gr_color3).

Note: the integer form is less explicit than the identifier form. In the
configuration query primitives (get_attribute(ob1, :background, x)), Prolog
returns the values in the identifier form.

© PrologIA
Aociation Prolog
U 5 - 26 Windows User's Manual HERITAGE

 gr_choosecolor(p,s,i,f)
Displays the color selection dialog at point p (in the form <x,y>) on the
screen. s is a string that will be displayed in the dialog. i and f are integer
triples between 0 and 65535 in the form <r, g, b> representing a color in
components of r: red, g: green and b: blue. i is the initial dialog color and
must be known when the call is made, f will be unified with the chosen color.
Fails if the user clicks the Cancel button.

gr_pen(w,p)
 gr_pen(w,h,p)
Defines the size in pixels and the pattern of the pen in the current graphics
unit.
w = width,
 h = height,
p = pattern, which is an integer or an identifier.
p p
0 :clear
1 :solid
2 :halfPattern
3 :lightPattern
4 :darkPattern
Note: the integer form is less explicit than the identifier form. In the
configuration query primitives (gr_get_pen(l, h, m)), Prolog returns the values
in the identifier form.

s gr_get_pen(w,p)
s gr_get_pen(w,h,p)
Indicates the size and pattern of the pen in the current graphics unit. w,h,p
have the same meaning as in the primitive gr_pen(w,h,p). Prolog returns an
identifier for the pen pattern.

gr_stringwidth(s,n)
Unifies n with the length of the string s according to the current font, size, and
style defined for the current graphics unit.

gr_mode(b,p)
Defines the pattern application mode on the background, for the current
graphics unit.
b=0 Concerns drawing, and therefore the pen pattern.
b=1 Concerns text, and therefore the pattern corresponding to each
character.
There are four basic operations: Copy, Or, Xor and Bic.
The Copy operation simply replaces the target pixels with the pixels in the
pattern or source. The target pixels are "painted over" without regard to their
initial state.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 27

The Or, Xor and Bic operations leave unchanged the target pixels located
under the white part of the pattern or source. They differ in the way they
process the pixels under the black part, as follows:
Or (adds) replaces them with black pixels.
Xor (inverts) inverts them.
Bic (deletes) replaces them with white pixels.
Depending on the mode, the operation is either performed on the pattern itself
(src) or on its inversion (notSrc).

For color machines, the white part of the pattern corresponds to the
background color part, the black part of the pattern corresponds to the
pen color part, and the inverted color is determined by the machine.
Here are the values of p for the different modes.
p p application modes
0 :srcCopy srcCopy
1 :srcOr srcOr
2 :srcXor srcXor
3 :srcBic srcBic
4 :notSrcCopy notSrcCopy
5 :notSrcOr notSrcOr
6 :notSrcXor notSrcXor
7 :notSrcBic notSrcBic
Note: the integer form is less explicit than the identifier form. In the
configuration query primitives (gr_get_mode(1, x)), Prolog returns the values
in the identifier form.

s gr_get_mode(b,p)
Indicates the pattern application mode in the current graphics unit. b, p have
the same meaning as in gr_mode(b,p). Prolog returns the mode as an
identifier.

 gr_text(f,s,l)
Defines the font, size and style of output in the current graphics unit. f = font
number; s = font size; l = list of style numbers.
N° font | N° style
0 systemFont | 0 bold
1 applFont | 1 italics
2 newYork | 2 underline
3 geneva | 3 outline
4 monaco | 4 shadow
5 venice | 5 condensed
6 london | 6 expanded
7 athens |
8 san Franscico |

© PrologIA
Aociation Prolog
U 5 - 28 Windows User's Manual HERITAGE

...
The empty list represents normal text. The default combination is
gr_text(4,12,nil).
For example gr_text(3,18,1.3.4.nil) corresponds to Geneva size 18, italic,
outline and shadow.
It is possible to call this rule by giving it identifiers that have been assigned
appropriate constant values. For example:
> assign(Geneva,3) assign(Italic,1) assign(Outline,3);
{}
> gr_text(Geneva,18,Italic.Outline.nil)
output("graphic") outm("Hello") output("console");

displays Hello in the graphics unit.

s gr_font(f)
Loads the font represented by f for the current graphics unit. The basic font is
the font proposed automatically by the system and is denoted by :ftdefault .
The other available fonts take the form :ft(i) or i, where i is an integer between
1 and 50. The correspondances between the integer and the name of the host
system's font is defined in the fonts.usr file. You can take a look at all the
available fonts, when Prolog has been started for the first time, in the fonts.all
file (created when graphics starts up).
Example:
> gr_font(:ft(2));

5.6 Drawing and positioning


The primitives described below apply to the current graphics unit (which can be a
GRAPHICS window or a drawing area). They are used to define a coordinate
system and create drawings in this unit.

gr_setorigin(x,y)
Changes the origin of the axes so that x,y represent the coordinates of the top
inside left-hand corner of the current graphics unit. The window's appearance
is not modified.

s gr_getorigin(x,y)
Indicates the coordinates of the top inside left-hand corner of the current
graphics window installed by gr_setorigin

gr_penloc(x,y)
Returns the integer coordinates of the pen position in the current graphics
unit.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 29

gr_penlocr(x,y)
Identical to gr_penloc(x,y) but gives a real number result.

gr_erase
Erases the contents of the current graphics unit, positions the pen in the top
left-hand corner and deletes all events linked to the unit and its objects.

gr_move(x,y)
Moves the pen position x horizontal pixels and y vertical pixels from its
current position.

gr_moveto(x,y)
Positions the writing point (pen) in the current graphics unit at x,y.

gr_line(x,y)
Draws a line from the current pen position to a new position x pixels away
horizontally and y pixels away vertically.

gr_lineto(x,y)
Draws a line by moving the pen from the current position to point (x,y).

gr_rect(n,r)
gr_rect(n,x1,y1,x2,y2)
Produce calls to the basic routines for drawing in a rectangle.
r is the tree denoting the rectangle. x1,y1 are the coordinates of the top left-
hand corner, and x2,y2 are those of the bottom right-hand corner of the
rectangle.
The first argument n, which is an identifier or integer, determines which
procedure is called:

0, :frameRect, :frame
Draws the perimeter of the rectangle.
1, :paintRect, :paint
Fills the rectangle with current pen-pattern.
2, :eraseRect, :erase
Erases the contents of the rectangle.
3, :invertRect, :invert
Inverts the color of each point inside the rectangle. If the rectangle
contains colors other than black and white, the results depends on the
machine.
4, :frameOval
Draws the oval in the rectangle.

© PrologIA
Aociation Prolog
U 5 - 30 Windows User's Manual HERITAGE

5, :paintOval
Fills the oval with current pen-pattern.
6, :eraseOval
Erases the contents and perimiter of the oval.
7, :invertOval
Inverts the bits of the oval. If it contains colors other than black and
white, the result depends on the machine.
8, :frameRoundRect
Same as :frameRect but with rounded corners.
9, :paintRoundRect
Same as :paintRect but with rounded corners.
10, :eraseRoundRect
Same as :eraseRect but with rounded corners.
11, :invertRoundRect
Same as :invertRect but with rounded corners.
12, :clipRect
Subsequent drawings will only be drawn inside the rectangle, i.e. a
visibility rectangle is defined for all future drawings. To cancel this
action, repeat it with the coordinates of the screen.

gr_polygon(n,L)
Draws a polygon in the current graphics unit. L is a list of <x,y> (or <> (x,y))
pairs indicating the coordinates of the points that define the polygon.
When the first argument n is an integer or identifier, it determines the called
function.
0, :frame
Draws the perimeter of the polygon.
1, :paint
Fills the polygon with the current pen-pattern.
2, :erase
Erases the contents of the polygon (some broken lines forming the
polygon contour may remain).
3, :invert
Inverts the color of each point inside the polygon. If the polygon
contains colors other than black and white, the result depends on the
machine.

gr_arc(n,r,a1,a2)
gr_arc(n,x1,y1,x2,y2,a1,a2)
Draws an elliptical arc inside the rectangle r between the angles a1 and a2.
Angles a1 and a2 are given in degrees.
The first argument n, which is an integer or identifier, determines which
procedure is called:

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 31

0, :frame
Draws the elliptical arc.
1, :paint
Fills the sector defined by the elliptical arc with the pen pattern.
2, :erase
Erases the arc and the sector.
3, :invert
Inverts the color of each point inside the elliptical sector. If it contains
colors other than black and white, the result depends on the machine.
> gr_arc(:frame,100,100,200,170,20,110);
a2

x1,y1

a1

x2,y2

gr_arc'(n,r,a1,a2)
gr_arc'(n,x1,y1,x2,y2,a1,a2)
Draws an elliptical arc in the rectangle r between the angles a1 and a2. a1
and a2 are given in degrees. The arguments are the same as for gr_arc but
the origin is on the vertical axis, a2 is relative to the position a1, and the
positive direction is clockwise.
> gr_arc'(:frame,100,100,200,170,20,30);

© PrologIA
Aociation Prolog
U 5 - 32 Windows User's Manual HERITAGE

a1

a2
x1,y1

x2,y2

 gr_icon(n,x1,y1,x2,y2)
 gr_icon(n,r)
Draws an icon described in an 'ICON' resource numbered n in the current
graphics unit, and writes it in the specified rectangle. The software first
searches for this resource in the Prolog II+ executable file, and then in the
system file. The system always contains the following icons:
0 Stop.
1 Note.
2 Caution.
The best results are obtained by giving a square with equal sides of 32 as the
rectangle.

gr_load(s)
Draws the contents of graphics file s in the current graphics unit. This
graphics file is a non-Prolog II+ file and is created using any graphics editor
from the host system. It is possible to draw selected parts of a file in different
locations, using the primitives gr_setorigin and gr_rect(:clipRect,..).

5.7 Mouse position in a graphics unit

A click event selects an item, activates a process asynchronously or simple selects a


point on a GRAPHICS type object. The primitives described below concern the
current graphics unit (which can be a GRAPHICS window or a drawing area).

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 33

 gr_click(b,x,y)
Tests whether a mouse button has been pressed since the last call to gr_erase
or gr_click. If a click has indeed occurred, x and y are unified with the
coordinates of the click position in the current graphics unit. Otherwise, the
primitive is controlled by b, a boolean value which must be known when the
call is made and has the following meanings:
b=1 The system waits for a click in the current graphics unit.
b=0 The system doesn't wait, and performs backtracking.

s gr_click(b,x,y)
Tests whether a click event in the current graphics unit is present in the event
queue. If it is, x and y are unified with the click coordinates in the current
graphics unit, and the event is removed from the queue. Otherwise the
primitive is controlled by b, a boolean value which must be known when the
call is made and has the following meanings:
b=1 The system waits for a click in the current graphics unit.
b=0 The system doesn't wait, and performs backtracking.
Please refer also to the get_event primitive.

gr_click(b,x,y,m)
Identical to gr_click(b,x,y) but also indicates the state of the main modification
keys, by unifying m with the sum of the following values:
1 The SHIFT key is pressed.
2 The CONTROL1 key is pressed.
 4 An option key is pressed (OPTION on Mac).
 8 The COMMAND key is pressed.
 16 The SHIFT-LOCK key is kept down.
s 32 A DOUBLE_CLICK is carried out.

Therefore m=0 if no modification key is pressed during the click.

gr_clickr(b,x,y)
Identical to gr_click(b,x,y) but xand y are reals.

1 This key is not present on the Macintosh + keyboard.

© PrologIA
Aociation Prolog
U 5 - 34 Windows User's Manual HERITAGE

s gr_sensitive(x1,y1,x2,y2,p)
Defines the rectangle with coordinates x1,y1,x2,y2 in the current graphics unit f
as a click-sensitive zone, to which the predicate p is attached. If p is not the nil
or get_event identifier, each time a click occurs inside the rectangle, the goal
p(f) will be launched. By default, all the zones are defined with get_event, and
so all clicks in the unit are sent to the Prolog event queue.
gr_sensitive(x,y,x',y',nil) is used to ignore the clicks in the defined zone.
The various defined rectangles must be disjoined. If this is not the case, and a
click occurs in a common zone, the result cannot be guaranteed. One of the
zones will sense the click, but it is not possible to know which one.

gr_getmouse(x,y)
gr_getmouse(x,y,b)
Gives the current mouse position in the current graphics unit, in integer
coordinates relative to the unit origin. b=0 if the mouse button(s) is/are not
pressed, otherwise b equals the number of the pressed button, starting from
the left for a multi-button mouse (the first button is number 1).

gr_getmouser(x,y)
Identifcal to gr_getmouse(x,y) but produces a real number result.

5.8 Special user input primitives

5.8.1 Button simulation

 To use the two primitives described below, you must first load the drawing module
dessin.mo.

These primitives simulate buttons in the current graphics unit.

gr_draw_buttons(b)
Draws all the buttons of the database whose access identifier is b. The button
database is constructed by the user. It will assign a rule name to each group
of buttons. The rules must have three arguments:
- the rectangle the button is written in.
- the string displayed in the button.
- a term to associate with the button.
For example, the following user-defined buttons:
wtButton(<5,160>.<50,175>,"Edit",edit)->;
wtButton(<5,180>.<50,195>,"Set",nil)->;
are drawn by launching the following goal:
> gr_draw_buttons(wtButton);

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 35

gr_button_hit(b,<x,y>,t)
b is the access identifier for the button database. This rule succeeds if x,y are
the coordinates of a point inside one of the buttons in database b. t is then
unified with the third argument of the rule for the relevant button.
By combining the gr_click and gr_button_hit primitives, it is easy to write a
button monitoring loop.

5.8.2 Display of messages with confirmation

s message_box(t,s,m,b,x)
Creates a modal graphics window to display a message. When the user has
pressed one of the buttons, the window is deleted and x is unified with the
number of the button. The window comprises:
- a title given by the character string s,
- an icon defined by the identifier t: :warning, :info, :question, :wait, :error.
The way the icon is drawn depends on the machine's graphics environment.
- a message given by the character string m,
- a line of buttons (maximum of 3), such that:
if b is an integer, there will be b buttons containing texts that depend on the
number of buttons, the type of icon and the machine's graphics environment.
if b is a list of strings, each string defines the text of a button.

5.8.3 Text editing

gr_editf(<s1,p1,p2>,r,s,k)
gr_editf(<s1,p1,p2>,x1,y1,x2,y2,s,k)
These primitives create an editing field in the current graphics unit, which
must be a window. If the unit is a drawing area, an error is generated. To end
editing, hit the return key or a tab key, or click in the window outside the
editing field, but not on an object. If k is not a variable, the field and its text
are only drawn, without editing.
s1 is the initial string to place in the editor.
p1, p2 are integers defining the indices of the characters that start
(included) and end (not included) the text selection indicated by
highlighting. The first index is 0. Initialization of an empty field
corresponds to the values <"",0,0>.
r defines the position of the enclosing rectangle. Text is left-aligned.
x1,y1,x2,y2 are the coordinates of the top left-hand and bottom right-hand
corners of the rectangle in the window.
s is the variable that will be unified with the edited string.

© PrologIA
Aociation Prolog
U 5 - 36 Windows User's Manual HERITAGE

k if k is a variable, it is unified in output with the termination mode:


0 for a return,
1 for a mouse-click inside the window 1 but outside the editing
field,
2 for a TAB.
If k is input as a constant, it is output immediately after display of the
zone.
A simpler form of this rule can also be used for a string which is initially
empty:
gr_editf(<>,x1,y1,x2,y2,s,k)
s Note: this function can also be performed with the primitives to create and
handle editfield or label objects.

 get_key(c)
 get_key(a,t,m)
This primitive takes a character. There is no echo of this character in any
window, and so this primitive can be used to enter a pass word. Its operation
is described in detail in the paragraph about stty below.
get_key(c)
returns a character in c.
get_key(a, t, m)
returns three integers:
- in a the extended ASCII code
- in t the key number (virtual key code described in Inside Macintosh vol. V
p.192))
- in m the state of the modification keys ( see the gr_click primitive).

 stty("USEGETKEY", t)
Governs use of the get_key primitve.
t=0
Default mode, in which get_key always fails. The characters typed are
inserted in the text windows if appropriate. In this mode, the user can edit text
windows while Prolog II+ is working.
t<0
get_key takes a character which cannot be older than t ticks (1 s = 60 ticks)
before the call. Fails if no character is available when the call is made, or if the
character is too "old".
t>0

1 Its position can be read using gr-click(0,x,y).

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 37

get_key will wait for a character for no more than t ticks. It fails if no
character is found after this time. get_key doesn't wait for the time period to
end before executing, if a character is provided in time. A character can be
typed in advance. This mode makes it possible to enter a pass word in a
specified time period.
Examples :
> stty("USEGETKEY", -60);
The next call to get_key will fail if no unread character has been typed less
than a second before this call.
> stty("USEGETKEY", 300);
The next call to get_key will fail if no unread character can be obtained in the
five seconds following this call. It is possible to type the character in advance.
get_key will succeed as soon as the character is obtained, without waiting for
the five seconds to elapse.

 stty("FLUSH")
Removes all characters from the event queue. They are no longer available to
get_key. This enables get_key to get an answer which has not been typed in
advance.

 gtty(s, v)
Recovers the value of a parameter concerning the terminal:
gtty("USEGETKEY", v) returns 0 or a signed number of ticks.
gtty("TERM", x) at present returns "TTY" or "MPW".

5.8.4 Choice boxes

gr_list(r, l, l_i, v_i, l_o, v_o, o)


The rule gr_list manages a choice of elements in a list. This list is displayed
in the current graphics unit. The parameters are described below.
r
The enclosing rectangle (including scroll bars) in the form
<x1,y1>.<x2,y2> or <x1,y1,x2,y2>.
l
The list of items. It must be a list of constants. They can be mixed:
string, integer, real, identifier, <>.
l_i
The initial selection, in the form of a possibly empty list of integers which
are the ranks (starting from 1) in l of the elements you wish to select.
v_i
The rank of the element which must appear at the top of the rectangle.
l_o
Writes the list of ranks of the selected items (same convention as for l_i).
v_o
Writes the rank of the first visible item in the rectangle .

© PrologIA
Aociation Prolog
U 5 - 38 Windows User's Manual HERITAGE

o
Describes one of the four following operations to perform:
<0> Draws only (no user input possible).
<1,k> Draws and takes control until a character input or click event
occurs in the window but outside the list. NEITHER THE CLICK
NOR THE CHARACTER ARE READ. Returns the following for
k:
0 : carriage return typed
1 : click outside the list
2 : TAB typed
<2,x,y,m>
Draws the list and processes the click x,y,m (given for example by
gr_click(?,x,y,m) ). Exits immediately afterwards.
<3,x,y,m,k>
Draws, processes the click (given for example by gr_click(?,x,y,m))
and takes control until a character input or click event occurs in the
window but outside the rectangle. Neither the click nor the character
are read.
Returns the following for k:
0 : carriage return typed
1 : click outside the list
2 : TAB typed
The click to end selection can be read by gr_click(0,x,y).
s Note: this function can also be carried out using the primitives to create and
handle listbox objects.

 gr_popupItem(r,L,n1)
 gr_popupItem(r,L,n1,n2)
Create popup menu items.
L is a list of constants. r is the rectangle in which item number n1 from list L
is displayed. If n2 is missing, the item is simply drawn. If n2 is present, a
menu presenting the list of choices L partially covers the item, and the
inversion of the fields is continued for as long as the mouse button remains
pressed. When the button is released, the selected field is drawn in the
rectangle in place of the previous one, and n2 is unified with its number (n1 if
no field is selected).
Example. Make the graphics window visible and type in the following
example:
> gr_popupItem(<20,20,120,40>, ["aa","bb","cc","dd",3,4], 2)
gr_click(1,x,y)
gr_popupItem(<20,20,120,40>, ["aa","bb","cc","dd",3,4], 2,
i);

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 39

When you click in the window and keep the button pressed:

aa
bb
cc
dd
3
4

5.8.5 Choosing files

input(x)
output(x)
This facility is added to the input and output primitives, with x as a free
variable when the call is made. This facility asks the user for the file name
using a dialog box. The input or output unit is then changed as normal (see
input output), and the file is opened, if appropriate. In output, unifies x with
the complete file name. If the Cancel button is clicked in the file selection
dialog, the primitive fails and no action is performed.

sfgetfile(s)
s sfgetfile(s,Filter,InitialName,Point)
Displays a dialog area to enable you to view the names of those files on the
disk(s) that are filtered by Filter, and select one of them.
Point is a point in <x,y> format indicating the location of the dialog display.
This dialog comprises a list of choices for the proposed files, and an editing
field initialized with the string InitialName.
Unifies s with the user's selection. s is the complete file name (including the
access path and the selected name). The file is not opened. This rule fails if
the Cancel button is clicked.

 sfgetfile(Point,Ltypes,Filter,S)
Displays a dialog area to enable you to view the names of those files on the
disk(s) whose type belongs to the list of types Ltypes, and to select one of
them.
Point is a point in <x,y> format indicating the location of the dialog display.
Ltypes is a list of file types which must be displayed. A type is a 4 character
string as defined in Inside Macintosh. For example: "TEXT"."APPL".nil
selects all text only or application files.
Filter is a filtering procedure to manage acceptance of the selected files. This
must be nil for the moment.

© PrologIA
Aociation Prolog
U 5 - 40 Windows User's Manual HERITAGE

S is unified with the user's selection. It has the form: <C,T,N> where C is the
creator (4 character string), T is the file type (4 characer string), and N is a
string indicating the access path and name of the selected file (the file is not
opened).
The rule fails if the Cancel button is pressed.

sfputfile(s)
Displays a dialog box to choose the name of a file to create, and unifies s with
the name and path of this file. The file is not opened. The rule fails if the
Cancel button is pressed.

 sfputfile(Point,Prompt,InitialName,s)
Displays a dialog box to enable the user to choose a name, volume and
directory for a file.
The file name is entered at the keyboard in an editing field initialized with the
possibly empty string InitialName which must be a filename without a path.
If the user enters an existing filename, an alert gives a warning. The file is not
created or opened.
s is unified with the name and path confirmed by the user.
Point is a point in <x,y> format, indicating the location of dialog display.
Prompt is a possibly empty string, containing a message for the user at the
top of the dialog box.
The rule fails if the Cancel button is pressed.

5.8.6 Choosing a node of a tree

gr_tree_click(t,l,n)
To use this primitive, you must load the drawing module dessin.mo.
Draws the tree t in the current graphics unit, and waits for the user to click on
one of the tree nodes. When this is done, l is unified with the path leading to
the node and n is unified with the node. The path is a list of the numbers of
the sons to pass through, starting from the root, e.g. node dd in the tree
aa(bb,cc(ee(dd),ff)) is represented by the path 2.1.1.nil.

5.9 Rules to manage structured objects

gendialog(D,l1,l2)
gendialog(P,D,l1,l2)
To use this primitive, you must first load the obdialog.mo module. This
primitive gives the user a very quick way of creating graphics screen sources,
that can then be integrated into applications.
P, D and l1 have the same meaning as in the gr_dialog primitive described
below.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 41

In l2 this primitive generates a list of goals that make it possible to create the
dialog screen defined by D.
gendialog(<100,100>.3.nil,"Hello".buttonD,nil,g_oals) g_oals;
will unify g_oals with the list of goals to perform to create this dialog and
then execute these goals.

gr_dialog(D,l1,l2)
gr_dialog(P,D,l1,l2)
To use this primitive, you must first load the obdialog.mo module. This
module contains the Prolog II+ dialog manager which is used to create and
activate the dialogs described by D.
In the second version of this primitive, the additional argument P takes the
form of a list formed by one of the following:
- a pair <x,y> to determine the position of the top left-hand corner of the
dialog.
- an integer i to choose the font of the dialog's text. i is as specirfied in the
gr_font primitive.
- the term :title(s) where s is a string which represents the title of the dialog
window.
D can either be a tree describing a dialog, or the identifier of a unary rule
which has such a tree as an argument. l1 is a possibly empty list of pairs:
(zone_name . initial_value)
This list is used to define or redefine the contents of the zones. In output, if l2
is a variable it is unified with the list of dialog pairs (zone_name .
final_value). If l2 is a list of (zone_name . X) pairs, each of these pairs is
unified with the corresponding dialog pair.
A dialog is described with primitive objects (text areas, editing fields, buttons,
etc) and primitives for formatting in columns or rows. These primitives adjust
the size of the zones dynamically, according to their contents. Zones whose
value can be modified are identified by a name, so that their value can be
redefined when they are called.
Example:
> load("obdialog.mo");
> gr_dialog("Hello".buttonD("OK"),nil,L);

> gr_dialog( "Name:"


.editf(10,field1)
.buttonD("OK")

© PrologIA
Aociation Prolog
U 5 - 42 Windows User's Manual HERITAGE

The primitives to describe the objects are as follows:


:text(s) , :text(s,f), :text(s,f,c) or s
Describes a line of non-editable text represented by s, where s is a
string. f denotes the font in the same way as the gr_font predicate, and c
denotes the text color in the same way as the :foreground attribute of
the set_attribute predicate.
:text(i)
Describes a line of non-editable text in a zone i, where i is an identifier.
If a value is associated with i in l1 this will be the initial value of the
field, otherwise it is the empty string. A final value is never associated
with this zone, since it cannot be modified.
:cb(i), :cb(i,v), :cb(i,v,s)
Describes a yes/no box. "Yes" and "No" are represented respectively
by the two possible values for v: 1/0. The name of the box's zone is i.
If v's value is given neither in an argument nor in the list l1, the value 0
will be given by default. When v is redefined in l1, it is this latter value
which is taken into account. s is a string, it defines the box's label.
:rb(<g,i>), :rb(<g,i>,v), :rb(<g,i>,v,s)
Describes a radio-button i in a group g (where g is an identifier, and i is
any constant). This radio-button of value 0/1, is part of the group g,
and only one button in the group can have the value 1.In output,
zone_name is represented by g(i), and final_value by 0 or 1. This
applies to each radio-button in the group.
:rb1(<g,i>), :rb1(<g,i>,v), :rb1(<g,i>,v,s)
The same as rb, except that at least one of the elements in the group
must not be at zero. Only the element having the value 1 appears in the
output list. zone_name is represented by g, and final_value by i. This
output format is therefore different from rb and is also simpler.
:editf(n,i), :editf(n,i,s)
Describes an editable line of text i, where i is an identifier and s
represents the initial value of the editing field. This initial value is the
empty string if it is specified neither in an argument nor in the list l1. n
is an integer representing the minimum number of characters in the
zone. If s is greater, the zone expands dynamically.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 43

:button(s,i)
Describes a button labeled s associated with an action i. When the
button is pressed, an action is performed:
- If i is fail, the dialog terminates and gr_dialog fails.
- If i is nil, nothing happens.
- Otherwise, the goal i(l) is activated, in which l is the list of
name.value pairs in the dialog zones when the button is clicked.
When the goal i has been executed, the dialog management continues as
before. To stop the current dialog, the user can program a
block_exit(<fail,L>) in i to cause backtracking of gr_dialog, or a
block_exit(<nil,L>) which results in normal termination, since l2 is
constructed from the list of name.value pairs indicated by L.
:button2(s,i)
This item behaves in the same way as the :button item, except that the i
rule is called with two arguments. The first is a list describing the state
of the dialog items. The rule defines a relation between the first
argument (input argument representing the list of present values), and
the second argument (output argument representing the list of new
values).
:buttonD, :buttonD(s), :buttonD(s,i)
Describes a dialog termination button labeled s, associated with an
action i. Normally, s is the string "OK", and i is nil. This button can be
activated by mouse-clicking or by entering a Return.
glist(Lines,Columns,Identifier,ValueList)
Defines an item which is a list of values, with a scroll bar. The
meanings of the arguments are as follows:
Lines
Integer representing the number of items visible. The height of the
rectangle is automatically calculated according to this parameter.
Columns
Integer representing the number of characters visible for an item. The
width of the rectangle is automatically calculated according to this
parameter.
Identifier
Identifier giving the manager an internal name. It is used to give the
output result.
ValueList
Any list of constants (strings, identifiers, numbers) which represents the
list of values presented, or else a triple describing the initial state of the
manager. This triple must have the following form:
<ValueList, ListOfSelectedNbs, TopNumber>
The first argument is any list of constants (strings, identifiers,
numbers).

© PrologIA
Aociation Prolog
U 5 - 44 Windows User's Manual HERITAGE

The second argument is the ordered list of the ranks of the items
constituting the initial selection. This list may comprise 0 (no
selection), 1 or several elements.
The third argument indicates the item number to display at the top of the
display rectangle.
The result is given in output, therefore in l2, in the normal form of a
pair:
(identifier.ListOfSelectedItems)
In the internal representation, the state of the manager is represented by
the triple described above. In the programs linked to buttons, the value
of the glist must be handled in this form, i.e. in the lists handled by
these programs, it is the pair (identifier . < ValueList,
ListOfSelectedNbs, TopNumber>) which must appear.

The formatting primitives are based on the notion of rectangle combination, i.e. by
placing two rectangles in a column, a new rectangle is defined which encompasses
the other two.
:col(l) or l
Describes a left-aligned column whose contents are described by l. If l
is a series, the primitive calculates the size of each element and
constitutes a column of elements arranged one above the other, aligned
to the left.
:ccol(l)
Describes a vertically centered column, whose contents are described by
the series l.
:row(l)
Describes a horizontal row described by the (series of) primitive(s) l,
whose elements are aligned to their top edges. If l is a series, the
primitive calculates the size of each element, and constitutes a row of
elements arranged side by side, aligned to their top edges.
:crow(l)
Describes a row of objects described by l and centered horizontally, i.e.
arranged so that their median points are aligned on the same horizontal
axis.
:vfill(n)
Describes a vertical space of n pixels, where n is an integer.
:hfill(n)
Describes a horizontal space of n pixels, where n is an integer.

The following grouping primitive is used to manage the activation or deactivation of


entire zones during dialog input.

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 45

:group(identifier.value,ItemDescription)
Enables an identifier to be associated with a set of spatially and
semantically grouped items. value indicates whether or not the group is
active (0 for inactive, 1 for active). When the group is inactive, it
appears grey-colored and the state of its items cannot be modified. The
state of a group can only be modified in the present version by the
actions associated with buttons. The state of a group is not given in the
output list but it is given in the list of states passed to the buttons, in the
form of a pair as follows:
(identifier.value)

Examples:
> gr_dialog( ccol("Do you want to re-start the test?"
.buttonD
.button("Cancel",fail))
, nil
, L);

> gr_dialog( "Choose the color you want"


.crow( rb(rb_1(red),1,"Red").
rb(rb_1(green))."Green")
.crow( cb(cb_1,0)."Extended colors")
.ccol( buttonD("Show Color")
.button("Cancel",fail)
)
, (cb_1.1).nil
, (cb_1.C).(rb_1(red).R).(rb_1(green).G).nil );

{C=1, R=1, G=0}


> gr_dialog( :crow( "abcdefgh"
.:ccol( :button("Stop",fail)

© PrologIA
Aociation Prolog
U 5 - 46 Windows User's Manual HERITAGE

.:buttonD("OK",nil)
.:button("Cancel",fail)
."HELLO WORLD"
)
."ijklmnopq"
)
, nil,l);

> gr_dialog( glist( 5, 10, list1


, < [red,green,blue,yellow,
violet,black,white,orange]
, [4,6]
, 2
>)
.buttonD
, nil
, L);
{L=(list1.yellow.black.nil).nil}

> insert;
enable( l1, l3 ) ->
set_item(l1, zone1, 1, l2)
set_item(l2, zone2, 0, l3);

disable( l1, l3 ) ->


set_item(l1, zone1, 0, l2)
set_item(l2, zone2, 1, l3);

set_item( nil, i, b, nil ) -> block_exit(816, "set_item,


absent: ".i);

© PrologIA
Aociation Prolog

HERITAGE Graphics Primitives U 5 - 47

set_item( (i._).l, i, b, (i.b).l ) -> ! ;


set_item(e.l, i, b, e.l' ) -> set_item( l, i, b, l' ) ;;
{}
> gr_dialog( group(zone1.0, "Hello"
.crow( rb1(color(red),0,"Red") )
.crow( rb1(color(green),1,"Green")
.editf(5,ed1,"aa")
.button2("Disable",disable)
)
.group(zone2.1, button2("Enable",enable))
.buttonD
, nil
, L);

{L=(color.green).(ed1."aa").nil}

5.10 Sending events to Prolog from an external object


The term "external object" refers to any graphics object not created by calling
graphics predicates. This may be done during a call to an external predicate, or in
the main program before starting Prolog; e.g. by loading an object described in a
resources file generated by an external tool (e.g. Dialog Editor in Windows).

This feature enables you to make this object communicate with Prolog, using the
events principle.

This will be done by means of a call to a C function:

send_external_event(no,str,bool,int1,int2)
sends an event to Prolog.

© PrologIA
Aociation Prolog
U 5 - 48 Windows User's Manual HERITAGE

Both event management modes can be used; you can process the event
immediately, or put it in the event queue.
The arguments have the following meaning:
bool is the int type with a boolean value, and indicates the required processing
mode:

- if bool is not zero, the event is to be processed immediately:


str, which is the char * type, represents the Prolog goal to call,
no, int1, int2, are ignored.

- if the value of bool is 0, the event is to be placed in the Prolog event


queue:
no, which is the int type, can be used to identify the object,
int1, int2, which are the int type, and str, have values whose meanings
can be defined by the user.

This event will be accessible via the event reading predicates:


get_event(b, e, o) and peek_event(b, e, o) where:
o will be unified with no,
e will be unified with the Prolog term :extern_event(str, int1, int2)
:extern_event(s, i1, i2): for the external objects. s, i1 and i2 are data sent by
the user at the same time as the event by means of the
send_external_event procedure.

© PrologIA
Aociation Prolog

HERITAGE

Index

^ R 1 - 20 =< R 10 - 2; 7
^R2-4 == R 10 - 2; 11
~R4-6 =\= R 4 - 4
^ R 10 - 3 =\= R 10 - 20; 2; 7
* R 1 - 20 > R 1 - 20
* R 10 - 3 > R 10 - 2; 7
** R 1 - 20 >= R 1 - 20
** R 4 - 6 >= R 10 - 2; 7
** R 10 - 3 >> R 1 - 20
+ R 1 - 20 >> R 4 - 6
+ R 10 - 2; 3 >> R 10 - 3
, R 10 - 2; 3 ?- R 10 - 2
- R 1 - 20 @< R 10 - 2; 12
- R 10 - 2; 3 @=< R 10 - 2; 12
--> R 10 - 2 @> R 10 - 2; 12
-> R 10 - 2; 3 @>= R 10 - 2; 12
/ R 1 - 20 abolish R 10 - 5
/ R 10 - 3 abs R 4 - 5
// R 10 - 3; 7 access R 0 - 7
/\ R 1 - 20 activity U 5 - 17
/\ R 4 - 5 add R 4 - 4
/\ R 10 - 2 add_implicit R 3 - 12
:- R 10 - 2 add_sentence_terminator R 5 - 6
< R 1 - 20 add_stdmenu U 5 - 21
< R 10 - 2; 7 add_tlv R 2 - 14
<< R 1 - 20 alias R 10 - 13
<< R 4 - 6 alloc / 12 R 6 - 23
<< R 10 - 3 alloc R 6 - 23
= R 10 - 2; 3 append R 5 - 2
=.. R 10 - 2; 8 arg R 4 - 11
=:= R 1 - 20 arg R 10 - 8
=:= R 10 - 2; 7 arg2 R 4 - 10
=< R 1 - 20 assert R 2 - 12

© PrologIA
Aociation Prolog
I-2 Prolog II+ Windows Index HERITAGE

assert R 3 - 21 bounded R 10 - 19
assert R 10 - 5 break point R 6 - 7
assert U 2 - 7 buttonD U 5 - 14
assert'' R 3 - 21 call R 10 - 4
asserta R 3 - 21 callC R 7 - 23
asserta R 10 - 5 callpro.def U 1 - 6
assertn R 3 - 22 callpro.h U 1 - 5
assertz R 3 - 21 callprol.lib U 1 - 5
assertz R 10 - 5 callpros.lib U 1 - 5
assign R 3 - 20 cassign R 4 - 7
assign R 4 - 7 catch R 10 - 4
assign U 2 - 7 ceiling R 4 - 5
at R 10 - 14 char U 5 - 20
atan R 4 - 6 characters R 1 - 2
atom R 10 - 6 chars_nb U 5 - 14
atomic R 10 - 6 CHAR_ARRAY R 7 - 15; 18
atom_chars R 10 - 8 char_code R 4 - 9
atom_codes R 10 - 9 char_conversion R 10 - 19
atom_concat R 10 - 9 Check button U 5 - 4
atom_length R 10 - 9 check_button U 5 - 16
at_end_of_stream R 10 - 15 check_item U 5 - 24
background U 5 - 17 chrono R 6 - 4
backtrack_term R 4 - 8 clause R 10 - 5
bagof R 2 - 4 clear_events U 5 - 20
beep R 5 - 9 clear_input R 5 - 8
binary R 5 - 1 clear_menubar U 5 - 21
block R 2 - 4; 5 clear_window U 5 - 9
block R 3 - 20 click U 5 - 20
block U 2 - 7 click_down U 5 - 20
block_exit R 2 - 4; 5 click_up U 5 - 20
block_exit U 2 - 8 close R 10 - 13
bottom_attach U 5 - 13 close_context_dictionary R 3 - 12
bottom_right U 5 - 17 close_input R 5 - 8
bound R 2 - 6 close_output R 5 - 12
bound R 4 - 2 code R 6 - 25

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I-3

command_menu U 5 - 24 C_FUNCTION_BACKTRACK_PROTECTE
Composition and decomposition of D R 7 - 15; 20
objects R 4 - 10 C_FUNCTION_PROTECTED R 7 - 15; 20
compound R 10 - 6 date R 6 - 4
conc_list_string R 4 - 11 date_string R 6 - 4
conc_string R 4 - 10 date_stringF R 6 - 4
ConnectDescriptors R 8 - 10 dbgbase.mo R 2 - 6
ConnectInString R 8 - 11 dbgbase.mo U 1 - 4
ConnectOutString R 8 - 11 dbgedin.mo R 2 - 6
console R 5 - 1 dbgedin.mo U 1 - 4
constant R 1 - 4 dbggraph.mo R 2 - 6
consult R 10 - 5 dbggraph.mo U 1 - 4
consult U 1 - 7 dde.mo U 1 - 3
copy_term R 4 - 11 ddeCbServerClosing U 4 - 10
copy_term_with_constraints R 4 - 11 ddeCbServerUpdate U 4 - 10
cos R 4 - 6 ddePublishExternalEvent U 4 - 4
cpu_time R 6 - 4 debug R 3 - 20
create_window U 5 - 9 debug R 6 - 17
cross U 5 - 17 debug R 10 - 19
current_context R 3 - 12 debugger R 6 - 6
current_file R 5 - 2 Declaration of operators R 5 - 14
current_input R 10 - 15 default R 2 - 7
current_op R 10 - 3 default U 5 - 17
current_output R 10 - 17 def_array R 4 - 8
current_predicate R 3 - 22 delay R 6 - 4
current_prolog_flag R 10 - 20 descriptor R 7 - 16
cursor U 5 - 17 Dessin R 5 - 13
customColor U 5 - 17 dessin.m2 R 5 - 13
customiz.dll U 1 - 3 dessin.m2 U 1 - 3
customiz.dll U 3 - 2 dessin.mo U 1 - 3
customiz.dl_ U 1 - 3 dictionary R 3 - 13
customiz.dl_ U 3 - 3 dictionary R 3 - 13
C_FUNCTION R 7 - 15; 20 dictionary R 3 - 25
C_FUNCTION_BACKTRACK R 7 - 15; 20 dictionary R 6 - 25
dif R 2 - 6

© PrologIA
Aociation Prolog
I-4 Prolog II+ Windows Index HERITAGE

DIRECT_C_FUNCTION R 7 - 15; 23 eof_action R 10 - 13; 14


discontiguous R 3 - 22 eof_code R 10 - 13
DISTANCE U 5 - 8 eol R 5 - 3
distance U 5 - 8 eq R 2 - 8
div R 4 - 4 eql R 4 - 4
dot R 4 - 1 equation R 1 - 12
double R 4 - 1; 5 equations R 2 - 12
DOUBLE_ARRAY R 7 - 15; 18 equations R 3 - 21
double_quotes R 10 - 19 equations R 3 - 22
Drawing area U 5 - 4 err.txt U 1 - 2; 8
draw_equ R 5 - 11 err.txt U 2 - 9
draw_mode R 5 - 12 ERROR R 8 - 2
draw_tree R 5 - 11 error R 10 - 13
dynamic R 3 - 22 exit R 3 - 32
echo R 5 - 13 exit R 6 - 1
edinburg.mo U 1 - 3; 8 exit U 1 - 7
edinburg.mo U 2 - 4 exit U 2 - 2
edinburgh R 6 - 23 exp R 4 - 6
EDIT U 5 - 2; 7 expredef.c R 7 - 1
edit R 6 - 3; 4 extern_event U 5 - 48
edit U 5 - 7; 16 fail R 2 - 8
Editfield U 5 - 4 fail_if R 10 - 4
editm R 3 - 14; 15; 27 fasserta R 3 - 23
editm R 6 - 3 fassertz R 3 - 23
editor R 0 - 4 fgetargtype R 7 - 3
edit_area R 5 - 2 fgetdouble R 7 - 5
edit_field U 5 - 16 fgetinteger R 7 - 5
enable_menu U 5 - 24 fgetmaxstring R 7 - 5
end_module R 3 - 15 fgetreal R 7 - 5
end_of_file R 10 - 15; 16 fgetstring R 7 - 5
end_of_stream R 10 - 14 fgetstrterm R 7 - 8
end_screen U 5 - 6 fgetterm R 7 - 14
ensure_loaded R 3 - 23 file.end U 1 - 8
enum R 4 - 12 file_dictionary R 3 - 13
eof R 5 - 3 file_name R 10 - 13

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I-5

file_window U 5 - 9 freeze R 3 - 20
findall R 2 - 8 freplace R 3 - 23
find_pattern R 4 - 10 frequent errors R 0 - 5
float R 4 - 5 fresetpermanentsymbol R 7 - 14
float R 10 - 6 fretract R 3 - 23
floor R 4 - 5 fretractall R 3 - 24
flush R 5 - 9 front_window U 5 - 10
flush_output R 10 - 17 fr_err.txt U 1 - 2; 3
focus U 5 - 17 fr_err.txt U 2 - 9
focus_in U 5 - 20 fsetpermanentsymbol R 7 - 14
focus_out U 5 - 20 fsymbolstring R 7 - 13
FONT U 5 - 8 functor R 10 - 9
font U 5 - 8; 17 gc R 6 - 25
fontheight U 5 - 17 gendialog U 5 - 40
fonts.all U 5 - 28 gensymbol R 4 - 12
fonts.usr U 1 - 2 get R 10 - 15
fonts.usr U 5 - 28 get0 R 10 - 16
FONTSIZE U 5 - 8 getenv R 6 - 5
fontsize U 5 - 8 get_arg_type R 7 - 3
force R 10 - 13 get_attribute U 5 - 16
foreground U 5 - 17 get_byte R 10 - 15
fprefixlimit R 7 - 13 get_char R 10 - 15
fprosymbol R 7 - 13 get_code R 10 - 16
fprouser.eg R 7 - 1 get_double R 7 - 4
fputdouble R 7 - 7 get_error_complement R 8 - 11
fputinteger R 7 - 6 get_event U 5 - 13
fputreal R 7 - 7 get_event U 5 - 19
fputstring R 7 - 7 get_formats R 8 - 8; 9
fputstrterm R 7 - 8 get_integer R 7 - 4
fputterm R 7 - 15 get_key U 5 - 36
FRAMEPANEL U 5 - 3; 7 get_local_object U 5 - 19
framepanel U 5 - 7; 16 get_max_string R 7 - 4
free R 2 - 8 get_objects U 5 - 19
free R 4 - 2 get_option R 6 - 23
Freeze R 2 - 9 get_real R 7 - 4

© PrologIA
Aociation Prolog
I-6 Prolog II+ Windows Index HERITAGE

get_screen U 5 - 6 gr_get_pen U 5 - 26
get_string R 7 - 4 gr_icon U 5 - 32
get_strterm R 7 - 8 gr_line U 5 - 29
get_term R 7 - 14 gr_lineto U 5 - 29
get_tlv R 2 - 15 gr_list U 5 - 37
get_window U 5 - 10 gr_load U 5 - 32
graphic.mo U 1 - 3 gr_mode U 5 - 26
graphic.mo U 5 - 5 gr_move U 5 - 29
GRAPHICS U 5 - 3; 7 gr_moveto U 5 - 29
graphics U 5 - 7; 16 gr_pen U 5 - 26
graphic_area R 5 - 2 gr_penloc U 5 - 29
graphic_system U 5 - 6 gr_penlocr U 5 - 29
graphstr.mo U 1 - 3 gr_polygon U 5 - 30
group U 5 - 17 gr_popupItem U 5 - 38
gr_arc U 5 - 31 gr_print U 5 - 10
gr_arc' U 5 - 31 gr_rect U 5 - 29
gr_button_hit U 5 - 35 gr_sensitive U 5 - 34
gr_choosecolor U 5 - 26 gr_setorigin U 5 - 28
gr_click U 5 - 33 gr_stringwidth U 5 - 26
gr_clickr U 5 - 33 gr_text U 5 - 27
gr_color U 5 - 25 gr_tree_click U 5 - 40
gr_color1 U 5 - 25 gr_window U 5 - 10
gr_color2 U 5 - 25 gr_window_is U 5 - 10
gr_color3 U 5 - 25 gtty U 5 - 37
gr_dialog U 1 - 3 halt R 10 - 20
gr_dialog U 5 - 41 heap R 6 - 25
gr_draw_buttons U 5 - 34 hidden R 3 - 25
gr_editf U 5 - 35 hidden_debug R 3 - 25
gr_erase U 5 - 29 hidden_rule R 3 - 24
gr_font U 1 - 2 hscroll U 5 - 14; 15; 16
gr_font U 5 - 28 ident R 4 - 1
gr_getmouse U 5 - 34 if R 4 - 5
gr_getmouser U 5 - 34 ignore_ops R 10 - 19
gr_getorigin U 5 - 29 in R 5 - 4
gr_get_mode U 5 - 27 include R 3 - 25

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I-7

index R 3 - 20 int_edit.moU 5 - 6
index R 3 - 31 in_char R 5 - 3
indexing R 3 - 20 in_char' R 5 - 4
inequation R 1 - 12 in_double R 5 - 5
inf R 4 - 4 in_ident R 5 - 5
infe R 4 - 4 in_integer R 5 - 5
Infinite trees R 2 - 11 in_real R 5 - 5
infinite R 2 - 11 in_sentence R 5 - 6
infinite_flag R 2- 12 in_string R 5 - 5
initial.po R 3 - 4 in_word R 5 - 6
initial.po U 1 - 2; 8 is R 10 - 2; 7
initial.po U 2 - 2 is_array R 4 - 9
initialization R 3 - 26 is_uncompiled R 3 - 28
InitializeProlog U 3 - 3 items U 5 - 18
init_fassert R 3 - 25 items_nb U 5 - 17
init_screen U 5 - 5 keysort R 4 - 15; 16
ini_module R 3 - 14 kill_array R 4 - 9
ini_module R 3 - 17 kill_array R 7 - 16
inl R 5 - 4 kill_array U 2 - 8
Input R 5 - 2; 8 kill_goal R 8 - 3
input R 10 - 13 kill_module R 3 - 31
input U 1 - 7 kill_module R 7 - 16
input U 5 - 39 kill_module U 2 - 8
input_is R 5 - 8 kill_object U 5 - 13
insert R 3 - 26; 27 kill_window U 5 - 9
insert R 3 - 32 Label U 5 - 4
insert U 1 - 7 label U 5 - 16
insert U 2 - 7 left U 5 - 15
insertz R 3 - 26; 27 left_attach U 5 - 13
integer R 4 - 1 lg_buffer R 10 - 13
integer_rounding_function R 10 - 20 line R 5 - 10
Interruption R 2 - 6 line_width R 5 - 13
interruption R 0 - 5 list R 3 - 14
INT_ARRAY R 7 - 15; 18 list R 3 - 28
int_edit.mo U 1 - 4 Listbox U 5 - 4

© PrologIA
Aociation Prolog
I-8 Prolog II+ Windows Index HERITAGE

listbox U 5 - 16 new_drawing_area U 5 - 13
listing R 10 - 6 new_edit_field U 5 - 14
list_of R 2 - 8 new_goal R 8 - 3
list_string R 4 - 12 new_label U 5 - 15
list_tuple R 4 - 12 new_listbox U 5 - 15
lkload R 6 - 5 new_pattern R 8 - 8
lkload R 7 - 24 new_popup_menu U 5 - 15
ln R 4 - 6 new_pulldown_menu U 5 - 16
load R 3 - 31 new_push_button U 5 - 14
load U 2 - 8 new_radio_button U 5 - 14
log R 10 - 7 new_scrollbar U 5 - 16
max_arity R 10 - 19 new_tlv R 2 - 14
member R 4 - 12 new_window U 5 - 7
memory_file R 5 - 1 next_char R 5 - 4
memory_file R 5 - 2 next_char' R 5 - 4
message_box U 5 - 35 next_solution R 8 - 3
mod R 1 - 20 nl R 10 - 17
mod R 4 - 4 nonvar R 10 - 6
mod R 10 - 2 not R 2 - 8
MODAL U 5 - 7; 8 not R 10 - 14
modal U 5 - 7; 8 not_defined R 3 - 28
mode R 10 - 13 no_border U 5 - 13; 15
module R 3 - 15 no_debug R 6 - 17
module R 3 - 19 no_echo R 5 - 13
module U 2 - 7 NO_GOAL R 8 - 2
module_context R 3 - 27 no_index R 3 - 32
module_file R 3 - 27 no_infinite R 2 - 11
month R 6 - 4 no_paper R 5 - 11
"MPW" U 5 - 37 NO_RESIZE U 5 - 8
ms_err R 6 - 5 no_resize U 5 - 8
mul R 4 - 4 no_spy R 6 - 18
multifile R 3 - 28 no_trace R 6 - 7; 17
multiple U 5 - 14; 15 number R 10 - 6
name R 10 - 9 numbervars R 10 - 19
new_check_button U 5 - 13 number_chars R 10 - 10

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I-9

number_codes R 10 - 10 phrase R 10 - 10
obdialog.mo U 1 - 3 Popup menu U 5 - 4
OFFSET_ZERO_BASED R 7 - 16 popup_menu U 5 - 16
omodule R 3 - 15 position R 10 - 13
omodule R 3 - 19 predefined R 3 - 29
once R 10 - 4 predicate U 5 - 17
op R 5 - 15 prefix_limit R 3 - 7
open R 10 - 13 prefix_limit R 7 - 13
operators R 1 - 13; 19 princip.c U 1 - 4
operators R 5 - 14 princip.c U 3 - 4
optimization U 2 - 7 princip.obj U 1 - 4
optimizations R 2 - 5; 11 print_window U 5 - 10
optimizations R 4 - 3; 7 proentry.c U 1 - 4
optimizations R 6 - 6 proentry.c U 3 - 3
optimizations R3 - 20 proentry.obj U 1 - 4
option U 5 - 10 proext.h R 7 - 16
or R 2 - 9 proext.h U 1 - 4
out R 5 - 9 ProFinal R 8 - 3; 5
outl R 5 - 9 ProFinal U 3 - 4
outm R 5 - 10 prolink R 7 - 16
outml R 5 - 10 prolink.bat U 1 - 4
Output R 5 - 9; 12 prolink.bat U 2 - 11
output R 10 - 13 prolog U 5 - 21
output U 5 - 39 prolog.def U 1 - 4
output_is R 5 - 12 prolog.def U 3 - 3
out_equ R 5 - 10 prolog.exe U 1 - 3
page R 5 - 10 prolog.exe U 3 - 2
paper R 5 - 10 prolog.lib U 1 - 4
parasite R 1 - 17 prolog.log U 2 - 8
parent U 5 - 16 prolog.po U 2 - 2; 10
past R 10 - 14 prolog.res U 1 - 5
peek_byte R 10 - 16 prolog2.pre U 1 - 3
peek_char R 10 - 16 prolog2.pre U 2 - 3
peek_code R 10 - 16 prolog32.exe U 1 - 4
peek_event U 5 - 20 PrologDir2 U 1 - 3; 8

© PrologIA
Aociation Prolog
I - 10 Prolog II+ Windows Index HERITAGE

PrologDir2 U 2 - 2; 9 radio_button U 5 - 16
PrologEdit U 1 - 4; 8 rank U 5 - 18
PrologEdit U 5 - 6 read R 5 - 2
prologII R 6 - 24 read R 10 - 16
prologIIE R 6 - 24 read_line R 10 - 16
ProStart R 8 - 3; 5 read_rule R 5 - 7
ProStart U 3 - 3 read_term R 10 - 16
protected U 5 - 18 read_unit R 5 - 7
prouser.c R 4 - 10 real R 4 - 1
prouser.c U 1 - 5 realloc R 6 - 25
prouser.c U 2 - 11 reconsult R 10 - 5
prouser.c U 3 - 3 redef_array R 4 - 9
prouser.obj U 1 - 5 reinsert R 3 - 26; 27
pro_signal R 9 - 2 reload R 3 - 32
pro_symbol R 7 - 13 reload U 2 - 8
Pulldown menu U 5 - 4 rem R 1 - 20
pulldown_menu U 5 - 16 rem R 4 - 4
Push button U 5 - 4 rem R 10 - 2
push_button U 5 - 16 remove_implicit R 3 - 12
put R 10 - 18 remove_sentence_terminator R 5 - 7
put_byte R 10 - 18 repeat R 2 - 9
put_char R 10 - 18 reposition R 10- 13
put_code R 10 - 18 reposition R 10 - 14
put_double R 7 - 6 reset R 10 - 13
put_integer R 7 - 6 reset_chrono R 6 - 4
put_real R 7 - 6 reset_cpu_time R 6 - 4
put_string R 7 - 6 reset_permanent_symbol R 6 - 25
put_strterm R 7 - 8 reset_permanent_symbol R 7 - 14
put_term R 7 - 14 reset_window U 5 - 11
quit R 0 - 5 restore_C_backtrack_data R 7 - 21
quit R 6 - 1 restore_menubar U 5 - 21
quit U 2 - 2 restore_sysmenus U 5 - 21
quoted R 10 - 19 retract R 3 - 30
rad R 4 - 6 retract R 10 - 6
Radio button U 5 - 4 retractall R 10 - 6

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I - 11

right U 5 - 15 set_input R 10 - 17
right_attach U 5 - 13 set_line_cursor R 5 - 11
round R 4 - 5 set_line_width R 5 - 13
rule R 1 - 13 set_menu U 5 - 22
rule R 3 - 20 set_options R 6 - 24
rule R 3 - 29 set_output R 10 - 18
rule U 2 - 7 set_permanent_symbol R 6 - 25
rule_nb R 3 - 30 set_permanent_symbol R 7 - 14; 19
SAVE U 5 - 8 set_prefix_limit R 3 - 7; 17
save R 3 - 32 set_prolog_flag R 10 - 20
save U 2 - 8 set_stream_position R 10 - 13
save U 5 - 8; 13 set_tlv R 2 - 15
save_menubar U 5 - 21 set_window U 5 - 11
save_state R 3 - 32 sfgetfile U 5 - 39
save_window U 5 - 11 sfputfile U 5 - 40
Scrollbar U 5 - 5 SHAPE U 5 - 8
scrollbar U 5 - 16 shape U 5 - 8
scrollb_page U 5 - 19 show_spy R 6 - 18
scrollb_pos U 5 - 19 sign R 4 - 5
scrollb_range U 5 - 19 sin R 4 - 6
scrollb_step U 5 - 19 singleton R 3 - 27
see R 10 - 17 singletons R 10 - 17
seeing R 10 - 17 SINGLE_FLOAT_ARRAY R 7 - 15; 18
seen R 10 - 17 SOLUTION_EXISTS R 8 - 2
selected_items U 5 - 18 sort R 4 - 15; 16
send_external_event U 5 - 47 specified fact R 1 - 13; 15
send_prolog_interrupt R 9 - 3 split R 4 - 13
setarg R 4 - 12 sprintf R 5 - 11
setof R 2 - 9 sprintf R 7 - 23
set_alias R 1 - 26 spy R 6 - 18
set_attribute U 5 - 17 sqrt R 4 - 6
set_context R 3 - 11 sscanf R 5 - 7
set_cursor R 5 - 11 sscanf R 7 - 23
set_draw_mode R 5 - 12 stack R 6 - 25
set_import_dir R 6 - 5 stacks R 6 - 25

© PrologIA
Aociation Prolog
I - 12 Prolog II+ Windows Index HERITAGE

StartPrologMainGoal U 3 - 4 TerminateProlog U 3 - 4
state R 6 - 24 terms R 1 - 11
state U 5 - 18 term_cmp R 2 - 8; 9
statistics R 6 - 24 term_cmp R 4 - 15
store_C_backtrack_data R 7 - 20 term_cmpv R 4 - 15
stream_property R 10 - 13 term_expansion R 10 - 21
String operations R 4 - 9 term_vars R 4 - 14
string R 4 - 1 text R 5 - 1
STRING_ARRAY R 7 - 15; 18 text U 5 - 18
string_double R 4 - 13 text_selection U 5 - 18
string_ident R 4 - 13 The cut "!" R 2 - 2
string_integer R 4 - 13 throw R 10 - 4
string_real R 4 - 13 time R 6 - 4; 5
string_term R 4 - 14 told R 10 - 18
stty U 5 - 36 toplist U 5 - 19
style_menu U 5 - 24 top_attach U 5 - 13
sub R 4 - 4 top_left U 5 - 18
substring R 4 - 10 trace R 6 - 7; 17
sub_atom R 10 - 11 trail R 6 - 25
sup R 4 - 5 tree R 1 - 8
supe R 4 - 5 true R 10 - 5
suppress R 3 - 30 trunc R 4 - 5
suppress R 7 - 16 truncate R 10 - 7
suppress U 2 - 8 TTY U 5 - 3; 7
SYMBOL_ARRAY R 7 - 15; 19 "TTY" U 5 - 37
symbol_string R 7 - 13 tty U 5 - 7; 16
sys_command R 6 - 5 tty_area R 5 - 2
tab R 10 - 18 tuple R 4 - 1
tab_user_param U 2 - 9 tval R 4 - 3
tan R 4 - 6 Type testing rules R 4 - 1
tassign R 4 - 7 type R 10 - 13; 14
tell R 10 - 18 type U 5 - 16
telling R 10 - 18 unification R 1 - 16
TEMP U 1 - 8 unify_tlv R 2 - 15
term R 1 - 8 unify_with_occurs_check R 10 - 5

© PrologIA
Aociation Prolog

HERITAGE Prolog II+ Windows Index I - 13

unix_pipe R 5 - 1
unknown R 10 - 19
update U 5 - 20
userdll.mak U 1 - 6
usermpty.c U 1 - 5
userrsc.rc U 3 - 3
user_field U 5 - 18
use_win.h U 1 - 5
val R 3 - 20
val R 4 - 3
val U 2 - 7
var R 10 - 6
variable R 1 - 3
variables R 10 - 16
variable_names R 10 - 16
var_time R 4 - 2
version R 6 - 24
visibility U 5 - 18
vscroll U 5 - 14; 16
wait U 5 - 17
week R 6 - 4
width_height U 5 - 18
write R 5 - 2
write R 10 - 18
writeq R 10 - 18
write_canonical R 10 - 18
write_term R 10 - 18
\ R 10 - 3; 7
\+ R 10 - 2; 3
\/ R 1 - 20
\/ R 4 - 6
\/ R 10 - 2
\= R 10 - 2; 3
\== R 10 - 2; 11

© PrologIA
Aociation Prolog
I - 14 Prolog II+ Windows Index HERITAGE

© PrologIA

 

   

You might also like