static int AddBindName( void *theEnv, SYMBOL_HN *variableName, CONSTRAINT_RECORD *theConstraint) { CONSTRAINT_RECORD *tmpConstraint; struct BindInfo *currentBind, *lastBind; int theIndex = 1; /*=========================================================*/ /* Look for the variable name in the list of bind variable */ /* names already parsed. If it is found, then return the */ /* index to the variable and union the new constraint */ /* information with the old constraint information. */ /*=========================================================*/ lastBind = NULL; currentBind = ProcedureParserData(theEnv)->ListOfParsedBindNames; while (currentBind != NULL) { if (currentBind->name == variableName) { if (theConstraint != NULL) { tmpConstraint = currentBind->constraints; currentBind->constraints = UnionConstraints(theEnv,theConstraint,currentBind->constraints); RemoveConstraint(theEnv,tmpConstraint); RemoveConstraint(theEnv,theConstraint); } return(theIndex); } lastBind = currentBind; currentBind = currentBind->next; theIndex++; } /*===============================================================*/ /* If the variable name wasn't found, then add it to the list of */ /* variable names and store the constraint information with it. */ /*===============================================================*/ currentBind = get_struct(theEnv,BindInfo); currentBind->name = variableName; currentBind->constraints = theConstraint; currentBind->next = NULL; if (lastBind == NULL) ProcedureParserData(theEnv)->ListOfParsedBindNames = currentBind; else lastBind->next = currentBind; return(theIndex); }
globle int CheckArgumentAgainstRestriction( struct expr *theExpression, int theRestriction) { CONSTRAINT_RECORD *cr1, *cr2, *cr3; /*=============================================*/ /* Generate a constraint record for the actual */ /* argument passed to the function. */ /*=============================================*/ cr1 = ExpressionToConstraintRecord(theExpression); /*================================================*/ /* Generate a constraint record based on the type */ /* of argument expected by the function. */ /*================================================*/ cr2 = ArgumentTypeToConstraintRecord(theRestriction); /*===============================================*/ /* Intersect the two constraint records and then */ /* discard them. */ /*===============================================*/ cr3 = IntersectConstraints(cr1,cr2); RemoveConstraint(cr1); RemoveConstraint(cr2); /*====================================================*/ /* If the intersection of the two constraint records */ /* is empty, then the argument passed to the function */ /* doesn't satisfy the restrictions for the argument. */ /*====================================================*/ if (UnmatchableConstraint(cr3)) { RemoveConstraint(cr3); return(TRUE); } /*===================================================*/ /* The argument satisfies the function restrictions. */ /*===================================================*/ RemoveConstraint(cr3); return(FALSE); }
/*************************************************** NAME : DeleteSlots DESCRIPTION : Deallocates a list of slots and their values INPUTS : The address of the slot list RETURNS : Nothing useful SIDE EFFECTS : The slot list is destroyed NOTES : None ***************************************************/ globle void DeleteSlots( void *theEnv, EXEC_STATUS, TEMP_SLOT_LINK *slots) { TEMP_SLOT_LINK *stmp; while (slots != NULL) { stmp = slots; slots = slots->nxt; DeleteSlotName(theEnv,execStatus,stmp->desc->slotName); DecrementSymbolCount(theEnv,execStatus,stmp->desc->overrideMessage); RemoveConstraint(theEnv,execStatus,stmp->desc->constraint); if (stmp->desc->dynamicDefault == 1) { ExpressionDeinstall(theEnv,execStatus,(EXPRESSION *) stmp->desc->defaultValue); ReturnPackedExpression(theEnv,execStatus,(EXPRESSION *) stmp->desc->defaultValue); } else if (stmp->desc->defaultValue != NULL) { ValueDeinstall(theEnv,execStatus,(DATA_OBJECT *) stmp->desc->defaultValue); rtn_struct(theEnv,execStatus,dataObject,stmp->desc->defaultValue); } rtn_struct(theEnv,execStatus,slotDescriptor,stmp->desc); rtn_struct(theEnv,execStatus,tempSlotLink,stmp); } }
/*************************************************** NAME : DeleteSlots DESCRIPTION : Deallocates a list of slots and their values INPUTS : The address of the slot list RETURNS : Nothing useful SIDE EFFECTS : The slot list is destroyed NOTES : None ***************************************************/ void DeleteSlots( Environment *theEnv, TEMP_SLOT_LINK *slots) { TEMP_SLOT_LINK *stmp; while (slots != NULL) { stmp = slots; slots = slots->nxt; DeleteSlotName(theEnv,stmp->desc->slotName); ReleaseLexeme(theEnv,stmp->desc->overrideMessage); RemoveConstraint(theEnv,stmp->desc->constraint); if (stmp->desc->dynamicDefault == 1) { ExpressionDeinstall(theEnv,(Expression *) stmp->desc->defaultValue); ReturnPackedExpression(theEnv,(Expression *) stmp->desc->defaultValue); } else if (stmp->desc->defaultValue != NULL) { ReleaseUDFV(theEnv,(UDFValue *) stmp->desc->defaultValue); rtn_struct(theEnv,udfValue,stmp->desc->defaultValue); } rtn_struct(theEnv,slotDescriptor,stmp->desc); rtn_struct(theEnv,tempSlotLink,stmp); } }
/******************************************************************* NAME : ParseRestrictionType DESCRIPTION : Takes a string of type character codes (as given in DefineFunction2()) and converts it into a method restriction structure INPUTS : The type character code RETURNS : The restriction SIDE EFFECTS : Restriction allocated NOTES : None *******************************************************************/ static RESTRICTION *ParseRestrictionType( void *theEnv, int code) { RESTRICTION *rptr; CONSTRAINT_RECORD *rv; EXPRESSION *types = NULL; rptr = get_struct(theEnv,restriction); rptr->query = NULL; rv = ArgumentTypeToConstraintRecord(theEnv,code); if (rv->anyAllowed == FALSE) { if (rv->symbolsAllowed && rv->stringsAllowed) types = GenTypeExpression(theEnv,types,LEXEME_TYPE_CODE,-1,LEXEME_TYPE_NAME); else if (rv->symbolsAllowed) types = GenTypeExpression(theEnv,types,SYMBOL,SYMBOL,NULL); else if (rv->stringsAllowed) types = GenTypeExpression(theEnv,types,STRING,STRING,NULL); if (rv->floatsAllowed && rv->integersAllowed) types = GenTypeExpression(theEnv,types,NUMBER_TYPE_CODE,-1,NUMBER_TYPE_NAME); else if (rv->integersAllowed) types = GenTypeExpression(theEnv,types,INTEGER,INTEGER,NULL); else if (rv->floatsAllowed) types = GenTypeExpression(theEnv,types,FLOAT,FLOAT,NULL); if (rv->instanceNamesAllowed && rv->instanceAddressesAllowed) types = GenTypeExpression(theEnv,types,INSTANCE_TYPE_CODE,-1,INSTANCE_TYPE_NAME); else if (rv->instanceNamesAllowed) types = GenTypeExpression(theEnv,types,INSTANCE_NAME,INSTANCE_NAME,NULL); else if (rv->instanceAddressesAllowed) types = GenTypeExpression(theEnv,types,INSTANCE_ADDRESS,INSTANCE_ADDRESS,NULL); if (rv->externalAddressesAllowed && rv->instanceAddressesAllowed && rv->factAddressesAllowed) types = GenTypeExpression(theEnv,types,ADDRESS_TYPE_CODE,-1,ADDRESS_TYPE_NAME); else { if (rv->externalAddressesAllowed) types = GenTypeExpression(theEnv,types,EXTERNAL_ADDRESS,EXTERNAL_ADDRESS,NULL); if (rv->instanceAddressesAllowed && (rv->instanceNamesAllowed == 0)) types = GenTypeExpression(theEnv,types,INSTANCE_ADDRESS,INSTANCE_ADDRESS,NULL); if (rv->factAddressesAllowed) types = GenTypeExpression(theEnv,types,FACT_ADDRESS,FACT_ADDRESS,NULL); } if (rv->multifieldsAllowed) types = GenTypeExpression(theEnv,types,MULTIFIELD,MULTIFIELD,NULL); } RemoveConstraint(theEnv,rv); PackRestrictionTypes(theEnv,rptr,types); return(rptr); }
globle void ClearParsedBindNames() { struct BindInfo *temp_bind; while (ListOfParsedBindNames != NULL) { temp_bind = ListOfParsedBindNames->next; RemoveConstraint(ListOfParsedBindNames->constraints); rtn_struct(BindInfo,ListOfParsedBindNames); ListOfParsedBindNames = temp_bind; } }
void COXLayoutManager::SetDefaultConstraint(UINT nChildWnd) { ASSERT(m_pContainerWnd); CWnd* pWnd = m_pContainerWnd->GetDlgItem(nChildWnd); ASSERT(pWnd); if (pWnd == NULL) { TRACE0("COXLayoutManager::SetDefaultConstraint(): failed. Default constraint can only be applied after window has been created.\r\n"); return; } CRect rect; pWnd->GetWindowRect(rect); m_pContainerWnd->ScreenToClient(rect); SetConstraint(nChildWnd, OX_LMS_TOP, OX_LMT_SAME, rect.top); SetConstraint(nChildWnd, OX_LMS_LEFT, OX_LMT_SAME, rect.left); RemoveConstraint(nChildWnd, OX_LMS_BOTTOM); RemoveConstraint(nChildWnd, OX_LMS_RIGHT); }
void DynamicsWorld::AddConstraint(PointToPointConstraint &constraint, bool disableCollisionsBetweenLinkedBodies) { auto prevWorld = constraint.GetWorld(); if (prevWorld != nullptr) { prevWorld->RemoveConstraint(constraint); } constraint.SetWorld(this); constraint.IsCollisionBetweenLinkedBodiesDisabled(disableCollisionsBetweenLinkedBodies); this->world.addConstraint(&constraint, disableCollisionsBetweenLinkedBodies); }
globle void ClearParsedBindNames( void *theEnv) { struct BindInfo *temp_bind; while (ProcedureParserData(theEnv)->ListOfParsedBindNames != NULL) { temp_bind = ProcedureParserData(theEnv)->ListOfParsedBindNames->next; RemoveConstraint(theEnv,ProcedureParserData(theEnv)->ListOfParsedBindNames->constraints); rtn_struct(theEnv,BindInfo,ProcedureParserData(theEnv)->ListOfParsedBindNames); ProcedureParserData(theEnv)->ListOfParsedBindNames = temp_bind; } }
static void ReturnDeftemplate( void *theEnv, void *vTheConstruct) { #if (MAC_MCW || WIN_MCW) && (RUN_TIME || BLOAD_ONLY) #pragma unused(theEnv,vTheConstruct) #endif #if (! BLOAD_ONLY) && (! RUN_TIME) struct deftemplate *theConstruct = (struct deftemplate *) vTheConstruct; struct templateSlot *slotPtr; if (theConstruct == NULL) return; /*====================================================================*/ /* If a template is redefined, then we want to save its debug status. */ /*====================================================================*/ #if DEBUGGING_FUNCTIONS DeftemplateData(theEnv)->DeletedTemplateDebugFlags = 0; if (theConstruct->watch) BitwiseSet(DeftemplateData(theEnv)->DeletedTemplateDebugFlags,0); #endif /*===========================================*/ /* Free storage used by the templates slots. */ /*===========================================*/ slotPtr = theConstruct->slotList; while (slotPtr != NULL) { DecrementSymbolCount(theEnv,slotPtr->slotName); RemoveHashedExpression(theEnv,slotPtr->defaultList); slotPtr->defaultList = NULL; RemoveHashedExpression(theEnv,slotPtr->facetList); slotPtr->facetList = NULL; RemoveConstraint(theEnv,slotPtr->constraints); slotPtr->constraints = NULL; slotPtr = slotPtr->next; } ReturnSlots(theEnv,theConstruct->slotList); /*==================================*/ /* Free storage used by the header. */ /*==================================*/ DeinstallConstructHeader(theEnv,&theConstruct->header); rtn_struct(theEnv,deftemplate,theConstruct); #endif }
globle void ReturnSlots( void *theEnv, struct templateSlot *slotPtr) { #if (! BLOAD_ONLY) && (! RUN_TIME) struct templateSlot *nextSlot; while (slotPtr != NULL) { nextSlot = slotPtr->next; ReturnExpression(theEnv,slotPtr->defaultList); ReturnExpression(theEnv,slotPtr->facetList); RemoveConstraint(theEnv,slotPtr->constraints); rtn_struct(theEnv,templateSlot,slotPtr); slotPtr = nextSlot; } #endif }
void IKPhysicalNode::Stop () { if (!isPlaying) return; isPlaying = false; // Stop the child node if (childNode) childNode->Stop (); // Remove all constraints // TODO: really? for (csHash<ConstraintData, CS::Animation::EffectorID>::GlobalIterator it = constraints.GetIterator (); it.HasNext (); ) { csTuple2<ConstraintData, CS::Animation::EffectorID> tuple = it.NextTuple (); RemoveConstraint (tuple.second); } }
globle void RemoveParsedBindName( struct symbolHashNode *bname) { struct BindInfo *prv,*tmp; prv = NULL; tmp = ListOfParsedBindNames; while ((tmp != NULL) ? (tmp->name != bname) : FALSE) { prv = tmp; tmp = tmp->next; } if (tmp != NULL) { if (prv == NULL) ListOfParsedBindNames = tmp->next; else prv->next = tmp->next; RemoveConstraint(tmp->constraints); rtn_struct(BindInfo,tmp); } }
globle void RemoveParsedBindName( void *theEnv, struct symbolHashNode *bname) { struct BindInfo *prv,*tmp; prv = NULL; tmp = ProcedureParserData(theEnv)->ListOfParsedBindNames; while ((tmp != NULL) ? (tmp->name != bname) : FALSE) { prv = tmp; tmp = tmp->next; } if (tmp != NULL) { if (prv == NULL) ProcedureParserData(theEnv)->ListOfParsedBindNames = tmp->next; else prv->next = tmp->next; RemoveConstraint(theEnv,tmp->constraints); rtn_struct(theEnv,BindInfo,tmp); } }
static int PropagateVariableToNodes( void *theEnv, struct lhsParseNode *theNode, int theType, struct symbolHashNode *variableName, struct lhsParseNode *theReference, int startDepth, int assignReference, int ignoreVariableTypes) { struct constraintRecord *tempConstraints; /*===========================================*/ /* Traverse the nodes using the bottom link. */ /*===========================================*/ while (theNode != NULL) { /*==================================================*/ /* If the field/slot contains a predicate or return */ /* value constraint, then propagate the variable to */ /* the expression associated with that constraint. */ /*==================================================*/ if (theNode->expression != NULL) { PropagateVariableToNodes(theEnv,theNode->expression,theType,variableName, theReference,startDepth,assignReference,TRUE); } if (theNode->secondaryExpression != NULL) { PropagateVariableToNodes(theEnv,theNode->secondaryExpression,theType,variableName, theReference,startDepth,assignReference,TRUE); } /*======================================================*/ /* If the field/slot is a single or multifield variable */ /* with the same name as the propagated variable, */ /* then propagate the variable location to this node. */ /*======================================================*/ else if (((theNode->type == SF_VARIABLE) || (theNode->type == MF_VARIABLE)) && (theNode->value == (void *) variableName)) { /*======================================================*/ /* Check for mixing of single and multifield variables. */ /*======================================================*/ if (ignoreVariableTypes == FALSE) { if (((theType == SF_VARIABLE) && (theNode->type == MF_VARIABLE)) || ((theType == MF_VARIABLE) && (theNode->type == SF_VARIABLE))) { return(TRUE); } } /*======================================================*/ /* Intersect the propagated variable's constraints with */ /* the current constraints for this field/slot. */ /*======================================================*/ if ((theReference->constraints != NULL) && (! theNode->negated)) { tempConstraints = theNode->constraints; theNode->constraints = IntersectConstraints(theEnv,theReference->constraints, tempConstraints); if (theNode->derivedConstraints) { RemoveConstraint(theEnv,tempConstraints); } theNode->derivedConstraints = TRUE; } /*=====================================================*/ /* Don't propagate the variable if it originates from */ /* a different type of pattern object and the variable */ /* reference has already been resolved. */ /*=====================================================*/ if (assignReference) { if (theNode->referringNode == NULL) { theNode->referringNode = theReference; } else if (theReference->pattern == theNode->pattern) { theNode->referringNode = theReference; } else if (theReference->patternType == theNode->patternType) { theNode->referringNode = theReference; } } } /*========================================================*/ /* If the field/slot is the node representing the entire */ /* pattern, then propagate the variable location to the */ /* fact address associated with the pattern (if it is the */ /* same variable name). */ /*========================================================*/ else if ((theNode->type == PATTERN_CE) && (theNode->value == (void *) variableName) && (assignReference == TRUE)) { if (theType == MF_VARIABLE) return(TRUE); theNode->referringNode = theReference; } /*=====================================================*/ /* Propagate the variable to other fields contained */ /* within the same & field constraint or same pattern. */ /*=====================================================*/ if (theNode->right != NULL) { if (PropagateVariableToNodes(theEnv,theNode->right,theType,variableName, theReference,startDepth,assignReference,ignoreVariableTypes)) { return(TRUE); } } /*============================================================*/ /* Propagate the variable to other patterns within the same */ /* semantic scope (if dealing with the node for an entire */ /* pattern) or to the next | field constraint within a field. */ /*============================================================*/ if ((theNode->type == PATTERN_CE) || (theNode->type == TEST_CE)) { if (theNode->endNandDepth < startDepth) theNode = NULL; else theNode = theNode->bottom; } else { theNode = theNode->bottom; } } /*========================================================*/ /* Return FALSE to indicate that no errors were detected. */ /*========================================================*/ return(FALSE); }
static BOOLEAN CheckArgumentForConstraintError( struct expr *expressionList, struct expr *lastOne, int i, struct FunctionDefinition *theFunction, struct lhsParseNode *theLHS) { int theRestriction; CONSTRAINT_RECORD *constraint1, *constraint2, *constraint3, *constraint4; struct lhsParseNode *theVariable; struct expr *tmpPtr; int rv = FALSE; /*=============================================================*/ /* Skip anything that isn't a variable or isn't an argument to */ /* a user defined function (i.e. deffunctions and generic have */ /* no constraint information so they aren't checked). */ /*=============================================================*/ if ((expressionList->type != SF_VARIABLE) || (theFunction == NULL)) { return (rv); } /*===========================================*/ /* Get the restrictions for the argument and */ /* convert them to a constraint record. */ /*===========================================*/ theRestriction = GetNthRestriction(theFunction,i); constraint1 = ArgumentTypeToConstraintRecord(theRestriction); /*================================================*/ /* Look for the constraint record associated with */ /* binding the variable in the LHS of the rule. */ /*================================================*/ theVariable = FindVariable((SYMBOL_HN *) expressionList->value,theLHS); if (theVariable != NULL) { if (theVariable->type == MF_VARIABLE) { constraint2 = GetConstraintRecord(); SetConstraintType(MULTIFIELD,constraint2); } else if (theVariable->constraints == NULL) { constraint2 = GetConstraintRecord(); } else { constraint2 = CopyConstraintRecord(theVariable->constraints); } } else { constraint2 = NULL; } /*================================================*/ /* Look for the constraint record associated with */ /* binding the variable on the RHS of the rule. */ /*================================================*/ constraint3 = FindBindConstraints((SYMBOL_HN *) expressionList->value); /*====================================================*/ /* Union the LHS and RHS variable binding constraints */ /* (the variable must satisfy one or the other). */ /*====================================================*/ constraint3 = UnionConstraints(constraint3,constraint2); /*====================================================*/ /* Intersect the LHS/RHS variable binding constraints */ /* with the function argument restriction constraints */ /* (the variable must satisfy both). */ /*====================================================*/ constraint4 = IntersectConstraints(constraint3,constraint1); /*====================================*/ /* Check for unmatchable constraints. */ /*====================================*/ if (UnmatchableConstraint(constraint4) && GetStaticConstraintChecking()) { PrintErrorID("RULECSTR",3,TRUE); PrintRouter(WERROR,"Previous variable bindings of ?"); PrintRouter(WERROR,ValueToString((SYMBOL_HN *) expressionList->value)); PrintRouter(WERROR," caused the type restrictions"); PrintRouter(WERROR,"\nfor argument #"); PrintLongInteger(WERROR,(long int) i); PrintRouter(WERROR," of the expression "); tmpPtr = lastOne->nextArg; lastOne->nextArg = NULL; PrintExpression(WERROR,lastOne); lastOne->nextArg = tmpPtr; PrintRouter(WERROR,"\nfound in the rule's RHS to be violated.\n"); rv = TRUE; } /*===========================================*/ /* Free the temporarily created constraints. */ /*===========================================*/ RemoveConstraint(constraint1); RemoveConstraint(constraint2); RemoveConstraint(constraint3); RemoveConstraint(constraint4); /*========================================*/ /* Return TRUE if unmatchable constraints */ /* were detected, otherwise FALSE. */ /*========================================*/ return(rv); }
static struct lhsParseNode *AddToVariableConstraints( struct lhsParseNode *oldList, struct lhsParseNode *newItems) { CONSTRAINT_RECORD *newConstraints; struct lhsParseNode *temp, *trace; /*=================================================*/ /* Loop through each of the new constraints adding */ /* it to the list if it's not already present or */ /* modifying the constraint if it is. */ /*=================================================*/ while (newItems != NULL) { /*==========================================*/ /* Get the next item since the next pointer */ /* value (right) needs to be set to NULL. */ /*==========================================*/ temp = newItems->right; newItems->right = NULL; /*===================================*/ /* Search the list for the variable. */ /*===================================*/ for (trace = oldList; trace != NULL; trace = trace->right) { /*=========================================*/ /* If the variable is already in the list, */ /* modify the constraint already there to */ /* include the new constraint. */ /*=========================================*/ if (trace->value == newItems->value) { newConstraints = IntersectConstraints(trace->constraints, newItems->constraints); RemoveConstraint(trace->constraints); trace->constraints = newConstraints; ReturnLHSParseNodes(newItems); break; } } /*=================================*/ /* Add the variable constraints to */ /* the list if it wasn't found. */ /*=================================*/ if (trace == NULL) { newItems->right = oldList; oldList = newItems; } /*===========================*/ /* Move on to the next item. */ /*===========================*/ newItems = temp; } return(oldList); }
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); }
static BOOLEAN MultifieldCardinalityViolation( 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 != 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 == 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(); else tempConstraint = CopyConstraintRecord(theNode->constraints); ReturnExpression(tempConstraint->minFields); ReturnExpression(tempConstraint->maxFields); tempConstraint->minFields = GenConstant(INTEGER,AddLong((long) minFields)); if (posInfinity) tempConstraint->maxFields = GenConstant(SYMBOL,PositiveInfinity); else tempConstraint->maxFields = GenConstant(INTEGER,AddLong((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(theNode->constraints,tempConstraint); if (theNode->derivedConstraints) RemoveConstraint(theNode->constraints); RemoveConstraint(tempConstraint); theNode->constraints = newConstraint; theNode->derivedConstraints = TRUE; /*===================================================================*/ /* Determine if the final cardinality for the slot can be satisfied. */ /*===================================================================*/ if (GetStaticConstraintChecking() == FALSE) return(FALSE); if (UnmatchableConstraint(newConstraint)) return(TRUE); return(FALSE); }
globle struct expr *ParseDefault( void *theEnv, char *readSource, int multifield, int dynamic, int evalStatic, int *noneSpecified, int *deriveSpecified, int *error) { struct expr *defaultList = NULL, *lastDefault = NULL; struct expr *newItem, *tmpItem; struct token theToken; DATA_OBJECT theValue; CONSTRAINT_RECORD *rv; int specialVarCode; *noneSpecified = FALSE; *deriveSpecified = FALSE; SavePPBuffer(theEnv,(char*)" "); GetToken(theEnv,readSource,&theToken); /*===================================================*/ /* Read the items contained in the default attribute */ /* until a closing right parenthesis is encountered. */ /*===================================================*/ while (theToken.type != RPAREN) { /*========================================*/ /* Get the next item in the default list. */ /*========================================*/ newItem = ParseAtomOrExpression(theEnv,readSource,&theToken); if (newItem == NULL) { ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } /*===========================================================*/ /* Check for invalid variable usage. With the expection of */ /* ?NONE for the default attribute, local variables may not */ /* be used within the default or default-dynamic attributes. */ /*===========================================================*/ if ((newItem->type == SF_VARIABLE) || (newItem->type == MF_VARIABLE)) { if (strcmp(ValueToString(newItem->value),"NONE") == 0) { specialVarCode = 0; } else if (strcmp(ValueToString(newItem->value),"DERIVE") == 0) { specialVarCode = 1; } else { specialVarCode = -1; } if ((dynamic) || (newItem->type == MF_VARIABLE) || (specialVarCode == -1) || ((specialVarCode != -1) && (defaultList != NULL))) { if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); ReturnExpression(theEnv,newItem); ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } ReturnExpression(theEnv,newItem); /*============================================*/ /* Check for the closing right parenthesis of */ /* the default or default dynamic attribute. */ /*============================================*/ GetToken(theEnv,readSource,&theToken); if (theToken.type != RPAREN) { if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); PPBackup(theEnv); SavePPBuffer(theEnv,(char*)" "); SavePPBuffer(theEnv,theToken.printForm); *error = TRUE; } if (specialVarCode == 0) *noneSpecified = TRUE; else *deriveSpecified = TRUE; return(NULL); } /*====================================================*/ /* Look to see if any variables have been used within */ /* expressions contained within the default list. */ /*====================================================*/ if (ExpressionContainsVariables(newItem,FALSE) == TRUE) { ReturnExpression(theEnv,defaultList); ReturnExpression(theEnv,newItem); *error = TRUE; if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); return(NULL); } /*============================================*/ /* Add the default value to the default list. */ /*============================================*/ if (lastDefault == NULL) { defaultList = newItem; } else { lastDefault->nextArg = newItem; } lastDefault = newItem; /*=======================================*/ /* Begin parsing the next default value. */ /*=======================================*/ SavePPBuffer(theEnv,(char*)" "); GetToken(theEnv,readSource,&theToken); } /*=====================================*/ /* Fix up pretty print representation. */ /*=====================================*/ PPBackup(theEnv); PPBackup(theEnv); SavePPBuffer(theEnv,(char*)")"); /*=========================================*/ /* A single field slot's default attribute */ /* must contain a single value. */ /*=========================================*/ if (multifield == FALSE) { if (defaultList == NULL) { *error = TRUE; } else if (defaultList->nextArg != NULL) { *error = TRUE; } else { rv = ExpressionToConstraintRecord(theEnv,defaultList); rv->multifieldsAllowed = FALSE; if (UnmatchableConstraint(rv)) *error = TRUE; RemoveConstraint(theEnv,rv); } if (*error) { PrintErrorID(theEnv,(char*)"DEFAULT",1,TRUE); EnvPrintRouter(theEnv,WERROR,(char*)"The default value for a single field slot must be a single field value\n"); ReturnExpression(theEnv,defaultList); return(NULL); } } /*=======================================================*/ /* If the dynamic-default attribute is not being parsed, */ /* evaluate the expressions to make the default value. */ /*=======================================================*/ if (dynamic || (! evalStatic) || (defaultList == NULL)) return(defaultList); tmpItem = defaultList; newItem = defaultList; defaultList = NULL; while (newItem != NULL) { SetEvaluationError(theEnv,FALSE); if (EvaluateExpression(theEnv,newItem,&theValue)) *error = TRUE; if ((theValue.type == MULTIFIELD) && (multifield == FALSE) && (*error == FALSE)) { PrintErrorID(theEnv,(char*)"DEFAULT",1,TRUE); EnvPrintRouter(theEnv,WERROR,(char*)"The default value for a single field slot must be a single field value\n"); *error = TRUE; } if (*error) { ReturnExpression(theEnv,tmpItem); ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } lastDefault = ConvertValueToExpression(theEnv,&theValue); defaultList = AppendExpressions(defaultList,lastDefault); newItem = newItem->nextArg; } ReturnExpression(theEnv,tmpItem); /*==========================*/ /* Return the default list. */ /*==========================*/ return(defaultList); }
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; }
static int ProcessVariable( void *theEnv, struct lhsParseNode *thePattern, struct lhsParseNode *multifieldHeader, struct lhsParseNode *patternHead, int patternHeadType, struct nandFrame *theNandFrames) { int theType; struct symbolHashNode *theVariable; struct constraintRecord *theConstraints; /*=============================================================*/ /* If a pattern address is being propagated, then treat it as */ /* a single field pattern variable and create a constraint */ /* which indicates that is must be a fact or instance address. */ /* This code will have to be modified for new data types which */ /* can match patterns. */ /*=============================================================*/ if (thePattern->type == PATTERN_CE) { theType = SF_VARIABLE; theVariable = (struct symbolHashNode *) thePattern->value; if (thePattern->derivedConstraints) RemoveConstraint(theEnv,thePattern->constraints); theConstraints = GetConstraintRecord(theEnv); thePattern->constraints = theConstraints; thePattern->constraints->anyAllowed = FALSE; thePattern->constraints->instanceAddressesAllowed = TRUE; thePattern->constraints->factAddressesAllowed = TRUE; thePattern->derivedConstraints = TRUE; } /*===================================================*/ /* Otherwise a pattern variable is being propagated. */ /*===================================================*/ else { theType = thePattern->type; theVariable = (struct symbolHashNode *) thePattern->value; } /*===================================================*/ /* Propagate the variable location to any additional */ /* fields associated with the binding variable. */ /*===================================================*/ if (thePattern->type != PATTERN_CE) { PropagateVariableToNodes(theEnv,thePattern->bottom,theType,theVariable, thePattern,patternHead->beginNandDepth, TRUE,FALSE); if (ProcessField(theEnv,thePattern,multifieldHeader,patternHead,patternHeadType,theNandFrames)) { return(TRUE); } } /*=================================================================*/ /* Propagate the constraints to other fields, slots, and patterns. */ /*=================================================================*/ return(PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,theType, theVariable,thePattern,TRUE,patternHeadType)); }
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); }
void dgWorld::DestroyConstraint(dgConstraint* const constraint) { RemoveConstraint (constraint); delete constraint; }