📄 cstrnchk.c
字号:
/* If the value wasn't found in the list, then return */ /* FALSE because the constraint has been violated. */ /*====================================================*/ return(CLIPS_FALSE); }/*************************************************************//* CheckRangeConstraint: Determines if a primitive data type *//* satisfies the range constraint of a constraint record. *//*************************************************************/static BOOLEAN CheckRangeConstraint(type,vPtr,constraints) int type; VOID *vPtr; CONSTRAINT_RECORD *constraints; { struct expr *minList, *maxList; /*===================================*/ /* If the constraint record is NULL, */ /* there are no range restrictions. */ /*===================================*/ if (constraints == NULL) return(CLIPS_TRUE); /*============================================*/ /* If the value being checked isn't a number, */ /* then the range restrictions don't apply. */ /*============================================*/ if ((type != INTEGER) && (type != FLOAT)) return(CLIPS_TRUE); /*=====================================================*/ /* Check each of the range restrictions to see if the */ /* number falls within at least one of the allowed */ /* ranges. If it falls within one of the ranges, then */ /* return TRUE since the constraint is satisifed. */ /*=====================================================*/ minList = constraints->minValue; maxList = constraints->maxValue; while (minList != NULL) { if (CompareNumbers(type,vPtr,minList->type,minList->value) == LESS_THAN) { minList = minList->nextArg; maxList = maxList->nextArg; } else if (CompareNumbers(type,vPtr,maxList->type,maxList->value) == GREATER_THAN) { minList = minList->nextArg; maxList = maxList->nextArg; } else { return(CLIPS_TRUE); } } /*===========================================*/ /* Return FALSE since the number didn't fall */ /* within one of the allowed numeric ranges. */ /*===========================================*/ return(CLIPS_FALSE); } /************************************************//* ConstraintViolationErrorMessage: Generalized *//* error message for constraint violations. *//************************************************/globle VOID ConstraintViolationErrorMessage(theWhat,thePlace,command,thePattern, theSlot,theField,violationType, theConstraint,printPrelude) char *theWhat; char *thePlace; int command; int thePattern; struct symbolHashNode *theSlot; int theField; int violationType; CONSTRAINT_RECORD *theConstraint; int printPrelude; { /*======================================================*/ /* Don't print anything other than the tail explanation */ /* of the error unless asked to do so. */ /*======================================================*/ if (printPrelude) { /*===================================*/ /* Print the name of the thing which */ /* caused the constraint violation. */ /*===================================*/ if (violationType == FUNCTION_RETURN_TYPE_VIOLATION) { PrintErrorID("CSTRNCHK",1,CLIPS_TRUE); PrintCLIPS(WERROR,"The function return value "); } else if (theWhat != NULL) { PrintErrorID("CSTRNCHK",1,CLIPS_TRUE); PrintCLIPS(WERROR,theWhat); PrintCLIPS(WERROR," "); } /*=======================================*/ /* Print the location of the thing which */ /* caused the constraint violation. */ /*=======================================*/ if (thePlace != NULL) { PrintCLIPS(WERROR,"found in "); if (command) PrintCLIPS(WERROR,"the "); PrintCLIPS(WERROR,thePlace); if (command) PrintCLIPS(WERROR," command"); } /*================================================*/ /* If the violation occured in the LHS of a rule, */ /* indicate which pattern was at fault. */ /*================================================*/ if (thePattern > 0) { PrintCLIPS(WERROR,"found in CE #"); PrintLongInteger(WERROR,(long int) thePattern); } } /*===============================================================*/ /* Indicate the type of constraint violation (type, range, etc). */ /*===============================================================*/ if ((violationType == TYPE_VIOLATION) || (violationType == FUNCTION_RETURN_TYPE_VIOLATION)) { PrintCLIPS(WERROR,"\ndoes not match the allowed types"); } else if (violationType == RANGE_VIOLATION) { PrintCLIPS(WERROR,"\ndoes not fall in the allowed range "); PrintRange(WERROR,theConstraint); } else if (violationType == ALLOWED_VALUES_VIOLATION) { PrintCLIPS(WERROR,"\ndoes not match the allowed values"); } else if (violationType == CARDINALITY_VIOLATION) { PrintCLIPS(WERROR,"\ndoes not satisfy the cardinality restrictions"); } /*==============================================*/ /* Print either the slot name or field position */ /* where the constraint violation occured. */ /*==============================================*/ if (theSlot != NULL) { PrintCLIPS(WERROR," for slot "); PrintCLIPS(WERROR,ValueToString(theSlot)); } else if (theField > 0) { PrintCLIPS(WERROR," for field #"); PrintLongInteger(WERROR,(long) theField); } PrintCLIPS(WERROR,".\n"); }/********************************************************************//* PrintRange: Prints the range restriction of a constraint record. *//* For example, 8 to +00 (eight to positive infinity). *//********************************************************************/static VOID PrintRange(logicalName,theConstraint) char *logicalName; CONSTRAINT_RECORD *theConstraint; { if (theConstraint->minValue->value == NegativeInfinity) { PrintCLIPS(logicalName,ValueToString(NegativeInfinity)); } else PrintExpression(logicalName,theConstraint->minValue); PrintCLIPS(logicalName," to "); if (theConstraint->maxValue->value == PositiveInfinity) { PrintCLIPS(logicalName,ValueToString(PositiveInfinity)); } else PrintExpression(logicalName,theConstraint->maxValue); } /*************************************************************//* ConstraintCheckDataObject: Given a value stored in a data *//* object structure and a constraint record, determines if *//* the data object satisfies the constraint record. *//*************************************************************/globle int ConstraintCheckDataObject(theData,theConstraints) DATA_OBJECT *theData; CONSTRAINT_RECORD *theConstraints; { long i; /* 6.04 Bug Fix */ int rv; struct field *theMultifield; if (theConstraints == NULL) return(NO_VIOLATION); if (theData->type == MULTIFIELD) { if (CheckCardinalityConstraint((theData->end - theData->begin) + 1, theConstraints) == CLIPS_FALSE) { return(CARDINALITY_VIOLATION); } theMultifield = ((struct multifield *) theData->value)->theFields; for (i = theData->begin; i <= theData->end; i++) { if ((rv = ConstraintCheckValue(theMultifield[i].type, theMultifield[i].value, theConstraints)) != NO_VIOLATION) { return(rv); } } return(NO_VIOLATION); } if (CheckCardinalityConstraint(1L,theConstraints) == CLIPS_FALSE) { return(CARDINALITY_VIOLATION); } return(ConstraintCheckValue(theData->type,theData->value,theConstraints)); } /****************************************************************//* ConstraintCheckValue: Given a value and a constraint record, *//* determines if the value satisfies the constraint record. *//****************************************************************/globle int ConstraintCheckValue(theType,theValue,theConstraints) int theType; VOID *theValue; CONSTRAINT_RECORD *theConstraints; { if (CheckTypeConstraint(theType,theConstraints) == CLIPS_FALSE) { return(TYPE_VIOLATION); } else if (CheckAllowedValuesConstraint(theType,theValue,theConstraints) == CLIPS_FALSE) { return(ALLOWED_VALUES_VIOLATION); } else if (CheckRangeConstraint(theType,theValue,theConstraints) == CLIPS_FALSE) { return(RANGE_VIOLATION); } else if (theType == FCALL) { if (CheckFunctionReturnType((int) ValueFunctionType(theValue),theConstraints) == CLIPS_FALSE) { return(FUNCTION_RETURN_TYPE_VIOLATION); } } return(NO_VIOLATION); }/********************************************************************//* ConstraintCheckExpressionChain: Checks an expression and nextArg *//* links for constraint conflicts (argList is not followed). *//********************************************************************/globle int ConstraintCheckExpressionChain(theExpression,theConstraints) struct expr *theExpression; CONSTRAINT_RECORD *theConstraints; { struct expr *exp; int min = 0, max = 0, vCode; /*===========================================================*/ /* Determine the minimum and maximum number of value which */ /* can be derived from the expression chain (max of -1 means */ /* positive infinity). */ /*===========================================================*/ for (exp = theExpression ; exp != NULL ; exp = exp->nextArg) { if (ConstantType(exp->type)) min++; else if (exp->type == FCALL) { if ((ExpressionFunctionType(exp) != 'm') && (ExpressionFunctionType(exp) != 'u')) min++; else max = -1; } else max = -1; } /*====================================*/ /* Check for a cardinality violation. */ /*====================================*/ if (max == 0) max = min; if (CheckRangeAgainstCardinalityConstraint(min,max,theConstraints) == CLIPS_FALSE) { return(CARDINALITY_VIOLATION); } /*========================================*/ /* Check for other constraint violations. */ /*========================================*/ for (exp = theExpression ; exp != NULL ; exp = exp->nextArg) { vCode = ConstraintCheckValue(exp->type,exp->value,theConstraints); if (vCode != NO_VIOLATION) return(vCode); } return(NO_VIOLATION); } #if (! RUN_TIME) && (! BLOAD_ONLY)/***************************************************//* ConstraintCheckExpression: Checks an expression *//* for constraint conflicts. Returns TRUE if *//* conflicts are found, otherwise FALSE. *//***************************************************/globle int ConstraintCheckExpression(theExpression,theConstraints) struct expr *theExpression; CONSTRAINT_RECORD *theConstraints; { int rv = NO_VIOLATION; if (theConstraints == NULL) return(rv); while (theExpression != NULL) { rv = ConstraintCheckValue(theExpression->type, theExpression->value, theConstraints); if (rv != NO_VIOLATION) return(rv); rv = ConstraintCheckExpression(theExpression->argList,theConstraints); if (rv != NO_VIOLATION) return(rv); theExpression = theExpression->nextArg; } return(rv); }#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */#if (! RUN_TIME) /*****************************************************//* UnmatchableConstraint: Determines if a constraint *//* record can still be satisfied by some value. *//*****************************************************/globle BOOLEAN UnmatchableConstraint(theConstraint) CONSTRAINT_RECORD *theConstraint; { if (theConstraint == NULL) return(CLIPS_FALSE); if ((! theConstraint->anyAllowed) && (! theConstraint->symbolsAllowed) && (! theConstraint->stringsAllowed) && (! theConstraint->floatsAllowed) && (! theConstraint->integersAllowed) && (! theConstraint->instanceNamesAllowed) && (! theConstraint->instanceAddressesAllowed) && (! theConstraint->multifieldsAllowed) && (! theConstraint->externalAddressesAllowed) && (! theConstraint->factAddressesAllowed)) { return(CLIPS_TRUE); } return(CLIPS_FALSE); } #endif /* (! RUN_TIME) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -