CLIPS Reference Manual 6.40 Vol II
CLIPS Reference Manual 6.40 Vol II
Volume II
Advanced Programming Guide
CONTENTS
Section 1: Introduction..................................................................................................................1
1.1 C++ Compatibility ...............................................................................................................1
1.2 Threads and Concurrency ....................................................................................................1
ii Table of Contents
CLIPS Reference Manual
iv Table of Contents
CLIPS Reference Manual
vi Table of Contents
CLIPS Reference Manual
Index ............................................................................................................................................201
License Information
Permission is hereby granted, free of charge, to any person obtaining a copy of this software (the
“Software”), to deal in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Preface
About CLIPS
Developed at NASA’s Johnson Space Center from 1985 to 1996, the ‘C’ Language Integrated
Production System (CLIPS) is a rule-based programming language useful for creating expert
systems and other programs where a heuristic solution is easier to implement and maintain than
an algorithmic solution. Written in C for portability, CLIPS can be installed and used on a wide
variety of platforms. Since 1996, CLIPS has been available as public domain software.
CLIPS Documentation
• Volume III - The Interfaces Guide provides information on the CLIPS Integrated
Development Environments, wrapper classes, and example programs.
• The CLIPS User’s Guide provides an introduction to CLIPS and rule-based programming.
Section 1:
Introduction
This manual is the Advanced Programming Guide for CLIPS. It describes the Application
Programmer Interface (API) that allows users to integrate CLIPS programs with code written in
C. It is written with the assumption that the user has a basic understanding of both CLIPS and C.
It is advised that users complete the Basic Programming Guide before reading this manual.
Section 2 of this document describes how to install and tailor CLIPS to meet specific needs.
Section 3 describes the core API needed to embed CLIPS within a simple C program. Section 4
describes the API allowing the creation of constructs and the execution of commands and
functions. Section 5 describes the API that allows a C program to keep persistent references to
data structures subject to garbage collection. Section 6 describes the API for creating CLIPS
primitive data values. Section 7 describes the API for creating Facts and Instances. Section 8
describes the API for adding user-defined functions. Section 9 describes the API for the I/O
router system used by CLIPS for processing input and output requests. Section 10 describes the
environment API which allows multiple expert systems to be loaded and run concurrently.
Section 11 describes how to create run-time CLIPS programs which allow constructs to be save
as C data structures which can be compiled and linked with CLIPS. Section 12 describes the
additional APIs that are available for interacting with and retrieving information from CLIPS.
shared library such as a Dynamic Link Library (DLL). The standard command line version of
CLIPS as well as the Integrated Development Environments (IDEs) provide access to a single
environment. It is not possible to load and run multiple expert systems using these versions of
CLIPS.
If multiple environments are created, a single thread of execution can be used to run each expert
system. In this situation, one environment must finish executing before control can be passed to
another environment. The user explicitly specifies which environment should process each API
call. Once execution of an API call for that environment begins, the user must wait for
completion of the API call before passing control to another environment.
Most likely, this type of execution control will be used when you need to make several expert
systems available to a single end user, but don’t want to go through the process of clearing the
current expert system from a single environment, loading another expert system into it, and then
resetting the environment. Instead, each expert system is loaded into its own environment, so to
change expert systems it is only necessary to switch to the new environment and reset it.
A less likely scenario for this type of execution control is to simulate multiple expert systems
running concurrently. In this scenario, each environment is allowed to execute a number of rules
before control is switched to the next environment.
Instead of simulating multiple expert systems running concurrently, using the multi-threading
capabilities native to the operating system on which CLIPS is running allows concurrent
execution to occur efficiently and prevents one environment from blocking the execution of
another. In this scenario, each environment uses a single thread of execution. Since each
environment maintains its own set of data structures, it is safe to run a separate thread on each
environment. This use of environments is most likely for a shared library where it is desirable to
have a single CLIPS engine running that is shared by multiple applications.
Warning
Each environment can have at most one thread of execution. The CLIPS internal data structures
can become corrupted if two CLIPS API calls are executing at the same time for a single
environment. For example, you can’t have one thread executing rules and another thread
asserting facts for the same environment without some synchronization between the two threads.
2 Section 1: Introduction
CLIPS Reference Manual
Section 2:
Installing and Tailoring CLIPS
This section describes how to install and tailor CLIPS to meet specific needs. Instructions are
included for creating a console executable by compiling the portable core CLIPS source files.
For instructions on compiling the Windows, macOS, and Java Integrated Development
Environments for CLIPS, see the Utilities and Interfaces Guide.
• Windows 10 Home Premium 32-bit and Windows 7 Professional 64-bit Operating Systems
with Visual Studio Community 2017.
• Ubuntu 16.04 LTS using gcc 5.4.0; Debian GNU/Linux 9.1 with gcc 6.3; Fedora 26 with
gcc 7.1.1; Linux Mint 18 with gcc 5.4.0; and CentOS Linux 7 with gcc 4.8.5.
CLIPS is designed for portability and should run on any operating system which supports an
ANSI C or C++ compiler. The following steps describe how to create a new executable version
of CLIPS:
In addition to these core files, the Integrated Development Environments require additional
files for compilation. See the Utilities and Interfaces Guide for details on compiling the
IDEs.
on what kind of machine the code is being compiled. The default setting for this definition is
GENERIC, which will create a version of CLIPS that will run on any computer. The user
may set the definition for the user’s type of system. If the system type is unknown, the
definition should be set to GENERIC (so for this situation you do not need to edit setup.h).
Other preprocessor definitions in the setup.h file also allow a user to tailor the features in
CLIPS to specific needs. For more information on using the flags, see section 2.2.
Optionally, preprocessor definitions can be set using the appropriate command line
argument used by your compiler, removing the need to directly edit the setup.h file. For
example, the command line option –DLINUX will work on many compilers to set the
preprocessor definition of LINUX to 1.
If user-defined functions are needed, compile the source code for those functions as well and
modify the UserFunctions definition in userfunctions.c to reflect the user's functions (see
section 3 for more on user-defined functions).
2.1.1 Makefiles
The makefiles ‘makefile.win’ and ‘makefile’ are provided with the core source code to create
executables and static libraries for Windows, MacOS, and Linux. The makefiles can be used to
create either release or debug versions of the executables/libraries and to compile the code as C
or C++.
The following steps assume you have Microsoft Visual Studio Community 2017 installed. First,
launch the Command Prompt application from the Start menu by selecting Visual Studio 2017
and then either VS2017 x64 Native Tools Command Prompt or VS2017 x86 Native Tools
Command Prompt. Next, use the cd command to change the current directory to the one
containing the core CLIPS source code and makefiles. To compile CLIPS as C code without
debugging information, use the command
nmake –f makefile.win
or
nmake –f makefile.win BUILD=RELEASE
To compile CLIPS as C++ code without debugging information, use the following command:
nmake –f makefile.win BUILD=RELEASE_CPP
To compile CLIPS as C code with debugging information, use the following command:
nmake –f makefile.win BUILD=DEBUG
To compile CLIPS as C++ code with debugging information, use the following command:
nmake –f makefile.win BUILD=DEBUG_CPP
When compilation is complete, the executable file clips.exe and the static library file clips.lib
will be created in the source directory.
Before rebuilding the executable and library with a different BUILD variable value, the clean
action should be run:
nmake –f makefile.win clean
First, launch the Terminal application. Use the cd command to change the current directory to
the one containing the core CLIPS source code and makefiles. To compile CLIPS as C code
without debugging information, use the command
make
or
make release
To compile CLIPS as C++ code without debugging information, use the following command:
make release_cpp
To compile CLIPS as C code with debugging information, use the following command:
make debug
To compile CLIPS as C++ code with debugging information, use the following command:
make debug_cpp
When compilation is complete, the executable file clips and the static library file libclips.a will
be created in the source directory.
Before rebuilding the executable and library with a different configuration, the clean action
should be run:
make clean
The first flag in setup.h indicates on what type of compiler/machine CLIPS is to run. The source
code is sent out with the flag for GENERIC CLIPS turned on. When compiled in this mode, all
system-dependent features of CLIPS are excluded and the program should run on any system. A
number of other flags are available in this file, indicating the types of compilers/machines on
which CLIPS has been compiled previously. If the user's implementation matches one of the
available flags, set that flag to 1 and turn the GENERIC flag off (set it to 0). The code for most
of the features controlled by the compiler/machine-type flag is in the sysdep.c file.
Many other flags are provided in setup.h. Each flag is described below.
BLOAD This flag controls access to the binary load command (bload). This
would be used to save some memory in systems which require
binary load but not save capability. This is off in the standard
CLIPS executable.
BLOAD_AND_BSAVE
This flag controls access to the binary load and save commands.
This would be used to save some memory in systems which require
neither binary load nor binary save capability. This is on in the
standard CLIPS executable.
BLOAD_INSTANCES
This flag controls the ability to load instances in binary format from
a file via the bload-instances command (see section 13.11.4.7 of
the Basic Programming Guide). This is on in the standard CLIPS
executable. Turning this flag off can save some memory.
BLOAD_ONLY This flag controls access to the binary and ASCII load commands
(bload and load). This would be used to save some memory in
systems which require binary load capability only. This flag is off
in the standard CLIPS executable.
BSAVE_INSTANCES
This flag controls the ability to save instances in binary format to a
file via the bsave-instances command (see section 13.11.4.4 of the
Basic Programming Guide). This is on in the standard CLIPS
executable. Turning this flag off can save some memory.
CONSTRUCT_COMPILER
This flag controls the construct compiler functions. If it is turned
on, constructs may be compiled to C code for use in a run-time
module (see section 11). This is off in the standard CLIPS
executable.
DEBUGGING_FUNCTIONS
This flag controls access to commands such as agenda, facts,
ppdefrule, ppdeffacts, etc. This would be used to save some
memory in BLOAD_ONLY or RUN_TIME systems. This flag is
on in the standard CLIPS executable.
DEFFACTS_CONSTRUCT
This flag controls the use of deffacts. If it is off, deffacts are not
allowed which can save some memory and performance during
resets. This is on in the standard CLIPS executable.
DEFFUNCTION_CONSTRUCT
This flag controls the use of deffunction. If it is off, deffunction is
not allowed which can save some memory. This is on in the
standard CLIPS executable.
DEFGENERIC_CONSTRUCT
This flag controls the use of defgeneric and defmethod. If it is off,
defgeneric and defmethod are not allowed which can save some
memory. This is on in the standard CLIPS executable.
DEFGLOBAL_CONSTRUCT
This flag controls the use of defglobal. If it is off, defglobal is not
allowed which can save some memory. This is on in the standard
CLIPS executable.
DEFINSTANCES_CONSTRUCT
This flag controls the use of definstances (see section 9.6.1.1 of the
Basic Programming Guide). If it is off, definstances are not allowed
which can save some memory and performance during resets. This
is on in the standard CLIPS executable.
DEFMODULE_CONSTRUCT
This flag controls the use of the defmodule construct. If it is off,
then new defmodules cannot be defined (however the MAIN
module will exist). This is on in the standard CLIPS executable.
DEFRULE_CONSTRUCT
This flag controls the use of the defrule construct. If it is off, the
defrule construct is not recognized by CLIPS. This is on in the
standard CLIPS executable.
DEFTEMPLATE_CONSTRUCT
This flag controls the use of deftemplate. If it is off, deftemplate is
not allowed which can save some memory. This is on in the
standard CLIPS executable.
EXTENDED_MATH_FUNCTIONS
This flag indicates whether the extended math package should be
included in the compilation. If this flag is turned off (set to 0), the
final executable will be about 25-30K smaller, a consideration for
machines with limited memory. This is on in the standard CLIPS
executable.
FACT_SET_QUERIES
This flag determines if the fact-set query functions are available.
These functions are any-factp, do-for-fact, do-for-all-facts,
delayed-do-for-all-facts, find-fact, and find-all-facts,. This is on
in the standard CLIPS executable. Turning this flag off can save
some memory.
INSTANCE_SET_QUERIES
This flag determines if the instance-set query functions are
available. These functions are any-instancep, do-for-instance,
do-for-all-instances, delayed-do-for-all-instances, find-instance,
and find-all-instances,. This is on in the standard CLIPS
executable. Turning this flag off can save some memory.
IO_FUNCTIONS This flag controls access to the I/O functions in CLIPS. These
functions are close, format, get-char, open, print, println,
printout, put-char, read, readline, read-number, rename,
remove, and set-locale. If this If this flag is off, these functions are
not available. This would be used to save some memory in systems
MULTIFIELD_FUNCTIONS
This flag controls access to the multifield manipulation functions in
CLIPS. These functions are delete$, delete-member$, explode$,
first$, foreach, implode$, insert$, member$, nth$, progn$,
replace$, replace-member$, rest$, subseq$, and subsetp. The
functions create$, expand$, and length$ are always available
regardless of the setting of this flag. This would be used to save
some memory in systems which performed limited or no operations
with multifield values. This flag is on in the standard CLIPS
executable.
OBJECT_SYSTEM
This flag controls the use of defclass, definstances, and defmessage-
handler. If it is off, these constructs are not allowed which can save
some memory. This is on in the standard CLIPS executable.
PROFILING_FUNCTIONS
This flag controls access to the profiling functions in CLIPS. These
functions are get-profile-percent-threshold, profile, profile-info,
profile-reset, and set-profile-percent-threshold. This flag is on in
the standard CLIPS executable.
RUN_TIME This flag will create a run-time version of CLIPS for use with
compiled constructs. It should be turned on only after the
constructs-to-c function has been used to generate the C code
representation of the constructs, but before compiling the constructs
C code. See section 11 for a description of how to use this. This is
off in the standard CLIPS executable.
STRING_FUNCTIONS
This flag controls access to the string manipulation functions in
CLIPS. These functions are build, eval, lowcase, string-to-field,
str-cat, str-compare, str-index, str-length, sub-string, sym-cat,
and upcase. This would be used to save some memory in systems
which perform limited or no operations with strings. This flag is on
in the standard CLIPS executable.
TEXTPRO_FUNCTIONS
This flag controls the CLIPS text-processing functions. It must be
turned on to use the fetch, get-region, print-region, and toss
WINDOW_INTERFACE
This flag indicates that a windowed interface is being used. This is
off in the standard CLIPS executable.
Section 3:
Core Functions
The core functions can be used to embed CLIPS within a simple C program for situations where
the user interacts with CLIPS through a text-only computer interface and there is no need for the
C program to retrieve information from CLIPS. This removes the need for users to have to
interact in any way with the CLIPS command prompt.
3.1.1 CreateEnvironment
Environment *CreateEnvironment();
3.1.2 DestroyEnvironment
bool DestroyEnvironment(
Environment *env);
3.2.1 Clear
bool Clear(
Environment *env);
The function Clear is the C equivalent of the CLIPS clear command. Parameter env is a pointer
to a previously created environment. This function removes all constructs and associated data
from the specified environment. It returns true if successful; otherwise, it returns false.
3.2.2 Load
LoadError Load(
Environment *env,
const char *fileName);
typedef enum
{
LE_NO_ERROR,
LE_OPEN_FILE_ERROR,
LE_PARSING_ERROR,
} LoadError;
The function Load is the C equivalent of the CLIPS load command. Parameter env is a pointer
to a previously created environment; and parameter fileName is a full or partial path string to an
ASCII or UTF-8 text file containing CLIPS constructs. This function returns
LE_OPEN_FILE_ERROR if an error occurred opening the file; LE_PARSING_ERROR if
errors occurred while parsing constructs contained in the file; and LE_NO_ERROR if no errors
occurred.
3.3.1 AssertString
Fact *AssertString(
Environment *env,
const char *str);
AssertStringError GetAssertStringError(
Environment *env);
typedef enum
{
ASE_NO_ERROR,
ASE_NULL_POINTER_ERROR,
ASE_PARSING_ERROR,
ASE_COULD_NOT_ASSERT_ERROR,
ASE_RULE_NETWORK_ERROR
} AssertStringError;
The function AssertString is the C equivalent of the CLIPS assert-string command. Parameter
env is a pointer to a previously created environment; and parameter str is a pointer to a character
array containing the text representation of an ordered or deftemplate fact. An example ordered
fact string is "(colors red green blue)". An example deftemplate fact string is "(person (name
Fred Jones) (age 37))". A pointer of type Fact * is returned if a fact is successfully created or
already exists; otherwise, a null pointer is returned. If the return value from AssertString is
persistently stored in a variable or data structure for later reference, then the function RetainFact
should be called to insure that the reference remains valid even if the fact has been retracted.
The function GetAssertStringError returns the error code for the last fact assertion. The value
ASE_NO_ERROR indicates no error occurred; the value ASE_NULL_POINTER_ERROR
indicates the str parameter was NULL; the value ASE_PARSING_ERROR indicates an error
was encountered parsing the str parameter; the value ASE_COULD_NOT_ASSERT indicates
the fact could not be asserted (such as when pattern matching of a fact or instance is already
occurring); and the value ASE_RULE_NETWORK_ERROR indicates an error occurred while
the assertion was being processed in the rule network.
3.3.2 MakeInstance
Instance *MakeInstance(
Environment *env,
const char *str);
typedef enum
{
MIE_NO_ERROR,
MIE_NULL_POINTER_ERROR,
MIE_PARSING_ERROR,
MIE_COULD_NOT_CREATE_ERROR,
MIE_RULE_NETWORK_ERROR
} MakeInstanceError;
MakeInstanceError GetMakeInstanceError(
Environment *env);
The function GetMakeInstanceError returns the error code for the last MakeInstance call. The
value MIE_NO_ERROR indicates no error occurred; the value MIE_NULL_POINTER_ERROR
indicates the str parameter was NULL; the value MIE_PARSING_ERROR indicates an error
was encountered parsing the str parameter; the value MIE_COULD_NOT_CREATE indicates
the instance could not be created (such as when pattern matching of a fact or instance is already
occurring); and the value MIE_RULE_NETWORK_ERROR indicates an error occurred while
the instance was being processed in the rule network.
3.3.3 Retract
RetractError Retract(
Fact *f);
typedef enum
{
RE_NO_ERROR,
RE_NULL_POINTER_ERROR,
RE_COULD_NOT_RETRACT_ERROR,
RE_RULE_NETWORK_ERROR
} RetractError;
The function Retract is the C equivalent of the CLIPS retract command. Parameter f is the fact
to be retracted. This function returns RE_NO_ERROR if the fact is successfully retracted;
otherwise it returns RE_NULL_POINTER_ERROR if parameter f is NULL,
RE_COULD_NOT_RETRACT_ERROR if the fact could not be retracted (such as when pattern
matching of a fact or instance is already occurring), or RE_RULE_NETWORK_ERROR if an
error occurs while the retraction is being processed in the rule network.
The caller of Retract is responsible for insuring that the fact passed as an argument is still valid.
If a persistent reference to this fact was previously created using RetainFact, the function
ReleaseFact should be called to remove that reference.
3.3.4 UnmakeInstance
UnmakeInstanceError UnmakeInstance(
Instance *i);
typedef enum
{
UIE_NO_ERROR,
UIE_NULL_POINTER_ERROR,
UIE_COULD_NOT_DELETE_ERROR,
UIE_DELETED_ERROR,
UIE_RULE_NETWORK_ERROR
} UnmakeInstanceError;
The caller of UnmakeInstance is responsible for insuring that the instance passed as an
argument is still valid. If a persistent reference to this instance was previously created using
RetainInstancee, the function ReleaseInstance should be called to remove that reference.
3.4.1 Reset
void Reset(
Environment *env);
The function Reset is the C equivalent of the CLIPS reset command. Parameter env is a pointer
to a previously created environment. This function removes all facts and instances; creates facts
and instances defined in deffacts and definstances constructs; and resets the values of global
variables in the specified environment.
3.4.2 Run
The function Run is the C equivalent of the CLIPS run command. Parameter env is a pointer to
a previously created environment; and parameter limit parameter is the maximum number of
rules that will fire before the function returns. If the limit parameter value is negative, rules will
fire until the agenda is empty. The return value of this function is the number of rules that were
fired.
3.5 Debugging
bool DribbleOn(
Environment *env,
const char *fileName);
bool DribbleOff(
Environment *env);
The function DribbleOn is the C equivalent of the CLIPS dribble-on command. Parameter env
is a pointer to a previously created environment; and parameter fileName is a full or partial path
string to the dribble file to be created. This function returns true if the dribble file is successfully
opened; otherwise, it returns false.
The function DribbleOff is the C equivalent of the CLIPS dribble-off command. Parameter env
is a pointer to a previously created environment. This function returns true if the dribble file is
successfully closed; otherwise, it returns false.
void Watch(
Environment *env,
WatchItem item);
void Unwatch(
Environment *env,
WatchItem item);
typedef enum
{
ALL,
FACTS,
INSTANCES,
SLOTS,
RULES,
ACTIVATIONS,
MESSAGES,
MESSAGE_HANDLERS,
GENERIC_FUNCTIONS,
METHODS,
DEFFUNCTIONS,
COMPILATIONS,
STATISTICS,
GLOBALS,
FOCUS
} WatchItem;
The function Watch is the C equivalent of the CLIPS watch command. The function Unwatch
is the C equivalent of the CLIPS unwatch command. Parameter env is a pointer to a previously
created environment; and parameter item is one of the specified WatchItem enumeration values
to be enabled (for watch) or disabled (for unwatch). If the ALL enumeration value is specified,
then all watch items will be enabled (for watch) or disabled (for unwatch).
3.6 Examples
This example demonstrates how to load and run rules from a C program. The following output
shows how you would typically perform this task from the CLIPS command prompt:
To achieve the same result from a C program, first create a text file named hello.clp with the
following contents:
(defrule hello
=>
(println "Hello World!"))
Next, change the contents of the main.c source file to the following:
#include "clips.h"
int main()
{
Environment *env;
env = CreateEnvironment();
Load(env,"hello.clp");
Reset(env);
Run(env,-1);
DestroyEnvironment(env);
}
Hello World!
3.6.2 Debugging
This example demonstrates how to generate and capture debugging information from a C
program. The following output shows how you would typically perform this task from the
CLIPS command prompt:
To achieve the same result from a C program, first create a text file named sort.clp with the
following contents:
(deftemplate list
(multislot numbers))
(defrule sort
?f <- (list (numbers $?b ?x ?y&:(> ?x ?y) $?e))
=>
(modify ?f (numbers ?b ?y ?x ?e)))
Next, change the contents of the main.c source file to the following:
#include "clips.h"
int main()
{
Environment *env;
env = CreateEnvironment();
Load(env,"sort.clp");
Watch(env,FACTS);
Watch(env,RULES);
Watch(env,ACTIVATIONS);
DribbleOn(env,"sort.dbg");
Reset(env);
Run(env,-1);
DribbleOff(env);
DestroyEnvironment(env);
}
The file sort.dbg will contain the same output that is printed to the screen.
Section 4:
Calling Functions and
Building Constructs
The Eval function provides a mechanism for executing functions and commands in CLIPS and
returning a value from CLIPS back to C. This is useful for executing commands from C in a
similar manner to using the CLIPS command prompt. In conjunction with the fact and instance
query functions, it is also a useful mechanism for retrieving the results of a CLIPS program.
The Build function provides a mechanism for defining individual constructs in a similar manner
to using the CLIPS command prompt. Much like entering constructs at the command prompt,
this functionality is primarily useful in examples and tutorials.
Since many CLIPS functions (including Eval and Build) take string arguments that may need to
be created dynamically, CLIPS provides StringBuilder functions that automate the allocation,
construction, and resizing of strings as character data is appended.
There are nine C types for used to represent CLIPS primitive values: TypeHeader for any
CLIPS primitive value; CLIPSLexeme for symbols, strings, and instance names, CLIPSFloat
for floats; CLIPSInteger for integers; CLIPSVoid for void; Fact for facts; Instance for
instances; CLIPSExternalAddress for external addresses; and Multifield for multifields.
4.1.1 TypeHeader
The C TypeHeader type is used to store the CLIPS primitive value type.
The integer stored in the type field is one of the following predefined constants:
EXTERNAL_ADDRESS_TYPE
FACT_ADDRESS_TYPE
FLOAT_TYPE
INSTANCE_ADDRESS_TYPE
INSTANCE_NAME_TYPE
INTEGER_TYPE
MULTIFIELD_TYPE
STRING_TYPE
SYMBOL_TYPE
VOID_TYPE
4.1.2 CLIPSValue
The C CLIPSValue type encapsulates all of the CLIPS primitive types. Functions returning
primitive values from CLIPS to C have parameters of type CLIPSValue *. The return value of
the function is stored in the CLIPSValue structure allocated by caller. The header field of the
CLIPSValue union can be examined to determine the CLIPS primitive value type and then the
appropriate field from the CLIPSValue union can be examined to retrieve the C representation
of the type.
The C CLIPSLexeme type is used to represent CLIPS symbol, string, and instance name
primitive types.
The contents field of the CLIPSLexeme contains the C string associated with the CLIPS
primitive value. This value should not be changed by user code.
4.1.4 Integers
The contents field of the CLIPSInteger contains the C long long associated with the CLIPS
primitive value. This value should not be changed by user code.
4.1.5 Floats
The contents field of the CLIPSFloat contains the C double associated with the CLIPS
primitive value. This value should not be changed by user code.
4.1.6 Multifields
The length field contains the number of CLIPS primitive values contained in the Multifield
type. The contents field is a pointer to an array containing a number of CLIPValue structs that is
specified by the length field.
4.1.7 Void
The contents field of the CLIPSExternalAddress contains the external address associated with
the CLIPS primitive value. This value should not be changed by user code.
BuildError Build(
Environment *env,
const char *str);
typedef enum
{
EE_NO_ERROR,
EE_PARSING_ERROR,
EE_PROCESSING_ERROR
} EvalError;
typedef enum
{
BE_NO_ERROR,
BE_COULD_NOT_BUILD_ERROR,
BE_CONSTRUCT_NOT_FOUND_ERROR,
BE_PARSING_ERROR,
} BuildError;
The function Eval is the C equivalent of the CLIPS eval command. The function Build is the C
equivalent of the CLIPS build command. For both functions, the env parameter is a pointer to a
previously created environment. The str parameter for the Eval function is a string containing a
CLIPS command or function call; and for the Build function is a string containing a construct
definition. If the cv parameter value for the Eval function is not a null pointer, then the return
value of the CLIPS command or function call is stored in the CLIPSValue structure allocated by
the caller and referenced by the pointer.
If no errors occur, the Eval function returns EE_NO_ERROR and the Build function returns
BE_NO_ERROR. If a syntax error is encountered while parsing, the Eval function returns
EE_PARSING_ERROR and the Build function returns BE_PARSING_ERROR. If the Build
function does not recognize the construct name following the opening left parenthesis, it returns
BE_CONSTRUCT_NOT_FOUND_ERROR. If constructs cannot be added (such as when
pattern matching is active), the Build function returns BE_COULD_NOT_BUILD_ERROR. If
an error occurs while executing the parsed expression, the Eval function returns
EE_PROCESSING_ERROR.
FunctionCallBuilder *CreateFunctionCallBuilder(
Environment *env,
size_t capacity);
FunctionCallBuilderError FCBCall(
FunctionCallBuilder *fcb,
const char *functionName,
CLIPSValue *cv);
void FCBReset(
FunctionCallBuilder *fcb);
void FCBDispose(
FunctionCallBuilder *fcb);
void FCBAppend(
FunctionCallBuilder *mb,
CLIPSValue *value);
void FCBAppendUDFValue(
FunctionCallBuilder *fcb,
UDFValue *);
void FCBAppendInteger(
FunctionCallBuilder *fcb,
long long value);
void FCBAppendFloat(
FunctionCallBuilder *fcb,
double value);
void FCBAppendSymbol(
FunctionCallBuilder *fcb,
const char *value);
void FCBAppendString(
FunctionCallBuilder *fcb,
const char *value);
void FCBAppendInstanceName(
FunctionCallBuilder *fcb,
const char *value);
void FCBAppendCLIPSInteger(
FunctionCallBuilder *fcb,
CLIPSInteger *value);
void FCBAppendCLIPSFloat(
FunctionCallBuilder *fcb,
CLIPSFloat *value);
void FCBAppendCLIPSLexeme(
FunctionCallBuilder *fcb,
CLIPSLexeme *value);
void FCBAppendFact(
FunctionCallBuilder *fcb,
Fact *value);
void FCBAppendInstance(
FunctionCallBuilder *fcb,
CLIPSValue *value);
void FCBAppendMultifield(
FunctionCallBuilder *fcb,
Multifield *value);
void FCBAppendCLIPSExternalAddress(
FunctionCallBuilder *fcb,
CLIPSExternalAddress *value);
The function FCBCall executes the function specified by the functionName parameter with the
arguments that were previously appended to the FunctionCallBuilder specified by parameter
fcb. If the parameter cv is not a NULL pointer, the return value of the executed function will be
stored in the specified CLIPSValue structure.
If no errors occur, the FCBCall function returns FCBE_NO_ERROR. If an error occurred, the
value FCBE_NULL_POINTER_ERROR indicates the fcb or functionName parameter was
NULL; the value FCBE_FUNCTION_NOT_FOUND_ERROR indicates a function, deffunction,
or generic function could not be found with the name specified by the functionName parameter;
the value FCBE_INVALID_FUNCTION_ERROR indicates the function or command has a
specialized parser (such as the assert command) and cannot be invoked; the value
FCBE_ARGUMENT_COUNT_ERROR indicates the function was passed the incorrect number
of arguments; the value FCBE_ARGUMENT_TYPE_ERROR indicates the function was passed
an argument with an invalid type; and the value ASE_PROCESSING_ERROR indicates an error
occurred while the function was being evaluated.
The function FCBReset resets the FunctionCallBuilder specified by parameter fcb to its initial
capacity. Any arguments previously appended are removed.
The function FCBDispose deallocates all memory associated with previously allocated
FunctionCallBuilder specified by parameter fcb.
The contents field of the StringBuilder type is a pointer to a character array containing all of
the characters that have been appended by calls to the SBAddChar and SBAppend functions.
The value of the contents field can change if appending to the StringBuilder exceeds the
current capacity, so it is recommended to always directly retrieve the contents field from the
StringBuilder pointer. Use the SBCopy function to create a copy of the contents field if
desired; otherwise, the contents field should never be directly modified.
The length field of the StringBuilder type contains the number of characters in the contents
field not including the null character at the end of the string.
4.4.1 CreateStringBuilder
StringBuilder *CreateStringBuilder(
Environment *env,
size_t capacity);
4.4.2 SBAddChar
void SBAddChar(
StringBuilder *sb,
int c);
The function SBAddChar appends the single character specified by parameter c to the contents
string of the previously allocated StringBuilder specified by parameter sb. If the c parameter
value is a backspace, then the last character of the contents string is removed.
void SBAppend(
StringBuilder *sb,
const char *value);
void SBAppendInteger(
StringBuilder *sb,
long long value);
void SBAppendFloat(
StringBuilder *sb,
double value);
The SBAppend functions append the parameter value to the contents string of the previously
allocated StringBuilder specified by parameter sb.
4.4.4 SBCopy
char *SBCopy(
StringBuilder *sb);
The function SBCopy returns a copy of contents string of the previously allocated StringBuffer
specified by parameter sb. The memory allocated for this string will not be freed by CLIPS, so it
is necessary for the user’s code to call the free C library function to deallocate the memory once
it is no longer needed.
4.4.5 SBDispose
void SBDispose(
StringBuilder *sb);
The function SBDispose deallocates all memory associated with previously allocated
StringBuilder specified by parameter sb.
4.4.6 SBReset
void SBReset(
StringBuilder *sb);
The function SBReset resets the StringBuilder specified by parameter sb to its initial capacity.
The contents string is set to an empty string and the length of the StringBuilder is set to 0.
4.5 Examples
This example reimplements the debugging example from section 3.6.2 but uses the Build
function for adding constructs and the Eval function for issuing commands.
#include "clips.h"
int main()
{
Environment *env;
env = CreateEnvironment();
Build(env,"(deftemplate list"
" (multislot numbers))");
Build(env,"(defrule sort"
" ?f <- (list (numbers $?b ?x ?y&:(> ?x ?y) $?e))"
" =>"
" (modify ?f (numbers ?b ?y ?x ?e)))");
Eval(env,"(watch facts)",NULL);
Eval(env,"(watch rules)",NULL);
Eval(env,"(watch activations)",NULL);
Eval(env,"(dribble-on sort.dbg)",NULL);
Eval(env,"(reset)",NULL);
Eval(env,"(run)",NULL);
Eval(env,"(dribble-off)",NULL);
DestroyEnvironment(env);
}
This example illustrates using the StringBuilder and Eval functions to construct and evaluate a
function call. The PrintString and PrintCLIPSValue Router functions (described in Section 9)
are used to print the value and type of each field in the multifield return value.
#include "clips.h"
int main()
{
Environment *env;
StringBuilder *sb;
CLIPSValue cv;
char *fullName;
// Create an Environment
// and StringBuilder.
env = CreateEnvironment();
sb = CreateStringBuilder(env,512);
SBAppend(sb," ");
fullName = SBCopy(sb);
SBReset(sb);
SBAppend(sb,"(upcase \"");
SBAppend(sb,fullName);
SBAppend(sb,"\")");
Eval(env,sb->contents,&cv);
Write(env,"Result is ");
Writeln(env,cv.lexemeValue->contents);
free(fullName);
SBDispose(sb);
DestroyEnvironment(env);
}
#include "clips.h"
int main()
{
Environment *env;
StringBuilder *sb;
CLIPSValue cv;
// Create an Environment
// and StringBuilder.
env = CreateEnvironment();
sb = CreateStringBuilder(env,512);
Eval(env,"(readline)",&cv);
SBAppend(sb,"(create$ ");
SBAppend(sb,cv.lexemeValue->contents);
SBAppend(sb,")");
Eval(env,sb->contents,&cv);
switch(cv.multifieldValue->contents[i].header->type)
{
case INTEGER_TYPE:
Write(env," is an integer\n");
break;
case FLOAT_TYPE:
Write(env," is a float\n");
break;
case STRING_TYPE:
Write(env," is a string\n");
break;
case SYMBOL_TYPE:
Write(env," is a symbol\n");
break;
case INSTANCE_NAME_TYPE:
Write(env," is an instance name\n");
break;
}
}
SBDispose(sb);
DestroyEnvironment(env);
}
This example illustrates how to use the StringBuilder and Eval functions to dynamically
construct and assert a fact, retrieve values from CLIPS function calls, and use a fact query to
retrieve a slot value from a fact after rules have executed.
The first section of code for this example (that includes the function CreateNumbers)
demonstrates the construction of a list fact with a numbers slot containing zero or more integers.
The number of integers to be created is specified by the howMany parameter.
#include "clips.h"
void CreateNumbers(
Environment *env,
StringBuilder *sb,
int howMany)
{
CLIPSValue cv;
SBAppend(sb,"(list (numbers");
SBAppend(sb," ");
SBAppend(sb,cv.lexemeValue->contents);
}
SBAppend(sb,"))");
Watch(env,FACTS);
AssertString(env,sb->contents);
Unwatch(env,FACTS);
SBReset(sb);
}
The next section of code (that includes the PrintNumbers function) demonstrates how to use a
query function to retrieve a slot value from a fact; and how to iterate through the contents of a
multifield value. The Write and WriteCLIPSValue Router functions (described in Section 9)
are used to print the slot value.
void PrintNumbers(
Environment *env)
{
CLIPSValue cv;
if (cv.header->type == MULTIFIELD_TYPE)
{
Write(env,"Sorted list is (");
Write(env,")\n");
}
}
The final section of code (that includes the main function) generates a list of random numbers
(using the CreateNumbers function), sorts them (using the sort rule), prints the sorted numbers
(using the PrintNumbers function), and then repeats the process a second time.
int main()
{
Environment *env;
StringBuilder *sb;
// Create an Environment
// and StringBuilder.
env = CreateEnvironment();
sb = CreateStringBuilder(env,512);
Build(env,"(deftemplate list"
" (multislot numbers))");
Build(env,"(defrule sort"
" ?f <- (list (numbers $?b ?x ?y&:(> ?x ?y) $?e))"
" =>"
" (modify ?f (numbers ?b ?y ?x ?e)))");
Reset(env);
CreateNumbers(env,sb,5);
Run(env,-1);
PrintNumbers(env);
Reset(env);
CreateNumbers(env,sb,7);
Run(env,-1);
PrintNumbers(env);
SBDispose(sb);
DestroyEnvironment(env);
}
Note that the sorted integers displayed will vary since the generated random integers are
dependent on the implementation of the C rand library function as well as the seeding of the
random number generator using the current time.
This example illustrates using the FunctionCallBuilder functions to send an instance a print
message.
#include "clips.h"
int main()
{
Environment *env;
FunctionCallBuilder *fcb;
Instance *ins;
env = CreateEnvironment();
fcb = CreateFunctionCallBuilder(env,2);
FCBAppendInstance(fcb,ins);
FCBAppendSymbol(fcb,"print");
FCBCall(fcb,"send",NULL);
FCBDispose(fcb);
DestroyEnvironment(env);
}
[p1] of POINT
(x 3)
(y 4)
Section 5:
Garbage Collection
5.1 Introduction
CLIPS primitive values (including those which have counterparts to C primitive values such as
integer, floats, and strings) are represented using data structures. As a CLIPS program executes,
it allocates memory for primitive values dynamically (such as when facts/instances are created or
functions are evaluated). CLIPS automatically tracks references to these primitive values so that
they can be deallocated once there are no longer any outstanding references to them. Data which
has been marked for later deallocation is referred to as garbage. The process of deallocating this
garbage is referred to as garbage collection.
If you use one of the interactive CLIPS executables, all garbage collection is handled
automatically for you including garbage created when entering commands and by constructs
which execute code (such as defrules and deffunctions).
Embedded applications, however, can generate garbage and trigger garbage collection when
invoking certain API calls to CLIPS, so it is necessary to follow some guidelines when using the
APIs to allow CLIPS to safely garbage collect data that is no longer needed and to prevent
primitive values that are referenced by user code from being garbage collected. First, functions
which can cause CLIPS code to be executed (such as Clear, Load, Reset, Run, Send, and Eval)
can trigger garbage collection. Second, a primitive value returned through an API call (such as
Eval) is not subject to garbage collection until a subsequent API call triggering garbage
collection is invoked. Third, use the Retain API functions to create an outstanding reference to a
primitive value and the Release API functions to remove an outstanding reference.
#include "clips.h"
int main()
{
Environment *env;
CLIPSValue cv;
CLIPSLexeme *sym1, *sym2;
env = CreateEnvironment();
The first call to Eval triggers garbage collection, but since no data has been returned yet to the
embedding program this does not cause any problems. The lexemeValue field of the
CLIPSLexeme returned in the variable cv is assigned to the variable sym1. The contents field
of this variable can be safely referenced because the returned value was excluded from garbage
collection.
The second call to Eval also triggers garbage collection. In this case, however, the value returned
by the prior call to Eval will be garbage collected as a result. Therefore it is not safe to reference
the value stored in the variable sym1 after this point. This is a problem if, for example, you want
to compare the contents fields of variables sym1 and sym2.
For float and integer primitive values, the contents field of the CLIPSInteger or CLIPSFloat
structure can be directly copied to a variable if the value needs to be preserved, however for
primitive types this problem can be corrected by using the Retain/Release APIs to inform CLIPS
about values that should not be garbage collected. For example:
#include "clips.h"
int main()
{
Environment *env;
CLIPSValue cv;
CLIPSLexeme *sym1, *sym2;
env = CreateEnvironment();
ReleaseLexeme(env,sym1);
In this case, the RetainLexeme function is called to prevent the result of the first Eval call from
being garbaged collected when the second Eval call is made. That result is protected until the
call to ReleaseLexeme is made.
5.3 Example
This example demonstrates how to retain a fact so that a subsequent call to retract the fact will
produce the correct result is the fact is retracted by a rule.
#include "clips.h"
int main()
{
Environment *env;
Fact *f1, *f2;
env = CreateEnvironment();
Build(env,"(deftemplate list"
" (multislot numbers))");
Build(env,"(defrule sort"
" ?f <- (list (numbers $?b ?x ?y&:(> ?x ?y) $?e))"
" =>"
" (retract ?f) "
" (assert (list (numbers ?b ?y ?x ?e))))");
Eval(env,"(facts)",NULL);
Run(env,-1);
Eval(env,"(facts)",NULL);
ReleaseFact(f1);
Retract(f1);
ReleaseFact(f2);
Retract(f2);
Eval(env,"(facts)",NULL);
DestroyEnvironment(env);
}
If the fact stored in the variable f1 had not been retained, the memory allocated for that fact
could have been reallocated to store another fact (such as f-6). In that case, the "Retract(f1);"
function call would have retracted the wrong fact rather than recognizing that the fact f-1 had
already been retracted.
Section 6:
Creating Primitive Values
Section 4 demonstrated how to examine primitive values returned by CLIPS. This section
documents the API for dynamically creating primitive values.
CLIPSLexeme *CreateSymbol(
Environment *env,
const char *str);
CLIPSLexeme *CreateString(
Environment *env,
const char *str);
CLIPSLexeme *CreateInstanceName(
Environment *env,
const char *str);
CLIPSLexeme *CreateBoolean(
Environment *env,
bool b);
CLIPSLexeme *FalseSymbol(
Environment *env);
CLIPSLexeme *TrueSymbol(
Environment *env);
is a pointer to a character array containing the text that will be assigned to the contents field of
the CLIPS symbol, string, or instance name being created. The return value of these functions is
a pointer to a CLIPSLexeme type.
The function CreateBoolean creates a primitive value with type field value of
SYMBOL_TYPE. Parameter env is a pointer to a previously created environment. If parameter
b is true, a pointer to the CLIPSLexeme for the symbol TRUE is returned; otherwise a pointer to
the CLIPSLexeme for the symbol FALSE is returned.
The function FalseSymbol returns a pointer to the CLIPSLexeme for the symbol FALSE. The
function TrueSymbol returns a pointer to the CLIPSLexeme for the symbol TRUE.
CLIPSInteger *CreateInteger(
Environment *env,
long long ll);
The function CreateInteger creates a primitive value with a type field value of
INTEGER_TYPE. Parameter env is a pointer to a previously created environment; and
parameter ll is the C integer value that will be assigned to the contents field of the CLIPS integer
being created. The return value of this function is a pointer to a CLIPSInteger type.
CLIPSFloat *CreateFloat(
Environment *theEnv,
double dbl);
The function CreateFloat creates a primitive value with a type field value of FLOAT_TYPE.
Parameter env is a pointer to a previously created environment; and parameter dbl is the C
double value that will be assigned to the contents field of the CLIPS float being created. The
return value of this function is a pointer to a CLIPSFloat type.
Multifield *EmptyMultifield(
Environment *env);
Multifield *StringToMultifield(
Environment *env,
const char *str);
MultifieldBuilder *CreateMultifieldBuilder(
Environment *env,
size_t capacity);
Multifield *MBCreate(
MultifieldBuilder *mb);
void MBReset(
MultifieldBuilder *mb);
void MBDispose(
MultifieldBuilder *mb);
void MBAppend(
MultifieldBuilder *mb,
CLIPSValue *value);
void MBAppendUDFValue(
MultifieldBuilder *mb,
UDFValue *);
void MBAppendInteger(
MultifieldBuilder *mb,
long long value);
void MBAppendFloat(
MultifieldBuilder *mb,
double value);
void MBAppendSymbol(
MultifieldBuilder *mb,
const char *value);
void MBAppendString(
MultifieldBuilder *mb,
const char *value);
void MBAppendInstanceName(
MultifieldBuilder *mb,
const char *value);
void MBAppendCLIPSInteger(
MultifieldBuilder *mb,
CLIPSInteger *value);
void MBAppendCLIPSFloat(
MultifieldBuilder *mb,
CLIPSFloat *value);
void MBAppendCLIPSLexeme(
MultifieldBuilder *mb,
CLIPSLexeme *value);
void MBAppendFact(
MultifieldBuilder *mb,
Fact *value);
void MBAppendInstance(
MultifieldBuilder *mb,
CLIPSValue *value);
void MBAppendMultifield(
MultifieldBuilder *mb,
Multifield *value);
void MBAppendCLIPSExternalAddress(
MultifieldBuilder *mb,
CLIPSExternalAddress *value);
The function StringToMultifield parses and creates a Multifield value from the values
contained in the parameter str. For example, if the str parameter value is "1 4.5 c", a multifield
with three values—the integer 1, the float 4.5, and the symbol c—will be created.
The function MBCreate creates and returns a Multifield based on values appended to the
MultifieldBuilder specified by parameter mb. The length of the MultifieldBuilder is reset to 0
after this function is called.
The function MBReset resets the MultifieldBuilder specified by parameter mb to its initial
capacity. Any values previously appended are removed and the length of the MultifieldBuilder
is set to 0.
The function MBDispose deallocates all memory associated with previously allocated
MultifieldBuilder specified by parameter mb.
CLIPSVoid *VoidConstant(
Environment *env);
The function VoidConstant returns a pointer to the CLIPS void primitive value.
CLIPSExternalAddress *CreateCExternalAddress(
Environment *theEnv,
void *ea);
Creates a CLIPS external address value from a C void pointer. Note that it is up to the user to
make sure that external addresses remain valid within CLIPS.
6.2 Examples
6.2.1 StringToMultifield
This example illustrates how to create a multifield primitive value from a string.
#include "clips.h"
int main()
{
Environment *env;
Multifield *mf;
env = CreateEnvironment();
mf = StringToMultifield(env,"\"abc\" 3 4.5");
DestroyEnvironment(env);
}
6.2.2 MultifieldBuilder
This example demonstrates how to create multifield primitive values using a MultifieldBuilder:
#include "clips.h"
int main()
{
Environment *env;
MultifieldBuilder *mb;
Multifield *mf;
env = CreateEnvironment();
mb = CreateMultifieldBuilder(env,10);
MBAppendString(mb,"abc");
MBAppendInt(mb,3);
MBAppendFloat(mb,4.5);
mf = MBCreate(mb);
MBAppendSymbol(mb,"def");
MBAppendInstanceName(mb,"i1");
mf = MBCreate(mb);
MBDispose(mb);
DestroyEnvironment(env);
}
Section 7:
Creating and Modifying
Facts and Instances
FactBuilder *CreateFactBuilder(
Environment *env,
const char *name);
Fact *FBAssert(
FactBuilder *fb);
void FBDispose(
FactBuilder *fb);
FactBuilderError FBSetDeftemplate(
FactBuilder *fb,
const char *name);
void FBAbort(
FactBuilder *fb);
FactBuilderError FBError (
Environment *env);
typedef enum
{
FBE_NO_ERROR,
FBE_NULL_POINTER_ERROR,
FBE_DEFTEMPLATE_NOT_FOUND_ERROR,
FBE_IMPLIED_DEFTEMPLATE_ERROR,
FBE_COULD_NOT_ASSERT_ERROR,
FBE_RULE_NETWORK_ERROR
} FactBuilderError;
If successful, this function returns a pointer to the created FactBuilder; otherwise, it returns a
null pointer. The error code for the function call be retrieved using the FBError function. The
value FBE_NO_ERROR indicates no error occurred; the value
FBE_DEFTEMPLATE_NOT_FOUND_ERROR indicates the specified deftemplate is either not
in scope in the current module or does not exist; and the value
FBE_IMPLIED_DEFTEMPLATE_ERROR indicates the specified deftemplate was not
explicitly defined.
The function FBAssert asserts the fact based on slot assignments made to the fact builder
specified by parameter fb. Slots which have not been explicitly assigned a value are set to their
default value. If successful, this function returns a pointer to the asserted Fact; otherwise it
returns a null pointer. Slot assignments are discarded after the fact is asserted, so slot values need
to be reassigned if the fact builder is used to build another fact. The error code for the function
call be retrieved using the FBError function. The value FBE_NO_ERROR indicates no error
occurred; the value FBE_NULL_POINTER_ERROR indicates the FactBuilder does not have
an associated deftemplate; the value FBE_COULD_NOT_ASSERT_ERROR indicates the fact
could not be asserted (such as when pattern matching of a fact or instance is already occurring);
and the value FBE_RULE_NETWORK_ERROR indicates an error occurred while the assertion
was being processed in the rule network.
The function FBDispose deallocates the memory associated with the FactBuilder specified by
parameter fb.
The function FBSetDeftemplate changes the type of fact created by the fact builder to the
deftemplate specified by the parameter name. Any slot values that have been assigned to the
builder are discarded. This function returns FBE_NO_ERROR if the deftemplate is successfully
set; otherwise it returns FBE_NULL_POINTER_ERROR if parameter fb is NULL,
FBE_DEFTEMPLATE_NOT_FOUND_ERROR if the deftemplate is not in scope in the current
module or does not exist, and FBE_IMPLIED_DEFTEMPLATE_ERROR if the deftemplate was
not explicitly defined.
The function FBAbort discards the slot value assignments that have been made for the fact
builder specified by parameter fb.
FactModifier *CreateFactModifier(
Environment *env,
Fact *f);
Fact *FMModify(
FactModifier *fm);
void FMDispose(
FactModifier *fm);
bool FMSetFact(
FactModifier *fm,
Fact *f);
void FMAbort(
FactModifier *fm);
FactModifierError FMError (
Environment *env);
typedef enum
{
FME_NO_ERROR,
FME_NULL_POINTER_ERROR,
FME_RETRACTED_ERROR,
FME_IMPLIED_DEFTEMPLATE_ERROR,
FME_COULD_NOT_MODIFY_ERROR,
FME_RULE_NETWORK_ERROR
} FactModifierError;
If successful, this function returns a pointer to the created FactModifier; otherwise, it returns a
null pointer. The error code for the function call be retrieved using the FMError function. The
value FME_NO_ERROR indicates no error occurred; the value FME_RETRACTED_ERROR
indicates the specified fact to be modified has been retracted; and the value
FBE_IMPLIED_DEFTEMPLATE_ERROR indicates the specified fact is associated with a
deftemplate that was not explicitly defined.
The function FMModify modifies the fact based on slot assignments made to the fact modifier
specified by parameter fm. If successful, this function returns a pointer to the modified Fact;
otherwise it returns a null pointer. Slot assignments are discarded after the fact is asserted, so slot
values need to be reassigned if the fact builder is used to modify another fact. The error code for
the function call be retrieved using the FMError function. The value FME_NO_ERROR
indicates no error occurred; the value FME_NULL_POINTER_ERROR indicates the
FactModifier does not have an associated fact; the value FME_RETRACTED indicates the fact
is retracted and cannot be modified; the value FME_COULD_NOT_MODIFY indicates the fact
could not be modified (such as when pattern matching of a fact or instance is already occurring);
and the value FME_RULE_NETWORK_ERROR indicates an error occurred while the
modification was being processed in the rule network.
The function FMDispose deallocates the memory associated with the FactModifier specified by
parameter fm.
The function FMSetFact changes the fact being modified to the value specified by parameter f.
Any slot values that have been assigned to the modifier are discarded. This function returns
FME_NO_ERROR if the fact is successfully set; otherwise it returns
FME_NULL_POINTER_ERROR if parameter fm is NULL, FME_RETRACTED_ERROR if
the fact has been retracted and cannot be modified, and
FME_IMPLIED_DEFTEMPLATE_ERROR if the specified fact is associated with a deftemplate
that was not explicitly defined.
The function FMAbort discards the slot value assignments that have been made for the fact
modifier specified by parameter fm.
InstanceBuilder *CreateInstanceBuilder(
Environment *env,
const char *name);
Instance *IBMake(
InstanceBuilder *ib,
const char *name);
void IBDispose(
InstanceBuilder *ib);
InstanceBuilderError IBSetDefclass(
InstanceBuilder *ib,
const char *name);
void IBAbort(
InstanceBuilder *ib);
InstanceBuilderError IBError (
Environment *env);
typedef enum
{
IBE_NO_ERROR,
IBE_NULL_POINTER_ERROR,
IBE_DEFCLASS_NOT_FOUND_ERROR,
IBE_COULD_NOT_CREATE_ERROR,
IBE_PROCESSING_ERROR
} InstanceBuilderError;
If successful, this function returns a pointer to the created InstanceBuilder; otherwise, it returns
a null pointer. The error code for the function call be retrieved using the IBError function. The
value IBE_NO_ERROR indicates no error occurred and the value
IBE_DEFCLASS_NOT_FOUND_ERROR indicates the specified defclass is either not in scope
in the current module or does not exist.
The function IBMake creates the instance based on slot assignments made to the instance
builder specified by parameter ib. Slots which have not been explicitly assigned a value are set to
their default value. If the parameter name is a null pointer, then an instance name is generated
for the newly created instance; otherwise, the name parameter value is used as the instance
name. If successful, this function returns a pointer to the created Instance; otherwise it returns a
null pointer. Slot assignments are discarded after the instance is created, so slot values need to be
reassigned if the instance builder is used to build another instance. The error code for the
function call be retrieved using the IBError function. The value IBE_NO_ERROR indicates no
error occurred; the value IBE_NULL_POINTER_ERROR indicates the InstanceBuilder does
not have an associated defclass; the value IBE_COULD_NOT_CREATE indicates the instance
could not be created (such as when pattern matching of a fact or instance is already occurring);
and the value IBE_RULE_NETWORK_ERROR indicates an error occurred while the instance
was being processed in the rule network
The function IBDispose deallocates the memory associated with the InstanceBuilder specified
by parameter ib.
The function IBSetDefclass changes the type of instance created by the instance builder to the
defclass specified by the parameter name. Any slot values that have been assigned to the builder
are discarded. This function returns IBE_NO_ERROR if the defclass is successfully set;
otherwise it returns IBE_NULL_POINTER_ERROR if parameter ib is NULL, and
IBE_DEFCLASS_NOT_FOUND_ERROR if the defclass is not in scope in the current module
or does not exist.
The function IBAbort discards the slot value assignments that have been made for the instance
builder specified by parameter ib.
InstanceModifier *CreateInstanceModifier(
Environment *env,
Instance *i);
Instance *IMModify(
InstanceModifier *im);
void IMDispose(
InstanceModifier *im);
InstanceModifierError IMSetInstance(
InstanceModifier *im,
Instance *i);
void IMAbort(
InstanceModifier *im);
InstanceModifierError IMError (
Environment *env);
typedef enum
{
IME_NO_ERROR,
IME_NULL_POINTER_ERROR,
IME_DELETED_ERROR,
IME_COULD_NOT_MODIFY_ERROR,
IME_RULE_NETWORK_ERROR
} InstanceModifierError;
The function IMModify modifies the instance based on slot assignments made to the instance
modifier specified by parameter im. If successful, this function returns a pointer to the modified
Instance; otherwise it returns a null pointer. Slot assignments are discarded after the instance is
modified, so slot values need to be reassigned if the instance builder is used to modify a different
instance. The error code for the function call be retrieved using the IMError function. The value
IME_NO_ERROR indicates no error occurred; the value IME_NULL_POINTER_ERROR
indicates the InstanceModifier does not have an associated instance; the value IME_DELETED
indicates the instance is deleted and cannot be modified; the value
IME_COULD_NOT_MODIFY indicates the instance could not be modified (such as when
pattern matching of a fact or instance is already occurring); and the value
IME_RULE_NETWORK_ERROR indicates an error occurred while the modification was being
processed in the rule network.
The function IMDispose deallocates the memory associated with the InstanceModifier
specified by parameter im.
The function IMSetInstance changes the instance being modified to the value specified by
parameter i. Any slot values that have been assigned to the modifier are discarded. This function
returns IME_NO_ERROR if the instance is successfully set; otherwise it returns
IME_NULL_POINTER_ERROR if parameter im is NULL or IME_DELETED_ERROR if the
instance has been deleted and cannot be modified.
The function IMAbort discards the slot value assignments that have been made for the instance
modifier specified by parameter im.
typedef enum
{
PSE_NO_ERROR,
PSE_NULL_POINTER_ERROR,
PSE_INVALID_TARGET_ERROR,
PSE_SLOT_NOT_FOUND_ERROR,
PSE_TYPE_ERROR,
PSE_RANGE_ERROR,
PSE_ALLOWED_VALUES_ERROR,
PSE_CARDINALITY_ERROR,
PSE_ALLOWED_CLASSES_ERROR
} PutSlotError;
The function FBPutSlot sets the slot specified by the parameter name to the value specified by
parameter v for the fact builder specified by parameter fb. This function returns true if the slot
was successfully set; otherwise, it returns false.
The function FMPutSlot sets the slot specified by the parameter name to the value specified by
parameter v for the fact modifier specified by parameter fm. This function returns true if the slot
was successfully set; otherwise, it returns false.
The function IBPutSlot sets the slot specified by the parameter name to the value specified by
parameter v for the instance builder specified by parameter ib. This function returns true if the
slot was successfully set; otherwise, it returns false.
The function IMPutSlot sets the slot specified by the parameter name to the value specified by
parameter v for the instance modifier specified by parameter im. This function returns true if the
slot was successfully set; otherwise, it returns false.
These functions assign an integer value in one of various forms to a FactBuilder (for parameter
fb), FactModifier (for parameter fm), InstanceBuilder (for parameter ib), or InstanceModifier
(for parameter im). Parameter name is the slot of either the fact or instance to be assigned.
Parameter i is the value assigned to the slot: a CLIPSInteger, int, long, or long long value.
These functions return true if the slot was successfully set; otherwise, they return false.
These functions assign a floating point value in one of various forms to a FactBuilder (for
parameter fb), FactModifier (for parameter fm), InstanceBuilder (for parameter ib), or
InstanceModifier (for parameter im). Parameter name is the slot of either the fact or instance to
be assigned. Parameter f is the value assigned to the slot: a CLIPSFloat, float, or double value.
These functions return true if the slot was successfully set; otherwise, they return false.
These functions assign a lexeme value (symbol, string, or instance name) in one of various forms
to a FactBuilder (for parameter fb), FactModifier (for parameter fm), InstanceBuilder (for
parameter ib), or InstanceModifier (for parameter im). Parameter name is the slot of either the
64 Section 7: Creating Facts and Instances
CLIPS Reference Manual
fact or instance to be assigned. Parameter lex is the value assigned to the slot: a CLIPSLexeme
or C string. These functions return true if the slot was successfully set; otherwise, they return
false.
These functions assign a fact or instance value to a FactBuilder (for parameter fb),
FactModifier (for parameter fm), InstanceBuilder (for parameter ib), or InstanceModifier (for
parameter im). Parameter name is the slot of either the fact or instance to be assigned. Parameter
f is the Fact value assigned to the slot; or parameter i is the Instance value assigned to the slot.
These functions return true if the slot was successfully set; otherwise, they return false.
These functions assign an external address or multifield value to a FactBuilder (for parameter
fb), FactModifier (for parameter fm), InstanceBuilder (for parameter ib), or InstanceModifier
(for parameter im). Parameter name is the slot of either the fact or instance to be assigned.
Parameter ea is the CLIPSExternalAddress value assigned to the slot; or parameter mf is the
Multifield value assigned to the slot. These functions return true if the slot was successfully set;
otherwise, they return false.
7.6 Examples
7.6.1 FactBuilder
#include "clips.h"
int main()
{
Environment *theEnv;
FactBuilder *theFB;
CLIPSValue cv;
theEnv = CreateEnvironment();
Build(theEnv,"(deftemplate person"
" (slot name)"
" (slot gender)"
" (slot age)"
" (slot marital-status (default single))"
" (multislot hobbies))");
theFB = CreateFactBuilder(theEnv,"person");
// Technique #1
// Technique #2
FBPutSlotCLIPSLexeme(theFB,"name",CreateString(theEnv,"Sam Jones"));
FBPutSlotCLIPSLexeme(theFB,"gender",CreateSymbol(theEnv,"male"));
FBPutSlotCLIPSInteger(theFB,"age",CreateInteger(theEnv,48));
FBPutSlotCLIPSLexeme(theFB,"marital-status",CreateSymbol(theEnv,"married"));
FBPutSlotMultifield(theFB,"hobbies",StringToMultifield(theEnv,"reading skiing"));
FBAssert(theFB);
// Technique #3
FBDispose(theFB);
DestroyEnvironment(theEnv);
}
(person
(name "Mary Sue Smith")
(gender female)
(age 25)
(marital-status single)
(hobbies))
(person
(name "Sam Jones")
(gender male)
(age 48)
(marital-status married)
(hobbies reading skiing))
(person
(name "John Doe")
(gender male)
(age 73)
(marital-status widowed)
(hobbies gardening))
7.6.2 FactModifier
int main()
{
Environment *theEnv;
FactModifier *theFM;
Fact *theFact;
theEnv = CreateEnvironment();
Build(theEnv,"(deftemplate print"
" (slot value))");
Build(theEnv,"(defrule print"
" (print (value ?v))"
" =>"
" (println ?v))");
theFM = CreateFactModifier(theEnv,theFact);
FMPutSlotString(theFM,"value","Middle");
FMModify(theFM);
Run(theEnv,-1);
FMPutSlotString(theFM,"value","End");
FMModify(theFM);
Run(theEnv,-1);
FMDispose(theFM);
DestroyEnvironment(theEnv);
}
Beginning
Middle
End
This example illustrates use of the FactBuilder and FactModifier APIs to iteratively change a
group of facts.
#include "clips.h"
int main()
{
Environment *theEnv;
FactBuilder *theFB;
FactModifier *theFM;
CLIPSValue cv;
Fact *sensors[2];
long long sensorValues[2] = { 6, 5 };
theEnv = CreateEnvironment();
Build(theEnv,"(deftemplate sensor"
" (slot id)"
Build(theEnv,"(defrule sensor-value-out-of-range"
" (sensor (id ?id) (value ?value) (range ?lower ?upper))"
" (test (or (< ?value ?lower) (> ?value ?upper)))"
" =>"
" (println ?id \" value \" ?value "
" \" out of range \" ?lower \" - \" ?upper))");
Watch(theEnv,FACTS);
theFB = CreateFactBuilder(theEnv,"sensor");
FBPutSlotSymbol(theFB,"id","sensor-1");
FBPutSlotMultifield(theFB,"range",StringToMultifield(theEnv,"4 8"));
FBPutSlotInteger(theFB,"value",sensorValues[0]);
sensors[0] = FBAssert(theFB);
RetainFact(sensors[0]);
FBPutSlotSymbol(theFB,"id","sensor-2");
FBPutSlotMultifield(theFB,"range",StringToMultifield(theEnv,"2 7"));
FBPutSlotInteger(theFB,"value",sensorValues[1]);
sensors[1] = FBAssert(theFB);
RetainFact(sensors[1]);
FBDispose(theFB);
theFM = CreateFactModifier(theEnv,NULL);
FMSetFact(theFM,oldValue);
Eval(theEnv,"(random -3 3)",&cv);
sensorValues[s] += cv.integerValue->contents;
FMPutSlotInteger(theFM,"value",sensorValues[s]);
sensors[s] = FMModify(theFM);
RetainFact(sensors[s]);
ReleaseFact(oldValue);
}
// Execute Rules
Run(theEnv,-1);
}
FMDispose(theFM);
DestroyEnvironment(theEnv);
}
Note that the specific values will vary because of calls to the random function.
Section 8:
User Defined Functions
CLIPS provides a collection of system defined functions and commands for a variety of
purposes. In addition, the deffunction construct can be used to create new functions and
commands within a CLIPS program. In some cases, however, it is necessary to integrate
functions written in C with the CLIPS C source code. This may be for performance reasons; to
integrate existing code written in C; or to integrate a C library.
Functions written in C that are integrated with CLIPS using the protocols described in this
section are referred to as User Defined Functions (UDFs) and can be used in the same manner as
system defined functions and commands. In fact, the system defined functions and commands
provided by CLIPS are integrated using the protocols described in this section. Note that while
the word ‘command’ is typically used throughout this documentation to refer to a function that
has no return value, the protocols used to implement functions and commands are the same.
This section describes the protocols for registering UDFs, passing arguments to them, and
returning values from them. Prototypes for the functions listed in this section can be included by
using the clips.h header file.
The UDFContext type contains the public field context, a pointer to user data supplied when the
UDF is registered, as well as several private fields used to track UDF argument requests (through
the udfc parameter value).
The UDFValue type is used both for returning a value from a UDF (through the out parameter
value) as well as requesting argument values passed to the UDF. The UDFValue type is similar
to the CLIPSValue type, but also includes begin and range fields. These fields allow you to
manipulate multifield values within a UDF without creating a new multifield. The begin field
represents the starting position and the range field represents the number of values within a
multifield. For example, if a UDFValue contained the multifield (a b c d), setting the begin field
to 1 and the range field to 2 would change the UDFValue to the multifield (b c).
typedef enum
{
AUE_NO_ERROR,
AUE_MIN_EXCEEDS_MAX,
AUE_FUNCTION_NAME_IN_USE,
AUE_INVALID_ARGUMENT_TYPE,
AUE_INVALID_RETURN_TYPE
} AddUDFError;
UDFs must be registered with CLIPS using the function AddUDF before they can be referenced
from CLIPS code. Calls to AddUDF can be made in the function UserFunctions contained in
the CLIPS userfunctions.c file. Within UserFunctions, a call should be made for every function
which is to be integrated with CLIPS. The user’s source code then can be compiled and linked
with CLIPS. Alternately, the user can call AddUDF from their own initialization code—the only
restrictions is that it must be called after CLIPS has been initialized and before the UDF is
referenced.
User-defined functions override system functions. If the user defines a function which is the
same as one of the defined functions already provided, the user function will be executed in its
place.
If the returnTypes parameter value is a null pointer, then CLIPS assumes that the UDF can
return any valid type. Specifying one or more type character codes, however, allows CLIPS to
detect errors when the return value of a UDF is used as a parameter value to a function that
specifies the types allowed for that parameter. The following codes are supported for return
values and argument types:
e External Address
f Fact Address
i Instance Address
l Long Long Integer
m Multifield
n Instance Name
s String
y Symbol
v Void—No Return Value
* Any Type
One or more characters can be specified. For example, "l" indicates the UDF returns an integer;
"ld" indicates the UDF returns an integer or float; and "syn" indicates the UDF returns a symbol,
string, or instance name.
The minArgs and maxArgs parameter values can be specified as the constant UNBOUNDED to
indicate that there is no restriction on the minimum or maximum number of arguments.
If the argTypes parameter value is a null pointer, then there are no argument type restrictions.
One or more character argument types can also be specified, separated by semicolons. The first
type specified is the default type (used when no other type is specified for an argument),
followed by types for specific arguments. For example, "ld" indicates that the default argument
type is an integer or float; "ld;s" indicates that the default argument type is an integer or float,
and the first argument must be a string; "*;;m" indicates that the default argument type is any
type, and the second argument must be a multifield; ";sy;ld" indicates that the default argument
type is any type, the first argument must be a string or symbol; and the second argument type
must be an integer or float.
CLIPS will generate an error and terminate the invocation of a UDF before it is called if the
incorrect number of arguments is supplied (either there are fewer arguments than the minimum
specified or more arguments than the maximum specified).
unsigned UDFArgumentCount(
UDFContext *udfc);
bool UDFFirstArgument(
UDFContext *udfc,
unsigned expectedType,
UDFValue *out);
bool UDFNextArgument(
UDFContext *udfc,
unsigned expectedType,
UDFValue *out);
bool UDFNthArgument(
UDFContext *udfc,
unsigned n,
unsigned expectedType,
UDFValue *out);
bool UDFHasNextArgument(
UDFContext *udfc);
void UDFThrowError (
UDFContext *udfc);
void SetErrorValue (
Environment *theEnv,
TypeHeader *theValue);
The function UDFArgumentCount returns the number of arguments passed to the UDF. At the
point the UDF is invoked, the argument count has been verified to fall within the range specified
by the minimum and maximum number of arguments specified in the call to AddUDF. Thus a
UDF should only need to check the argument count if the minimum and maximum number of
arguments are not the same.
The function UDFFirstArgument retrieves the first argument passed to the UDF. Parameter
udfc is a pointer to the UDFContext; parameter expectedType is a bit field containing the
expcted types for the argument; and parameter out is a pointer to a UDFValue in which the
retrieved argument value is stored. This function returns true if the argument was successfully
retrieved and is the expected type; otherwise, it returns false.
The function UDFNextArgument retrieves the argument following the previously retrieved
argument (either from UDFFirstArgument, UDFNextArgument, or UDFNthArgument). It
retrieves the first argument if no arguments have been previously retrieved. Parameter udfc is a
pointer to the UDFContext; parameter expectedType is a bit field containing the expcted types
for the argument; and parameter out is a pointer to a UDFValue in which the retrieved argument
value is stored. This function returns true if the argument was successfully retrieved and is the
expected type; otherwise, it returns false.
The function UDFNthArgument retrieves a specific argument passed to the UDF. Parameter
udfc is a pointer to the UDFContext; parameter n is the index of the argument to be retrieved
(with indices starting at 1); parameter expectedType is a bit field containing the expcted types
for the argument; and parameter out is a pointer to a UDFValue in which the retrieved argument
value is stored. This function returns true if the argument was successfully retrieved and is the
expected type; otherwise, it returns false.
The function UDFThrowError can be used by a UDF to indicate that an error has occurred and
execution should terminate.
The SetErrorValue function can be used to assign an error value which can be retrieved using
the get-error and set-error CLIPS functions. This function can be used for situations where a
function's return value can not be used to indicate an error and execution should not be
terminated.
These bit codes can be combined using the C | operator. For example, the following code
indicates that an argument should either be an integer or symbol:
INTEGER_BIT | SYMBOL_BIT
8.4 Examples
This example demonstrates returning a mathematical constant, Euler’s number, from a user
defined function.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
e; the return value type is a float; the UDF does not expect any arguments; and the C
implementation of the UDF is the function EulersNumber.
void UserFunctions(
Environment *env)
{
AddUDF(env,"e","d",0,0,NULL,EulersNumber,"EulersNumber",NULL);
}
The implementation of the CLIPS function e in the C function EulersNumber uses the function
CreateFloat to create the return value. The C library function exp is used to calculate the value
for Euler’s number.
#include <math.h>
void EulersNumber(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
out->floatValue = CreateFloat(env,exp(1.0));
}
After creating a new executable including the UDF code, the function e can be invoked within
CLIPS.
CLIPS> (e)
2.71828182845905
CLIPS>
This example demonstrates returning a multifield constant, the weekdays, from a user defined
function.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
weekdays; the return value type is a multifield value; the UDF does not expect any arguments;
and the C implementation of the UDF is the function Weekdays.
void UserFunctions(
Environment *env)
{
AddUDF(env,"weekdays","m",0,0,NULL,Weekdays,"Weekdays",NULL);
}
The implementation of the CLIPS function weekdays in the C function Weekdays uses the
function StringToMultifield to create the return value.
void Weekdays(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
out->multifieldValue =
StringToMultifield(env,"Monday Tuesday Wednesday Thursday Friday");
}
After creating a new executable including the UDF code, the function week-days can be invoked
within CLIPS.
CLIPS> (weekdays)
(Monday Tuesday Wednesday Thursday Friday)
CLIPS>
This example demonstrates a user defined function that cubes a numeric argument value and
returns either an integer or float depending upon the type of the argument value.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
cube; the return value type is an integer or float value; the UDF expects one argument that must
be an integer or a float; and the C implementation of the UDF is the function Cube.
void UserFunctions(
Environment *env)
{
AddUDF(env,"cube","ld",1,1,"ld",Cube,"Cube",NULL);
}
The implementation of the CLIPS function cube in the C function Cube uses the function
UDFFirstArgument to retrieve the numeric argument passed to the function. If the argument
value is an integer, the function CreateInteger is used to create the return value. If the argument
value is a float, the function CreateFloat is used to create the return value.
void Cube(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue theArg;
if (! UDFFirstArgument(udfc,NUMBER_BITS,&theArg))
{ return; }
if (theArg.header->type == INTEGER_TYPE)
{
long long integerValue = theArg.integerValue->contents;
integerValue = integerValue * integerValue * integerValue;
out->integerValue = CreateInteger(env,integerValue);
}
else /* the type must be FLOAT */
{
double floatValue = theArg.floatValue->contents;
floatValue = floatValue * floatValue * floatValue;
out->floatValue = CreateFloat(env,floatValue);
}
}
After creating a new executable including the UDF code, the function cube can be invoked
within CLIPS.
CLIPS> (cube 3)
27
CLIPS> (cube 3.5)
42.875
CLIPS>
This example demonstrates a user defined function that returns a boolean value indicating
whether a numeric argument value is positive.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
positivep; the return value type is a boolean value (either the symbol TRUE or FALSE); the
UDF expects one argument that must be an integer or a float; and the C implementation of the
UDF is the function Positivep.
void UserFunctions(
Environment *env)
{
AddUDF(env,"positivep","b",1,1,"ld",Positivep,"Positivep",NULL);
}
The implementation of the CLIPS function positivep in the C function Positivep uses the
function UDFFirstArgument to retrieve the numeric argument passed to the function. The
function CreateBoolean is used to create the return value.
void Positivep(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue theArg;
bool b;
if (! UDFFirstArgument(udfc,NUMBER_BITS,&theArg))
{ return; }
if (theArg.header->type == INTEGER_TYPE)
{ b = (theArg.integerValue->contents > 0); }
else /* the type must be FLOAT */
{ b = (theArg.floatValue->contents > 0.0); }
out->lexemeValue = CreateBoolean(env,b);
}
After creating a new executable including the UDF code, the function positivep can be invoked
within CLIPS.
8.4.5 Exclusive Or
This example demonstrates a user defined function that returns a boolean value indicating
whether an odd number of its arguments values are true (exclusive or).
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
xor; the return value type is a boolean value (either the symbol TRUE or FALSE); the UDF
expects at least two arguments; and the C implementation of the UDF is the function Xor.
void UserFunctions(
Environment *env)
{
AddUDF(env,"xor","b",2,UNBOUNDED,NULL,Xor,"Xor",NULL);
}
The implementation of the CLIPS function xor in the C function Xor uses the functions
UDFHasNextArgument and UDFNextArgument to retrieve the variable number of arguments
passed to the function. Any value other than the symbol FALSE is considered to be “TRUE” by
CLIPS, so when counting the number of argument values to be true, each argument is compared
for inequality to the return value of the FalseSymbol function. Finally, the function
CreateBoolean is used to create the return value.
void Xor(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue theArg;
int trueCount = 0;
while (UDFHasNextArgument(udfc))
{
UDFNextArgument(udfc,ANY_TYPE_BITS,&theArg);
if (theArg.value != FalseSymbol(env))
{ trueCount++; }
}
After creating a new executable including the UDF code, the function xor can be invoked within
CLIPS.
This example demonstrates a user defined function that reverses the characters in a CLIPS
symbol, string, or instance name.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
reverse; the return value type is a string, symbol, or instance name; the UDF expects one
argument that must be a string, symbol, or instance name; and the C implementation of the UDF
is the function Reverse.
void UserFunctions(
Environment *env)
{
AddUDF(env,"reverse","syn",1,1,"syn",Reverse,"Reverse",NULL);
}
The implementation of the CLIPS function reverse in the C function Reverse uses the function
UDFFirstArgument to retrieve the lexeme argument (string, symbol, or instance name) passed
to the function. The function genalloc is used to allocate temporary memory for reversing the
order of characters in the string. Depending upon the argument value type, the function
CreateString, CreateSymbol, or CreateInstanceName is used to create the return value.
Finally, the function genfree is used to deallocate the temporary memory.
void Reverse(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue theArg;
const char *theString;
char *tempString;
size_t length, i;
if (! UDFFirstArgument(udfc,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
{ return; }
theString = theArg.lexemeValue->contents;
length = strlen(theString);
tempString = (char *) genalloc(env,length + 1);
tempString[length] = '\0';
switch (theArg.header->type)
{
case STRING_TYPE:
out->lexemeValue = CreateString(env,tempString);
break;
case SYMBOL_TYPE:
out->lexemeValue = CreateSymbol(env,tempString);
break;
case INSTANCE_NAME_TYPE:
out->lexemeValue = CreateInstanceName(env,tempString);
break;
}
genfree(env,tempString,length+1);
}
After creating a new executable including the UDF code, the function reverse can be invoked
within CLIPS.
This example demonstrates a user defined function that creates a multifield value comprised
from its arguments values, but in reverse order.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
reverse$; the return value type is a multifield value; the UDF expects any number of arguments;
and the C implementation of the UDF is the function ReverseMF.
void UserFunctions(
Environment *env)
{
AddUDF(env,"reverse$","m",0,UNBOUNDED,NULL,ReverseMF,"ReverseMF",NULL);
}
The implementation of the CLIPS function reverse$ in the C function ReverseMF uses the
functions UDFArgumentCount and UDFNthArgument to retrieve arguments passed to the
function in reverse order. A multifield builder is created using the function
CreateMultifieldBuilder. Each function argument is appended to the multifield builder using
the function MBAppendUDFValue. The return value is created using MBCreate. Finally, the
multifield builder is deallocated using the function MBDispose.
void ReverseMF(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue theArg;
MultifieldBuilder *mb;
unsigned argCount;
mb = CreateMultifieldBuilder(env,20);
argCount = UDFArgumentCount(udfc);
UDFNthArgument(udfc,i,ANY_TYPE_BITS,&theArg);
MBAppendUDFValue(mb,&theArg);
}
out->multifieldValue = MBCreate(mb);
MBDispose(mb);
}
After creating a new executable including the UDF code, the function reverse$ can be invoked
within CLIPS.
CLIPS> (reverse$ 1 2 3)
(3 2 1)
CLIPS> (reverse$ a 6 (create$ 6.3 5.4) "s")
("s" 6.3 5.4 6 a)
CLIPS>
This example demonstrates a user defined function that trims values from the beginning and end
of a multifield value.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
trim$; the return value type is a multifield value; the UDF expects three arguments (the default
type is an integer and the first argument must be a multiefield value); and the C implementation
of the UDF is the function Trim.
void UserFunctions(
Environment *env)
{
AddUDF(env,"trim$","m",3,3,"l;m",Trim,"Trim",NULL);
}
The implementation of the CLIPS function trim$ in the C function Trim uses the functions
UDFFirstArgument and UDFNextArgument to retrieve arguments passed to the function. The
first argument is a multifield value; and the second and third arguments are integers (the number
of values to trim from the beginning and end of the multifield value). If the trim values are
negative or exceed the number of values contained in the multifield, then the functions
PrintString and UDFThrowError are used to indicate an error; otherwise the begin and range
fields of the argument value stored in the return value parameter out are modified to trim the
appropriate number of values from the beginning and end of the multifield.
void Trim(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
long long front, back;
UDFValue arg;
UDFFirstArgument(udfc,MULTIFIELD_BIT,out);
UDFNextArgument(udfc,INTEGER_BIT,&arg);
front = arg.integerValue->contents;
UDFNextArgument(udfc,INTEGER_BIT,&arg);
back = arg.integerValue->contents;
// Detect errors.
After creating a new executable including the UDF code, the function trim$ can be invoked
within CLIPS.
This example demonstrates a user defined function that removes duplicate values from a
multifield value.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
compact$; the return value type is a multifield value; the UDF expects one argument that must
be a multifield value; and the C implementation of the UDF is the function Compact.
void UserFunctions(
Environment *env)
{
AddUDF(env,"compact$","m",1,1,"m",Compact,"Compact",NULL);
}
The implementation of the CLIPS function compact$ in the C function Compact uses the
function UDFFirstArgument to retrieve the multifield argument value passed to the function. A
multifield builder is created using the function CreateMultifieldBuilder. The begin and range
fields are used to iterate over the values of the multifield argument value. If the value is not
contained within the multifield builder, then it is added using the MBAppend function. The
return value of the function is created using the MBCreate function. Finally, the multifield
builder is deallocated using the function MBDispose.
void Compact(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue arg;
MultifieldBuilder *mb;
size_t i, j;
UDFFirstArgument(udfc,MULTIFIELD_BIT,&arg);
mb = CreateMultifieldBuilder(env,20);
if (j == mb->length)
{ MBAppend(mb,&arg.multifieldValue->contents[i]); }
}
out->multifieldValue = MBCreate(mb);
MBDispose(mb);
}
After creating a new executable including the UDF code, the function compact$ can be invoked
within CLIPS.
This example demonstrates a user defined function that determines the prime factors of an
integer.
The AddUDF function call required in UserFunctions specifies that the CLIPS function name is
prime-factors; the return value type is an integer; the UDF expects one argument that must be
an integer; and the C implementation of the UDF is the function PrimeFactors.
void UserFunctions(
Environment *env)
{
AddUDF(env,"prime-factors","m",1,1,"l",PrimeFactors,"PrimeFactors",NULL);
}
The implementation of the CLIPS function prime-factors in the C function PrimeFactor uses
the function UDFFirstArgument to retrieve the integer argument value passed to the function. If
the integer is less than 2, the return value is created using the function EmptyMultifield to
indicate that there are no prime factors. Otherwise, a multifield builder is created using the
function CreateMultifieldBuilder. A trial division algorithm is then used to determine the prime
factors and, as each is found, it is added to the multifield builder using the MBAppendInteger
function. The return value of the function is created using the MBCreate function. Finally, the
multifield builder is deallocated using the function MBDispose.
#include <math.h>
void PrimeFactors(
Environment *env,
UDFContext *udfc,
UDFValue *out)
{
UDFValue value;
long long num, p, upper;
MultifieldBuilder *mb;
UDFFirstArgument(udfc,INTEGER_BIT,&value);
num = value.integerValue->contents;
if (num < 2)
{
out->multifieldValue = EmptyMultifield(env);
return;
}
mb = CreateMultifieldBuilder(env,10);
while ((num % p) == 0)
{
MBAppendInteger(mb,p);
num /= p;
}
}
if (num > 1)
{ MBAppendInteger(mb,num); }
out->multifieldValue = MBCreate(mb);
MBDispose(mb);
}
After creating a new executable including the UDF code, the function prime-factor can be
invoked within CLIPS.
CLIPS> (prime-factors 1)
()
CLIPS> (prime-factors 3)
(3)
CLIPS> (prime-factors 128)
(2 2 2 2 2 2 2)
CLIPS> (prime-factors 5040)
(2 2 2 2 3 3 5 7)
CLIPS> (prime-factors 1257383)
(373 3371)
CLIPS> (prime-factors 6469693230)
(2 3 5 7 11 13 17 19 23 29)
CLIPS>
Section 9:
I/O Routers
The I/O router system provided in CLIPS is quite flexible and will allow a wide variety of
interfaces to be developed and easily attached to CLIPS. The system is relatively easy to use and
is explained fully in sections 9.1 through 9.4. The CLIPS I/O functions for using the router
system are described in sections 9.5 and 9.6, and finally, in section 9.7, some examples are
included which show how I/O routing could be used for simple interfaces.
9.1 Introduction
The problem that originally inspired the idea of I/O routing will be considered as an introduction
to I/O routing. Because CLIPS was designed with portability as a major goal, it was not possible
to build a sophisticated user interface that would support many of the features found in the
interfaces of commercial expert system building tools. A prototype was built of a semi-portable
interface for CLIPS using the CURSES screen management package. Many problems were
encountered during this effort involving both portability concerns and CLIPS internal features.
For example, every statement in the source code which used the C print function, printf, for
printing to the terminal had to be replaced by the CURSES function, wprintw, which would
print to a window on the terminal. In addition to changing function call names, different types of
I/O had to be directed to different windows. The tracing information was to be sent to one
window, the command prompt was to appear in another window, and output from printout
statements was to be sent to yet another window.
This prototype effort pointed out two major needs: First, the need for generic I/O functions that
would remain the same regardless of whether I/O was directed to a standard terminal interface or
to a more complex interface (such as windows); and second, the need to be able to specify
different sources and destinations for I/O. I/O routing was designed in CLIPS to handle these
needs. The concept of I/O routing will be further explained in the following sections.
update Y:[A]payroll
If the data were moved to directory B on computer X, Joe’s command would have to be changed
to
update X:[B]payroll
To update the payroll file, Joe must know its location. If the file is moved, Joe must be informed
of its new location to be able to update it. From Joe’s point of view, he does not care where the
file is located physically. He simply wants to be able to specify that he wants the information
from the accounting data set. He would rather use a command like
update accounting:payroll
By using logical names, the information about where the accounting files are located physically
can be hidden from Joe while still allowing him to access them. The locations of the files are
equated with logical names as shown here.
accounting = X:[A]
documentation = X:[C]
personnel = Y:[B]
Now, if the files are moved, Joe does not have to be informed of their relocation so long as the
logical names are updated. This is the power of using logical names. Joe does not have to be
aware of the physical location of the files to access them; he only needs to be aware that
accounting is the logical name for the location of the accounting data files. Logical names allow
reference to an object without having to understand the details of the implementation of the
reference.
In CLIPS, logical names are used to send I/O requests without having to know which device
and/or function is handling the request. Consider the message that is printed in CLIPS when rule
tracing is turned on and a rule has just fired. A typical message would be
The routine that requests this message be printed should not have to know where the message is
being sent. Different routines are required to print this message to a standard terminal, a window
interface, or a printer. The tracing routine should be able to send this message to a logical name
(for example, trace-out) and should not have to know if the device to which the message is
being sent is a terminal or a printer. The logical name trace-out allows tracing information to be
sent simply to “the place where tracing information is displayed.” In short, logical names allow
I/O requests to be sent to specific locations without having to specify the details of how the I/O
request is to be handled.
Many functions in CLIPS make use of logical names. Both the printout and format functions
require a logical name as their first argument. The read function can take a logical name as an
optional argument. The open function causes the association of a logical name with a file, and
the close function removes this association.
Several logical names are predefined by CLIPS and are used extensively throughout the system
code. These are
Name Description
stdin The default for all user inputs. The read and readline functions
read from stdin if t is specified as the logical name.
stdout The default for all user outputs. The format and printout functions
send output to stdout if t is specified as the logical name.
Within CLIPS code, these predefined logical names should be specified in lower case (and
typically the only one you’ll use is t and depending upon which function you’re using this will
be mapped to either stdin or stdout). Within C code, these logical names can be specified using
constants that have been defined in upper case: STDIN, STDOUT, STDERR, and STDWRN.
9.3 Routers
The use of logical names solves two problems. Logical names make it easy to create generic I/O
functions, and they allow the specification of different sources and destinations for I/O. The use
of logical names allows CLIPS to ignore the specifics of an I/O request. However, such requests
must still be specified at some level. I/O routers are provided to handle the specific details of a
request.
A router consists of three components. The first component is a function which can determine
whether the router can handle an I/O request for a given logical name. The router which
recognizes I/O requests that are to be sent to the serial port may not recognize the same logical
names as that which recognizes I/O requests that are to be sent to the terminal. On the other
hand, two routers may recognize the same logical names. A router that keeps a log of a CLIPS
session (a dribble file) may recognize the same logical names as that which handles I/O requests
for the terminal.
The second component of a router is its priority. When CLIPS receives an I/O request, it begins
to query each router to discover whether it can handle an I/O request. Routers with high priorities
are queried before routers with low priorities. Priorities are very important when dealing with
one or more routers that can each process the same I/O request. This is particularly true when a
router is going to redefine the standard user interface. The router associated with the standard
interface will handle the same I/O requests as the new router; but, if the new router is given a
higher priority, the standard router will never receive any I/O requests. The new router will
“intercept” all of the I/O requests. Priorities will be discussed in more detail in the next section.
The third component of a router consists of the functions which actually handle an I/O request.
These include functions for printing strings, getting a character from an input buffer, returning a
character to an input buffer, and a function to clean up (e.g., close files, remove windows) when
CLIPS is exited.
Once the router system sends an I/O request out to a router, it considers the request satisfied. If a
router is going to share an I/O request (i.e., process it) then allow other routers to process the
request also, that router must deactivate itself and call WriteString again. These types of routers
should use a priority of either 30 or 40. An example is given in appendix 9.7.2.
40 Any router that wants to grab standard I/O and is willing to share it
with other routers. A dribble file is a good example of this type of
router. The dribble file router needs to grab all output that normally
would go to the terminal so it can be placed in the dribble file, but
this same output also needs to be sent to the router which displays
output on the terminal.
30 Any router that uses “unique” logical names and is willing to share
I/O with catch-all routers.
20 Any router that wants to grab standard logical names and is not
willing to share them with other routers.
0 This priority is used by the default router for handling standard and
file logical names. Other routers should not use this priority.
9.5.1 ExitRouter
void ExitRouter(
Environment *env,
int code);
The function ExitRouter calls the exit function callback associated with each active router
before exiting CLIPS. Parameter env is a pointer to a previously created environment; and
parameter code is an integer passed to the callback as well as the system exit function once all
callbacks have been executed. User code that detects an unrecoverable error should call this
function rather than calling the system exit function so that routers have the opportunity to
execute cleanup code.
9.5.2 Input
int ReadRouter(
Environment *env,
const char *logicalName);
int UnreadRouter(
Environment *env,
The function ReadRouter queries all active routers to retrieve character input. This function
should be used in place of getc to ensure that character input from the function can be received
from a custom interface. Parameter env is a pointer to a previously created environment; and
parameter logicalName is the query string that must be recognized by the router to be invoked to
handle the I/O request. The get character function callback for that router is invoked and the
return value of that callback is returned by this function.
The function UnreadRouter queries all active routers to push character input back into an input
source. This function should be used in place of ungetc to ensure that character input works
properly using a custom interface. Parameter env is a pointer to a previously created
environment; parameter logicalName is the query string that must be recognized by the router to
be invoked to handle the I/O request; and parameter ch is the character to be pushed back to the
input source. The unget character function callback for that router is invoked. The return value
for this function is the parameter value ch if the character is successfully pushed back to the
input source; otherwise, -1 is returned.
9.5.3 Output
void Write(
Environment *env,
const char *str);
void WriteCLIPSValue(
Environment *env,
const char *logicalName,
CLIPSValue *cv);
void WriteFloat(
Environment *env,
const char *logicalName,
double d);
void WriteInteger(
Environment *env,
const char *logicalName,
long long l);
void Writeln(
Environment *env,
const char *str);
void WriteString(
Environment *env,
const char *logicalName,
const char *str);
void WriteMultifield(
Environment *env,
const char *logicalName,
Multifield *mf);
void WriteUDFValue(
Environment *env,
const char *logicalName,
UDFValue *udfv);
For all of these functions, parameter env is a pointer to a previously created environment. For all
function except Write and Writeln, the parameter logicalName is the query string that must be
recognized by a router to indicate it can handle the output request. All active routers are queried
in order of their priority until the query function callback for a router returns true to indicate if
handles the specified logical name. The Write and Writeln functions automatically sent output
to the STDOUT logical name.
The remaining parameter for all of these functions is the value to be printed. The parameters d, l,
and str are the C types double, long long, and a char pointer to a null-terminated string.
Parameter mf is a pointer to a Multifield. Parameters cv and udfv are pointers to CLIPSValue
and UDFValue types that have been allocated and populated with data by the caller. The
Writeln function additionally prints a carriage return after printing the str parameter.
bool AddRouter(
Environment *env,
const char *name,
int priority,
RouterQueryFunction *queryCallback,
RouterWriteFunction *writeCallback,
RouterReadFunction *readCallback,
RouterUnreadFunction *unreadCallback,
RouterExitFunction *exitCallback,
void *context);
The function AddRouter creates and activates a new router. Parameter env is a pointer to a
previously created environment; parameter name is a string that uniquely identifies the router for
removal using DeleteRouter; parameters queryCallback, writeCallback, readCallback,
unreadCallback, and exitCallback are pointers to callback functions; parameter priority is the
priority of the router used to determine the order in which routers are queried (higher priority
routers are queried first); and parameter context is a user supplied pointer to data that is passed
to the router callback functions when they are invoked (a null pointer should be used if there is
no data that needs to be passed to the router callback functions). The queryCallback parameter
value must be a non-null function pointer, otherwise the other router callback functions will
never be invoked. If the router does not handle output requests, the writeCallback parameter
value should be a null pointer. If the router does not handle input requests, the readCallback and
unreadCallback parameter values should be null pointers. This function returns true if the router
was successfully added; otherwise, it returns false.
The RouterQueryFunction type has three parameters: env is a pointer to a previously created
environment; logicalName is the logical name associated with the I/O request; and context is the
user supplied data pointer provided when the router was created. This function should return true
if the logicalName parameter value is recognized by this router; otherwise, it should return false.
The RouterWriteFunction type has four parameters: env is a pointer to a previously created
environment; logicalName is the logical name associated with the I/O request; str is the null
character terminated string to be printed; and context is the user supplied data pointer provided
when the router was created.
The RouterExitFunction type has three parameters: env is a pointer to a previously created
environment; code is the exit code value (either the value passed to the CLIPS exit command or
the C ExitRouter function); and context is the user supplied data pointer provided when the
router was created.
The RouterReadFunction type has three parameters: env is a pointer to a previously created
environment; logicalName is the logical name associated with the I/O request; and context is the
user supplied data pointer provided when the router was created. The return value of this
function is an integer character code or -1 to indicate EOF (end of file).
The RouterUnreadFunction type has four parameters: env is a pointer to a previously created
environment; logicalName is the logical name associated with the I/O request; ch is the
character code to be pushed back into the router input source; and context is the user supplied
data pointer provided when the router was created. The return value of this function should be
the ch parameter value if the function successfully pushes the character code; otherwise, it
should return -1 (EOF).
bool DeleteRouter(
Environment *env,
const char *name);
The function DeleteRouter removes previously created router. Parameter env is a pointer to a
previously created environment; and parameter name is the string used to identify the router
when it was added using AddRouter. The function returns true if the router was successfully
deleted; otherwise, it returns false.
bool ActivateRouter(
Environment *env,
const char *name);
bool DeactivateRouter(
Environment *env,
const char *name);
The function ActivateRouter activates the I/O router specified by parameter name (the string
used to identify the router when it was created using AddRouter). The activated router will be
queried to see if it can handle an I/O request. Newly created routers do not have to be activated.
This function returns true if the router exists and was successfully activated; otherwise, false is
returned.
The function DeactivateRouter deactivates the I/O router specified by parameter name (the
string used to identify the router when it was created using AddRouter). The deactivated router
will not be queried to see if it can handle an I/O request. This function returns true if the router
exists and was successfully deactivated; otherwise, false is returned.
9.7 Examples
The following examples demonstrate the use of the I/O router system. These examples show the
necessary C code for implementing the basic capabilities described.
Write the necessary functions that will divert all error information to the file named "error.txt".
/*
First of all, we need to create an environment data structure for storing a file
pointer to the dribble file which will contain the error information. The data
position is offset to prevent conflict with other examples in this document. We also
need to declare prototypes for the functions used in this example.
*/
#include <stdio.h>
#include <stdlib.h>
#include "clips.h"
struct dribbleData
{
FILE *traceFP;
};
#define DribbleData(theEnv) \
((struct dribbleData *) GetEnvironmentData(theEnv,DRIBBLE_DATA))
/*
We want to recognize any output that is sent to the logical name STDERR because all
tracing information is sent to this logical name. The query function for our router
is defined below.
*/
bool QueryTraceCallback(
Environment *environment,
const char *logicalName,
void *context)
{
if (strcmp(logicalName,STDERR) == 0) return(true);
return(false);
}
/*
We now need to define a function which will print the tracing in¬formation to our
trace file. The print function for our router is defined below. The context argument
is used to retrieve the FILE pointer that will be supplied when AddRouter is called.
*/
void WriteTraceCallback(
Environment *environment,
const char *logicalName,
const char *str,
void *context)
{
FILE *theFile = (FILE *) context;
fprintf(theFile,"%s",str);
}
/*
When we exit CLIPS the trace file needs to be closed. The exit function for our
router is defined below. The context argument is used to retrieve the FILE pointer
that will be supplied when AddRouter is called.
*/
void ExitTraceCallback(
Environment *environment,
int exitCode,
void *context)
{
FILE *theFile = (FILE *) context;
fclose(theFile);
/*
There is no need to define a get character or ungetc character function since this
router does not handle input.
A function to turn the trace mode on needs to be defined. This function will check
if the trace file has already been opened. If the file is already open, then nothing
will happen. Otherwise, the trace file will be opened and the trace router will be
creat¬ed. This new router will intercept tracing information intended for the user
interface and send it to the trace file. The trace on function is defined below.
*/
void TraceOn(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
if (DribbleData(environment)->traceFP == NULL)
{
DribbleData(environment)->traceFP = fopen("error.txt","w");
if (DribbleData(environment)->traceFP == NULL)
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
}
else
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
AddRouter(environment,
"trace", /* Router name */
20, /* Priority */
QueryTraceCallback, /* Query function */
WriteTraceCallback, /* Write function */
NULL, /* Read function */
NULL, /* Unread function */
ExitTraceCallback, /* Exit function */
DribbleData(environment)->traceFP); /* Context */
returnValue->lexemeValue = environment->TrueSymbol;
}
/*
A function to turn the trace mode off needs to be defined. This function will check
if the trace file is already closed. If the file is already closed, then nothing
will happen. Otherwise, the trace router will be deleted and the trace file will be
closed. The trace off function is defined below.
*/
void TraceOff(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
if (DribbleData(environment)->traceFP != NULL)
{
DeleteRouter(environment,"trace");
if (fclose(DribbleData(environment)->traceFP) == 0)
{
DribbleData(environment)->traceFP = NULL;
returnValue->lexemeValue = environment->TrueSymbol;
return;
}
}
DribbleData(environment)->traceFP = NULL;
returnValue->lexemeValue = environment->FalseSymbol;
}
/*
Now add the definitions for these functions to the UserFunctions function in file
"userfunctions.c".
*/
void UserFunctions(
Environment *env)
{
if (! AllocateEnvironmentData(env,DRIBBLE_DATA,
sizeof(struct dribbleData),NULL))
{
printf("Error allocating environment data for DRIBBLE_DATA\n");
exit(EXIT_FAILURE);
}
AddUDF(env,"tron","b",0,0,NULL,TraceOn,"tron",NULL);
AddUDF(env,"troff","b",0,0,NULL,TraceOff,"troff",NULL);
}
/*
Compile and link the appropriate files. The trace functions should now be accessible
within CLIPS as external functions. For Example:
CLIPS> (tron)
TRUE
CLIPS> (+ 2 3)
5
CLIPS> (* 3 a)
CLIPS> (troff)
TRUE
CLIPS> (exit)
Modify example 1 so the error information is sent to the terminal as well as to the dribble file.
/*
This example requires a modification of the WriteTraceCallback function. After the
error string is printed to the file, the trace router must be deactivated. The error
string can then be sent through the WriteString function so that the next router in
line can handle the output. After this is done, then the trace router can be
reactivated.
*/
void WriteTraceCallback(
Environment *environment,
const char *logicalName,
const char *str,
void *context)
{
FILE *theFile = (FILE *) context;
fprintf(theFile,"%s",str);
DeactivateRouter(environment,"trace");
WriteString(environment,logicalName,str);
ActivateRouter(environment,"trace");
}
/*
The TraceOn function must also be modified. The priority of the router should be 40
instead of 20 since the router passes the output along to other routers.
*/
void TraceOn(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
if (DribbleData(environment)->traceFP == NULL)
{
DribbleData(environment)->traceFP = fopen("error.txt","w");
if (DribbleData(environment)->traceFP == NULL)
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
}
else
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
AddRouter(environment,
"trace", /* Router name */
40, /* Priority */
QueryTraceCallback, /* Query function */
WriteTraceCallback, /* Write function */
NULL, /* Read function */
NULL, /* Unread function */
ExitTraceCallback, /* Exit function */
DribbleData(environment)->traceFP); /* Context */
returnValue->lexemeValue = environment->TrueSymbol;
}
Write the necessary functions that will allow batch input from the file "batch.txt" to the CLIPS
top-level interface. Note that this example only works in the console version of CLIPS.
/*
First of all, we need a file pointer to the batch file which will contain the batch
command information.
*/
#include <stdio.h>
#include <stdlib.h>
#include "clips.h"
struct batchData
{
FILE *batchFP;
StringBuilder *batchBuffer;
};
#define BatchData(theEnv) \
((struct batchData *) GetEnvironmentData(theEnv,BATCH_DATA))
/*
We want to recognize any input requested from the logical name "stdin" because all
user input is received from this logical name. The recognizer function for our
router is defined below.
*/
bool QueryMybatchCallback(
Environment *environment,
const char *logicalName,
void *context)
{
if (strcmp(logicalName,STDIN) == 0) return true;
return false;
}
/*
We now need to define a function which will get and unget characters from our batch
file. The get and ungetc character functions for our router are defined below.
*/
int ReadMybatchCallback(
Environment *environment,
const char *logicalName,
void *context)
{
int rv;
rv = getc(BatchData(environment)->batchFP);
if (rv == EOF)
{
Write(environment,BatchData(environment)->batchBuffer->contents);
SBDispose(BatchData(environment)->batchBuffer);
BatchData(environment)->batchBuffer = NULL;
DeleteRouter(environment,"mybatch");
fclose(BatchData(environment)->batchFP);
return ReadRouter(environment,logicalName);
}
SBAddChar(BatchData(environment)->batchBuffer,rv);
return rv;
}
int UnreadMybatchCallback(
Environment *environment,
const char *logicalName,
int ch,
void *context)
{
SBAddChar(BatchData(environment)->batchBuffer,'\b');
return ungetc(ch,BatchData(environment)->batchFP);
}
/*
When we exit CLIPS the batch file needs to be closed. The exit function for our
router is defined below.
*/
void ExitMybatchCallback(
Environment *environment,
int exitCode,
void *context)
{
FILE *theFile = (FILE *) context;
if (BatchData(environment)->batchBuffer != NULL)
{
SBDispose(BatchData(environment)->batchBuffer);
BatchData(environment)->batchBuffer = NULL;
}
fclose(theFile);
}
/*
There is no need to define a print function since this router does not handle output
except for echoing the command line.
Now we define a function that turns the batch mode on.
*/
void MybatchOn(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
BatchData(environment)->batchFP = fopen("batch.txt","r");
if (BatchData(environment)->batchFP == NULL)
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
if (BatchData(environment)->batchBuffer == NULL)
{ BatchData(environment)->batchBuffer = CreateStringBuilder(environment,80); }
AddRouter(environment,
"mybatch", /* Router name */
20, /* Priority */
QueryMybatchCallback, /* Query function */
NULL, /* Write function */
ReadMybatchCallback, /* Read function */
UnreadMybatchCallback, /* Unread function */
ExitMybatchCallback, /* Exit function */
BatchData(environment)->batchFP); /* context */
returnValue->lexemeValue = environment->TrueSymbol;
}
/*
Now add the definition for this function to the UserFunctions function in file
"userfunctions.c".
*/
void UserFunctions(
Environment *env)
{
if (! AllocateEnvironmentData(env,BATCH_DATA,
sizeof(struct batchData),NULL))
{
printf("Error allocating environment data for BATCH_DATA\n");
exit(EXIT_FAILURE);
}
AddUDF(env,"mybatch","b",0,0,NULL,MybatchOn,"MybatchOn",NULL);
}
/*
Compile and link the appropriate files. The batch function should now be accessible
within CLIPS as external function. For Example, create the file batch.txt with the
following content:
(+ 2 3)
(* 4 5)
CLIPS> (mybatch)
TRUE
CLIPS> (+ 2 3)
5
CLIPS> (* 4 5)
20
CLIPS>
*/
Write the necessary functions using CURSES (a screen management function available in
UNIX) that will allow a top/bottom split screen interface. Output sent to the logical name top
will be printed in the upper window. All other screen I/O should go to the lower window.
(NOTE: Use of CURSES may require linking with special libraries. On UNIX systems try using
–lcurses when linking.)
/*
First of all, we need some pointers to the windows and a flag to indicate that the
windows have been initialized.
*/
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include "clips.h"
struct cursesData
{
WINDOW *lowerWindow, *upperWindow;
bool windowsInitialized;
bool useSave;
int saveChar;
bool sendReturn;
char buffer[512];
int charLocation;
};
#define CursesData(theEnv) \
((struct cursesData *) GetEnvironmentData(theEnv,CURSES_DATA))
/*
We want to intercept any I/O requests that the standard interface would handle. In
addition, we also need to handle requests for the logical name top. The recognizer
function for our router is defined below.
*/
bool QueryScreenCallback(
Environment *environment,
const char *logicalName,
void *context)
{
if ((strcmp(logicalName,STDOUT) == 0) ||
(strcmp(logicalName,STDIN) == 0) ||
(strcmp(logicalName,STDERR) == 0) ||
(strcmp(logicalName,STDWRN) == 0) ||
(strcmp(logicalName,"top") == 0) )
{ return true; }
return false;
}
/*
We now need to define a function which will print strings to the two windows. The
print function for our router is defined below.
*/
void WriteScreenCallback(
Environment *environment,
const char *logicalName,
if (strcmp(logicalName,"top") == 0)
{
wprintw(theData->upperWindow,"%s",str);
wrefresh(theData->upperWindow);
}
else
{
wprintw(theData->lowerWindow,"%s",str);
wrefresh(theData->lowerWindow);
}
}
/*
We now need to define a function which will get and unget characters from the lower
window. CURSES uses unbuffered input so we will simulate buffered input for CLIPS.
The get and ungetc character functions for our router are defined below.
*/
int ReadScreenCallback(
Environment *environment,
const char *logicalName,
void *context)
{
struct cursesData *theData = (struct cursesData *) context;
int rv;
if (theData->useSave)
{
theData->useSave = false;
return theData->saveChar;
}
if (theData->buffer[theData->charLocation] == '\0')
{
if (theData->sendReturn == false)
{
theData->sendReturn = true;
return '\n';
}
wgetnstr(theData->lowerWindow,&theData->buffer[0],511);
theData->charLocation = 0;
}
rv = theData->buffer[theData->charLocation];
if (rv == '\0') return '\n';
theData->charLocation++;
theData->sendReturn = false;
return rv;
}
int UnreadScreenCallback(
Environment *environment,
const char *logicalName,
int ch,
void *context)
{
theData->useSave = true;
theData->saveChar = ch;
return ch;
}
/*
When we exit CLIPS CURSES needs to be deactivated. The exit function for our router
is defined below.
*/
void ExitScreenCallback(
Environment *environment,
int exitCode,
void *context)
{
endwin();
}
/*
Now define a function that turns the screen mode on.
*/
void ScreenOn(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
int halfLines, i;
if (CursesData(environment)->windowsInitialized)
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
initscr();
echo();
CursesData(environment)->windowsInitialized = true;
CursesData(environment)->useSave = false;
CursesData(environment)->sendReturn = true;
CursesData(environment)->buffer[0] = '\0';
CursesData(environment)->charLocation = 0;
AddRouter(environment,
"screen", /* Router name */
10, /* Priority */
QueryScreenCallback, /* Query function */
WriteScreenCallback, /* Write function */
ReadScreenCallback, /* Read function */
UnreadScreenCallback, /* Unread function */
ExitScreenCallback, /* Exit function */
CursesData(environment)); /* Context */
halfLines = LINES / 2;
CursesData(environment)->upperWindow = newwin(halfLines,COLS,0,0);
CursesData(environment)->lowerWindow = newwin(halfLines - 1,COLS,halfLines + 1,0);
scrollok(CursesData(environment)->upperWindow,TRUE);
scrollok(CursesData(environment)->lowerWindow,TRUE);
wclear(CursesData(environment)->upperWindow);
wclear(CursesData(environment)->lowerWindow);
wmove(CursesData(environment)->lowerWindow,0,0);
returnValue->lexemeValue = environment->TrueSymbol;
}
/*
Now define a function that turns the screen mode off.
*/
void ScreenOff(
Environment *environment,
UDFContext *context,
UDFValue *returnValue)
{
/* Is CURSES already deactivated? */
if (CursesData(environment)->windowsInitialized == false)
{
returnValue->lexemeValue = environment->FalseSymbol;
return;
}
CursesData(environment)->windowsInitialized = false;
DeleteRouter(environment,"screen");
endwin();
returnValue->lexemeValue = environment->TrueSymbol;
}
/*
Now add the definitions for these functions to the UserFunctions function in file
"userfunctions.c".
*/
void UserFunctions(
Environment *env)
{
if (! AllocateEnvironmentData(env,CURSES_DATA,
sizeof(struct cursesData),NULL))
{
printf("Error allocating environment data for CURSES_DATA\n");
exit(EXIT_FAILURE);
}
AddUDF(env,"screen-on","b",0,0,NULL,ScreenOn,"ScreenOn",NULL);
AddUDF(env,"screen-off","b",0,0,NULL,ScreenOff,"ScreenOff",NULL);
}
/*
Compile and link the appropriate files. The screen functions should now be accessible
within CLIPS as external functions. For Example
CLIPS> (screen-on)
CLIPS> (printout top "Hello World" crlf)
•
•
•
CLIPS> (screen-off)
*/
Section 10:
Environments
CLIPS provides the ability to create multiple environments into which programs can be loaded
and run. Each environment maintains its own set of data structures and can be run independently
of the other environments. In many cases, the program’s main function will create a single
environment to be used as the argument for all embedded API calls. In other cases, such as
creating shared libraries or DLLs, new instances of environments will be created as they are
needed.
If you have integrated code with CLIPS and use multiple concurrent environments, any functions
or extensions which use global data should allocate this data for each environment by using the
AllocateEnvironmentData function, otherwise one environment may overwrite the data used by
another environment.
Once you are done with an environment, it can be deleted with the DestroyEnvironment
function call. This will deallocate all memory associated with that environment.
The following is an of example of a main program which makes use of multiple environments:
#include "clips.h"
int main()
{
Environment *theEnv1, *theEnv2;
theEnv1 = CreateEnvironment();
theEnv2 = CreateEnvironment();
Load(theEnv1,"program1.clp");
Load(theEnv2,"program2.clp");
Reset(theEnv1);
Reset(theEnv2);
Run(theEnv1,-1);
Run(theEnv2,-1);
DestroyEnvironment(theEnv1);
DestroyEnvironment(theEnv2);
}
bool AllocateEnvironmentData(
Environment *env,
unsigned id,
size_t size,
EnvironmentCleanupFunction f);
bool AddEnvironmentCleanupFunction(
Environment *env,
const char *name,
EnvironmentCleanupFunction f,
int p);
The id parameter value must be unique; calls to AllocateEnvironmentData using a value that
has already been allocated will fail. To avoid collisions with environment ids predefined by
CLIPS, use the macro constant USER_ENVIRONMENT_DATA as the base index for any ids
defined by user code.
For the size parameter, you'll typically you’ll define a struct containing the various values to be
stored in the environment data and use the sizeof operator to pass in the size of the struct to this
function which will automatically allocate the specified amount of memory, initialize it to
contain all zeroes, and then store the memory in the environment position associated with the id
parameter. Once the base storage has been allocated, additional allocation can be performed by
user code. When the environment is destroyed, CLIPS automatically deallocates the amount of
memory previously allocated for the base storage.
If the f parameter value is not a null pointer, then the specified callback function is invoked when
the associated environment is destroyed. CLIPS automatically handles the allocation and
deallocation of the base storage for environment data (the amount of data specified by the size
parameter value). If the base storage includes pointers to memory allocated by user code, then
this should be deallocated either by an EnvironmentCleanupFunction function specified by
this function or the function AddEnvironmentCleanupFunction.
Environment cleanup functions created using this function are called after all the cleanup
functions associated with environment data created using AllocateEnvironmentData have been
called.
void *GetEnvironmentData(
Environment *env,
unsigned id);
The function GetEnvironmentData returns a pointer to the environment data associated with
the identifier specified by parameter id.
As an example of allocating environment data, we’ll look at a get-index function that returns an
integer index starting with one and increasing by one each time it is called. For example:
CLIPS> (get-index)
1
CLIPS> (get-index)
2
CLIPS> (get-index)
3
CLIPS>
Each environment will need global data to store the current value of the index. The C source
code that implements the environment data first needs to specify the position index and specify a
data structure for storing the data:
struct indexData
{
long index;
};
#define IndexData(theEnv) \
((struct indexData *) GetEnvironmentData(theEnv,INDEX_DATA))
The next step in the C source code is to add the initialization code to the UserFunctions
function:
void UserFunctions(
Environment *env)
{
if (! AllocateEnvironmentData(env,INDEX_DATA,
sizeof(struct indexData),NULL))
{
Writeln(env,"Error allocating environment data for INDEX_DATA");
ExitRouter(env,EXIT_FAILURE);
}
IndexData(env)->index = 1;
AddUDF(env,"get-index","l",0,0,NULL,GetIndex,"GetIndex",NULL);
}
First, the call to AllocateEnvironmentData is made. If this fails, then an error message is
printed and a call to ExitRouter is made to terminate the program. Otherwise, the index member
of the environment data is initialized to one. If a starting value of zero was desired, it would not
be necessary to perform any initialization since the value of index is automatically initialized to
zero when the environment data is initialized. Finally, AddUDF is called to register the get-
index function.
The last piece of the C source code is the GetIndex C function which implements the get-index
function:
void GetIndex(
Environment *env,
UDFContext *context,
UDFValue *returnValue)
{
returnValue->integerValue = CreateInteger(env,IndexData(env)->index++);
}
Section 11:
Creating a CLIPS Run-time Program
1) Start CLIPS and load in all of the constructs that will constitute a run-time module. Call the
constructs-to-c command using the following syntax:
(constructs-to-c exp 1)
This command would store the converted constructs in several output files ("exp1_1.c",
"exp1_2.c", ... , "exp7_1.c") and use a module id of 1 for this collection of constructs. The
use of the module id will be discussed in greater detail later. Once the conversion is
complete, exit CLIPS. For large systems, this output may be very large (> 200K). If
<target-path> is specified, it is prepended to the name of the file when it is created,
allowing target directory to be specified for the generated files. For example, specifying the
target path Temp\ on a Unix system would place the generated files in the directory Temp
(assuming that it already exists).
It is possible to limit the size of the generated files by using the <max-elements> argument.
This argument indicates the maximum number of structures which may be placed in a
single array stored in a file. Where possible, if this number is exceeded new files will be
created to store additional information. This feature is useful for compilers that may place a
limitation on the size of a file that may be compiled.
Note that the .c extension is added by CLIPS. When giving the file name prefix, users
should consider the maximum number of characters their system allows in a file name.
Constraint information associated with constructs is not saved to the C files generated by the
constructs-to-c command unless dynamic constraint checking is enabled (using the set-
dynamic-constraint-checking command).
2) Set the RUN_TIME setup flag in the setup.h header file to 1 and compile all of the c files
just generated.
3) Modify the main.c module for embedded operation. Unless the user has other specific uses,
the argc and argv arguments to the main function should be eliminated. Also do not call the
CommandLoop or RerouteStdin functions which are normally called from the main
function of a command line version of CLIPS. Do not define any functions in
UserFunctions functions. These functions are not called during initialization. All of the
function definitions have already been compiled in the 'C' constructs code. In order for your
run-time program to be loaded, a function must be called to initialize the constructs module.
This function is defined in the 'C' constructs code, and its name is dependent upon the id
used when translating the constructs to 'C' code. The name of the function is
InitCImage_<id> where <id> is the integer used as the construct module <id>. In the
example above, the function name would be InitCImage_1. The return value of this
function is a pointer to an environment (see section 9) which was created and initialized to
contain your run-time program. This initialization steps probably would be followed by any
user initialization, then by a reset and run. Finally, when you are finished with a run-time
module, you can call DestroyEnvironment to remove it. An example main.c file would be
#include <stdio.h>
#include "clips.h"
main()
{
Environment *env;
extern Environment *InitCImage_1(void);
env = InitCImage_1();
•
• /* Any user Initialization */
•
Reset(env);
Run(env,-1);
•
• /* Any other code */
•
DestroyEnvironment(env);
}
4) Recompile all of the CLIPS source code (the RUN_TIME flag should still be 1). This causes
several modifications in the CLIPS code. The run-time CLIPS module does not have the
capability to load new constructs. Do NOT change any other compiler flags.
5) Link all regular CLIPS modules together with any user-defined function modules and the 'C'
construct modules. Any user-defined functions must have global scope.
6) The run-time module which includes user constructs is now ready to run.
Note that individual constructs may not be added or removed in a run-time environment.
Because of this, the load function is not available for use in run-time programs. The clear
command will also not remove any constructs (although it will clear facts and instances). Use
calls to the InitCImage_... functions to clear the environment and replace it with a new set of
constructs. In addition, the build function does not work in a run-time environment.
Since new constructs can’t be added, a run-time program can’t dynamically load a deffacts or
definstances construct. To dynamically load facts and/or instances in a run-time program, the
CLIPS load-facts and load-instances functions or the C LoadFacts and LoadInstances
functions should be used in place of deffacts and definstances constructs.
Important Note
Each call to separate InitCImage functions creates a unique environment into which the run-
time program is loaded. Only the first call to a given InitCImage function will create an
environment containing the specified run-time program. Subsequent calls have no effect and a
value of NULL is returned by the function. Once the DestroyEnvironment function has been
called to remove an environment created by an InitCImage call, there is no way to reload the
run-time program.
Section 12:
Embedding CLIPS
CLIPS was designed to be embedded within other programs. When CLIPS is used as an em-
bedded application, the user must provide a main program. Calls to CLIPS are made like any
other subroutine. To embed CLIPS, add the following include statements to the user’s main
program file:
#include "clips.h"
Most of the embedded API function calls require an environment pointer argument. Each
environment represents a single instance of the CLIPS engine which can load and run a program.
A program must create at least one environment in order to make embedded API calls. In many
cases, the program’s main function will create a single environment to be used as the argument
for all embedded API calls. In other cases, such as creating shared libraries or DLLs, new
instances of environments will be created as they are needed. New environments can be created
by calling the function CreateEnvironment (see section 9).
To create an embedded program, compile and link all of the user’s code with all CLIPS files
except main.c. If a library is being created, it may be necessary to use different link options or
compile and link “wrapper” source code with the CLIPS source files. Otherwise, the embedded
program must provide a replacement main function for the one normally provided by CLIPS.
When running CLIPS as an embedded program, many of the capabilities available in the
interactive interface (in addition to others) are available through function calls. The functions are
documented in the following sections. Prototypes for these functions can be included by using
the clips.h header file.
12.1.1 LoadFromString
bool LoadFromString(
Environment *env,
const char *str,
size_t length);
The function LoadFromString loads a set of constructs from a string input source (much like
the Load function only using a string for input rather than a file). Parameter env is a pointer to a
previously created environment; parameter str is a string containing constructs; and parameter
length is the maximum number of characters to be read from the input string. If the length
parameter value is SIZE_MAX, then the str parameter value must be terminated by a null
character; otherwise, the length parameter value indicates the maximum number characters that
will be read from the str parameter value. This function returns true if no error occurred while
loading constructs; otherwise, it returns false.
bool AddClearFunction(
Environment *env,
const char *name,
VoidCallFunction *f,
int p,
void *context);
bool RemoveClearFunction(
Environment *env,
const char *name);
The function AddClearFunction adds a callback function to the list of functions invoked when
the CLIPS clear command is executed. Parameter env is a pointer to a previously created
environment; parameter name is a string that uniquely identifies the callback for removal using
RemoveClearFunction; parameter f is a pointer to the callback function of type
VoidCallFunction; parameter p is the priority of the callback function; and parameter context is
a user supplied pointer to data that is passed to the callback function when it is invoked (a null
pointer should be used if there is no data that needs to be passed to the callback function). The
priority parameter determines the order in which the callback functions are invoked (higher
priority items are called first); the values -2000 to 2000 are reserved for internal use by CLIPS.
This function returns true if the callback function was successfully added; otherwise, it returns
false.
The function RemoveClearFunction removes a callback function from the list of functions
invoked when the CLIPS clear command is executed. Parameter env is a pointer to a previously
created environment; and parameter name is the string used to identify the callback when it was
added using AddClearFunction. The function returns true if the callback was successfully
removed; otherwise, it returns false.
bool AddPeriodicFunction(
Environment *env,
const char *name
VoidCallFunction *f,
int p,
void *context);
bool RemovePeriodicFunction(
Environment *env,
const char *name);
The function AddPeriodicFunction adds a callback function to the list of functions invoked
periodically when CLIPS is executing. Among other possible uses, this functionality allows
event processing during execution when CLIPS is embedded within an application that must
periodically perform tasks. Care should be taken not to use any operations in a periodic function
which would affect CLIPS data structures constructively or destructively, i.e. CLIPS internals
may be examined but not modified during a periodic callback.
Parameter env is a pointer to a previously created environment; parameter name is a string that
uniquely identifies the callback for removal using RemovePeriodicFunction; parameter f is a
pointer to the callback function of type VoidCallFunction; parameter p is the priority of the
callback function; and parameter context is a user supplied pointer to data that is passed to the
callback function when it is invoked (a null pointer should be used if there is no data that needs
to be passed to the callback function). The priority parameter determines the order in which the
callback functions are invoked (higher priority items are called first); the values -2000 to 2000
are reserved for internal use by CLIPS. This function returns true if the callback function was
successfully added; otherwise, it returns false.
The function RemovePeriodicFunction removes a callback function from the list of functions
invoked periodically when CLIPS is executing. Parameter env is a pointer to a previously
created environment; and parameter name is the string used to identify the callback when it was
added using AddPeriodicFunction. The function returns true if the callback was successfully
removed; otherwise, it returns false.
bool AddResetFunction(
Environment *env,
bool RemoveResetFunction(
Environment *env,
const char *name);
The function AddResetFunction adds a callback function to the list of functions invoked when
the CLIPS reset command is executed. Parameter env is a pointer to a previously created
environment; parameter name is a string that uniquely identifies the callback for removal using
RemoveResetFunction; parameter f is a pointer to the callback function of type
VoidCallFunction; parameter p is the priority of the callback function; and parameter context is
a user supplied pointer to data that is passed to the callback function when it is invoked (a null
pointer should be used if there is no data that needs to be passed to the callback function). The
priority parameter determines the order in which the callback functions are invoked (higher
priority items are called first); the values -2000 to 2000 are reserved for internal use by CLIPS.
This function returns true if the callback function was successfully added; otherwise, it returns
false.
The function RemoveResetFunction removes a callback function from the list of functions
invoked when the CLIPS reset command is executed. Parameter env is a pointer to a previously
created environment; and parameter name is the string used to identify the callback when it was
added using AddResetFunction. The function returns true if the callback was successfully
removed; otherwise, it returns false.
bool BatchStar(
Environment *env
const char *fileName);
bool Bload(
Environment *env,
const char *fileName);
bool Bsave(
Environment *env,
const char *fileName);
bool Save(
Environment *env,
const char *fileName);
The function BatchStar is the C equivalent of the CLIPS batch* command. The env parameter
is a pointer to a previously created environment; the filename parameter is a full or partial path
string to an ASCII or UTF-8 file containing CLIPS functions, commands, and constructs. This
function returns true if the file was successfully opened; otherwise, it returns false.
The function Bload is the C equivalent of the CLIPS bload command. The env parameter is a
pointer to a previously created environment; the filename parameter is a full or partial path
string to a binary save file that was created using the C Bsave function or the CLIPS bsave
command. This function returns true if the file was successfully opened; otherwise, it returns
false.
The function Bsave is the C equivalent of the CLIPS bsave command. The env parameter is a
pointer to a previously created environment; the filename parameter is a full or partial path
string for the binary save file to be created. This function returns true if the file was successfully
created; otherwise, it returns false.
The function Save is the C equivalent of the CLIPS save command. The env parameter is a
pointer to a previously created environment; the fileName parameter is a full or partial path
string for the text save file to be created. This function returns true if the file was successfully
created; otherwise, it returns false.
12.1.6 Settings
bool GetDynamicConstraintChecking(
Environment *env);
bool GetSequenceOperatorRecognition(
Environment *env);
bool SetDynamicConstraintChecking(
Environment *env,
bool b);
bool SetSequenceOperatorRecognition(
Environment *env,
bool b);
created environment. This function returns true if the dynamic constraint checking behavior is
enabled; otherwise, it returns false.
12.2.1 DribbleActive
bool DribbleActive(
Environment *env);
The function DribbleActive returns true if the environment specified by parameter env has an
active dribble file for capturing output; otherwise, it returns false.
bool GetWatchState(
Environment *env,
WatchItem item);
void SetWatchState(
Environment *env,
WatchItem item,
bool b);
typedef enum
{
ALL,
FACTS,
INSTANCES,
SLOTS,
RULES,
ACTIVATIONS,
MESSAGES,
MESSAGE_HANDLERS,
GENERIC_FUNCTIONS,
METHODS,
DEFFUNCTIONS,
COMPILATIONS,
STATISTICS,
GLOBALS,
FOCUS
} WatchItem;
The function GetWatchState returns the current state of the watch item specified by the
parameter item in the environment specified by the parameter env: true if the watch item is
enabled; otherwise, false. If ALL is specified for the parameter item, the return value of this
function is undefined.
The function SetWatchState sets the state of the watch item specified by the parameter item in
the environment specified by the parameter env. If parameter b is true, the watch item is enabled;
otherwise, it is disabled. If ALL is specified for the parameter item, then all watch items are set
to the state specified by parameter b.
Deftemplate *FindDeftemplate(
Environment *env,
const char *name);
Deftemplate *GetNextDeftemplate(
Environment *env,
Deftemplate *d);
void GetDeftemplateList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDeftemplates(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDeftemplate searches for the deftemplate specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named
deftemplate if it exists; otherwise, it returns a null pointer.
The function GetNextDeftemplate provides iteration support for the list of deftemplates in the
current module. If parameter d is a null pointer, then a pointer to the first Deftemplate in the
current module is returned by this function; otherwise, a pointer to the next Deftemplate
following the Deftemplate specified by parameter d is returned. If parameter d is the last
Deftemplate in the current module, a null pointer is returned.
12.3.2 Attributes
void DeftemplateSlotNames(
Deftemplate *d,
CLIPSValue *out);
The function DeftemplateName returns the name of the deftemplate specified by the d
parameter.
The function DeftemplatePPForm returns the text representation of the Deftemplate specified
by the d parameter. The null pointer is returned if the text representation is not available.
12.3.3 Deletion
bool DeftemplateIsDeletable(
Deftemplate *d);
bool Undeftemplate(
Deftemplate *d,
Environment *env);
bool DeftemplateGetWatch(
Deftemplate *d);
void DeftemplateSetWatch(
Deftemplate *d,
bool b);
The function DeftemplateGetWatch returns true if facts are being watched for the deftemplate
specified by the d parameter value; otherwise, it returns false.
The function DeftemplateSetWatch sets the fact watch state for the deftemplate specified by the
d parameter value to the value specified by the parameter b.
bool DeftemplateSlotAllowedValues(
Deftemplate *d,
const char *name,
CLIPSValue *out);
bool DeftemplateSlotCardinality(
Deftemplate *d,
const char *name,
CLIPSValue *out);
bool DeftemplateSlotRange(
Deftemplate *d,
const char *name,
CLIPSValue *out);
bool DeftemplateSlotDefaultValue(
Deftemplate *d,
const char *name,
CLIPSValue *out);
bool DeftemplateSlotTypes(
Deftemplate *d,
const char *name,
CLIPSValue *out);
Parameter d is a pointer to a Deftemplate; parameter name specifies a valid slot name for the
specified deftemplate; and parameter out is a pointer to a CLIPSValue allocated by the caller.
The output of the function call—a multifield containing the attribute values—is stored in the out
parameter value. These function return true if a valid slot name was specified and the output
value is successfully set; otherwise, false is returned.
bool DeftemplateSlotExistP(
Deftemplate *d,
const char *name);
bool DeftemplateSlotMultiP(
Deftemplate *d,
const char *name);
bool DeftemplateSlotSingleP(
Deftemplate *d,
const char *name);
DefaultType DeftemplateSlotDefaultP(
Deftemplate *deftemplatePtr,
const char *slotName);
typedef enum
{
NO_DEFAULT,
STATIC_DEFAULT,
DYNAMIC_DEFAULT
} DefaultType;
Fact *GetNextFact(
Environment *env,
Fact *f);
Fact *GetNextFactInTemplate(
Deftemplate *d,
Fact *f);
void GetFactList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void Facts(
Environment *env,
const char *logicalName,
Defmodule *d,
long long start,
long long end,
long long max);
void PPFact(
Fact *f,
const char *logicalName,
bool ignoreDefaults);
The function GetNextFact provides iteration support for the list of facts in an environment. If
parameter f is a null pointer, then a pointer to the first Fact in the environment specified by
parameter env is returned by this function; otherwise, a pointer to the next Fact following the
Fact specified by parameter f is returned. If parameter f is the last Fact in the specified
environment, a null pointer is returned.
The function GetNextFactInTemplate provides iteration support for the list of facts belonging
to a deftemplate. If parameter f is a null pointer, then a pointer to the first Fact for the
deftemplate specified by parameter d is returned by this function; otherwise, a pointer to the next
Fact of the specified deftemplate following the Fact specified by parameter f is returned. If
parameter f is the last Fact for the specified deftemplate, a null pointer is returned.
Do not call GetNextFact or GetNextFactInTemplate with a pointer to a fact that has been
retracted. If the return value of these functions is stored as part of a persistent data structure or in
a static data area, then the function RetainFact should be called to insure that the fact cannot be
disposed while external references to the fact still exist.
The function GetFactList is the C equivalent of the CLIPS get-fact-list function. Parameter env
is a pointer to a previously created environment; parameter out is a pointer to a CLIPSValue
allocated by the caller; and parameter d is a pointer to a Defmodule. The output of the function
call—a multifield containing a list of fact addresses—is stored in the out parameter value. If
parameter d is a null pointer, then all facts in all modules will be included in parameter out;
otherwise, only facts associated with deftemplates in the specified module will be included.
The function Facts is the C equivalent of the CLIPS facts command. Parameter env is a pointer
to a previously created environment; parameter logicalName is the router output destination;
parameter d is a pointer to a Defmodule; parameter start is the lower fact index range of facts to
be listed; parameter end is the upper fact index range of facts to be listed; and parameter max is
the maximum number of facts to be listed. If parameter d is a non-null pointer, then only facts
visible to the specified module are printed; otherwise, all facts will be printed. A value of -1 for
the start, end, or max parameter indicates the parameter is unspecified and should not restrict
the facts that are listed.
The function PPFact is the C equivalent of the CLIPS ppfact command. Parameter f is a pointer
to the Fact to be displayed; parameter logicalName is the router output destination; and
parameter ignoreDefaults is a boolean flag indicating whether slots should be excluded from
display if their current value is the same as their static default value.
12.4.2 Attributes
Deftemplate *FactDeftemplate(
Fact *f);
void FactPPForm(
Fact *f,
StringBuilder *sb);
void FactSlotNames(
Fact *f,
CLIPSValue *out);
GetSlotError GetFactSlot(
Fact *f,
const char *name,
CLIPSValue *out);
typedef enum
{
GSE_NO_ERROR,
GSE_NULL_POINTER_ERROR,
GSE_INVALID_TARGET_ERROR,
GSE_SLOT_NOT_FOUND_ERROR,
} GetSlotError;
The function FactDeftemplateModule returns a pointer to the Deftemplate associated with the
Fact specified by parameter f.
The function FactIndex is the C equivalent of the CLIPS fact-index command. It returns the
fact-index of the fact specified by parameter f.
The function FactPPForm stores the text representation of the Fact specified by the f parameter
in the StringBuilder specified by parameter sb.
The function GetFactSlot retrieves the slot value specified by parameter name from the fact
specified by parameter f and stores it in parameter out, a CLIPSValue allocated by the caller.
For ordered facts—which have an implied multifield slot—a null pointer or the string "implied"
should be used for the name parameter value.
The GetFactSlot function returns GSE_NO_ERROR if the slot value is successfully retrieved;
otherwise it returns GSE_NULL_POINTER_ERROR if any of the function arguments are
NULL pointers (except for the name parameter which may be NULL for an ordered fact),
GSE_INVALID_TARGET_ERROR if the fact specified by parameter f has been retracted, and
GSE_SLOT_NOT_FOUND_ERROR if the fact does not have the specified slot.
12.4.3 Deletion
RetractError RetractAllFacts(
Environment *env);
bool FactExistp(
Fact *f);
The function RetractAllFacts retracts all of the facts in the environment specified by parameter
env. It returns RE_NO_ERROR if all facts were successfully retracted. See the Retract
command in section 3.3.3 for the list of error codes in the RetractError enumeration.
The function FactExistp is the C equivalent of the CLIPS fact-existp function. It returns true if
the fact has not been retracted. The parameter f must be a Fact that has either not been retracted
or has been retained (see section 5.2).
bool LoadFacts(
Environment *env,
const char *fileName);
bool LoadFactsFromString(
Environment *env,
const char *str,
size_t length);
bool SaveFacts(
Environment *env,
const char *filename,
SaveScope scope);
typedef enum
{
LOCAL_SAVE,
VISIBLE_SAVE
} SaveScope;
The function LoadFacts is the C equivalent of the CLIPS load-facts command. Parameter env is
a pointer to a previously created environment; and parameter fileName is a full or partial path
string to an ASCII or UTF-8 file containing facts. This function returns true if no errors occurred
while loading facts; otherwise, it returns false.
The function LoadFactsFromString loads a set of facts from a string input source (much like
the LoadFacts function only using a string for input rather than a file). Parameter env is a
pointer to a previously created environment; parameter str is a string containing facts; and
parameter length is the maximum number of characters to be read from the input string. If the
length parameter value is SIZE_MAX, then the str parameter value must be terminated by a null
character; otherwise, the length parameter value indicates the maximum number characters that
will be read from the str parameter value. This function returns true if no error occurred while
loading facts; otherwise, it returns false.
The function SaveFacts is the C equivalent of the CLIPS save-facts command. Parameter env is
a pointer to a previously created environment; parameter fileName is a full or partial path string
to the fact save file that will be created; and parameter scope indicates whether all facts visible to
the current module should be saved (VISIBLE_SAVE) or just those associated with deftemplates
defined in the current module (LOCAL_SAVE). This function returns true if no errors occurred
while saving facts; otherwise, it returns false.
12.4.5 Settings
bool GetFactDuplication(
Environment *env);
bool SetFactDuplication(
Environment *env,
bool b);
bool GetFactListChanged(
Environment *env);
void SetFactListChanged(
Environment *env,
bool b);
The function GetFactsChanged returns true if changes to facts for the environment specified by
parameter env have occurred (either assertions, retractions, or modifications); otherwise, it
returns false. To track future changes, SetFactsChanged should reset the change tracking value
to false.
The function SetFactsChanged sets the facts change tracking value for the environment
specified by the parameter env to the value specified by the parameter b.
Deffacts *FindDeffacts(
Environment *env,
const char *name);
Deffacts *GetNextDeffacts(
Environment *env,
Deffacts *d);
void GetDeffactsList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDeffacts(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDeffacts searches for the deffacts specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named deffacts if
it exists; otherwise, it returns a null pointer.
The function GetNextDeffacts provides iteration support for the list of deffacts in the current
module. If parameter d is a null pointer, then a pointer to the first Deffacts in the current module
is returned by this function; otherwise, a pointer to the next Deffacts following the Deffacts
specified by parameter d is returned. If parameter d is the last Deffacts in the current module, a
null pointer is returned.
The function ListDeffacts is the C equivalent of the CLIPS list-deffacts command. Parameter
env is a pointer to a previously created environment; parameter logicalName is the router output
destination; and parameter d is a pointer to a defmodule. If parameter d is a null pointer, then
deffacts in all modules will be listed; otherwise, only deffacts in the specified module will be
listed.
12.5.2 Attributes
The function DeffactsModule is the C equivalent of the CLIPS deffacts-module function. The
return value of this function is the name of the module in which the deffacts specified by
parameter d is defined.
The function DeffactsName returns the name of the deffacts specified by the d parameter.
The function DeffactsPPForm returns the text representation of the Deffacts specified by the d
parameter. The null pointer is returned if the text representation is not available.
12.5.3 Deletion
bool DeffactsIsDeletable(
Deffacts *d);
bool Undeffacts(
Deffacts *d,
Environment *env);
The function DeffactsIsDeletable returns true if the deffacts specified by parameter d can be
deleted; otherwise it returns false.
138 Section 14: Microsoft .NET Integration
CLIPS Reference Manual
The Undeffacts function is the C equivalent of the CLIPS undeffacts command. It deletes the
deffacts specified by parameter d; or if parameter d is a null pointer, it deletes all deffacts in the
environment specified by parameter env. This function returns true if the deletion is successful;
otherwise, it returns false.
Defrule *FindDefrule(
Environment *env,
const char *name);
Defrule *GetNextDefrule(
Environment *env,
Defrule *d);
void GetDefruleList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDefrules(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDefrule searches for the defrule specified by the name parameter in the
environment specified by the env parameter. This function returns a pointer to the named defrule
if it exists; otherwise, it returns a null pointer.
The function GetNextDefrule provides iteration support for the list of defrules in the current
module. If the d parameter value is a null pointer, then a pointer to the first Defrule in the
current module is returned by this function; otherwise, the next Defrule following the d
parameter value is returned. If the d parameter is the last Defrule in the current module, a null
pointer is returned.
The function GetDefruleList is the C equivalent of the CLIPS get-defrule-list function. The
env parameter is a pointer to a previously created environment; the out parameter is a pointer to
a CLIPSValue allocated by the caller; and the d parameter is a pointer to a Defmodule. The
output of the function call—a multifield containing a list of defrule names—is stored in the out
parameter value. If the parameter d is a null pointer, then defrules in all modules will be included
in the out parameter value; otherwise, only defrules in the specified module will be included.
The function ListDefrules is the C equivalent of the CLIPS list-defrules command. The env
parameter is a pointer to a previously created environment; the logicalName parameter is the
router output destination; and the d parameter is a pointer to a defmodule. If the parameter d is a
null pointer, then defrules in all modules will be listed; otherwise, only defrules in the specified
module will be listed.
12.6.2 Attributes
The function DefruleModule is the C equivalent of the CLIPS defrule-module command). The
return value of this function is the name of the module in which the Defrule specified by the d
parameter is defined.
The function DefruleName returns the name of the Defrule specified by the d parameter.
The function DefrulePPForm returns the text representation of the Defrule specified by the d
parameter. The null pointer is returned if the text representation is not available.
12.6.3 Deletion
bool DefruleIsDeletable(
Defrule *d);
bool Undefrule(
Defrule *d,
Environment *env);
The function DefruleIsDeletable returns true if the Defrule specified by the d parameter value
can be deleted; otherwise it returns false.
The function Undefrule is the C equivalent of the CLIPS undefrule command. It deletes the
defrule specified by the d parameter; or if the d parameter is a null pointer, it deletes all defrules
in the environment specified by the env parameter. The function returns true if the deletion was
successful; otherwise, it returns false.
bool DefruleGetWatchActivations(
Defrule *d);
bool DefruleGetWatchFirings(
Defrule *d);
void DefruleSetWatchActivations(
Defrule *d,
bool b);
void DefruleSetWatchFirings(
Defrule *d,
bool b);
The function DefruleGetWatchActivations returns true if rule activations are being watched for
the defrule specified by the d parameter value; otherwise, it returns false.
The function DefruleGetWatchFirings returns true if rule firings are being watched for the
Defrule specified by the d parameter; otherwise, it returns false.
The function DefruleSetWatchActivations sets the rule activations watch state for the defrule
specified by the d parameter value to the value specified by the parameter b.
The function DefruleSetWatchFirings sets the rule firings watch state for the defrule specified
by the d parameter value to the value specified by the parameter b.
12.6.5 Breakpoints
bool DefruleHasBreakpoint(
Defrule *d);
bool RemoveBreak(
Defrule *d);
void SetBreak(
Defrule *d);
void ShowBreaks(
Environment *env,
The function DefruleHasBreakpoint returns true if the defrule specified by the d parameter
value has a breakpoint set; otherwise it returns false.
The function SetBreak is the C equivalent of the CLIPS set-break command. It sets a
breakpoint for the defrule specified by the d parameter value.
The function ShowBreaks is the C equivalent of the CLIPS show-breaks command. The env
parameter is a pointer to a previously created environment; the logicalName parameter is the
router output destination; and the d parameter is a pointer to a defmodule. If the parameter d is a
null pointer, then breakpoints for defrules in all modules will be listed; otherwise, only
breakpoints for defrules in the specified module will be listed.
12.6.6 Matches
void Matches(
Defrule *d,
Verbosity v,
CLIPSValue *out);
typedef enum
{
VERBOSE,
SUCCINCT,
TERSE
} Verbosity;
The function Matches is the C equivalent of the CLIPS matches command. The d parameter is a
pointer to a Defrule; the v parameter specifies the level of information displayed in the printed
output; and the out parameter is a pointer to a CLIPSValue allocated by the caller. The output of
the function call—a multifield containing three integer fields indicating the number of pattern
matches, partial matches, and activations—is stored in the out parameter value.
12.6.7 Refresh
void Refresh(
Defrule *d);
Activation *GetNextActivation(
Environment *env,
Activation *a);
FocalModule *GetNextFocus(
Environment *env,
FocalModule *fm);
void GetFocusStack(
Environment *env,
CLIPSValue *out);
void Agenda(
Environment *env,
const char *logicalName,
Defmodule *d);
void ListFocusStack(
Environment *env,
const char *logicalName);
The function GetNextActivation provides iteration support for the list of activations on the
agenda of the current module in an environment. If parameter a is a null pointer, then a pointer to
the first Activation on the agenda of the current module in the environment specified by
parameter env is returned by this function; otherwise, a pointer to the next Activation following
the Activation specified by parameter a is returned. If parameter a is the last Activation on the
agenda of the current module in the specified environment, a null pointer is returned.
The function GetNextFocus provides iteration support for the list of modules on the focus stack
of an environment. If parameter fm is a null pointer, then a pointer to the first FocusModule on
the focus stack in the environment specified by parameter env is returned by this function;
otherwise, a pointer to the next FocusModule following the FocusModule specified by
parameter fm is returned. If parameter fm is the last FocusModule on the agenda of the current
module in the specified environment, a null pointer is returned.
The function Agenda is the C equivalent of the CLIPS agenda command. Parameter env is a
pointer to a previously created environment; parameter logicalName is the router output
destination; and parameter d is a pointer to a Defmodule. If parameter d is a null pointer, then
the agenda of every module is listed; otherwise, only the agenda of the specified module is listed.
void ActivationPPForm(
Activation *a,
StringBuilder *sb);
int ActivationGetSalience(
Activation *a);
int ActivationSetSalience(
Activation *a,
int s);
The function ActivationRuleName returns the name of the defrule that generated the activation
specified by parameter a.
The function ActivationPPForm stores the text representation of the Activation specified by
parameter a in the StringBuilder specified by parameter sb.
The function ActivationGetSalience returns the salience of the activation specified by parameter
a. This salience value may be different from the the salience value of the defrule which
generated the activation (due to dynamic salience).
The function ActivationSetSalience sets the salience of the activation specified by parameter a
to the integer specified by parameter s. Salience values greater than 10,000 will assign the value
10,000 instead and salience values less than -10,000 will assign the value -10 instead. The
function ReorderAgenda should be called after salience values have been changed to update the
agenda.
Defmodule *FocalModuleModule(
FocalModule *fm);
The function FocalModuleName returns the name of the defmodule associated with the
FocalModule specified by parameter fm.
The function FocalModuleModule returns a pointer to the Defmodule associated with the
FocalModule specified by parameter fm.
bool AddBeforeRuleFiresFunction(
Environment *env,
const char *name,
RuleFiredFunction *f,
int p,
void *context);
bool AddAfterRuleFiresFunction(
Environment *env,
const char *name,
RuleFiredFunction *f,
int p,
void *context);
bool RemoveBeforeRuleFiresFunction(
Environment *env,
const char *name);
bool RemoveAfterRuleFiresFunction(
Environment *env,
const char *name);
Activation *a,
void *context);
When invoked, the RuleFiredFunction is passed parameter a that is a pointer to the Activation
being executed. In the event that no rules are executed, the callbacks added by
AddAfterRuleFiresFunction are invoked once with the parameter value a set to a null pointer.
void ClearFocusStack(
Environment *env);
void Focus(
Defmodule *d);
Defmodule *PopFocus(
Environment *env);
Defmodule *GetFocus(
Environment *env);
The function PopFocus is the C equivalent of the CLIPS pop-focus function. It removes the
current focus from the focus stack and returns the Defmodule associated with that focus.
The function GetFocus is the C equivalent of the CLIPS get-focus function. It returns a pointer
to the Defmodule that is the current focus on the focus stack. A null pointer is returned if the
focus stack is empty.
void RefreshAgenda(
Defmodule *d);
void RefreshAllAgendas(
Environment *env);
void ReorderAgenda(
Defmodule *d);
void ReorderAllAgendas(
Environment *env);
void DeleteActivation(
Activation *a);
void DeleteAllActivations(
Defmodule *d);
The function RefreshAgenda is the C equivalent of the CLIPS refresh-agenda command. For
the agenda of the module specified by parameter d, it recomputes the salience values for all
activations and then reorders the agenda.
The function RefreshAllAgendas invokes the RefreshAgenda function for every module in the
evironment specified by parameter env.
The function ReorderAgenda reorders the agenda of the module specified by parameter d using
the current conflict resolution strategy and current activation saliences.
The function ReorderAllAgendas invokes the ReorderAgenda function for every module in
the evironment specified by parameter env.
The function DeleteAllActivations removes all activations from the agenda of the module
specified by parameter d;
bool GetAgendaChanged(
Environment *env);
void SetAgendaChanged(
Environment *env,
bool b);
The function GetAgendaChanged returns true if changes to the agenda for the environment
specified by parameter env have occurred (either activations, firings, or deactivations);
otherwise, it returns false. To track future changes, SetAgendaChanged should reset the change
tracking value to false.
The function SetAgendaChanged sets the agenda change tracking value for the environment
specified by the parameter env to the value specified by the parameter b.
12.7.9 Settings
SalienceEvaluationType GetSalienceEvaluation(
Environment *env);
SalienceEvaluationType SetSalienceEvaluation(
Environment *env,
SalienceEvaluationType set);
StrategyType GetStrategy(
Environment *env);
StrategyType SetStrategy(
Environment *env,
StrategyType st);
typedef enum
{
WHEN_DEFINED,
WHEN_ACTIVATED,
EVERY_CYCLE
} SalienceEvaluationType;
typedef enum
{
DEPTH_STRATEGY,
BREADTH_STRATEGY,
LEX_STRATEGY,
MEA_STRATEGY,
COMPLEXITY_STRATEGY,
SIMPLICITY_STRATEGY,
RANDOM_STRATEGY
} StrategyType;
The function GetStrategy is the C equivalent of the CLIPS get-strategy command. The env
parameter is a pointer to a previously created environment. This function returns the enumeration
value corresponding to the current setting.
The function SetStrategy is the C equivalent of the CLIPS set-strategy command. The env
parameter is a pointer to a previously created environment; and the parameter st is the new
setting for the behavior. This function returns the old setting for the behavior.
12.7.10 Examples
The following code is a simple example that prints a period after each rule firing:
#include "clips.h"
int main()
{
Environment *env;
env = CreateEnvironment();
Build(env,"(defrule loop"
" ?f <- (loop)"
" =>"
" (retract ?f)"
" (assert (loop)))");
AssertString(env,"(loop)");
AddAfterRuleFiresFunction(env,"print-dot",PrintPeriod,0,NULL);
Run(env,20);
Write(env,"\n");
}
void PrintPeriod(
Environment *env,
Activation *a,
void *context)
{
Write(env,".");
}
Defglobal *FindDefglobal(
Environment *env,
const char *name);
Defglobal *GetNextDefglobal(
Environment *env,
Defglobal *d);
void GetDefglobalList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDefglobals(
Environment *env,
const char *logicalName,
Defmodule *d);
void ShowDefglobals(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDefglobal searches for the defrule specified by the name parameter in the
environment specified by the env parameter. For example, to retrieve the value of the global
variable ?*x*, use the value "x" for the name parameter. This function returns a pointer to the
named defglobal if it exists; otherwise, it returns a null pointer.
The function GetNextDefglobal provides iteration support for the list of defglobals in the
current module. If parameter d is a null pointer, then a pointer to the first Defglobal in the
current module is returned by this function; otherwise, a pointer to the next Defglobal following
the Defglobal specified by parameter d is returned. If parameter d is the last Defglobal in the
current module, a null pointer is returned.
The function ListDefglobals is the C equivalent of the CLIPS list-defglobals command. The
parameter env is a pointer to a previously created environment; the parameter logicalName is the
router output destination; and the parameter d is a pointer to a defmodule. If the parameter d is a
null pointer, then defglobals in all modules will be listed; otherwise, only defglobals in the
specified module will be listed.
The function ShowDefglobals is the C equivalent of the CLIPS show-defglobals command. The
parameter env is a pointer to a previously created environment; the parameter logicalName is the
router output destination; and the parameter d is a pointer to a defmodule. If the parameter d is a
null pointer, then defglobals in all modules will be listed with their current value; otherwise, only
defglobals in the specified module will be listed with their current value.
12.8.2 Attributes
void DefglobalValueForm(
Defglobal *d,
StringBuilder *sb);
void DefglobalGetValue(
Defglobal *d,
CLIPSValue *out);
void DefglobalSetValue(
Defglobal *d,
CLIPSValue *value);
void DefglobalSetInteger (
Defglobal *d,
long long value);
void DefglobalSetFloat (
Defglobal *d,
double value);
void DefglobalSetSymbol (
Defglobal *d,
const char *value);
void DefglobalSetString (
Defglobal *d,
const char *value);
void DefglobalSetInstanceName (
Defglobal *d,
const char *value);
void DefglobalSetCLIPSInteger (
Defglobal *d,
CLIPSInteger *value);
void DefglobalSetCLIPSFloat (
Defglobal *d,
CLIPSFloat *value);
void DefglobalSetCLIPSLexeme (
Defglobal *d,
CLIPSLexeme *value);
void DefglobalSetFact (
Defglobal *d,
Fact *value);
void DefglobalSetInstance (
Defglobal *d,
Instance *value);
void DefglobalSetMultifield (
Defglobal *d,
Multifield *value);
void DefglobalSetCLIPSExternalAddress (
Defglobal *d,
CLIPSExternalAddress *value);
The function DefglobalName returns the name of the defglobal specified by parameter d.
The function DefglobalPPForm returns the text representation of the defglobal specified by
parameter d. The null pointer is returned if the text representation is not available.
The function DefglobalValueForm returns a string representation of a defglobal and its current
value. Parameter d is a pointer to a Defglobal; and parameter sb is a pointer to a StringBuilder
allocated by the caller in which the representation is stored.
The function DefglobalGetValue returns the value of the defglobal specified by parameter d in
parameter out, a CLIPSValue allocated by the caller.
The function DefglobalSet… functions set the value of the defglobal specified by parameter d to
the value specified by parameter value, a CLIPSValue allocated by the caller. This function can
trigger garbage collection.
12.8.3 Deletion
bool DefglobalIsDeletable(
Defglobal *d);
bool Undefglobal(
Defglobal *d,
Environment *env);
The function DefglobalIsDeletable returns true if the defglobal specified by parameter d can be
deleted; otherwise it returns false.
The function Undefglobal is the C equivalent of the CLIPS undefglobal command. It deletes the
defglobal specified by parameter d; or if parameter d is a null pointer, it deletes all defglobals in
the environment specified by parameter env. The function returns true if the deletion was
successful; otherwise, it returns false.
bool DefglobalGetWatch(
Defglobal *d);
void DeftemplateSetWatch(
Deftemplate *d,
bool b);
bool GetGlobalsChanged(
Environment *env);
void SetGlobalsChanged(
Environment *env,
bool b);
The function DefglobalGetWatch returns true if the defglobal specified by parameter d is being
watched; otherwise, it returns false.
The function DefglobalSetWatch sets the watch state for the defglobal specified by parameter d.
If parameter b is true, the watch state is enabled; otherwise, it is disabled.
The function GetGlobalsChanged returns true if changes to global variables for the
environment specified by parameter env have occurred (either additions, deletions, or value
modifications); otherwise, it returns false. To track future changes, SetGlobalsChanged should
reset the change tracking value to false.
The function SetGlobalsChanged sets the global change tracking value for the environment
specified by the parameter env to the value specified by the parameter b.
bool GetResetGlobals(
Environment *env);
bool SetResetGlobals(
Environment *env,
bool b);
12.8.6 Examples
env = CreateEnvironment();
Write(env,"Listing Globals:\n\n");
ListDefglobals(env,STDOUT,NULL);
Write(env,"\nShowing Values:\n\n");
ShowDefglobals(env,STDOUT,NULL);
Write(env,"\nSetting Values:\n\n");
Watch(env,GLOBALS);
Eval(env,"(* 3 4)",&value);
DefglobalSetValue(FindDefglobal(env,"x"),&value);
DestroyEnvironment(env);
}
Listing Globals:
MAIN:
x
y
For a total of 2 defglobals.
Showing Values:
MAIN:
?*x* = 3
?*y* = (a b c)
Setting Values:
Deffunction *FindDeffunction(
Environment *env,
const char *name);
Deffunction *GetNextDeffunction(
Environment *env,
Deffunction *d);
void GetDeffunctionList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDeffunctions(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDeffunction searches for the deffunction specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named
deffunction if it exists; otherwise, it returns a null pointer.
The function GetNextDeffunction provides iteration support for the list of deffunctions in the
current module. If parameter d is a null pointer, then a pointer to the first Deffunction in the
current module is returned by this function; otherwise, a pointer to the next Deffunction
following the Deffunction specified by parameter d is returned. If parameter d is the last
Deffunction in the current module, a null pointer is returned.
12.9.2 Attributes
The function DeffunctionName returns the name of the deffunction specified by the d
parameter.
The function DeffunctionPPForm returns the text representation of the Deffunction specified
by the d parameter. The null pointer is returned if the text representation is not available.
12.9.3 Deletion
bool DeffunctionIdDeletable(
Deffunction *d);
bool Undeffunction(
Deffunction *d,
Environment *env);
The function DeffactsIsDeletable returns true if the deffacts specified by parameter d can be
deleted; otherwise it returns false.
bool DeffunctionGetWatch(
Deffunction *d);
void DeffunctionSetWatch(
Deffunction *d,
bool b);
The function DeffunctionGetWatch returns true if the watch state is enabled for the deffunction
specified by the d parameter value; otherwise, it returns false.
The function DeffunctionSetWatch sets the watch state for the deffunction specified by the d
parameter value to the value specified by the parameter b.
Defgeneric *FindDefgeneric(
Environment *env,
const char *name);
Defgeneric *GetNextDefgeneric(
Environment *env,
Defgeneric *d);
void GetDefgenericList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDefgenerics(
Environment *env,
const char *logicalName,
Defmodule *d);
The function FindDefgeneric searches for the defgeneric specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named defgeneric
if it exists; otherwise, it returns a null pointer.
The function GetNextDefgeneric provides iteration support for the list of defgenerics in the
current module. If parameter d is a null pointer, then a pointer to the first Defgeneric in the
current module is returned by this function; otherwise, a pointer to the next Defgeneric
following the Defgeneric specified by parameter d is returned. If parameter d is the last
Defgeneric in the current module, a null pointer is returned.
pointer, then defgenerics in all modules will be listed; otherwise, only defgenerics in the
specified module will be listed.
12.10.2 Attributes
The function DefgenericName returns the name of the defgeneric specified by the d parameter.
The function DefgenericPPForm returns the text representation of the Defgeneric specified by
the d parameter. The null pointer is returned if the text representation is not available.
12.10.3 Deletion
bool DefgenericIsDeletable(
Defgeneric *d);
bool Undefgeneric(
Defgeneric *d,
Environment *env);
The function DefgenericIsDeletable returns true if the defgeneric specified by parameter d can
be deleted; otherwise it returns false.
The function Undefgeneric is the C equivalent of the CLIPS undefgeneric command. It deletes
the defgeneric specified by parameter d; or if parameter d is a null pointer, it deletes all
defgenerics in the environment specified by parameter env. This function returns true if the
deletion is successful; otherwise, it returns false.
bool DefgenericGetWatch(
Defgeneric *d);
void DefgenericSetWatch(
Defgeneric *d,
bool b);
The function DefgenericGetWatch returns true if execution is being watched for the defgeneric
specified by the d parameter value; otherwise, it returns false.
The function DefgenericSetWatch sets the watch state for the defgeneric specified by the d
parameter value to the value specified by the parameter b.
unsigned GetNextDefmethod(
Defgeneric *d,
unsigned index);
void GetDefmethodList(
Environment *environment,
CLIPSValue *out,
Defgeneric *d);
void ListDefmethods(
Environment *env,
const char *logicalName,
Defgeneric *d);
The function GetNextDefmethod provides iteration support for the list of defmethods for a
defgeneric. If parameter index is a 0, then a pointer to the first Defmethod for the defgeneric
specified by parameter d is returned by this function; otherwise, a pointer to the next Defmethod
following the Defmethod specified by parameter index is returned. If parameter index is the last
Defmethod for the specified defgeneric, 0 is returned.
12.11.2 Attributes
void DefmethodDescription(
Defgeneric *d,
unsigned index,
StringBuilder *sb);
void GetMethodRestrictions(
Defgeneric *d,
unsigned index,
CLIPSValue *out);
The function DefmethodPPForm returns the text representation of the Defmethod specified by
parameter d, the generic function, and parameter index, the method index. The null pointer is
returned if the text representation is not available.
12.11.3 Deletion
bool DefmethodIsDeletable(
Defgeneric *d,
unsigned index);
bool Undefmethod(
Defgeneric *d,
unsigned index,
Environment *env);
The function DefmethodIsDeletable returns true if the defmethod specified by parameter d, the
generic function, and index, the method index, can be deleted; otherwise it returns false.
The function Undefmethod is the C equivalent of the CLIPS undefmethod command. It deletes
the defmethod specified by parameter d, parameter index, and parameter env. If parameter d is a
null pointer and parameter index is 0, it deletes all methods for all generic functions in the
environment specified by parameter env; if parameter d is not a null pointer and parameter index
is 0, it deletes all methods of the generic function; otherwise, the defmethod specified by the
generic function and method index is deleted. This function returns true if the deletion is
successful; otherwise, it returns false.
bool DefmethodGetWatch(
Defgeneric *d,
unsigned index);
void DefmethodSetWatch(
Defgeneric *d,
unsigned index,
bool b);
The function DefmethodGetWatch returns true if the method specified by parameter d, the
generic function, and parameter index, the method index, is being watched; otherwise, it returns
false.
The function DefmethodSetWatch sets the method watch state for the defmethod specified by
the d parameter, the generic function, and parameter index, the method index, to the value
specified by the parameter b.
Defclass *FindDefclass(
Environment *env,
const char *name);
Defclass *GetNextDefclass(
Environment *env,
Defclass *d);
void GetDefclassList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDefclasses(
Environment *env,
const char *logicalName,
Defmodule *d);
void BrowseClasses(,
Defclass *d,
const char *logicalName);
void DescribeClass(
Defclass *d,
const char *logicalName);
The function FindDefclass searches for the defclass specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named defclass if
it exists; otherwise, it returns a null pointer.
The function GetNextDefclass provides iteration support for the list of defclasses in the current
module. If parameter d is a null pointer, then a pointer to the first Defclass in the current module
is returned by this function; otherwise, a pointer to the next Defclass following the Defclass
specified by parameter d is returned. If parameter d is the last Defclass in the current module, a
null pointer is returned.
CLIPSValue allocated by the caller; and parameter d is a pointer to a Defmodule. The output of
the function call—a multifield containing a list of defclass names—is stored in the out parameter
value. If parameter d is a null pointer, then defclasses in all modules will be included in
parameter out; otherwise, only defclasses in the specified module will be included.
The function ListDefclass is the C equivalent of the CLIPS list-defclass command. Parameter
env is a pointer to a previously created environment; parameter logicalName is the router output
destination; and parameter d is a pointer to a defmodule. If parameter d is a null pointer, then
defclasses in all modules will be listed; otherwise, only defclasses in the specified module will be
listed.
The function DescribeClass is the C equivalent of the CLIPS describe-class command. It prints
a summary of the class specified by parameter d to the router output destination specified by the
logicalName parameter. This summary includes abstract/concrete behavior, slots and facets
(direct and inherited), and recognized message-handlers (direct and inherited).
void ClassSlots(
Defclass *d,
CLIPSValue *out,
bool inherit);
void ClassSubclasses(
Defclass *d,
CLIPSValue *out,
bool inherit);
void ClassSuperclasses(
Defclass *d,
CLIPSValue *out,
bool inherit);
The function DefclassModule is the C equivalent of the CLIPS defclass-module function. The
return value of this function is the name of the module in which the defclass specified by
parameter d is defined.
The function DefclassName returns the name of the defclass specified by the d parameter.
The function DefclassPPForm returns the text representation of the Defclass specified by the d
parameter. The null pointer is returned if the text representation is not available.
The function ClassSlots is the C equivalent of the CLIPS class-slots command. Parameter d is a
pointer to a Defclass; parameter out is a pointer to a CLIPSValue allocated by the caller; and
parameter inherit is a boolean flag. The output of the function call—a multifield containing the
defclass’s slot names—is stored in the out parameter value. If the inherit parameter is true, then
inherited slots are included; otherwise, only slot explicitly defined by the class are included.
12.12.3 Deletion
bool DefclassIsDeletable(
Defclass *d);
bool Undefclass(
Defclass *d,
Environment *env);
The function DefclassIsDeletable returns true if the defclass specified by parameter d can be
deleted; otherwise it returns false.
The Undefclass function is the C equivalent of the CLIPS undefclass command. It deletes the
defclass specified by parameter d; or if parameter d is a null pointer, it deletes all defclasses in
the environment specified by parameter env. This function returns true if the deletion is
successful; otherwise, it returns false.
bool DefclassGetWatchInstances(
Defclass *d);
bool DefclassGetWatchSlots(
Defclass *d);
void DefclassSetWatchInstances(
Defclass *d,
bool b);
void DefclassSetWatchSlots(
Defclass *d,
bool b);
The function DefclassGetWatchInstances returns true if instances (creations and deletions) are
being watched for the defclass specified by the d parameter value; otherwise, it returns false.
The function DefclassGetWatchSlots returns true if slot changes are being watched for the
defclass specified by the d parameter value; otherwise, it returns false.
The function DeftemplateSetWatchInstances sets the instances creation and deletion watch
state for the defclass specified by the d parameter value to the value specified by the parameter
b.
The function DeftemplateSetWatchSlots sets the slot changes watch state for the defclass
specified by the d parameter value to the value specified by the parameter b.
bool ClassAbstractP(
Defclass *d);
bool ClassReactiveP(
Defclass *d);
bool SubclassP(
Defclass *d1,
Defclass *d2);
bool SuperclassP(
Defclass *d1,
Defclass *d2);
The function SubclassP returns true if the class specified by parameter d1 is a subclass of the
class specified by parameter d2; otherwise, it returns false.
The function SuperclassP returns true if the class specified by parameter d1 is a superclass of
the class specified by parameter d2; otherwise, it returns false.
bool SlotAllowedClasses(
Defclass *d,
const char *name,
CLIPSValue *out);
bool SlotAllowedValues(
Defclass *d,
const char *name,
CLIPSValue *out);
bool SlotCardinality(
Defclass *d,
const char *name,
CLIPSValue *out);
bool SlotDefaultValue(
Defclass *d,
const char *name,
CLIPSValue *out);
bool SlotFacets(
Defclass *d,
bool SlotRange(
Defclass *d,
const char *name,
CLIPSValue *out);
bool SlotSources(
Defclass *d,
const char *name
CLIPSValue *out);
bool SlotTypes(
Defclass *d,
const char *name,
CLIPSValue *out);
Parameter d is a pointer to a Defclass; parameter name specifies a valid slot name for the
specified defclass; and parameter out is a pointer to a CLIPSValue allocated by the caller. The
output of the function call—a multifield containing the attribute values—is stored in the out
parameter value. These function return true if a valid slot name was specified and the output
value is successfully set; otherwise, false is returned.
bool SlotDirectAccessP(
Defclass *d,
const char *name);
bool SlotExistP(
Defclass *d,
const char *name,
bool inherit);
bool SlotInitableP(
Defclass *d,
const char *name);
bool SlotPublicP(
Defclass *d,
const char *name);
bool SlotWritableP(
Defclass *d,
const char *name);
The function SlotExistP is the C equivalent of the CLIPS slot-existp function. Parameter d is a
pointer to a Defclass; parameter name specifies a slot name; and parameter inherit is a boolean
flag. This function returns true if the specified slot exists; otherwise, it returns false. If the
inherit parameter value is true, then inherited classes will be searched for the slot; otherwise,
only the specified class will be searched.
The function SlotInitableP is the C equivalent of the CLIPS slot-initablep function. Parameter
d is a pointer to a Defclass; and parameter name specifies a slot name. This function returns true
if the slot is initable; otherwise, it returns false.
The function SlotPublicP is the C equivalent of the CLIPS slot-publicp function. Parameter d is
a pointer to a Defclass; and parameter name specifies a slot name. This function returns true if
the slot is public; otherwise, it returns false.
12.12.8 Settings
ClassDefaultsMode GetClassDefaultsMode(
Environment *env);
ClassDefaultsMode SetClassDefaultsMode(
Environment *env,
ClassDefaultsMode mode);
typedef enum
{
CONVENIENCE_MODE,
CONSERVATION_MODE
} ClassDefaultsMode;
Instance *FindInstance(
Environment *env,
Defmodule *d,
const char *name,
bool searchImports);
Instance *GetNextInstance(
Environment *env,
Instance *i);
Instance *GetNextInstanceInClass(
Defclass *d,
Instance *i);
Instance *GetNextInstanceInClassAndSubclasses(
Defclass **d,
Instance *i,
UDFValue *iterator);
void Instances(
Environment *env,
const char *logicalName,
Defmodule *d,
const char *className,
bool listSubclasses);
The function FindInstance searches for the named instance specified by parameter name in the
module specified by parameter d in the environment specified by parameter env. If parameter d
is a null pointer, then the current module will be searched. If parameter searchImports is true,
then imported modules will also be searched for the instance. If the named instance is found, a
pointer to it is returned; otherwise, the null pointer is returned.
The function GetNextInstance provides iteration support for the list of instance in an
environment. If parameter i is a null pointer, then a pointer to the first Instance in the
environment specified by parameter env is returned by this function; otherwise, a pointer to the
next Instance following the Instance specified by parameter i is returned. If parameter i is the
last Instance in the specified environment, a null pointer is returned.
The function GetNextInstanceInClass provides iteration support for the list of instances
belonging to a defclass. If parameter i is a null pointer, then a pointer to the first Instance for the
defclass specified by parameter d is returned by this function; otherwise, a pointer to the next
Instance of the specified defclass following the Instance specified by parameter i is returned. If
parameter i is the last Instance for the specified defclass, a null pointer is returned.
The function Instances is the C equivalent of the CLIPS instances command. Parameter env is a
pointer to a previously created environment; parameter logicalName is the router output
destination; parameter d is a pointer to a Defmodule; parameter name is the name of a defclass;
and parameter listSubclasses is a boolean value indicating whether instances of subclasses
should be listed. If parameter d is a null pointer, then all instances of all classes in all modules
are listed (and the parameters values for name and listSubclasses are ignored). If parameter d is
not a null pointer and parameter name is a null pointer, all instance of all classes in the specified
module are listed (and parameter listSubclasses is ignored).
12.13.2 Attributes
Defclass *InstanceClass(
Instance *i);
void InstancePPForm(
Instance *i,
StringBuilder *sb);
GetSlotError DirectGetSlot(
Instance *i,
const char *name,
CLIPSValue *out);
PutSlotError DirectPutSlot(
Instance *i,
const char *name,
CLIPSValue *value);
PutSlotError DirectPutSlotInteger(
Instance *i,
const char *name,
long long value);
PutSlotError DirectPutSlotFloat(
Instance *i,
const char *name,
double value);
PutSlotError DirectPutSlotSymbol(
Instance *i,
const char *name,
const char *value);
PutSlotError DirectPutSlotString(
Instance *i,
const char *name,
const char *value);
PutSlotError DirectPutSlotInstanceName(
Instance *i,
PutSlotError DirectPutSlotCLIPSInteger(
Instance *i,
const char *name,
CLIPSInteger *value);
PutSlotError DirectPutSlotCLIPSFloat(
Instance *i,
const char *name,
CLIPSFloat *value);
PutSlotError DirectPutSlotCLIPSLexeme(
Instance *i,
const char *name,
CLIPSLexeme *value);
PutSlotError DirectPutSlotFact(
Instance *i,
const char *name,
Fact *value);
PutSlotError DirectPutSlotInstance(
Instance *i,
const char *name,
Instance *value);
PutSlotError DirectPutSlotMultifield(
Instance *i,
const char *name,
Multifield *value);
PutSlotError DirectPutSlotCLIPSExternalAddress(
Instance *i,
const char *name,
CLIPSExternalAddress *value);
typedef enum
{
GSE_NO_ERROR,
GSE_NULL_POINTER_ERROR,
GSE_INVALID_TARGET_ERROR,
GSE_SLOT_NOT_FOUND_ERROR,
} GetSlotError;
typedef enum
{
PSE_NO_ERROR,
PSE_NULL_POINTER_ERROR,
PSE_INVALID_TARGET_ERROR,
PSE_SLOT_NOT_FOUND_ERROR,
PSE_TYPE_ERROR,
PSE_RANGE_ERROR,
PSE_ALLOWED_VALUES_ERROR,
PSE_CARDINALITY_ERROR,
PSE_ALLOWED_CLASSES_ERROR,
PSE_RULE_NETWORK_ERROR
} PutSlotError;
The function InstanceClass returns a pointer to the Defclass associated with the Instance
specified by parameter i.
The function InstanceName returns the instance name of the Instance specified by parameter i.
The function InstancePPForm stores the text representation of the Instance specified by the
parameter i in the StringBuilder specified by parameter sb.
The function DirectGetSlot is the C equivalent of the CLIPS dynamic-get function. It retrieves
the slot value specified by parameter name from the instance specified by parameter i and stores
it in parameter out, a CLIPSValue allocated by the caller. This function bypasses
message-passing.
The DirectGetSlot function returns GSE_NO_ERROR if the slot value is successfully retrieved;
otherwise it returns GSE_NULL_POINTER_ERROR if any of the function arguments are
NULL pointers, GSE_INVALID_TARGET_ERROR if the instance specified by parameter i has
been deleted, and GSE_SLOT_NOT_FOUND_ERROR if the instance does not have the
specified slot.
The function DirectPutSlot function is the C equivalent of the CLIPS dynamic-put function. It
sets the slot value specified by parameter name of the instance specified by parameter i to the
value stored in parameter value, a CLIPSValue allocated and set by the caller. This function
bypasses message-passing. The additional DirectPutSlot… functions are wrappers for the
DirectPutSlot function which allow you to assign other CLIPS and C data types to a slot without
the need to allocate a CLIPSValue structure.
The DirectPutSlot function returns PSE_NO_ERROR if the slot value is successfully set;
otherwise it returns PSE_NULL_POINTER_ERROR if any of the function arguments are NULL
pointers, PSE_INVALID_TARGET_ERROR if the instance specified by parameter i has been
deleted, PSE_SLOT_NOT_FOUND_ERROR if the instance does not have the specified slot,
and PSE_RULE_NETWORK_ERROR if an error occurred while the slot assignment was being
processed in the rule network. When dynamic constraint checking is enabled, the remaining
enumeration values indicate that the specified slot value violates one of the constraints for the
allowed types or values for the slot.
12.13.3 Deletion
UnmakeInstanceError UnmakeAllInstances(
Environment *env);
UnmakeInstanceError DeleteInstance(
Instance *i);
UnmakeInstanceError DeleteAllInstances(
Environment *env);
bool ValidInstanceAddress(
Instance *i);
The function DeleteInstance directly deletes the instance specified by parameter i bypassing
message-passing. The function DeleteAllInstances directly deletes all instances in the
environment specified by parameter env bypassing message-passing. Both functions returns
UE_NO_ERROR if deletion is successful. See the Unmake command in section 3.3.4 for the list
of error codes in the UnmakeInstanceError enumeration.
long BinaryLoadInstances(
Environment *env,
const char *fileName);
long LoadInstances(
Environment *env,
const char *fileName);
long LoadInstancesFromString(
Environment *env,
const char *str,
size_t length);
long RestoreInstances(
Environment *env,
const char *fileName);
long RestoreInstancesFromString(
Environment *env,
const char *str,
size_t length);
long BinarySaveInstances(
Environment *env,
const char *fileName,
SaveScope saveCode);
long SaveInstances(
Environment *env,
const char *fileName,
SaveScope saveCode);
typedef enum
{
LOCAL_SAVE,
VISIBLE_SAVE
} SaveScope;
The function LoadInstancesFromString loads a set of instances from a string input source
(much like the LoadInstances function only using a string for input rather than a file). Parameter
env is a pointer to a previously created environment; parameter str is a string containing
instances; and parameter length is the maximum number of characters to be read from the input
string. If the length parameter value is SIZE_MAX, then the str parameter value must be
terminated by a null character; otherwise, the length parameter value indicates the maximum
number characters that will be read from the str parameter value. This function returns the
number of instances restored, or -1 if an error occurs.
The function RestoreInstancesFromString loads a set of instances from a string input source
(much like the RestoreInstances function only using a string for input rather than a file).
Parameter env is a pointer to a previously created environment; parameter str is a string
containing instances; and parameter length is the maximum number of characters to be read
from the input string. If the length parameter value is SIZE_MAX, then the str parameter value
must be terminated by a null character; otherwise, the length parameter value indicates the
maximum number characters that will be read from the str parameter value. This function
returns the number of instances restored, or -1 if an error occurs.
bool GetInstancesChanged(
Environment *env);
void SetInstancesChanged(
Environment *env,
bool b);
The function GetInstancesChanged returns true if changes to instances for the environment
specified by parameter env have occurred (either creations, deletions, or slot value changes);
otherwise, it returns false. To track future changes, SetInstanceChanged should reset the change
tracking value to false.
The function SetInstancesChanged sets the instances change tracking value for the environment
specified by the parameter env to the value specified by the parameter b.
12.13.6 Send
void Send(
Environment *env,
CLIPSValue *in,
const char *msg,
const char *msgArgs
CLIPSValue *out);
The function Send is the C equivalent of the CLIPS send function. Parameter env is a pointer to
a previously created environment; parameter in is a CLIPSValue allocated and assigned the
value of the object (instance, instance name, symbol, etc.) to receive the message; parameter msg
is the message to be received; parameter msgArgs is a string containing the constants arguments
to the message separated by spaces (a null pointer indicates no arguments); and parameter out is
a CLIPSValue allocated by the caller that is assigned the return value of the message call. If the
calling function does not need to examine the return value of the message, a null pointer can be
specified for the out parameter value. This function can trigger garbage collection.
12.13.7 Examples
int main()
{
Environment *theEnv;
UDFValue iterate;
Instance *theInstance;
Defclass *theClass;
theEnv = CreateEnvironment();
MakeInstance(theEnv,"(a1 of A)");
MakeInstance(theEnv,"(a2 of A)");
MakeInstance(theEnv,"(b1 of B)");
MakeInstance(theEnv,"(b2 of B)");
theClass = FindDefclass(theEnv,"USER");
DestroyEnvironment(theEnv);
}
12.13.7.2 Send
#include "clips.h"
int main()
{
Environment *theEnv;
char *cs;
CLIPSValue insdata;
theEnv = CreateEnvironment();
DestroyEnvironment(theEnv);
}
unsigned FindDefmessageHandler(
Defclass *d,
const char *name,
const char *type);
unsigned GetNextDefmessageHandler(
Defclass *d,
unsigned id);
void GetDefmessageHandlerList(
Environment *env,
Defclass *d,
CLIPSValue *out,
bool inherited);
void ListDefmessageHandlers(
Environment *env,
Defclass *d,
const char *logicalName,
bool inherited);
The function GetNextDefmessageHandler provides iteration support for the list of defmessage-
handlers for a defclass. If parameter id is a 0, then the integer id to the first defmessage-handler
for the defclass specified by parameter d is returned by this function; otherwise, the integer id to
the next defmessage-handler following the defmessage-handler specified by parameter id is
returned. If parameter id is the last defmessage-handler for the specified defclass, 0 is returned.
a null pointer, then message-handlers for all defclasses will be included in parameter out;
otherwise, only message-handlers for the specified defclass will be included.
12.14.2 Attributes
12.14.3 Deletion
bool DefmessageHandlerIsDeletable(
Defclass *d,
unsigned id);
bool UndefmessageHandler(
Defclass *d,
unsigned id,
Environment *env);
bool DefmessageHandlerGetWatch(
Defclass *d,
unsigned id);
void DefmessageHandlerSetWatch(
Defclass *d,
unsigned id,
bool b);
The function DefmessageHandlerSetWatch sets the message-handler watch state for the
defmessage-handler specified by parameter d, the defclass, and parameter id, the message-
handler id, to the value specified by the parameter b.
12.14.5 PreviewSend
void PreviewSend(
Defclass *d,
const char *logicalName,
const char *message);
The function PreviewSend is the C equivalent of the CLIPS preview-send command. Parameter
d is a pointer to a defclass; parameter logicalName is the router output destination; and
parameter message is the name of the message-handler to be previewed.
12.14.6 Example
This example demonstrates how to preview a send message and watch specific message-handlers
when a message is executed. The following output shows how you would typically perform this
task from the CLIPS command prompt:
To achieve the same result from a C program, change the contents of the main.c source file to the
following:
#include "clips.h"
int main()
{
Environment *env;
Defclass *classA, *classB;
env = CreateEnvironment();
classA = FindDefclass(env,"A");
classB = FindDefclass(env,"B");
Write(env,"Preview Send:\n\n");
PreviewSend(classB,STDOUT,"foo");
DefmessageHandlerSetWatch(classA,
FindDefmessageHandler(classA,"foo","primary"),
true);
DefmessageHandlerSetWatch(classB,
FindDefmessageHandler(classB,"foo","around"),
true);
MakeInstance(env,"([b1] of B)");
DestroyEnvironment(env);
}
Preview Send:
Definstances *FindDefinstances(
Environment *env,
const char *name);
Definstances *GetNextDefinstances(
Environment *env,
Definstances *d);
void GetDefinstancesList(
Environment *env,
CLIPSValue *out,
Defmodule *d);
void ListDefinstances(
Environment *env,
char *logicalName,
Defmodule *d);
The function FindDefinstances searches for the definstances specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named
definstances if it exists; otherwise, it returns a null pointer.
The function GetNextDefinstances provides iteration support for the list of definstances in the
current module. If parameter d is a null pointer, then a pointer to the first Definstances in the
current module is returned by this function; otherwise, a pointer to the next Definstances
following the Definstancess specified by parameter d is returned. If parameter d is the last
Deffacts in the current module, a null pointer is returned.
12.15.2 Attributes
The function DefinstancesName returns the name of the deffacts specified by the d parameter.
The function DefinstancePPForm returns the text representation of the Definstancess specified
by the d parameter. The null pointer is returned if the text representation is not available.
12.15.3 Deletion
bool DefinstancesIsDeletable(
Definstances *d);
bool Undefinstances(
Definstances *d,
Environment *env);
Defmodule *FindDefmodule(
Environment *env,
const char *name);
Defmodule *GetNextDefmodule(
Environment *env,
Defmodule *d);
void GetDefmoduleList(
Environment *env,
CLIPSValue *out);
void ListDefmodules(
Environment *env,
const char *logicalName);
The function FindDefmodule searches for the defmodule specified by parameter name in the
environment specified by parameter env. This function returns a pointer to the named defmodule
if it exists; otherwise, it returns a null pointer.
The function GetNextDefmodule provides iteration support for the list of defmodules. If
parameter d is a null pointer, then a pointer to the first Defmodule in the environment is returned
by this function; otherwise, a pointer to the next Defmodule following the Defmodule specified
by parameter d is returned. If parameter d is the last Defmodule in the environment, a null
pointer is returned.
12.16.2 Attributes
The function DefmoduleName returns the name of the defmodule specified by the d parameter.
The function DefmodulePPForm returns the text representation of the Defmodule specified by
the d parameter. The null pointer is returned if the text representation is not available.
Defmodule *GetCurrentModule(
Environment *env);
Defmodule *SetCurrentModule(
Environment *env,
Defmodule *d);
void *genalloc(
Environment *env,
size_t size);
void genfree(
Environment *env,
void *ptr,
size_t size);
The function genalloc allocates a block of memory using the CLIPS memory management
routines. CLIPS caches memory to improve to performance. Calls to genalloc will first attempt
to allocate memory from the cache before making a call to the C library malloc function.
Parameter env is a pointer to a previously allocated environment; and parameter size is the
number of bytes to be allocated. This function returns a pointer to a memory block of the
specified size if successful; otherwise, a null pointer is returned.
The function genfree returns a block of memory to the CLIPS memory management routines.
Calls to genfree adds the freed memory to the CLIPS cache for later reuse. The CLIPS
ReleaseMem function can be used to clear the cache and release memory back to the operating
system. Parameter env is a pointer to a previously allocated environment; parameter ptr is a
pointer to memory previously allocated by genalloc; and parameter size is the size in bytes of the
block of memory.
12.17.2 Settings
bool GetConserveMemory(
Environment *env);
bool SetConserveMemory(
Environment *env,
bool b;)
The function GetConserveMemory returns the current value of the conserve memory behavior.
If enabled (true), newly loaded constructs do not have their text (printy print) representation
stored with the construct. If there is no need to save or pretty print constructs, this will reduce the
amount of memory needed to load constructs.
The function SetConserveMemory sets the conserve memory behavior for the environment
specified by the parameter env to the value specified by the parameter b. Changing the value for
this behavior does not affect existing constructs.
The function MemRequests is the C equivalent of the CLIPS mem-requests command. The
return value of this function is the number of memory requests currently held by CLIPS. When
used in conjunction with MemUsed, the user can estimate the number of bytes CLIPS requests
per call to malloc.
The function MemUsed is the C equivalent of the CLIPS mem-used command. The return
value of this function is the total number of bytes requested and currently held by CLIPS. The
number of bytes used does not include any overhead for memory management or data creation. It
does include all free memory being held by CLIPS for later use; therefore, it is not a completely
accurate measure of the amount of memory actually used to store or process information. It is
used primarily as a minimum indication.
The function ReleaseMem is the C equivalent of the CLIPS release-mem command. It allows
free memory being cached by CLIPS to be returned to the operating system. Parameter env is a
previously allocated environment; and parameter limit is the amount of memory to be released.
If the limit parameter value is 0 or less, then all cached memory will be released; otherwise,
cached memory will be released until the amount of released memory exceeds the limit
parameter value. The return value of this function is the amount of cached memory released.
This section lists the steps needed to define and use an embedded CLIPS application. The
example illustrates how to call deffunctions and generic functions as well as manipulate objects
from C.
1) Copy all of the CLIPS source code file to the user directory.
#include "clips.h"
int main()
{
Environment *env;
Instance *c1, *c2, *c3;
CLIPSValue insdata, result;
env = CreateEnvironment();
/*=============================================*/
/* Load the code for handling complex numbers. */
/*=============================================*/
Load(env,"complex.clp");
/*=========================================================*/
/* Create two complex numbers. Message-passing is used to */
/* create the first instance c1, but c2 is created and has */
/* its slots set directly. */
/*=========================================================*/
result.integerValue = CreateInteger(env,3);
DirectPutSlot(c2,"real",&result);
result.integerValue = CreateInteger(env,-7);
DirectPutSlot(c2,"imag",&result);
/*===========================================================*/
/* Call the function '+' which has been overloaded to handle */
/* complex numbers. The result of the complex addition is */
/* stored in a new instance of the COMPLEX class. */
/*===========================================================*/
/*=======================================================*/
/* Print out a summary of the complex addition using the */
/* "print" and "magnitude" messages to get information */
/* about the three complex numbers. */
/*=======================================================*/
insdata.instanceValue = c1;
Send(env,&insdata,"print",NULL,NULL);
Write(env,"\nand\n\n");
insdata.instanceValue = c2;
Send(env,&insdata,"print",NULL,NULL);
Write(env,"\nis\n\n");
insdata.instanceValue = c3;
Send(env,&insdata,"print",NULL,NULL);
Send(env,&insdata,"magnitude",NULL,&result);
WriteCLIPSValue(env,STDOUT,&result);
Write(env,"\n");
return 0;
}
3) Define constructs which use the new function in a file called complex.clp (or any file; just
be sure the call to Load loads all necessary constructs prior to execution).
(defclass COMPLEX
(is-a USER)
(slot real)
(slot imag))
4) Compile all CLIPS files, except main.c, along with all user files.
The addition of
[c1] of COMPLEX
(real 1)
(imag 10)
and
[c2] of COMPLEX
(real 3)
(imag -7)
is
[gen1] of COMPLEX
(real 4)
(imag 3)
Appendix A:
Support Information
Questions regarding CLIPS can be posted to one of several online forums including the CLIPS
Expert System Group, http://groups.google.com/group/CLIPSESG/, the SourceForge CLIPS
Forums, http://sourceforge.net/forum/?group_id=215471, and Stack Overflow,
http://stackoverflow.com/questions/tagged/clips.
Inquiries related to the use or installation of CLIPS can be sent via electronic mail to
[email protected].
A.2 Documentation
The CLIPS Reference Manuals and other documentation is available at
http://www.clipsrules.net/?q=Documentation.
Expert Systems: Principles and Programming, 4th Edition, by Giarratano and Riley comes with
a CD-ROM containing CLIPS 6.22 executables (DOS, Windows XP, and Mac OS),
documentation, and source code. The first half of the book is theory oriented and the second half
covers rule-based, procedural, and object-oriented programming using CLIPS.
Appendix B:
Update Release Notes
The following sections denote the changes and bug fixes for CLIPS versions 6.30 and 6.40.
• Void Pointers – The use of generic (or universal) pointers in API calls when an appropriate
typed pointer exists has been discontinued.
• Bool Support – The APIs now utilize the bool type for representing boolean values.
• Primitive Value Redesign – The implementation of primitive values has been redesigned.
The function AddSymbol has been replaced with the functions CreateSymbol,
CreateString, CreateInstanceName, and CreateBoolean. The function AddLong has
been replaced with the function CreateInteger. The function AddDouble has been replaced
with the function CreateFloat. The function CreateMultifield has been replaced with the
MultifieldBuilder API and the functions EmptyMultifield and StringToMultifield. See
section 4.1 and section 6 for more information.
• User Defined Function API Redesign – The User Defined Function API has been
redesigned. The DefineFunction function has been renamed to AddUDF and its parameters
have changed. The function RtnArgCount has been renamed to UDFArgumentCount and
its parameters have changed. The functions ArgCountCheck and ArgRangeCheck are no
longer supported since the UDF argument count is automatically checked before a UDF is
invoked. The function ArgTypeCheck has been replaced with the functions
UDFFirstArgument, UDFNextArgument, UDFNthArgument, and
UDFHasNextArgument. See section 8 for more information.
• I/O Router API Redesign – The I/O router API has been redesigned. The parameters for
the AddRouter function have changed. The GetcRouter, UngetcRouter, and PrintRouter
functions have been renamed to ReadRouter, UnreadRouter, and WriteString. The
WPROMPT, WDISPLAY, WTRACE, and WDIALOG logical names are no longer
supported. The WWARNING and WERROR logical names have been renamed to
STDWRN and STDERR. See section 9 for more information.
• Garbage Collection API Redesign – The Garbage Collection API has been redesigned.
The functions IncrementGCLocks, DecrementGCLocks, IncrementFactCount,
DecrementFactCount, IncrementInstanceCount, and DecrementInstanceCount are no
longer supported. The Retain and Release functions should be used to prevent primitive
values from being garbage collected. See section 5 for more information.
• FactBuilder and FactModifier APIs – The FactBuilder and FactModifier APIs provides
functions for creating a modifying facts. See section 7 for more information.
• StringBuilder API – The StringBuilder API provides functions for dynamically allocating
and appending strings. See section 4.3 for more information.
• Eval Function – The Eval function is now available for use in run-time programs. See
sections 4.2 and 11 for more information.
• External Function 64-bit Interface - Several functions and macros have been modified to
support “long long” integers:
• Garbage Collection – The mechanism used for garbage collection has been modified. See
section 1.4 for information for more details. The EnvDecrementGCLocks function now
performs garbage collection if the lock count is reduced to 0.
• Block Memory – Block memory allocation is no longer supported. The associated source
code and BLOCK_MEMORY compiler directive flag have been removed.
• Help Functions – The help and help-path funtions are no longer supported. The
HELP_FUNCTIONS compiler directive flag has been removed.
• External Addresses – The method of retrieving and returning an external address from a
user defined function has changed (see sections 3.2.3, 3.3.4, and 3.3.5).
• Deleted Source Files – The following source files have been removed:
cmptblty.h
ed.h
edbasic.c
edmain.c
edmisc.c
edstruct.c
edterm.c
• Logical Name Defintions – Added logical name constants STDIN and STDOUT that can
be used in place of the strings "stdin" and "stdout".
• Command and Function Changes - The following commands and functions have been
changed:
• constructs-to-c (see section 5.1). A target directory path can be specified for the files
generated by this command.
• EnvMatches (see section 4.6.13). The number of parameter for this function has
changed.
• EnvSaveFacts (see section 4.4.24). The number of parameter for this function has
changed.
• EnvSaveInstances (see section 4.13.23). The number of parameter for this function has
changed.
• EnvDefineFunction (see section 3.1). New return types ‘g’ (long long integer) and ‘y’
(fact address) have been added.
• EnvReleaseMem (see section 8.2.4). The number of parameter for this function has
changed.
Index
202 Index
CLIPS Reference Manual
204 Index
CLIPS Reference Manual
206 Index
CLIPS Reference Manual
208 Index
CLIPS Reference Manual
210 Index
CLIPS Reference Manual