static int CheckForVariableMixing( struct lhsParseNode *theRestriction) { struct lhsParseNode *tempRestriction; CONSTRAINT_RECORD *theConstraint; int multifield = FALSE; int singlefield = FALSE; int constant = FALSE; int singleReturnValue = FALSE; int multiReturnValue = FALSE; /*================================================*/ /* If the constraint contains a binding variable, */ /* determine whether it is a single field or */ /* multifield variable. */ /*================================================*/ if (theRestriction->type == SF_VARIABLE) singlefield = TRUE; else if (theRestriction->type == MF_VARIABLE) multifield = TRUE; /*===========================================*/ /* Loop through each of the or (|) connected */ /* constraints within the constraint. */ /*===========================================*/ for (theRestriction = theRestriction->bottom; theRestriction != NULL; theRestriction = theRestriction->bottom) { /*============================================*/ /* Loop through each of the and (&) connected */ /* constraints within the or (|) constraint. */ /*============================================*/ for (tempRestriction = theRestriction; tempRestriction != NULL; tempRestriction = tempRestriction->right) { /*=====================================================*/ /* Determine if the constraint contains a single field */ /* variable, multifield variable, constant (a single */ /* field), a return value constraint of a function */ /* returning a single field value, or a return value */ /* constraint of a function returning a multifield */ /* value. */ /*=====================================================*/ if (tempRestriction->type == SF_VARIABLE) singlefield = TRUE; else if (tempRestriction->type == MF_VARIABLE) multifield = TRUE; else if (ConstantType(tempRestriction->type)) constant = TRUE; else if (tempRestriction->type == RETURN_VALUE_CONSTRAINT) { theConstraint = FunctionCallToConstraintRecord(tempRestriction->expression->value); if (theConstraint->anyAllowed) { /* Do nothing. */ } else if (theConstraint->multifieldsAllowed) multiReturnValue = TRUE; else singleReturnValue = TRUE; RemoveConstraint(theConstraint); } } } /*================================================================*/ /* Using a single field value (a single field variable, constant, */ /* or function returning a single field value) together with a */ /* multifield value (a multifield variable or function returning */ /* a multifield value) is illegal. Return TRUE if this occurs. */ /*================================================================*/ if ((singlefield || constant || singleReturnValue) && (multifield || multiReturnValue)) { PrintErrorID("PATTERN",2,TRUE); PrintRouter(WERROR,"Single and multifield constraints cannot be mixed in a field constraint\n"); return(TRUE); } /*=======================================*/ /* Otherwise return FALSE to indicate no */ /* illegal variable mixing was detected. */ /*=======================================*/ return(FALSE); }
globle BOOLEAN ProcessConnectedConstraints( 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. */ /*=================================================*/ andConstraints = NULL; for (andNode = orNode; andNode != NULL; andNode = andNode->right) { if (! andNode->negated) { if (andNode->type == RETURN_VALUE_CONSTRAINT) { if (andNode->expression->type == FCALL) { rvConstraints = FunctionCallToConstraintRecord(andNode->expression->value); tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,rvConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(rvConstraints); } } else if (ConstantType(andNode->type)) { tmpExpr = GenConstant(andNode->type,andNode->value); rvConstraints = ExpressionToConstraintRecord(tmpExpr); tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,rvConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(rvConstraints); ReturnExpression(tmpExpr); } else if (andNode->constraints != NULL) { tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,andNode->constraints); RemoveConstraint(tmpConstraints); } } } /*===========================================================*/ /* Intersect the &'ed constraints with the slot constraints. */ /*===========================================================*/ tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,theNode->constraints); RemoveConstraint(tmpConstraints); /*===============================================================*/ /* Remove any negated constants from the list of allowed values. */ /*===============================================================*/ for (andNode = orNode; andNode != NULL; andNode = andNode->right) { if ((andNode->negated) && ConstantType(andNode->type)) { RemoveConstantFromConstraint(andNode->type,andNode->value,andConstraints); } } /*=======================================================*/ /* Union the &'ed constraints with the |'ed constraints. */ /*=======================================================*/ tmpConstraints = orConstraints; orConstraints = UnionConstraints(orConstraints,andConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(andConstraints); } /*===============================================*/ /* Replace the constraints for the slot with the */ /* constraints derived from the connected */ /* constraints (which should be a subset. */ /*===============================================*/ if (orConstraints != NULL) { if (theNode->derivedConstraints) RemoveConstraint(theNode->constraints); theNode->constraints = orConstraints; theNode->derivedConstraints = TRUE; } /*==================================*/ /* Check for constraint violations. */ /*==================================*/ if (CheckForUnmatchableConstraints(theNode,(int) patternHead->whichCE)) { return(TRUE); } /*=========================================*/ /* If the constraints are for a multifield */ /* slot, check for cardinality violations. */ /*=========================================*/ if ((multifieldHeader != NULL) && (theNode->right == NULL)) { if (MultifieldCardinalityViolation(multifieldHeader)) { ConstraintViolationErrorMessage("The group of restrictions", NULL,FALSE, (int) patternHead->whichCE, multifieldHeader->slot, multifieldHeader->index, CARDINALITY_VIOLATION, multifieldHeader->constraints,TRUE); return(TRUE); } } /*=======================================*/ /* Return FALSE indicating no constraint */ /* violations were detected. */ /*=======================================*/ return(FALSE); }
globle CONSTRAINT_RECORD *ExpressionToConstraintRecord( void *theEnv, EXEC_STATUS, struct expr *theExpression) { CONSTRAINT_RECORD *rv; /*================================================*/ /* A NULL expression is converted to a constraint */ /* record with no values allowed. */ /*================================================*/ if (theExpression == NULL) { rv = GetConstraintRecord(theEnv,execStatus); rv->anyAllowed = FALSE; return(rv); } /*=============================================================*/ /* Convert variables and function calls to constraint records. */ /*=============================================================*/ if ((theExpression->type == SF_VARIABLE) || (theExpression->type == MF_VARIABLE) || #if DEFGENERIC_CONSTRUCT (theExpression->type == GCALL) || #endif #if DEFFUNCTION_CONSTRUCT (theExpression->type == PCALL) || #endif (theExpression->type == GBL_VARIABLE) || (theExpression->type == MF_GBL_VARIABLE)) { rv = GetConstraintRecord(theEnv,execStatus); rv->multifieldsAllowed = TRUE; return(rv); } else if (theExpression->type == FCALL) { return(FunctionCallToConstraintRecord(theEnv,execStatus,theExpression->value)); } /*============================================*/ /* Convert a constant to a constraint record. */ /*============================================*/ rv = GetConstraintRecord(theEnv,execStatus); rv->anyAllowed = FALSE; if (theExpression->type == FLOAT) { rv->floatRestriction = TRUE; rv->floatsAllowed = TRUE; } else if (theExpression->type == INTEGER) { rv->integerRestriction = TRUE; rv->integersAllowed = TRUE; } else if (theExpression->type == SYMBOL) { rv->symbolRestriction = TRUE; rv->symbolsAllowed = TRUE; } else if (theExpression->type == STRING) { rv->stringRestriction = TRUE; rv->stringsAllowed = TRUE; } else if (theExpression->type == INSTANCE_NAME) { rv->instanceNameRestriction = TRUE; rv->instanceNamesAllowed = TRUE; } else if (theExpression->type == INSTANCE_ADDRESS) { rv->instanceAddressesAllowed = TRUE; } if (rv->floatsAllowed || rv->integersAllowed || rv->symbolsAllowed || rv->stringsAllowed || rv->instanceNamesAllowed) { rv->restrictionList = GenConstant(theEnv,execStatus,theExpression->type,theExpression->value); } return(rv); }
static bool CheckForVariableMixing( Environment *theEnv, struct lhsParseNode *theRestriction) { struct lhsParseNode *tempRestriction; CONSTRAINT_RECORD *theConstraint; bool multifield = false; bool singlefield = false; bool constant = false; bool singleReturnValue = false; bool multiReturnValue = false; /*================================================*/ /* If the constraint contains a binding variable, */ /* determine whether it is a single field or */ /* multifield variable. */ /*================================================*/ if (theRestriction->pnType == SF_VARIABLE_NODE) singlefield = true; else if (theRestriction->pnType == MF_VARIABLE_NODE) multifield = true; /*===========================================*/ /* Loop through each of the or (|) connected */ /* constraints within the constraint. */ /*===========================================*/ for (theRestriction = theRestriction->bottom; theRestriction != NULL; theRestriction = theRestriction->bottom) { /*============================================*/ /* Loop through each of the and (&) connected */ /* constraints within the or (|) constraint. */ /*============================================*/ for (tempRestriction = theRestriction; tempRestriction != NULL; tempRestriction = tempRestriction->right) { /*=====================================================*/ /* Determine if the constraint contains a single field */ /* variable, multifield variable, constant (a single */ /* field), a return value constraint of a function */ /* returning a single field value, or a return value */ /* constraint of a function returning a multifield */ /* value. */ /*=====================================================*/ if (tempRestriction->pnType == SF_VARIABLE_NODE) singlefield = true; else if (tempRestriction->pnType == MF_VARIABLE_NODE) multifield = true; else if (ConstantNode(tempRestriction)) constant = true; else if (tempRestriction->pnType == RETURN_VALUE_CONSTRAINT_NODE) { theConstraint = FunctionCallToConstraintRecord(theEnv,tempRestriction->expression->value); if (theConstraint->anyAllowed) { /* Do nothing. */ } else if (theConstraint->multifieldsAllowed) multiReturnValue = true; else singleReturnValue = true; RemoveConstraint(theEnv,theConstraint); } } } /*================================================================*/ /* Using a single field value (a single field variable, constant, */ /* or function returning a single field value) together with a */ /* multifield value (a multifield variable or function returning */ /* a multifield value) is illegal. Return true if this occurs. */ /*================================================================*/ if ((singlefield || constant || singleReturnValue) && (multifield || multiReturnValue)) { PrintErrorID(theEnv,"PATTERN",2,true); WriteString(theEnv,STDERR,"Single and multifield constraints cannot be mixed in a field constraint.\n"); return true; } /*=======================================*/ /* Otherwise return false to indicate no */ /* illegal variable mixing was detected. */ /*=======================================*/ return false; }