📄 factbld.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.30 10/19/06 */ /* */ /* FACT BUILD MODULE */ /*******************************************************//*************************************************************//* Purpose: Given a new fact pattern, adds the pattern to *//* the pattern network of the associated deftemplate. Also *//* contains routines for deleting a pattern from the fact *//* pattern network. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//* 6.24: Removed INCREMENTAL_RESET compilation flag. *//* *//* 6.30: Added support for hashed alpha memories. *//* *//*************************************************************/#define _FACTBLD_SOURCE_#include "setup.h"#if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT#include <stdio.h>#define _STDIO_INCLUDED_#include "memalloc.h"#include "reteutil.h"#include "router.h"#include "reorder.h"#include "factcmp.h"#include "factmch.h"#include "factgen.h"#include "factmngr.h"#include "factlhs.h"#include "argacces.h"#include "modulutl.h"#include "tmpltdef.h"#include "envrnmnt.h"#include "factbld.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if (! RUN_TIME) && (! BLOAD_ONLY) static struct factPatternNode *FindPatternNode(struct factPatternNode *,struct lhsParseNode *, struct factPatternNode **,unsigned,unsigned); static struct factPatternNode *CreateNewPatternNode(void *,struct lhsParseNode *,struct factPatternNode *, struct factPatternNode *,unsigned,unsigned); static void ClearPatternMatches(void *,struct factPatternNode *); static void DetachFactPattern(void *,struct patternNodeHeader *); static struct patternNodeHeader *PlaceFactPattern(void *,struct lhsParseNode *); static struct lhsParseNode *RemoveUnneededSlots(void *,struct lhsParseNode *); static void FindAndSetDeftemplatePatternNetwork(void *,struct factPatternNode *,struct factPatternNode *);#endif/*********************************************************//* InitializeFactPatterns: Adds fact patterns to the set *//* of patterns recognized by the rule pattern parsing *//* and pattern/join network integration routines. *//*********************************************************/globle void InitializeFactPatterns( void *theEnv) {#if DEFRULE_CONSTRUCT struct patternParser *newPtr; InitializeFactReteFunctions(theEnv); newPtr = get_struct(theEnv,patternParser); newPtr->name = "facts"; newPtr->priority = 0; newPtr->entityType = &FactData(theEnv)->FactInfo; #if (! RUN_TIME) && (! BLOAD_ONLY) newPtr->recognizeFunction = FactPatternParserFind; newPtr->parseFunction = FactPatternParse; newPtr->postAnalysisFunction = NULL; newPtr->addPatternFunction = PlaceFactPattern; newPtr->removePatternFunction = DetachFactPattern; newPtr->genJNConstantFunction = NULL; newPtr->replaceGetJNValueFunction = FactReplaceGetvar; newPtr->genGetJNValueFunction = FactGenGetvar; newPtr->genCompareJNValuesFunction = FactJNVariableComparison; newPtr->genPNConstantFunction = FactGenPNConstant; newPtr->replaceGetPNValueFunction = FactReplaceGetfield; newPtr->genGetPNValueFunction = FactGenGetfield; newPtr->genComparePNValuesFunction = FactPNVariableComparison; newPtr->returnUserDataFunction = NULL; newPtr->copyUserDataFunction = NULL;#else newPtr->recognizeFunction = NULL; newPtr->parseFunction = NULL; newPtr->postAnalysisFunction = NULL; newPtr->addPatternFunction = NULL; newPtr->removePatternFunction = NULL; newPtr->genJNConstantFunction = NULL; newPtr->replaceGetJNValueFunction = NULL; newPtr->genGetJNValueFunction = NULL; newPtr->genCompareJNValuesFunction = NULL; newPtr->genPNConstantFunction = NULL; newPtr->replaceGetPNValueFunction = NULL; newPtr->genGetPNValueFunction = NULL; newPtr->genComparePNValuesFunction = NULL; newPtr->returnUserDataFunction = NULL; newPtr->copyUserDataFunction = NULL; #endif newPtr->markIRPatternFunction = MarkFactPatternForIncrementalReset; newPtr->incrementalResetFunction = FactsIncrementalReset;#if (! RUN_TIME) && (! BLOAD_ONLY) newPtr->initialPatternFunction = CreateInitialFactPattern;#if CONSTRUCT_COMPILER newPtr->codeReferenceFunction = FactPatternNodeReference;#else newPtr->codeReferenceFunction = NULL;#endif#else newPtr->initialPatternFunction = NULL; newPtr->codeReferenceFunction = NULL;#endif AddPatternParser(theEnv,newPtr);#endif }#if (! RUN_TIME) && (! BLOAD_ONLY)/******************************************************************************//* PlaceFactPattern: Integrates a fact pattern into the fact pattern network. *//******************************************************************************/static struct patternNodeHeader *PlaceFactPattern( void *theEnv, struct lhsParseNode *thePattern) { struct lhsParseNode *tempPattern = NULL; struct factPatternNode *currentLevel, *lastLevel; struct factPatternNode *nodeBeforeMatch, *newNode = NULL; unsigned endSlot; int count; char *deftemplateName; /*======================================================================*/ /* Get the name of the deftemplate associated with the pattern being */ /* added (recall that the first field of any pattern must be a symbol). */ /*======================================================================*/ deftemplateName = ValueToString(thePattern->right->bottom->value); /*=====================================================*/ /* Remove any slot tests that test only for existance. */ /*=====================================================*/ thePattern->right = RemoveUnneededSlots(theEnv,thePattern->right); /*========================================================*/ /* If the constant test for the relation name is the only */ /* pattern network test and there are no other network */ /* tests, then remove the test, but keep the node since */ /* there must be a link from the fact pattern network to */ /* the join network. Otherwise, remove the test for the */ /* relation name since this test has already been done */ /* before entering the pattern network (since each */ /* deftemplate has its own pattern network). */ /*========================================================*/ if (thePattern->right->right == NULL) { ReturnExpression(theEnv,thePattern->right->networkTest); ReturnExpression(theEnv,thePattern->right->constantSelector); ReturnExpression(theEnv,thePattern->right->constantValue); thePattern->right->networkTest = NULL; thePattern->right->constantSelector = NULL; thePattern->right->constantValue = NULL; } else { tempPattern = thePattern->right; thePattern->right = thePattern->right->right; tempPattern->right = NULL; ReturnLHSParseNodes(theEnv,tempPattern); tempPattern = NULL; } /*====================================================*/ /* Get the expression for hashing in the alpha memory */ /* and attach it to the last node of the pattern. */ /*====================================================*/ tempPattern = thePattern->right; while (tempPattern->right != NULL) { tempPattern = tempPattern->right; } if ((tempPattern->multifieldSlot) && (tempPattern->bottom != NULL)) { tempPattern = tempPattern->bottom; while (tempPattern->right != NULL) { tempPattern = tempPattern->right; } } tempPattern->rightHash = thePattern->rightHash; thePattern->rightHash = NULL; tempPattern = NULL; /*============================================================*/ /* Get a pointer to the deftemplate data structure associated */ /* with the pattern (use the deftemplate name extracted from */ /* the first field of the pattern). */ /*============================================================*/ FactData(theEnv)->CurrentDeftemplate = (struct deftemplate *) FindImportedConstruct(theEnv,"deftemplate",NULL, deftemplateName,&count, TRUE,NULL); /*================================================*/ /* Initialize some pointers to indicate where the */ /* pattern is being added to the pattern network. */ /*================================================*/ currentLevel = FactData(theEnv)->CurrentDeftemplate->patternNetwork; lastLevel = NULL; thePattern = thePattern->right; /*===========================================*/ /* Loop until all fields in the pattern have */ /* been added to the pattern network. */ /*===========================================*/ while (thePattern != NULL) { /*===========================================================*/ /* If a multifield slot is being processed, then process the */ /* pattern nodes attached to the multifield pattern node. */ /*===========================================================*/ if (thePattern->multifieldSlot) { tempPattern = thePattern; thePattern = thePattern->bottom; } /*============================================*/ /* Determine if the last pattern field within */ /* a multifield slot is being processed. */ /*============================================*/ if ((thePattern->right == NULL) && (tempPattern != NULL)) { endSlot = TRUE; } else { endSlot = FALSE; } /*========================================*/ /* Is there a node in the pattern network */ /* that can be reused (shared)? */ /*========================================*/ newNode = FindPatternNode(currentLevel,thePattern,&nodeBeforeMatch,endSlot,FALSE); /*================================================*/ /* If the pattern node cannot be shared, then add */ /* a new pattern node to the pattern network. */ /*================================================*/ if (newNode == NULL) { newNode = CreateNewPatternNode(theEnv,thePattern,nodeBeforeMatch,lastLevel,endSlot,FALSE); } if (thePattern->constantSelector != NULL) { currentLevel = newNode->nextLevel; lastLevel = newNode; newNode = FindPatternNode(currentLevel,thePattern,&nodeBeforeMatch,endSlot,TRUE); if (newNode == NULL) { newNode = CreateNewPatternNode(theEnv,thePattern,nodeBeforeMatch,lastLevel,endSlot,TRUE); } } /*===========================================================*/ /* Move on to the next field in the new pattern to be added. */ /*===========================================================*/ if ((thePattern->right == NULL) && (tempPattern != NULL)) { thePattern = tempPattern; tempPattern = NULL; } thePattern = thePattern->right; /*==========================================================*/ /* If there are no more pattern nodes to be added to the */ /* pattern network, then mark the last pattern node added */ /* as a stop node (i.e. if you get to this node and the */ /* network test succeeds, then a pattern has been matched). */ /*==========================================================*/ if (thePattern == NULL) newNode->header.stopNode = TRUE; /*================================================*/ /* Update the pointers which indicate where we're */ /* trying to add the new pattern to the currently */ /* existing pattern network. */ /*================================================*/ lastLevel = newNode; currentLevel = newNode->nextLevel; } /*==================================================*/ /* Return the leaf node of the newly added pattern. */ /*==================================================*/ return((struct patternNodeHeader *) newNode); }/*************************************************************//* FindPatternNode: Looks for a pattern node at a specified *//* level in the pattern network that can be reused (shared) *//* with a pattern field being added to the pattern network. *//*************************************************************/static struct factPatternNode *FindPatternNode( struct factPatternNode *listOfNodes, struct lhsParseNode *thePattern, struct factPatternNode **nodeBeforeMatch, unsigned endSlot, unsigned constantSelector) { struct expr *compareTest;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -