📄 factqury.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 07/01/05 */
/* */
/* */
/*******************************************************/
/*************************************************************/
/* Purpose: Query Functions for Objects */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* */
/* Contributing Programmer(s): */
/* Gary D. Riley */
/* */
/* Revision History: */
/* */
/* 6.23: Added fact-set queries. */
/* */
/* 6.24: Corrected errors when compiling as a C++ file. */
/* DR0868 */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/*************************************************************/
/* =========================================
*****************************************
EXTERNAL DEFINITIONS
=========================================
***************************************** */
#include "setup.h"
#if FACT_SET_QUERIES
#include "argacces.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "exprnpsr.h"
#include "modulutl.h"
#include "tmpltutl.h"
#include "insfun.h"
#include "factqpsr.h"
#include "prcdrfun.h"
#include "router.h"
#include "utility.h"
#define _FACTQURY_SOURCE_
#include "factqury.h"
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTION HEADERS
=========================================
***************************************** */
static void PushQueryCore(void *);
static void PopQueryCore(void *);
static QUERY_CORE *FindQueryCore(void *,int);
static QUERY_TEMPLATE *DetermineQueryTemplates(void *,EXPRESSION *,char *,unsigned *);
static QUERY_TEMPLATE *FormChain(void *,char *,DATA_OBJECT *);
static void DeleteQueryTemplates(void *,QUERY_TEMPLATE *);
static int TestForFirstInChain(void *,QUERY_TEMPLATE *,int);
static int TestForFirstFactInTemplate(void *,struct deftemplate *,QUERY_TEMPLATE *,int);
static void TestEntireChain(void *,QUERY_TEMPLATE *,int);
static void TestEntireTemplate(void *,struct deftemplate *,QUERY_TEMPLATE *,int);
static void AddSolution(void *);
static void PopQuerySoln(void *);
/****************************************************
NAME : SetupFactQuery
DESCRIPTION : Initializes fact query H/L
functions and parsers
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Sets up kernel functions and parsers
NOTES : None
****************************************************/
globle void SetupFactQuery(
void *theEnv)
{
AllocateEnvironmentData(theEnv,FACT_QUERY_DATA,sizeof(struct factQueryData),NULL);
#if ! RUN_TIME
FactQueryData(theEnv)->QUERY_DELIMETER_SYMBOL = (SYMBOL_HN *) EnvAddSymbol(theEnv,QUERY_DELIMETER_STRING);
IncrementSymbolCount(FactQueryData(theEnv)->QUERY_DELIMETER_SYMBOL);
EnvDefineFunction2(theEnv,"(query-fact)",'u',
PTIEF GetQueryFact,"GetQueryFact",NULL);
EnvDefineFunction2(theEnv,"(query-fact-slot)",'u',
PTIEF GetQueryFactSlot,"GetQueryFactSlot",NULL);
EnvDefineFunction2(theEnv,"any-factp",'b',PTIEF AnyFacts,"AnyFacts",NULL);
AddFunctionParser(theEnv,"any-factp",FactParseQueryNoAction);
EnvDefineFunction2(theEnv,"find-fact",'m',
PTIEF QueryFindFact,"QueryFindFact",NULL);
AddFunctionParser(theEnv,"find-fact",FactParseQueryNoAction);
EnvDefineFunction2(theEnv,"find-all-facts",'m',
PTIEF QueryFindAllFacts,"QueryFindAllFacts",NULL);
AddFunctionParser(theEnv,"find-all-facts",FactParseQueryNoAction);
EnvDefineFunction2(theEnv,"do-for-fact",'u',
PTIEF QueryDoForFact,"QueryDoForFact",NULL);
AddFunctionParser(theEnv,"do-for-fact",FactParseQueryAction);
EnvDefineFunction2(theEnv,"do-for-all-facts",'u',
PTIEF QueryDoForAllFacts,"QueryDoForAllFacts",NULL);
AddFunctionParser(theEnv,"do-for-all-facts",FactParseQueryAction);
EnvDefineFunction2(theEnv,"delayed-do-for-all-facts",'u',
PTIEF DelayedQueryDoForAllFacts,
"DelayedQueryDoForAllFacts",NULL);
AddFunctionParser(theEnv,"delayed-do-for-all-facts",FactParseQueryAction);
#endif
}
/*************************************************************
NAME : GetQueryFact
DESCRIPTION : Internal function for referring to fact
array on fact-queries
INPUTS : None
RETURNS : The name of the specified fact-set member
SIDE EFFECTS : None
NOTES : H/L Syntax : ((query-fact) <index>)
*************************************************************/
globle void GetQueryFact(
void *theEnv,
DATA_OBJECT *result)
{
register QUERY_CORE *core;
core = FindQueryCore(theEnv,DOPToInteger(GetFirstArgument()));
result->type = FACT_ADDRESS;
result->value = core->solns[DOPToInteger(GetFirstArgument()->nextArg)];
/* return(GetFullInstanceName(theEnv,core->solns[DOPToInteger(GetFirstArgument()->nextArg)])); */
}
/***************************************************************************
NAME : GetQueryFactSlot
DESCRIPTION : Internal function for referring to slots of fact in
fact array on fact-queries
INPUTS : The caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : Caller's result buffer set appropriately
NOTES : H/L Syntax : ((query-fact-slot) <index> <slot-name>)
**************************************************************************/
globle void GetQueryFactSlot(
void *theEnv,
DATA_OBJECT *result)
{
struct fact *theFact;
DATA_OBJECT temp;
QUERY_CORE *core;
short position;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
core = FindQueryCore(theEnv,DOPToInteger(GetFirstArgument()));
theFact = core->solns[DOPToInteger(GetFirstArgument()->nextArg)];
EvaluateExpression(theEnv,GetFirstArgument()->nextArg->nextArg,&temp);
if (temp.type != SYMBOL)
{
ExpectedTypeError1(theEnv,"get",1,"symbol");
SetEvaluationError(theEnv,TRUE);
return;
}
/*==================================================*/
/* Make sure the slot exists (the symbol implied is */
/* used for the implied slot of an ordered fact). */
/*==================================================*/
if (theFact->whichDeftemplate->implied)
{
if (strcmp(ValueToString(temp.value),"implied") != 0) /* TBD - no str compare */
{
SlotExistError(theEnv,ValueToString(temp.value),"fact-set query");
return;
}
position = 1;
}
else if (FindSlot((struct deftemplate *) theFact->whichDeftemplate,
(struct symbolHashNode *) temp.value,&position) == NULL)
{
SlotExistError(theEnv,ValueToString(temp.value),"fact-set query");
return;
}
result->type = theFact->theProposition.theFields[position-1].type;
result->value = theFact->theProposition.theFields[position-1].value;
if (result->type == MULTIFIELD)
{
SetpDOBegin(result,1);
SetpDOEnd(result,((struct multifield *) result->value)->multifieldLength);
}
}
/* =============================================================================
=============================================================================
Following are the instance query functions :
any-factp : Determines if any facts satisfy the query
find-fact : Finds first (set of) fact(s) which satisfies
the query and stores it in a multi-field
find-all-facts : Finds all (sets of) facts which satisfy the
the query and stores them in a multi-field
do-for-fact : Executes a given action for the first (set of)
fact(s) which satisfy the query
do-for-all-facts : Executes an action for all facts which satisfy
the query as they are found
delayed-do-for-all-facts : Same as above - except that the list of facts
which satisfy the query is formed before any
actions are executed
Fact candidate search algorithm :
All permutations of first restriction template facts with other
restriction template facts (Rightmost are varied first)
For any one template, fact are examined in the order they were defined
Example :
(deftemplate a (slot v))
(deftemplate b (slot v))
(deftemplate c (slot v))
(assert (a (v a1)))
(assert (a (v a2)))
(assert (b (v b1)))
(assert (b (v b2)))
(assert (c (v c1)))
(assert (c (v c2)))
(assert (d (v d1)))
(assert (d (v d2)))
(any-factp ((?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),
(b1 c1),(b1 c2),(b2 c1),(b2 c2)
=============================================================================
============================================================================= */
/******************************************************************************
NAME : AnyFacts
DESCRIPTION : Determines if there any existing facts which satisfy
the query
INPUTS : None
RETURNS : TRUE if the query is satisfied, FALSE otherwise
SIDE EFFECTS : The query template-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on fact restrictions
and how early the expression evaluates to TRUE - if at all).
NOTES : H/L Syntax : See FactParseQueryNoAction()
******************************************************************************/
globle intBool AnyFacts(
void *theEnv)
{
QUERY_TEMPLATE *qtemplates;
unsigned rcnt;
int TestResult;
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg,
"any-factp",&rcnt);
if (qtemplates == NULL)
return(FALSE);
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **) gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
TestResult = TestForFirstInChain(theEnv,qtemplates,0);
FactQueryData(theEnv)->AbortQuery = FALSE;
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
return(TestResult);
}
/******************************************************************************
NAME : QueryFindFact
DESCRIPTION : Finds the first set of facts which satisfy the query and
stores their addresses 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 template-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on fact restrictions
and how early the expression evaulates to TRUE - if at all).
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle void QueryFindFact(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_TEMPLATE *qtemplates;
unsigned rcnt,i;
result->type = MULTIFIELD;
result->begin = 0;
result->end = -1;
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg,
"find-fact",&rcnt);
if (qtemplates == NULL)
{
result->value = (void *) EnvCreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **)
gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
if (TestForFirstInChain(theEnv,qtemplates,0) == TRUE)
{
result->value = (void *) EnvCreateMultifield(theEnv,rcnt);
SetpDOEnd(result,rcnt);
for (i = 1 ; i <= rcnt ; i++)
{
SetMFType(result->value,i,FACT_ADDRESS);
SetMFValue(result->value,i,FactQueryData(theEnv)->QueryCore->solns[i - 1]);
}
}
else
result->value = (void *) EnvCreateMultifield(theEnv,0L);
FactQueryData(theEnv)->AbortQuery = FALSE;
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
}
/******************************************************************************
NAME : QueryFindAllFacts
DESCRIPTION : Finds all sets of facts 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 template-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every fact set.
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle void QueryFindAllFacts(
void *theEnv,
DATA_OBJECT *result)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -