📄 rulecstr.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* RULE CONSTRAINTS MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provides routines for detecting constraint */
/* conflicts in the LHS and RHS of rules. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/*************************************************************/
#define _RULECSTR_SOURCE_
#include "setup.h"
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
#include <stdio.h>
#define _STDIO_INCLUDED_
#include "analysis.h"
#include "cstrnchk.h"
#include "cstrnops.h"
#include "cstrnutl.h"
#include "envrnmnt.h"
#include "extnfunc.h"
#include "prcdrpsr.h"
#include "reorder.h"
#include "router.h"
#include "rulepsr.h"
#include "rulecstr.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static intBool CheckForUnmatchableConstraints(void *,struct lhsParseNode *,int);
static intBool MultifieldCardinalityViolation(void *,struct lhsParseNode *);
static struct lhsParseNode *UnionVariableConstraints(void *,struct lhsParseNode *,
struct lhsParseNode *);
static struct lhsParseNode *AddToVariableConstraints(void *,struct lhsParseNode *,
struct lhsParseNode *);
static void ConstraintConflictMessage(void *,struct symbolHashNode *,
int,int,struct symbolHashNode *);
static intBool CheckArgumentForConstraintError(void *,struct expr *,struct expr*,
int,struct FunctionDefinition *,
struct lhsParseNode *);
/***********************************************************/
/* CheckForUnmatchableConstraints: Determines if a LHS CE */
/* node contains unmatchable constraints. Return TRUE if */
/* there are unmatchable constraints, otherwise FALSE. */
/***********************************************************/
static intBool CheckForUnmatchableConstraints(
void *theEnv,
struct lhsParseNode *theNode,
int whichCE)
{
if (EnvGetStaticConstraintChecking(theEnv) == FALSE) return(FALSE);
if (UnmatchableConstraint(theNode->constraints))
{
ConstraintConflictMessage(theEnv,(SYMBOL_HN *) theNode->value,whichCE,
theNode->index,theNode->slot);
return(TRUE);
}
return(FALSE);
}
/******************************************************/
/* ConstraintConflictMessage: Error message used when */
/* a constraint restriction for a slot prevents any */
/* value from matching the pattern constraint. */
/******************************************************/
static void ConstraintConflictMessage(
void *theEnv,
struct symbolHashNode *variableName,
int thePattern,
int theField,
struct symbolHashNode *theSlot)
{
/*=========================*/
/* Print the error header. */
/*=========================*/
PrintErrorID(theEnv,"RULECSTR",1,TRUE);
/*======================================================*/
/* Print the variable name (if available) and CE number */
/* for which the constraint violation occurred. */
/*======================================================*/
if (variableName != NULL)
{
EnvPrintRouter(theEnv,WERROR,"Variable ?");
EnvPrintRouter(theEnv,WERROR,ValueToString(variableName));
EnvPrintRouter(theEnv,WERROR," in CE #");
PrintLongInteger(theEnv,WERROR,(long int) thePattern);
}
else
{
EnvPrintRouter(theEnv,WERROR,"Pattern #");
PrintLongInteger(theEnv,WERROR,(long int) thePattern);
}
/*=======================================*/
/* Print the slot name or field position */
/* in which the violation occurred. */
/*=======================================*/
if (theSlot == NULL)
{
EnvPrintRouter(theEnv,WERROR," field #");
PrintLongInteger(theEnv,WERROR,(long int) theField);
}
else
{
EnvPrintRouter(theEnv,WERROR," slot ");
EnvPrintRouter(theEnv,WERROR,ValueToString(theSlot));
}
/*======================================*/
/* Print the rest of the error message. */
/*======================================*/
EnvPrintRouter(theEnv,WERROR,"\nhas constraint conflicts which make the pattern unmatchable.\n");
}
/***************************************************************/
/* MultifieldCardinalityViolation: Determines if a cardinality */
/* violation has occurred for a LHS CE node. */
/***************************************************************/
static intBool MultifieldCardinalityViolation(
void *theEnv,
struct lhsParseNode *theNode)
{
struct lhsParseNode *tmpNode;
struct expr *tmpMax;
long minFields = 0;
long maxFields = 0;
int posInfinity = FALSE;
CONSTRAINT_RECORD *newConstraint, *tempConstraint;
/*================================*/
/* A single field slot can't have */
/* a cardinality violation. */
/*================================*/
if (theNode->multifieldSlot == FALSE) return(FALSE);
/*=============================================*/
/* Determine the minimum and maximum number of */
/* fields the slot could contain based on the */
/* slot constraints found in the pattern. */
/*=============================================*/
for (tmpNode = theNode->bottom;
tmpNode != NULL;
tmpNode = tmpNode->right)
{
/*====================================================*/
/* A single field variable increases both the minimum */
/* and maximum number of fields by one. */
/*====================================================*/
if ((tmpNode->type == SF_VARIABLE) ||
(tmpNode->type == SF_WILDCARD))
{
minFields++;
maxFields++;
}
/*=================================================*/
/* Otherwise a multifield wildcard or variable has */
/* been encountered. If it is constrained then use */
/* minimum and maximum number of fields constraint */
/* associated with this LHS node. */
/*=================================================*/
else if (tmpNode->constraints != NULL)
{
/*=======================================*/
/* The lowest minimum of all the min/max */
/* pairs will be the first in the list. */
/*=======================================*/
if (tmpNode->constraints->minFields->value != SymbolData(theEnv)->NegativeInfinity)
{ minFields += ValueToLong(tmpNode->constraints->minFields->value); }
/*=========================================*/
/* The greatest maximum of all the min/max */
/* pairs will be the last in the list. */
/*=========================================*/
tmpMax = tmpNode->constraints->maxFields;
while (tmpMax->nextArg != NULL) tmpMax = tmpMax->nextArg;
if (tmpMax->value == SymbolData(theEnv)->PositiveInfinity)
{ posInfinity = TRUE; }
else
{ maxFields += ValueToLong(tmpMax->value); }
}
/*================================================*/
/* Otherwise an unconstrained multifield wildcard */
/* or variable increases the maximum number of */
/* fields to positive infinity. */
/*================================================*/
else
{ posInfinity = TRUE; }
}
/*==================================================================*/
/* Create a constraint record for the cardinality of the sum of the */
/* cardinalities of the restrictions inside the multifield slot. */
/*==================================================================*/
if (theNode->constraints == NULL) tempConstraint = GetConstraintRecord(theEnv);
else tempConstraint = CopyConstraintRecord(theEnv,theNode->constraints);
ReturnExpression(theEnv,tempConstraint->minFields);
ReturnExpression(theEnv,tempConstraint->maxFields);
tempConstraint->minFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long) minFields));
if (posInfinity) tempConstraint->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
else tempConstraint->maxFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long) maxFields));
/*================================================================*/
/* Determine the final cardinality for the multifield slot by */
/* intersecting the cardinality sum of the restrictions within */
/* the multifield slot with the original cardinality of the slot. */
/*================================================================*/
newConstraint = IntersectConstraints(theEnv,theNode->constraints,tempConstraint);
if (theNode->derivedConstraints) RemoveConstraint(theEnv,theNode->constraints);
RemoveConstraint(theEnv,tempConstraint);
theNode->constraints = newConstraint;
theNode->derivedConstraints = TRUE;
/*===================================================================*/
/* Determine if the final cardinality for the slot can be satisfied. */
/*===================================================================*/
if (EnvGetStaticConstraintChecking(theEnv) == FALSE) return(FALSE);
if (UnmatchableConstraint(newConstraint)) return(TRUE);
return(FALSE);
}
/***************************************************/
/* ProcessConnectedConstraints: Examines a single */
/* connected constraint searching for constraint */
/* violations. */
/***************************************************/
globle intBool ProcessConnectedConstraints(
void *theEnv,
struct lhsParseNode *theNode,
struct lhsParseNode *multifieldHeader,
struct lhsParseNode *patternHead)
{
struct constraintRecord *orConstraints = NULL, *andConstraints;
struct constraintRecord *tmpConstraints, *rvConstraints;
struct lhsParseNode *orNode, *andNode;
struct expr *tmpExpr;
/*============================================*/
/* Loop through all of the or (|) constraints */
/* found in the connected constraint. */
/*============================================*/
for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom)
{
/*=================================================*/
/* Intersect all of the &'ed constraints together. */
/*=================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -