📄 lgcldpnd.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 05/17/06 */
/* */
/* LOGICAL DEPENDENCIES MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provide support routines for managing truth */
/* maintenance using the logical conditional element. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Removed LOGICAL_DEPENDENCIES compilation flag. */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/* Rule with exists CE has incorrect activation. */
/* DR0867 */
/* */
/*************************************************************/
#define _LGCLDPND_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include "setup.h"
#if DEFRULE_CONSTRUCT
#include "memalloc.h"
#include "router.h"
#include "envrnmnt.h"
#include "evaluatn.h"
#include "engine.h"
#include "reteutil.h"
#include "pattern.h"
#include "argacces.h"
#include "factmngr.h"
#if OBJECT_SYSTEM
#include "insfun.h"
#endif
#include "lgcldpnd.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static struct partialMatch *FindLogicalBind(struct joinNode *,struct partialMatch *);
static struct dependency *DetachAssociatedDependencies(void *,struct dependency *,void *);
/***********************************************************************/
/* AddLogicalDependencies: Adds the logical dependency links between a */
/* data entity (such as a fact or instance) and the partial match */
/* which logically supports that data entity. If a data entity is */
/* unconditionally asserted (i.e. the global variable TheLogicalJoin */
/* is NULL), then existing logical support for the data entity is no */
/* longer needed and it is removed. If a data entity is already */
/* unconditionally supported and that data entity is conditionally */
/* asserted (i.e. the global variable TheLogicalJoin is not NULL), */
/* then the logical support is ignored. Otherwise, the partial match */
/* is linked to the data entity and the data entity is linked to the */
/* partial match. Note that the word assert is used to refer to */
/* creating a fact with the assert command and creating an instance */
/* with the make-instance command. */
/***********************************************************************/
globle intBool AddLogicalDependencies(
void *theEnv,
struct patternEntity *theEntity,
int existingEntity)
{
struct partialMatch *theBinds;
struct dependency *newDependency;
/*==============================================*/
/* If the rule has no logical patterns, then no */
/* dependencies have to be established. */
/*==============================================*/
if (EngineData(theEnv)->TheLogicalJoin == NULL)
{
if (existingEntity) RemoveEntityDependencies(theEnv,theEntity);
return(TRUE);
}
else if (existingEntity && (theEntity->dependents == NULL))
{ return(TRUE); }
/*============================================================*/
/* Find the partial match in the logical join associated with */
/* activation partial match. If the partial match cannot be */
/* found, then the partial match must have been deleted by a */
/* previous RHS action and the dependency link should not be */
/* added. */
/*============================================================*/
theBinds = FindLogicalBind(EngineData(theEnv)->TheLogicalJoin,EngineData(theEnv)->GlobalLHSBinds);
if (theBinds == NULL) return(FALSE);
/*==============================================================*/
/* Add a dependency link between the partial match and the data */
/* entity. The dependency links are stored in the partial match */
/* behind the data entities stored in the partial match and the */
/* activation link, if any. */
/*==============================================================*/
newDependency = get_struct(theEnv,dependency);
newDependency->dPtr = (void *) theEntity;
newDependency->next = (struct dependency *)
theBinds->binds[theBinds->bcount + theBinds->activationf].gm.theValue;
theBinds->binds[theBinds->bcount + theBinds->activationf].gm.theValue = (void *) newDependency;
/*================================================================*/
/* Add a dependency link between the entity and the partialMatch. */
/*================================================================*/
newDependency = get_struct(theEnv,dependency);
newDependency->dPtr = (void *) theBinds;
newDependency->next = (struct dependency *) theEntity->dependents;
theEntity->dependents = (void *) newDependency;
/*==================================================================*/
/* Return TRUE to indicate that the data entity should be asserted. */
/*==================================================================*/
return(TRUE);
}
/************************************************************************/
/* FindLogicalBind: Finds the partial match associated with the logical */
/* CE which will provide logical support for a data entity asserted */
/* from the currently executing rule. The function is called when */
/* creating logical support links between the data entity and */
/* supporting partial matches. It compares each partial match found */
/* at a specified join to the partial match associated with a rule */
/* activation until it finds the partial match that generated the */
/* rule activation. */
/************************************************************************/
static struct partialMatch *FindLogicalBind(
struct joinNode *theJoin,
struct partialMatch *theBinds)
{
struct partialMatch *compPtr;
unsigned int i;
int found;
/*==================================*/
/* Loop through each of the partial */
/* matches in the beta memory. */
/*==================================*/
for (compPtr = theJoin->beta;
compPtr != NULL;
compPtr = compPtr->next)
{
/*==================================================*/
/* Compare each of the data entities in the partial */
/* match being examined and the partial match used */
/* in the dependency link. */
/*==================================================*/
found = TRUE;
for (i = 0; i < compPtr->bcount; i++)
{
if (compPtr->binds[i].gm.theMatch != theBinds->binds[i].gm.theMatch)
{
found = FALSE;
break;
}
}
/*========================================================*/
/* If all of the data entities in the partial match are */
/* identical to the partial match in the dependency link, */
/* then this is the partial match we're looking for. */
/*========================================================*/
if (found) return(compPtr);
}
/*========================================*/
/* The partial match corresponding to the */
/* logical dependency couldn't be found. */
/*========================================*/
return(NULL);
}
/*********************************************************************/
/* RemoveEntityDependencies: Removes all logical support links from */
/* a pattern entity that point to partial matches or other pattern */
/* entities. Also removes the associated links from the partial */
/* matches or pattern entities which point back to the pattern */
/* entities. */
/*********************************************************************/
globle void RemoveEntityDependencies(
void *theEnv,
struct patternEntity *theEntity)
{
struct dependency *fdPtr, *nextPtr, *theList;
struct partialMatch *theBinds;
/*===============================*/
/* Get the list of dependencies. */
/*===============================*/
fdPtr = (struct dependency *) theEntity->dependents;
/*========================================*/
/* Loop through each of the dependencies. */
/*========================================*/
while (fdPtr != NULL)
{
/*===============================*/
/* Remember the next dependency. */
/*===============================*/
nextPtr = fdPtr->next;
/*================================================================*/
/* Remove the link between the data entity and the partial match. */
/*================================================================*/
theBinds = (struct partialMatch *) fdPtr->dPtr;
theList = (struct dependency *)
theBinds->binds[theBinds->bcount + theBinds->activationf].gm.theValue;
theList = DetachAssociatedDependencies(theEnv,theList,(void *) theEntity);
theBinds->binds[theBinds->bcount + theBinds->activationf].gm.theValue = (void *) theList;
/*========================*/
/* Return the dependency. */
/*========================*/
rtn_struct(theEnv,dependency,fdPtr);
/*=================================*/
/* Move on to the next dependency. */
/*=================================*/
fdPtr = nextPtr;
}
/*=====================================================*/
/* Set the dependency list of the data entity to NULL. */
/*=====================================================*/
theEntity->dependents = NULL;
}
/********************************************************************/
/* ReturnEntityDependencies: Removes all logical support links from */
/* a pattern entity. This is unidirectional. The links from the */
/* the partial match to the entity are not removed. */
/********************************************************************/
globle void ReturnEntityDependencies(
void *theEnv,
struct patternEntity *theEntity)
{
struct dependency *fdPtr, *nextPtr;
fdPtr = (struct dependency *) theEntity->dependents;
while (fdPtr != NULL)
{
nextPtr = fdPtr->next;
rtn_struct(theEnv,dependency,fdPtr);
fdPtr = nextPtr;
}
theEntity->dependents = NULL;
}
/*******************************************************************/
/* DetachAssociatedDependencies: Removes all logical support links */
/* which pointer to a pattern entity from a list of dependencies */
/* (which may be associated with either a partial match or */
/* another pattern entity). Does not remove links which point in */
/* the other direction. */
/*******************************************************************/
static struct dependency *DetachAssociatedDependencies(
void *theEnv,
struct dependency *theList,
void *theEntity)
{
struct dependency *fdPtr, *nextPtr, *lastPtr = NULL;
fdPtr = theList;
while (fdPtr != NULL)
{
if (fdPtr->dPtr == theEntity)
{
nextPtr = fdPtr->next;
if (lastPtr == NULL) theList = nextPtr;
else lastPtr->next = nextPtr;
rtn_struct(theEnv,dependency,fdPtr);
fdPtr = nextPtr;
}
else
{
lastPtr = fdPtr;
fdPtr = fdPtr->next;
}
}
return(theList);
}
/**************************************************************************/
/* RemovePMDependencies: Removes all logical support links from a partial */
/* match that point to any data entities. Also removes the associated */
/* links from the data entities which point back to the partial match. */
/**************************************************************************/
globle void RemovePMDependencies(
void *theEnv,
struct partialMatch *theBinds)
{
struct dependency *fdPtr, *nextPtr, *theList;
struct patternEntity *theEntity;
fdPtr = (struct dependency *) theBinds->binds[theBinds->bcount + theBinds->activationf].gm.theValue;
while (fdPtr != NULL)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -