\hy-9{0}{
}








\hy-5{2}{Manual for PROLOGIO: a Prolog-compatible I/O and RPC library for C++}

\hy-6{3}{Julian Smart
Decision Support Group
Artificial Intelligence Applications Institute
80 South Bridge
University of Edinburgh
EH1 1HN}

October 1994






\hy-5{1}{Contents}

\hy-6{4}{Summary}

\hy-6{8}{Introduction}

\hy-6{50}{PROLOGIO requirements}

\hy-6{55}{Bugs and future developments}

\hy-6{63}{Tutorial}

\hy-6{71}{Class reference}


\hy-10{5}{Summary}




PROLOGIO is a C++ library for performing two main functions:


\hy-8{6}{1.}  reading and writing a subset of Prolog syntax
\hy-8{7}{2.}  implementing a remote procedure call facility (RPC) for
client-server communication


This document describes the PROLOGIO API (Application Programming
Interface). It can be used to develop programs with readable, robust and
Prolog-compatible data files, as well as making RPC communication simple
to program on UNIX and PCs. The library requires the wxWindows library
for XView and Windows 3.

The Prolog I/O and RPC facilities are combined in the one package since
they both relate to reading and writing complex structures to and from
ASCII strings or files, and use the same YACC and LEX-based parser to do
so.


\hy-10{9}{Introduction}




During the development of the tool HARDY within the AIAI, a need arose
for a data file format for C++ that was easy for both humans and
programs to read, was robust in the face of fast-moving software
development, and that provided some compatibility with AI languages
such as Prolog and LISP.

The result was the PROLOGIO library, which is able to read and write a
Prolog-like attribute-value syntax, and is additionally capable of
writing LISP syntax for no extra programming effort.  The advantages of
such a library are as follows:


\hy-8{10}{1.}  The data files are readable by humans
\hy-8{11}{2.}  I/O routines are easier to write and debug compared with using binary files
\hy-8{12}{3.}  The files are robust: unrecognised data will just be ignored by the application
\hy-8{13}{4.}  Inbuilt hashing gives a random access capability, useful for when linking
up C++ objects as data is read in
\hy-8{14}{5.}  Prolog and LISP programs can load the files using a single command


The library was extended to use the ability to read and write
Prolog-like structures for remote procedure call (RPC) communication.
The next two sections outline the two main ways the library can be used.

\hy-8{15}{PROLOGIO for data file manipulation}

\hy-8{28}{PROLOGIO for RPC}

\hy-8{48}{Availability and location of PROLOGIO}


\hy-10{51}{PROLOGIO requirements}




To make use of PROLOGIO, you currently need the following:


\hy-8{52}{1.}  GNU C++ version 2.1 or later, or Microsoft C/C++ version 7 or Visual C++
\hy-8{53}{2.}  The PROLOGIO library (libproio.a or prologio.lib) and header files
\hy-8{54}{3.}  The wxWindows library (available from Julian Smart at AIAI)


To recompile the library, you need YACC and LEX on UNIX, Gnu YACC on DOS.

If possible, use the LEX-generated output lex_yy.c (supplied).
However, users have reported difficulties in parsing lex_yy.c with
Borland C++. If this is the case, or you need to regenerate lex_yy.c
locally, use FLEX (widely available).  See badcase.txt in the docs
directory, and try loading it into the test program: it should
thoroughly test out the PROLOGIO parser and lexer.

In the distribution, the file flexyy.c is the FLEX generated output,
and lexyy.c is the LEX generated output. If compiling the FLEX
version, copy flexyy.c over lex_yy.c.


\hy-10{56}{Bugs and future developments}




\hy-8{57}{Bugs}

\hy-8{61}{Future developments}


\hy-10{64}{Tutorial}



This chapter is a brief introduction to using the PROLOGIO package.

First, some terminology.  A \hy-7{65}{Prolog database} is a list of \hy-7{66}{clauses},
each of which represents an object or record which needs to be saved to a file.
A clause has a \hy-7{67}{functor} (name), and a list of attributes, each of which
has a value.  Attributes may take the following types of value: string, word,
integer, floating point number, and list.  A list can itself contain any
type, allowing for nested data structures.

Consider the following code.

\hy-14{68}{PrologDatabase db;

PrologExpr *my_clause = new PrologExpr("object");
my_clause->AddAttributeValue("id", (long)1);
my_clause->AddAttributeValueString("name", "Julian Smart");
db.Append(my_clause);

ofstream file("my_file");
db.WriteProlog(file);
}
This creates a database, constructs a clause, adds it to the database,
and writes the whole database to a file.  The file it produces looks like
this:

\hy-14{69}{object(id = 1,
  name = "Julian Smart").
}
To read the database back in, the following will work:

\hy-14{70}{PrologDatabase db;
db.ReadProlog("my_file");

db.BeginFind();

PrologExpr *my_clause = db.FindClauseByFunctor("object");
int id = 0;
char *name = "None found";

my_clause->AssignAttributeValue("id", &id);
my_clause->AssignAttributeValue("name", &name);

cout << "Id is " << id << ", name is " << name << "\n";
}
Note the setting of defaults before attempting to retrieve attribute values,
since they may not be found.

\hy-10{72}{Class reference}




These are the main PROLOGIO classes.

\hy-8{73}{ClipsTemplate: wxObject}

\hy-8{95}{PrologDatabase: wxList}

\hy-8{185}{PrologExpr}

\hy-8{379}{Functions and Macros}


\hy-10{16}{PROLOGIO for data file manipulation}



The fact that the output is in Prolog syntax may be irrelevant for most
programmers, who just need a reasonable I/O facility.  Typical output
looks like this:

\hy-14{17}{diagram_definition(type = "Spirit Belief Network").

node_definition(type = "Model",
  image_type = "Diamond",
  attribute_for_label = "name",
  attribute_for_status_line = "label",
  colour = "CYAN",
  default_width = 120,
  default_height = 80,
  text_size = 10,
  can_resize = 1,
  has_hypertext_item = 1,
  attributes = ["name", "combining_function", "level_of_belief"]).

arc_definition(type = "Potentially Confirming",
  image_type = "Spline",
  arrow_type = "End",
  line_style = "Solid",
  width = 1,
  segmentable = 0,
  attribute_for_label = "label",
  attribute_for_status_line = "label",
  colour = "BLACK",
  text_size = 10,
  has_hypertext_item = 1,
  can_connect_to = ["Evidence", "Cluster", "Model", "Evidence", "Evidence", "Cluster"],
  can_connect_from = ["Data", "Evidence", "Cluster", "Evidence", "Data", "Cluster"]).
}
This is substantially easier to read and debug than a series of numbers and
strings.

Note the object-oriented style: a file comprises a series of \hy-7{18}{clauses}.
Each clause is an object with a \hy-7{19}{functor} or object name, followed
by a list of attribute-value pairs enclosed in parentheses, and finished
with a full stop.  Each attribute value may be a string, a word (no quotes),
an integer, a real number, or a list with potentially recursive elements.

The way that the facility is used by an application to read in a file is
as follows:


\hy-8{20}{1.}  The application creates a PrologDatabase instance.
\hy-8{21}{2.}  The application tells the database to read in the entire file.
\hy-8{22}{3.}  The application searches the database for objects it requires,
decomposing the objects using the PROLOGIO API. The database may be hashed,
allowing rapid linking-up of application data.
\hy-8{23}{4.}  The application deletes or clears the PrologDatabase.


Writing a file is just as easy:


\hy-8{24}{1.}  The application creates a PrologDatabase instance.
\hy-8{25}{2.}  The application adds objects to the database using the API.
\hy-8{26}{3.}  The application tells the database to write out the entire database,
in Prolog, LISP or CLIPS notation.
\hy-8{27}{4.}  The application deletes or clears the PrologDatabase.


To use the library, include "wx.h", "read.h" and link with libproio.a
(UNIX) or prologio.lib (PC) and the wxWindows library.


\hy-10{29}{PROLOGIO for RPC}



An RPC package is required because one application cannot simply call
into another's program area. The arguments and return value(s) need to
be wrapped up at one end and parsed at the other. This library provides
a convenient way of doing so, allowing a range of types of data to be passed
between applications, namely integers, reals, strings, words (unquoted
strings), and lists of these types (which can include further lists).
Therefore two main capabilities are required: a way of encoding
information in a string, and a way of communicating this string between
applications.  The basic PROLOGIO functions described above are used for
the first, and the wxWindows implementation of DDE is used for the
second.

The RPC facility is used in much the same way as the DDE facility in
wxWindows, only the base classes to use are rpcServer, rpcClient and
rpcConnection.  From these derive your own client, server and connection classes,
overriding \hy-8{30}{OnAcceptConnection} (server) and \hy-8{31}{OnMakeConnection}
(client) as usual. You now have a choice of how the server connection
responds to calls: either you can install your own \hy-8{32}{OnCall} handler
which accepts and returns Prolog structures, or you may install an \hy-8{33}{
rpcCallTable} so calls get automatically routed to appropriate C++
functions.  If no call table has been installed, the library will call
\hy-8{34}{OnCall} instead.

Note that the topic name when using the RPC package must always be
"RPC".

RPC is implemented as follows. When the client calls \hy-8{35}{
rpcConnection::Call} with a \hy-8{36}{PrologExpr} structure as argument, this
structure is written to a string and \hy-8{37}{Execute} is called. At the
server end, the data is parsed back into a \hy-8{38}{PrologExpr} structure,
and either \hy-8{39}{OnCall} is called, or, if there is a call table, a
functor (procedure name) matching the supplied name is searched for. If
one is found, the argument types are checked. If they are incorrect, an
error structure is sent back to the client. If they are correct, the
appropriate user-supplied C++ function implementing this command is
called, which returns another \hy-8{40}{PrologExpr}. This structure is
written to a string, and when the client side \hy-8{41}{Requests} the result, is
returned. The client side parses the result and returns a \hy-8{42}{
PrologExpr} as the result of the original \hy-8{43}{Call}.

To the client application, the \hy-8{44}{Call} is like a normal procedure
call except the name and arguments need to be wrapped up in a \hy-8{45}{
PrologExpr} structure, and the result is also a \hy-8{46}{PrologExpr}.
Similarly, the server application implements a series of functions, one
per command, receiving and returning \hy-8{47}{PrologExpr} structures.

To use the library, include "wx.h", "read.h", "prorpc.h" and link with
libproio.a (UNIX) or prologio.lib (PC) and the wxWindows library.


\hy-10{49}{Availability and location of PROLOGIO}



PROLOGIO is distributed as part of the wxWindows GUI library. Anyone
interested in using the library can contact Julian Smart, email
J.Smart@ed.ac.uk, tel. 031-650-2746.


\hy-10{58}{Bugs}



These are the known bugs:


\hy-8{59}{1.}  Functors are permissable only in the main clause (object).
Therefore nesting of structures must be done using lists, not predicates
as in Prolog.
\hy-8{60}{2.}  There is a limit to the size of strings read in (about 5000 bytes).



\hy-10{62}{Future developments}



None envisaged as yet.


\hy-10{74}{ClipsTemplate: wxObject}



A \hy-8{75}{ClipsTemplate} object represents a simplified representation of a
CLIPS deftemplate. ClipsTemplates can be added to a list stored with the
\hy-8{76}{PrologDatabase} to be written out along with the deffacts contained
in the database.  They may optionally be used to filter out unwanted
slots when the facts are being written out.

\hy-8{77}{ClipsTemplate::ClipsTemplate}

\hy-8{81}{ClipsTemplate::AddSlot}

\hy-8{87}{ClipsTemplate::SlotExists}

\hy-8{91}{ClipsTemplate::Write}


\hy-10{96}{PrologDatabase: wxList}



The \hy-8{97}{PrologDatabase} class represents a database, or list,
of Prolog-like expressions.  Instances of this class are used for reading,
writing and creating data files.

\hy-8{98}{PrologDatabase::PrologDatabase}

\hy-8{112}{PrologDatabase::AddTemplate}

\hy-8{116}{PrologDatabase::Append}

\hy-8{120}{PrologDatabase::BeginFind}

\hy-8{124}{PrologDatabase::ClearDatabase}

\hy-8{127}{PrologDatabase::FindClause}

\hy-8{140}{PrologDatabase::FindClauseByFunctor}

\hy-8{144}{PrologDatabase::FindTemplate}

\hy-8{148}{PrologDatabase::GetErrorCount}

\hy-8{151}{PrologDatabase::HashFind}

\hy-8{161}{PrologDatabase::ReadProlog}

\hy-8{165}{PrologDatabase::ReadPrologFromString}

\hy-8{169}{PrologDatabase::WriteClips}

\hy-8{173}{PrologDatabase::WriteClipsFiltering}

\hy-8{177}{PrologDatabase::WriteLisp}

\hy-8{181}{PrologDatabase::WriteProlog}


\hy-10{186}{PrologExpr}



The \hy-8{187}{PrologExpr} class is the building brick of Prolog expressions.
It can represent both a clause, and any subexpression (long integer, float, string, word,
or list).

\hy-8{188}{PrologExpr::PrologExpr}

\hy-8{209}{PrologExpr::~PrologExpr}

\hy-8{212}{PrologExpr::AddAttributeValue}

\hy-8{231}{PrologExpr::AddAttributeValueString}

\hy-8{236}{PrologExpr::AddAttributeValueStringList}

\hy-8{243}{PrologExpr::AddAttributeValueWord}

\hy-8{248}{PrologExpr::Append}

\hy-8{254}{PrologExpr::Arg}

\hy-8{261}{PrologExpr::Insert}

\hy-8{267}{PrologExpr::AssignAttributeValue}

\hy-8{284}{PrologExpr::AssignAttributeValueStringList}

\hy-8{289}{PrologExpr::AttributeValue}

\hy-8{294}{PrologExpr::Copy}

\hy-8{297}{PrologExpr::DeleteAttributeValue}

\hy-8{301}{PrologExpr::Functor}

\hy-8{304}{PrologExpr::GetClientData}

\hy-8{308}{PrologExpr::GetFirst}

\hy-8{314}{PrologExpr::GetLast}

\hy-8{320}{PrologExpr::GetNext}

\hy-8{326}{PrologExpr::IntegerValue}

\hy-8{329}{PrologExpr::Nth}

\hy-8{336}{PrologExpr::RealValue}

\hy-8{339}{PrologExpr::SetClientData}

\hy-8{344}{PrologExpr::StringValue}

\hy-8{347}{PrologExpr::Type}

\hy-8{352}{PrologExpr::WordValue}

\hy-8{355}{PrologExpr::WriteClipsClause}

\hy-8{364}{PrologExpr::WriteLispExpr}

\hy-8{369}{PrologExpr::WritePrologClause}

\hy-8{374}{PrologExpr::WritePrologExpr}


\hy-10{380}{Functions and Macros}



Below are miscellaneous functions and macros associated with PrologExpr objects.

\hy-8{381}{Functions}

\hy-8{401}{Macros}


\hy-10{78}{ClipsTemplate::ClipsTemplate}



\hy-8{79}{void ClipsTemplate(char * \hy-8{80}{name})}

Construct a new template.


\hy-10{82}{ClipsTemplate::AddSlot}



\hy-8{83}{void AddSlot(char * \hy-8{84}{slot_name},
  char * \hy-8{85}{default = NULL}, Bool \hy-8{86}{ multi=FALSE})}

Add a slot to a CLIPS template definition, with optional default and
multislot flag (currently only one multislot allowed per template).


\hy-10{88}{ClipsTemplate::SlotExists}



\hy-8{89}{ClipsTemplateSlot * SlotExists(char * \hy-8{90}{slot_name})}

Returns a template slot if it exists.


\hy-10{92}{ClipsTemplate::Write}



\hy-8{93}{void Write(ostream& \hy-8{94}{ stream})}

Write the template to the given stream.


\hy-10{99}{PrologDatabase::PrologDatabase}



\hy-8{100}{void PrologDatabase(proioErrorHandler \hy-8{101}{ handler = 0})}

Construct a new, unhashed database, with an optional error handler. The
error handler must be a function returning a Bool and taking an integer and a string
argument. When an error occurs when reading or writing a database, this function is
called. The error is given as the first argument (currently one of PROIO_ERROR_GENERAL,
PROIO_ERROR_SYNTAX) and an error message is given as the second argument. If FALSE
is returned by the error handler, processing of the PROLOGIO operation stops.

Another way of handling errors is simply to call \hy-13{102}{GetErrorCount} after
the operation, to check whether errors have occurred, instead of installing an error handler.
If the error count is more than zero, \hy-13{103}{WriteProlog} and \hy-13{104}{ReadProlog} will return FALSE to
the application.

For example:

\hy-14{105}{Bool myErrorHandler(int err, chat *msg)
{
  if (err == PROIO_ERROR_SYNTAX)
  {
    wxMessageBox(msg, "Syntax error");
  }
  return FALSE;
}

PrologDatabase database(myErrorHandler);
}

\hy-8{106}{void PrologDatabase(PrologType \hy-8{107}{ type}, char * \hy-8{108}{attribute},

 int \hy-8{109}{ size = 500}, proioErrorHandler \hy-8{110}{ handler = 0})}

Construct a new database hashed on a combination of the clause functor and
a named attribute (often an integer identification).

See above for an explanation of the error handler.

\hy-8{111}{void ~PrologDatabase(void)}

Delete the database and contents.


\hy-10{113}{PrologDatabase::AddTemplate}



\hy-8{114}{void AddTemplate(ClipsTemplate * \hy-8{115}{temp})}

Add a CLIPS template definition to the template list associated with the
database.



\hy-10{117}{PrologDatabase::Append}



\hy-8{118}{void Append(PrologExpr * \hy-8{119}{clause})}

Append a clause to the end of the database. If the database is hashing,
the functor and a user-specified attribute will be hashed upon, giving the
option of random access in addition to linear traversal of the database.


\hy-10{121}{PrologDatabase::BeginFind}



\hy-8{122}{void BeginFind(void)}

Reset the current position to the start of the database. Subsequent
\hy-7{123}{FindClause} calls will move the pointer.


\hy-10{125}{PrologDatabase::ClearDatabase}



\hy-8{126}{void ClearDatabase(void)}

Clears the contents of the database.


\hy-10{128}{PrologDatabase::FindClause}



Various ways of retrieving clauses from the database. A return
value of NULL indicates no (more) clauses matching the given criteria.
Calling the functions repeatedly retrieves more matching clauses, if any.

\hy-8{129}{PrologExpr * FindClause(long \hy-8{130}{ id})}

Find a clause based on the special ``id'' attribute.

\hy-8{131}{PrologExpr * FindClause(char * \hy-8{132}{attribute}, char * \hy-8{133}{value})}

Find a clause which has the given attribute set to the given string or word value.

\hy-8{134}{PrologExpr * FindClause(char * \hy-8{135}{attribute}, long \hy-8{136}{ value})}

Find a clause which has the given attribute set to the given integer value.

\hy-8{137}{PrologExpr * FindClause(char * \hy-8{138}{attribute}, float \hy-8{139}{ value})}

Find a clause which has the given attribute set to the given floating point value.


\hy-10{141}{PrologDatabase::FindClauseByFunctor}



\hy-8{142}{PrologExpr * FindClauseByFunctor(char * \hy-8{143}{ functor})}

Find the next clause with the specified functor.


\hy-10{145}{PrologDatabase::FindTemplate}



\hy-8{146}{ClipsTemplate * FindTemplate(char * \hy-8{147}{template_name})}

Finds a named CLIPS template definition associated with the database.


\hy-10{149}{PrologDatabase::GetErrorCount}



\hy-8{150}{int GetErrorCount(void)}

Returns the number of errors encountered during the last read or write operation.


\hy-10{152}{PrologDatabase::HashFind}



\hy-8{153}{PrologExpr * HashFind(char * \hy-8{154}{ functor}, long \hy-8{155}{ value})}

Finds the clause with the given functor and with the attribute specified
in the database constructor having the given integer value.

For example,

\hy-14{156}{// Hash on a combination of functor and integer "id" attribute when reading in
PrologDatabase db(PrologInteger, "id");

// Read it in
db.ReadProlog("data");

// Retrieve a clause with specified functor and id
PrologExpr *clause = db.HashFind("node", 24);
}
This would retrieve a clause which is written: \hy-14{157}{node(id = 24, ..., )}.

\hy-8{158}{PrologExpr * HashFind(char * \hy-8{159}{ functor}, char * \hy-8{160}{value})}

Finds the clause with the given functor and with the attribute specified
in the database constructor having the given string value.


\hy-10{162}{PrologDatabase::ReadProlog}



\hy-8{163}{Bool ReadProlog(char * \hy-8{164}{ filename})}

Reads in the given file, returning TRUE if successful.


\hy-10{166}{PrologDatabase::ReadPrologFromString}



\hy-8{167}{Bool ReadProlog(char * \hy-8{168}{ buffer})}

Reads a Prolog database from the given string buffer, returning TRUE if
successful.


\hy-10{170}{PrologDatabase::WriteClips}



\hy-8{171}{void WriteClips(ostream&  \hy-8{172}{stream})}

Writes the database as a CLIPS deftemplate and deffacts file.


\hy-10{174}{PrologDatabase::WriteClipsFiltering}



\hy-8{175}{void WriteClipsFiltering(ostream&  \hy-8{176}{stream})}

Writes the database as a CLIPS deftemplate and deffacts file, filtering
slots in the facts according to the template definitions (e.g. to reduce
the size of the output file by not including irrelevant slots).


\hy-10{178}{PrologDatabase::WriteLisp}



\hy-8{179}{void WriteLisp(ostream&  \hy-8{180}{stream})}

Writes the database as a LISP-format file.


\hy-10{182}{PrologDatabase::WriteProlog}



\hy-8{183}{void WriteProlog(ostream&  \hy-8{184}{stream})}

Writes the database as a Prolog-format file.


\hy-10{189}{PrologExpr::PrologExpr}



\hy-8{190}{void PrologExpr(char * \hy-8{191}{functor})}

Construct a new clause with this form, supplying the functor name.

\hy-8{192}{void PrologExpr(PrologType \hy-8{193}{ type}, char * \hy-8{194}{word_or_string},

Bool  \hy-8{195}{allocate = TRUE})}

Construct a new empty list, word (will be output with no quotes) or a string, depending on the
value of \hy-7{196}{type} (\hy-8{197}{PrologList}, \hy-8{198}{PrologWord}, \hy-8{199}{PrologString}).

If a word or string, the \hy-8{200}{allocate} parameter determines whether a new copy of the
value is allocated, the default being TRUE.

\hy-8{201}{void PrologExpr(long \hy-8{202}{ the_int})}

Construct an integer expression.

\hy-8{203}{void PrologExpr(float \hy-8{204}{ the_float})}

Construct a floating point expression.

\hy-8{205}{void PrologExpr(wxList * \hy-8{206}{the_list})}

Construct a list expression. The list's nodes' data should
themselves be \hy-8{207}{PrologExpr}s.

The current version of this library no longer uses the \hy-8{208}{wxList}
internally, so this constructor turns the list into its internal
format (assuming a non-nested list) and then deletes the supplied
list.


\hy-10{210}{PrologExpr::~PrologExpr}



\hy-8{211}{void ~PrologExpr(void)}

Destructor.


\hy-10{213}{PrologExpr::AddAttributeValue}



Use these on clauses ONLY. Note that the functions for adding strings
and words must be differentiated by function name which is why
they are missing from this group (see \hy-7{214}{AddAttributeValueString} and
\hy-7{215}{AddAttributeValueWord}).

\hy-8{216}{void AddAttributeValue(char * \hy-8{217}{attribute}, float  \hy-8{218}{value})}

Adds an attribute and floating point value pair to the clause.

\hy-8{219}{void AddAttributeValue(char * \hy-8{220}{attribute}, long  \hy-8{221}{value})}

Adds an attribute and long integer value pair to the clause.

\hy-8{222}{void AddAttributeValue(char * \hy-8{223}{attribute}, wxList * \hy-8{224}{value})}

Adds an attribute and list value pair to the clause, converting the list into
internal form and then deleting \hy-8{225}{value}. Note that the list should not contain
nested lists (except if in internal \hy-8{226}{PrologExpr} form.)

\hy-8{227}{void AddAttributeValue(char * \hy-8{228}{attribute}, PrologExpr ** \hy-8{229}{value})}

Adds an attribute and PrologExpr value pair to the clause. Do not delete
\hy-7{230}{value} once this function has been called.


\hy-10{232}{PrologExpr::AddAttributeValueString}



\hy-8{233}{void AddAttributeValueString(char * \hy-8{234}{attribute}, char * \hy-8{235}{value})}

Adds an attribute and string value pair to the clause.


\hy-10{237}{PrologExpr::AddAttributeValueStringList}



\hy-8{238}{void AddAttributeValueStringList(char * \hy-8{239}{attribute}, wxList * \hy-8{240}{value})}

Adds an attribute and string list value pair to the clause.

Note that the list passed to this function is a list of strings, NOT a list
of \hy-8{241}{PrologExpr}s; it gets turned into a list of \hy-8{242}{PrologExpr}s
automatically. This is a convenience function, since lists of strings
are often manipulated in C++.


\hy-10{244}{PrologExpr::AddAttributeValueWord}



\hy-8{245}{void AddAttributeValueWord(char * \hy-8{246}{attribute}, char * \hy-8{247}{value})}

Adds an attribute and word value pair to the clause.


\hy-10{249}{PrologExpr::Append}



\hy-8{250}{void Append(PrologExpr * \hy-8{251}{value})}

Append the \hy-8{252}{value} to the end of the list. The \hy-8{253}{PrologExpr}
must be a list.


\hy-10{255}{PrologExpr::Arg}



\hy-8{256}{PrologExpr * Arg(PrologType \hy-8{257}{ typ}, int \hy-8{258}{ n})}

Get nth arg of the given clause (starting from 1). NULL is returned if
the expression is not a clause, or \hy-7{259}{n} is invalid, or the given type
does not match the actual type. See also \hy-13{260}{Nth}.


\hy-10{262}{PrologExpr::Insert}



\hy-8{263}{void Insert(PrologExpr * \hy-8{264}{value})}

Insert the \hy-8{265}{value} at the start of the list. The \hy-8{266}{PrologExpr} 
must be a list.


\hy-10{268}{PrologExpr::AssignAttributeValue}



These functions are the easiest way to retrieve attribute values, by
passing a pointer to variable. If the attribute is present, the
variable will be filled with the appropriate value.  If not, the
existing value is left alone.  This style of retrieving attributes
makes it easy to set variables to default values before calling these
functions; no code is necesary to check whether the attribute is
present or not.

\hy-8{269}{void AssignAttributeValue(char * \hy-8{270}{attribute}, char ** \hy-8{271}{value})}

Retrieve a string (or word) value.

\hy-8{272}{void AssignAttributeValue(char * \hy-8{273}{attribute}, float * \hy-8{274}{value})}

Retrieve a floating point value.

\hy-8{275}{void AssignAttributeValue(char * \hy-8{276}{attribute}, int * \hy-8{277}{value})}

Retrieve an integer value.

\hy-8{278}{void AssignAttributeValue(char * \hy-8{279}{attribute}, long * \hy-8{280}{value})}

Retrieve a long integer value.

\hy-8{281}{void AssignAttributeValue(char * \hy-8{282}{attribute}, PrologExpr ** \hy-8{283}{value})}

Retrieve a PrologExpr pointer.


\hy-10{285}{PrologExpr::AssignAttributeValueStringList}



\hy-8{286}{void AssignAttributeValueStringList(char * \hy-8{287}{attribute},
 wxList * \hy-8{288}{value})}

Use this on clauses ONLY. See above for comments on this style of
attribute value retrieval. This function expects to receive a pointer to
a new list (created by the calling application); it will append strings
to the list if the attribute is present in the clause.


\hy-10{290}{PrologExpr::AttributeValue}



\hy-8{291}{PrologExpr * AttributeValue(char * \hy-8{292}{word})}

Use this on clauses ONLY. Searches the clause for an attribute
matching \hy-7{293}{word}, and returns the value associated with it.


\hy-10{295}{PrologExpr::Copy}



\hy-8{296}{PrologExpr * Copy(void)}

Recursively copies the expression, allocating new storage space.


\hy-10{298}{PrologExpr::DeleteAttributeValue}



\hy-8{299}{void DeleteAttributeValue(char * \hy-8{300}{attribute})}

Use this on clauses ONLY. Deletes the attribute and its value (if any) from the
clause.


\hy-10{302}{PrologExpr::Functor}



\hy-8{303}{char * Functor(void)}

Use this on clauses ONLY. Returns the clause's functor (object name).


\hy-10{305}{PrologExpr::GetClientData}



\hy-8{306}{wxObject * GetClientData(void)}

Retrieve arbitrary data stored with this clause. This can be useful when
reading in data for storing a pointer to the C++ object, so when another
clause makes a reference to this clause, its C++ object can be retrieved.
See \hy-7{307}{SetClientData}.


\hy-10{309}{PrologExpr::GetFirst}



\hy-8{310}{PrologExpr * GetFirst(void)}

If this is a list expression (or clause), gets the first element in the list.

See also \hy-13{311}{GetLast}, \hy-13{312}{GetNext}, \hy-13{313}{Nth}.


\hy-10{315}{PrologExpr::GetLast}



\hy-8{316}{PrologExpr * GetLast(void)}

If this is a list expression (or clause), gets the last element in the list.

See also \hy-13{317}{GetFirst}, \hy-13{318}{GetNext}, \hy-13{319}{Nth}.


\hy-10{321}{PrologExpr::GetNext}



\hy-8{322}{PrologExpr * GetNext(void)}

If this is a node in a list (any PrologExpr may be a node in a list), gets the
next element in the list.

See also \hy-13{323}{GetFirst}, \hy-13{324}{GetLast}, \hy-13{325}{Nth}.


\hy-10{327}{PrologExpr::IntegerValue}



\hy-8{328}{long IntegerValue(void)}

Returns the integer value of the expression.


\hy-10{330}{PrologExpr::Nth}



\hy-8{331}{PrologExpr * Nth(int \hy-8{332}{ n})}

Get nth arg of the given list expression (starting from 0). NULL is returned if
the expression is not a list expression, or \hy-7{333}{n} is invalid. See also \hy-13{334}{Arg}.

Normally, you would use attribute-value pairs to add and retrieve data
from objects (clauses) in a data file. However, if the data gets complex,
you may need to store attribute values as lists, and pick them apart
yourself.

Here is an example of using lists.

\hy-14{335}{  int regionNo = 1;
  char regionNameBuf[20];

  PrologExpr *regionExpr = NULL;
  sprintf(regionNameBuf, "region%d", regionNo);

  // Keep getting attribute values until no more regions.
  while (regionExpr = clause->AttributeValue(regionNameBuf))
  {
    /*
     * Get the region information
     *
     */

    char *regionName = NULL;
    char *formatString = NULL;
    Bool formatMode = FORMAT_NONE;
    int fontSize = 10;
    int fontFamily = wxSWISS;
    int fontStyle = wxNORMAL;
    int fontWeight = wxNORMAL;
    char *textColour = NULL;

    if (regionExpr->Type() == PrologList)
    {
      PrologExpr *nameExpr = regionExpr->Nth(0);
      PrologExpr *stringExpr = regionExpr->Nth(1);
      PrologExpr *formatExpr = regionExpr->Nth(2);
      PrologExpr *sizeExpr = regionExpr->Nth(3);
      PrologExpr *familyExpr = regionExpr->Nth(4);
      PrologExpr *styleExpr = regionExpr->Nth(5);
      PrologExpr *weightExpr = regionExpr->Nth(6);
      PrologExpr *colourExpr = regionExpr->Nth(7);

      regionName = copystring(nameExpr->StringValue());
      formatString = copystring(stringExpr->StringValue());
      formatMode = (int)formatExpr->IntegerValue();
      fontSize = (int)sizeExpr->IntegerValue();
      fontFamily = (int)familyExpr->IntegerValue();
      fontStyle = (int)styleExpr->IntegerValue();
      fontWeight = (int)weightExpr->IntegerValue();
      textColour = copystring(colourExpr->StringValue());
    }
    wxFont *font = wxTheFontList->FindOrCreateFont(fontSize, fontFamily, fontStyle, fontWeight);
    ObjectRegion *region = new ObjectRegion;
    region->regionName = regionName;
    region->formatString = formatString;
    region->formatMode = formatMode;
    region->regionFont = font;
    region->textColour = textColour;

    regions.Append(region);

    regionNo ++;
    sprintf(regionNameBuf, "region%d", regionNo);
  }
}

\hy-10{337}{PrologExpr::RealValue}



\hy-8{338}{float RealValue(void)}

Returns the floating point value of the expression.


\hy-10{340}{PrologExpr::SetClientData}



\hy-8{341}{void SetClientData(wxObject * \hy-8{342}{data})}

Associate arbitrary data with this clause. This can be useful when
reading in data for storing a pointer to the C++ object, so when another
clause makes a reference to this clause, its C++ object can be retrieved.
See \hy-7{343}{GetClientData}.


\hy-10{345}{PrologExpr::StringValue}



\hy-8{346}{char * StringValue(void)}

Returns the string value of the expression.


\hy-10{348}{PrologExpr::Type}



\hy-8{349}{PrologType Type(void)}

Returns the type of the expression. \hy-8{350}{PrologType} is defined as follows:

\hy-14{351}{typedef enum {
    PrologNull,
    PrologInteger,
    PrologReal,
    PrologWord,
    PrologString,
    PrologList
} PrologType;
}

\hy-10{353}{PrologExpr::WordValue}



\hy-8{354}{char * WordValue(void)}

Returns the word value of the expression.


\hy-10{356}{PrologExpr::WriteClipsClause}



\hy-8{357}{void WriteClipsClause(ostream& \hy-8{358}{ stream},
  Bool \hy-8{359}{ filtering=FALSE}, PrologDatabase * \hy-8{360}{database = NULL})}

Writes the clause to the given stream in CLIPS `deffacts' format. If
\hy-8{361}{filtering} is TRUE, the deftemplates associated with \hy-8{362}{database} are
used to filter out slots which exist in the CLIPS facts but not in the
deftemplates (see \hy-8{363}{PrologDatabase::AddTemplate}).


\hy-10{365}{PrologExpr::WriteLispExpr}



\hy-8{366}{void WriteLispExpr(ostream& \hy-8{367}{ stream})}

Writes the expression or clause to the given stream in LISP format.
Not normally needed, since the whole \hy-8{368}{PrologDatabase} will usually
be written at once. Lists are enclosed in parentheses will no commas.


\hy-10{370}{PrologExpr::WritePrologClause}



\hy-8{371}{void WritePrologClause(ostream& \hy-8{372}{ stream})}

Writes the clause to the given stream in Prolog format. Not normally needed, since
the whole \hy-8{373}{PrologDatabase} will usually be written at once. The format is:
functor, open parenthesis, list of comma-separated expressions, close parenthesis,
full stop.


\hy-10{375}{PrologExpr::WritePrologExpr}



\hy-8{376}{void WritePrologExpr(ostream& \hy-8{377}{ stream})}

Writes the expression (not clause) to the given stream in Prolog
format. Not normally needed, since the whole \hy-8{378}{PrologDatabase} will
usually be written at once. Lists are written in square bracketed,
comma-delimited format.


\hy-10{382}{Functions}



\hy-8{383}{PrologExpr * wxMakeCall(char * \hy-8{384}{functor}, ... \hy-8{385}{})}

Make a PrologExpr clause from a functor and a list of PrologExpr
objects \hy-7{386}{terminated with a zero (or NULL)}. Since this is normally
used for making a procedure-call expression, the arguments will not be
attribute-value pairs but straightforward data types.

\hy-8{387}{char * wxCheckClauseTypes(PrologExpr * \hy-8{388}{expr},
wxList * \hy-8{389}{type_list})}

Compares the types of the arguments of \hy-7{390}{expr} (assumed to be a
procedure call expression) against a list of types. Returns NULL if no error, or an error string if there is a
type error.

\hy-8{391}{char * wxCheckTypes(PrologExpr * \hy-8{392}{expr}, ... \hy-8{393}{})}

Compares the types of the arguments of \hy-7{394}{expr} (assumed to be a
procedure call expression) against the remaining arguments, terminated
with a NULL. Returns NULL if no error, or an error string if there is a
type error.

\hy-14{395}{char *s = wxCheckTypes(expr, PrologInteger, PrologReal, 0);
}
\hy-8{396}{Bool wxIsFunctor(PrologExpr * \hy-8{397}{expr}, char * \hy-8{398}{functor})}

Checks that the functor of \hy-7{399}{expr} is \hy-7{400}{functor}.


\hy-10{402}{Macros}



The following macros have been defined to make constructing PrologExpr
objects slightly easier:

\hy-14{403}{#define wxMakeInteger(x) (new PrologExpr((long)x))
#define wxMakeReal(x)    (new PrologExpr((float)x))
#define wxMakeString(x)  (new PrologExpr(PrologString, x))
#define wxMakeWord(x)    (new PrologExpr(PrologWord, x))
#define wxMake(x)        (new PrologExpr(x))
}




\hyindex{
"PROLOGIO Manual"
4 5
8 9
15 16
28 29
48 49
50 51
55 56
57 58
61 62
63 64
71 72
73 74
77 78
81 82
87 88
91 92
95 96
98 99
112 113
116 117
120 121
124 125
127 128
140 141
144 145
148 149
151 152
161 162
165 166
169 170
173 174
177 178
181 182
185 186
188 189
209 210
212 213
231 232
236 237
243 244
248 249
254 255
261 262
267 268
284 285
289 290
294 295
297 298
301 302
304 305
308 309
314 315
320 321
326 327
329 330
336 337
339 340
344 345
347 348
352 353
355 356
364 365
369 370
374 375
379 380
381 382
401 402
102 149
103 182
104 162
260 330
311 315
312 321
313 330
317 309
318 321
319 330
323 309
324 315
325 330
334 255
102 149
103 182
104 162
260 330
311 315
312 321
313 330
317 309
318 321
319 330
323 309
324 315
325 330
334 255
}
