📄 cstrnops.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* CONSTRAINT OPERATIONS MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides functions for performing operations on *//* constraint records including computing the intersection *//* and union of constraint records. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _CSTRNOPS_SOURCE_#include "setup.h"#include <stdio.h>#define _CLIPS_STDIO_#if ANSI_COMPILER#include <stdlib.h>#endif#if (! RUN_TIME)#include "constant.h"#include "clipsmem.h"#include "router.h"#include "extnfunc.h"#include "scanner.h"#include "multifld.h"#include "constrnt.h"#include "cstrnchk.h"#include "cstrnutl.h"#include "cstrnops.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static VOID IntersectNumericExpressions(CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *,int); static VOID IntersectAllowedValueExpressions(CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static int FindItemInExpression(int,VOID *,int,struct expr *); static VOID UpdateRestrictionFlags(CONSTRAINT_RECORD *);#if (! BLOAD_ONLY) static VOID UnionRangeMinMaxValueWithList(struct expr *, struct expr *, struct expr **, struct expr **); static VOID UnionNumericExpressions(CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *,int); static struct expr *AddToUnionList(struct expr *,struct expr *, CONSTRAINT_RECORD *); static VOID UnionAllowedValueExpressions(CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static int RestrictionOnType(int,CONSTRAINT_RECORD *);#endif#else static VOID IntersectNumericExpressions(); static VOID IntersectAllowedValueExpressions(); static int FindItemInExpression(); static VOID UpdateRestrictionFlags();#if (! BLOAD_ONLY) static VOID UnionRangeMinMaxValueWithList(); static VOID UnionNumericExpressions(); static struct expr *AddToUnionList(); static VOID UnionAllowedValueExpressions(); static int RestrictionOnType();#endif#endif /**************************************************************//* IntersectConstraints: Creates a new constraint record that *//* is the intersection of two other constraint records. *//**************************************************************/globle struct constraintRecord *IntersectConstraints(c1,c2) CONSTRAINT_RECORD *c1, *c2; { struct constraintRecord *rv; int c1Changed = CLIPS_FALSE, c2Changed = CLIPS_FALSE; /*=================================================*/ /* If both constraint records are NULL,then create */ /* a constraint record that allows any value. */ /*=================================================*/ if ((c1 == NULL) && (c2 == NULL)) { rv = GetConstraintRecord(); rv->multifieldsAllowed = CLIPS_TRUE; return(rv); } /*=================================================*/ /* If one of the constraint records is NULL, then */ /* the intersection is the other constraint record */ /* (a NULL value means no constraints). */ /*=================================================*/ if (c1 == NULL) return(CopyConstraintRecord(c2)); if (c2 == NULL) return(CopyConstraintRecord(c1)); /*=================================*/ /* Create a new constraint record. */ /*=================================*/ rv = GetConstraintRecord(); /*==============================*/ /* Intersect the allowed types. */ /*==============================*/ if ((c1->multifieldsAllowed != c2->multifieldsAllowed) && (c1->singlefieldsAllowed != c2->singlefieldsAllowed)) { rv->anyAllowed = CLIPS_FALSE; return(rv); } if (c1->multifieldsAllowed && c2->multifieldsAllowed) { rv->multifieldsAllowed = CLIPS_TRUE; } else { rv->multifieldsAllowed = CLIPS_FALSE; } if (c1->singlefieldsAllowed && c2->singlefieldsAllowed) { rv->singlefieldsAllowed = CLIPS_TRUE; } else { rv->singlefieldsAllowed = CLIPS_FALSE; } if (c1->anyAllowed && c2->anyAllowed) rv->anyAllowed = CLIPS_TRUE; else { if (c1->anyAllowed) { c1Changed = CLIPS_TRUE; SetAnyAllowedFlags(c1,CLIPS_FALSE); } else if (c2->anyAllowed) { c2Changed = CLIPS_TRUE; SetAnyAllowedFlags(c2,CLIPS_FALSE); } rv->anyAllowed = CLIPS_FALSE; rv->symbolsAllowed = (c1->symbolsAllowed && c2->symbolsAllowed); rv->stringsAllowed = (c1->stringsAllowed && c2->stringsAllowed); rv->floatsAllowed = (c1->floatsAllowed && c2->floatsAllowed); rv->integersAllowed = (c1->integersAllowed && c2->integersAllowed); rv->instanceNamesAllowed = (c1->instanceNamesAllowed && c2->instanceNamesAllowed); rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed && c2->instanceAddressesAllowed); rv->externalAddressesAllowed = (c1->externalAddressesAllowed && c2->externalAddressesAllowed); rv->multifieldsAllowed = (c1->multifieldsAllowed && c2->multifieldsAllowed); rv->factAddressesAllowed = (c1->factAddressesAllowed && c2->factAddressesAllowed); if (c1Changed) SetAnyAllowedFlags(c1,CLIPS_TRUE); if (c2Changed) SetAnyAllowedFlags(c2,CLIPS_TRUE); } /*=====================================*/ /* Intersect the allowed-values flags. */ /*=====================================*/ if (c1->anyRestriction || c2->anyRestriction) rv->anyRestriction = CLIPS_TRUE; else { rv->anyRestriction = CLIPS_FALSE; rv->symbolRestriction = (c1->symbolRestriction || c2->symbolRestriction); rv->stringRestriction = (c1->stringRestriction || c2->stringRestriction); rv->floatRestriction = (c1->floatRestriction || c2->floatRestriction); rv->integerRestriction = (c1->integerRestriction || c2->integerRestriction); rv->instanceNameRestriction = (c1->instanceNameRestriction || c2->instanceNameRestriction); } /*============================================*/ /* Intersect the allowed values list, the min */ /* and max values, and the range values. */ /*============================================*/ IntersectAllowedValueExpressions(c1,c2,rv); IntersectNumericExpressions(c1,c2,rv,CLIPS_TRUE); IntersectNumericExpressions(c1,c2,rv,CLIPS_FALSE); /*==========================================*/ /* Update the allowed-values flags based on */ /* the previous intersection for allowed, */ /* min and max, and range values. */ /*==========================================*/ UpdateRestrictionFlags(rv); /*============================================*/ /* If multifields are allowed, then intersect */ /* the constraint record for them. */ /*============================================*/ if (rv->multifieldsAllowed) { rv->multifield = IntersectConstraints(c1->multifield,c2->multifield); if (UnmatchableConstraint(rv->multifield)) { rv->multifieldsAllowed = CLIPS_FALSE; } } /*========================*/ /* Return the intersected */ /* constraint record. */ /*========================*/ return(rv); } /*************************************************//* IntersectAllowedValueExpressions: Creates the *//* intersection of two allowed-values lists. *//*************************************************/static VOID IntersectAllowedValueExpressions(constraint1,constraint2,newConstraint) CONSTRAINT_RECORD *constraint1, *constraint2, *newConstraint; { struct expr *theList1, *theList2; struct expr *theHead = NULL, *tmpExpr; /*===========================================*/ /* Loop through each value in allowed-values */ /* list of the first constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*===========================================*/ for (theList1 = constraint1->restrictionList; theList1 != NULL; theList1 = theList1->nextArg) { if (CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint1) && CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint2)) { tmpExpr = GenConstant(theList1->type,theList1->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*===========================================*/ /* Loop through each value in allowed-values */ /* list of the second constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*===========================================*/ for (theList2 = constraint2->restrictionList; theList2 != NULL; theList2 = theList2->nextArg) { if (FindItemInExpression(theList2->type,theList2->value,CLIPS_TRUE,theHead)) { /* The value is already in the list--Do nothing */ } else if (CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint1) && CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint2)) { tmpExpr = GenConstant(theList2->type,theList2->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*================================================*/ /* Set the allowed values list for the constraint */ /* record to the intersected values of the two */ /* other constraint records. */ /*================================================*/ newConstraint->restrictionList = theHead; } /*********************************************************//* IntersectNumericExpressions: Creates the intersection *//* of two range or two min/max-fields constraints. *//*********************************************************/static VOID IntersectNumericExpressions(constraint1,constraint2,newConstraint,range) CONSTRAINT_RECORD *constraint1, *constraint2, *newConstraint; int range; { struct expr *tmpmin1, *tmpmax1, *tmpmin2, *tmpmax2, *theMin, *theMax; struct expr *theMinList, *theMaxList, *lastMin = NULL, *lastMax = NULL; int cmaxmax, cminmin, cmaxmin, cminmax; /*==========================================*/ /* Initialize the new range/min/max values */ /* for the intersection of the constraints. */ /*==========================================*/ theMinList = NULL; theMaxList = NULL; /*=================================*/ /* Determine the min/max values of */ /* the first constraint record. */ /*=================================*/ if (range) { tmpmin1 = constraint1->minValue; tmpmax1 = constraint1->maxValue; } else { tmpmin1 = constraint1->minFields; tmpmax1 = constraint1->maxFields; } /*===========================================*/ /* Loop through each of range/min/max values */ /* from the first constraint record. */ /*===========================================*/ for (; tmpmin1 != NULL; tmpmin1 = tmpmin1->nextArg, tmpmax1 = tmpmax1->nextArg) { /*============================================*/ /* Get the appropriate values from the second */ /* constraint record for comparison. */ /*============================================*/ if (range) { tmpmin2 = constraint2->minValue; tmpmax2 = constraint2->maxValue; } else { tmpmin2 = constraint2->minFields; tmpmax2 = constraint2->maxFields; } /*================================================*/ /* Loop through each of range/min/max values from */ /* the second constraint record comparing it to */ /* the values from the first constraint record. */ /*================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -