📄 insquery.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* */
/*******************************************************/
/*************************************************************/
/* Purpose: Query Functions for Objects */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* */
/* Contributing Programmer(s): */
/* */
/* */
/* Revision History: */
/* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
/* */
/* Corrected compilation errors for files */
/* generated by constructs-to-c. DR0861 */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/*************************************************************/
/* =========================================
*****************************************
EXTERNAL DEFINITIONS
=========================================
***************************************** */
#include "setup.h"
#if INSTANCE_SET_QUERIES
#include "argacces.h"
#include "classcom.h"
#include "classfun.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "exprnpsr.h"
#include "insfun.h"
#include "insmngr.h"
#include "insqypsr.h"
#include "prcdrfun.h"
#include "router.h"
#include "utility.h"
#define _INSQUERY_SOURCE_
#include "insquery.h"
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTION HEADERS
=========================================
***************************************** */
static void PushQueryCore(void *);
static void PopQueryCore(void *);
static QUERY_CORE *FindQueryCore(void *,int);
static QUERY_CLASS *DetermineQueryClasses(void *,EXPRESSION *,char *,unsigned *);
static QUERY_CLASS *FormChain(void *,char *,DATA_OBJECT *);
static void DeleteQueryClasses(void *,QUERY_CLASS *);
static int TestForFirstInChain(void *,QUERY_CLASS *,int);
static int TestForFirstInstanceInClass(void *,struct defmodule *,int,DEFCLASS *,QUERY_CLASS *,int);
static void TestEntireChain(void *,QUERY_CLASS *,int);
static void TestEntireClass(void *,struct defmodule *,int,DEFCLASS *,QUERY_CLASS *,int);
static void AddSolution(void *);
static void PopQuerySoln(void *);
/****************************************************
NAME : SetupQuery
DESCRIPTION : Initializes instance query H/L
functions and parsers
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Sets up kernel functions and parsers
NOTES : None
****************************************************/
globle void SetupQuery(
void *theEnv)
{
AllocateEnvironmentData(theEnv,INSTANCE_QUERY_DATA,sizeof(struct instanceQueryData),NULL);
#if ! RUN_TIME
InstanceQueryData(theEnv)->QUERY_DELIMETER_SYMBOL = (SYMBOL_HN *) EnvAddSymbol(theEnv,QUERY_DELIMETER_STRING);
IncrementSymbolCount(InstanceQueryData(theEnv)->QUERY_DELIMETER_SYMBOL);
EnvDefineFunction2(theEnv,"(query-instance)",'o',
PTIEF GetQueryInstance,"GetQueryInstance",NULL);
EnvDefineFunction2(theEnv,"(query-instance-slot)",'u',
PTIEF GetQueryInstanceSlot,"GetQueryInstanceSlot",NULL);
EnvDefineFunction2(theEnv,"any-instancep",'b',PTIEF AnyInstances,"AnyInstances",NULL);
AddFunctionParser(theEnv,"any-instancep",ParseQueryNoAction);
EnvDefineFunction2(theEnv,"find-instance",'m',
PTIEF QueryFindInstance,"QueryFindInstance",NULL);
AddFunctionParser(theEnv,"find-instance",ParseQueryNoAction);
EnvDefineFunction2(theEnv,"find-all-instances",'m',
PTIEF QueryFindAllInstances,"QueryFindAllInstances",NULL);
AddFunctionParser(theEnv,"find-all-instances",ParseQueryNoAction);
EnvDefineFunction2(theEnv,"do-for-instance",'u',
PTIEF QueryDoForInstance,"QueryDoForInstance",NULL);
AddFunctionParser(theEnv,"do-for-instance",ParseQueryAction);
EnvDefineFunction2(theEnv,"do-for-all-instances",'u',
PTIEF QueryDoForAllInstances,"QueryDoForAllInstances",NULL);
AddFunctionParser(theEnv,"do-for-all-instances",ParseQueryAction);
EnvDefineFunction2(theEnv,"delayed-do-for-all-instances",'u',
PTIEF DelayedQueryDoForAllInstances,
"DelayedQueryDoForAllInstances",NULL);
AddFunctionParser(theEnv,"delayed-do-for-all-instances",ParseQueryAction);
#endif
}
/*************************************************************
NAME : GetQueryInstance
DESCRIPTION : Internal function for referring to instance
array on instance-queries
INPUTS : None
RETURNS : The name of the specified instance-set member
SIDE EFFECTS : None
NOTES : H/L Syntax : ((query-instance) <index>)
*************************************************************/
globle void *GetQueryInstance(
void *theEnv)
{
register QUERY_CORE *core;
core = FindQueryCore(theEnv,DOPToInteger(GetFirstArgument()));
return(GetFullInstanceName(theEnv,core->solns[DOPToInteger(GetFirstArgument()->nextArg)]));
}
/***************************************************************************
NAME : GetQueryInstanceSlot
DESCRIPTION : Internal function for referring to slots of instances in
instance array on instance-queries
INPUTS : The caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : Caller's result buffer set appropriately
NOTES : H/L Syntax : ((query-instance-slot) <index> <slot-name>)
**************************************************************************/
globle void GetQueryInstanceSlot(
void *theEnv,
DATA_OBJECT *result)
{
INSTANCE_TYPE *ins;
INSTANCE_SLOT *sp;
DATA_OBJECT temp;
QUERY_CORE *core;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
core = FindQueryCore(theEnv,DOPToInteger(GetFirstArgument()));
ins = core->solns[DOPToInteger(GetFirstArgument()->nextArg)];
EvaluateExpression(theEnv,GetFirstArgument()->nextArg->nextArg,&temp);
if (temp.type != SYMBOL)
{
ExpectedTypeError1(theEnv,"get",1,"symbol");
SetEvaluationError(theEnv,TRUE);
return;
}
sp = FindInstanceSlot(theEnv,ins,(SYMBOL_HN *) temp.value);
if (sp == NULL)
{
SlotExistError(theEnv,ValueToString(temp.value),"instance-set query");
return;
}
result->type = (unsigned short) sp->type;
result->value = sp->value;
if (sp->type == MULTIFIELD)
{
result->begin = 0;
SetpDOEnd(result,GetInstanceSlotLength(sp));
}
}
/* =============================================================================
=============================================================================
Following are the instance query functions :
any-instancep : Determines if any instances satisfy the query
find-instance : Finds first (set of) instance(s) which satisfies
the query and stores it in a multi-field
find-all-instances : Finds all (sets of) instances which satisfy the
the query and stores them in a multi-field
do-for-instance : Executes a given action for the first (set of)
instance(s) which satisfy the query
do-for-all-instances : Executes an action for all instances which satisfy
the query as they are found
delayed-do-for-all-instances : Same as above - except that the list of instances
which satisfy the query is formed before any
actions are executed
Instance candidate search algorithm :
All permutations of first restriction class instances with other
restriction class instances (Rightmost are varied first)
All permutations of first restriction class's subclasses' instances with
other restriction class instances.
And so on...
For any one class, instances are examined in the order they were defined
Example :
(defclass a (is-a standard-user))
(defclass b (is-a standard-user))
(defclass c (is-a standard-user))
(defclass d (is-a a b))
(make-instance a1 of a)
(make-instance a2 of a)
(make-instance b1 of b)
(make-instance b2 of b)
(make-instance c1 of c)
(make-instance c2 of c)
(make-instance d1 of d)
(make-instance d2 of d)
(any-instancep ((?a a b) (?b c)) <query>)
The permutations (?a ?b) would be examined in the following order :
(a1 c1),(a1 c2),(a2 c1),(a2 c2),(d1 c1),(d1 c2),(d2 c1),(d2 c2),
(b1 c1),(b1 c2),(b2 c1),(b2 c2),(d1 c1),(d1 c2),(d2 c1),(d2 c2)
Notice the duplication because d is a subclass of both and a and b.
=============================================================================
============================================================================= */
/******************************************************************************
NAME : AnyInstances
DESCRIPTION : Determines if there any existing instances which satisfy
the query
INPUTS : None
RETURNS : TRUE if the query is satisfied, FALSE otherwise
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on instance restrictions
and how early the expression evaulates to TRUE - if at all).
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle intBool AnyInstances(
void *theEnv)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
int TestResult;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"any-instancep",&rcnt);
if (qclasses == NULL)
return(FALSE);
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
TestResult = TestForFirstInChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
return(TestResult);
}
/******************************************************************************
NAME : QueryFindInstance
DESCRIPTION : Finds the first set of instances which satisfy the query and
stores their names in the user's multi-field variable
INPUTS : Caller's result buffer
RETURNS : TRUE if the query is satisfied, FALSE otherwise
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on instance restrictions
and how early the expression evaulates to TRUE - if at all).
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle void QueryFindInstance(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_CLASS *qclasses;
unsigned rcnt,i;
result->type = MULTIFIELD;
result->begin = 0;
result->end = -1;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"find-instance",&rcnt);
if (qclasses == NULL)
{
result->value = (void *) EnvCreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **)
gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
if (TestForFirstInChain(theEnv,qclasses,0) == TRUE)
{
result->value = (void *) EnvCreateMultifield(theEnv,rcnt);
SetpDOEnd(result,rcnt);
for (i = 1 ; i <= rcnt ; i++)
{
SetMFType(result->value,i,INSTANCE_NAME);
SetMFValue(result->value,i,GetFullInstanceName(theEnv,InstanceQueryData(theEnv)->QueryCore->solns[i - 1]));
}
}
else
result->value = (void *) EnvCreateMultifield(theEnv,0L);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
/******************************************************************************
NAME : QueryFindAllInstances
DESCRIPTION : Finds all sets of instances which satisfy the query and
stores their names in the user's multi-field variable
The sets are stored sequentially :
Number of sets = (Multi-field length) / (Set length)
The first set is if the first (set length) atoms of the
multi-field variable, and so on.
INPUTS : Caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every instance set.
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle void QueryFindAllInstances(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
register unsigned i,j;
result->type = MULTIFIELD;
result->begin = 0;
result->end = -1;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"find-all-instances",&rcnt);
if (qclasses == NULL)
{
result->value = (void *) EnvCreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_set = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_size = rcnt;
InstanceQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
result->value = (void *) EnvCreateMultifield(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_cnt * rcnt);
while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -