?? 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,ValueToInteger(GetpValue(GetFirstArgument()))); return(GetFullInstanceName(theEnv,core->solns[ValueToInteger(GetpValue(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,ValueToInteger(GetpValue(GetFirstArgument()))); ins = core->solns[ValueToInteger(GetpValue(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 + -