globle void FactsIncrementalReset( void *theEnv) { struct fact *factPtr; for (factPtr = (struct fact *) EnvGetNextFact(theEnv,NULL); factPtr != NULL; factPtr = (struct fact *) EnvGetNextFact(theEnv,factPtr)) { EngineData(theEnv)->JoinOperationInProgress = TRUE; FactPatternMatch(theEnv,factPtr, factPtr->whichDeftemplate->patternNetwork, 0,NULL,NULL); EngineData(theEnv)->JoinOperationInProgress = FALSE; } }
static void ProcessMultifieldNode( void *theEnv, struct factPatternNode *thePattern, struct multifieldMarker *markers, struct multifieldMarker *endMark, int offset) { struct multifieldMarker *newMark, *oldMark; int repeatCount; struct multifield *theSlotValue; DATA_OBJECT theResult; struct factPatternNode *tempPtr; intBool success; /*========================================*/ /* Get a pointer to the slot value of the */ /* multifield slot being pattern matched. */ /*========================================*/ theSlotValue = (struct multifield *) FactData(theEnv)->CurrentPatternFact->theProposition.theFields[thePattern->whichSlot].value; /*===============================================*/ /* Save the value of the markers already stored. */ /*===============================================*/ oldMark = markers; /*===========================================*/ /* Create a new multifield marker and append */ /* it to the end of the current list. */ /*===========================================*/ newMark = get_struct(theEnv,multifieldMarker); newMark->whichField = thePattern->whichField - 1; newMark->where.whichSlotNumber = (short) thePattern->whichSlot; newMark->startPosition = (thePattern->whichField - 1) + offset; newMark->next = NULL; if (endMark == NULL) { markers = newMark; FactData(theEnv)->CurrentPatternMarks = markers; } else { endMark->next = newMark; } /*============================================*/ /* Handle a multifield constraint as the last */ /* constraint of a slot as a special case. */ /*============================================*/ if (thePattern->header.endSlot) { newMark->endPosition = (long) theSlotValue->multifieldLength - (thePattern->leaveFields + 1); /*=======================================================*/ /* Make sure the endPosition is never more than less one */ /* less of the startPosition (a multifield containing no */ /* values. */ /*=======================================================*/ if (newMark->endPosition < newMark->startPosition) { newMark->endPosition = newMark->startPosition - 1; } /*===========================================*/ /* Determine if the constraint is satisfied. */ /*===========================================*/ if (thePattern->header.selector) { if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg)) { EvaluateExpression(theEnv,thePattern->networkTest,&theResult); thePattern = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value); if (thePattern != NULL) { success = TRUE; } else { success = FALSE; } } else { success = FALSE; } } else if ((thePattern->networkTest == NULL) ? TRUE : (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest))) { success = TRUE; } else { success = FALSE; } if (success) { /*=======================================================*/ /* If a leaf pattern node has been successfully reached, */ /* then the pattern has been satisified. Generate an */ /* alpha match to store in the pattern node. */ /*=======================================================*/ if (thePattern->header.stopNode) { ProcessFactAlphaMatch(theEnv,FactData(theEnv)->CurrentPatternFact,FactData(theEnv)->CurrentPatternMarks,thePattern); } /*=============================================*/ /* Recursively continue pattern matching based */ /* on the multifield binding just generated. */ /*=============================================*/ FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, thePattern->nextLevel,0,FactData(theEnv)->CurrentPatternMarks,newMark); } /*================================================*/ /* Discard the multifield marker since we've done */ /* all the pattern matching for this binding of */ /* the multifield slot constraint. */ /*================================================*/ rtn_struct(theEnv,multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; FactData(theEnv)->CurrentPatternMarks = oldMark; return; } /*==============================================*/ /* Perform matching for nodes beneath this one. */ /*==============================================*/ for (repeatCount = (long) (theSlotValue->multifieldLength - (newMark->startPosition + thePattern->leaveFields)); repeatCount >= 0; repeatCount--) { newMark->endPosition = newMark->startPosition + (repeatCount - 1); if (thePattern->header.selector) { if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg)) { EvaluateExpression(theEnv,thePattern->networkTest,&theResult); tempPtr = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value); if (tempPtr != NULL) { FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, tempPtr->nextLevel,offset + repeatCount - 1, FactData(theEnv)->CurrentPatternMarks,newMark); } } } else if ((thePattern->networkTest == NULL) ? TRUE : (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest))) { FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, thePattern->nextLevel,offset + repeatCount - 1, FactData(theEnv)->CurrentPatternMarks,newMark); } } /*======================================================*/ /* Get rid of the marker created for a multifield node. */ /*======================================================*/ rtn_struct(theEnv,multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; FactData(theEnv)->CurrentPatternMarks = oldMark; }
globle void *Assert( void *vTheFact) { int hashValue; int length, i; struct field *theField; struct fact *theFact = (struct fact *) vTheFact; /*==========================================*/ /* A fact can not be asserted while another */ /* fact is being asserted or retracted. */ /*==========================================*/ if (JoinOperationInProgress) { ReturnFact(theFact); PrintErrorID("FACTMNGR",2,TRUE); PrintRouter(WERROR,"Facts may not be asserted during pattern-matching\n"); return(NULL); } /*=============================================================*/ /* Replace invalid data types in the fact with the symbol nil. */ /*=============================================================*/ length = theFact->theProposition.multifieldLength; theField = theFact->theProposition.theFields; for (i = 0; i < length; i++) { if (theField[i].type == RVOID) { theField[i].type = SYMBOL; theField[i].value = (void *) AddSymbol("nil"); } } /*========================================================*/ /* If fact assertions are being checked for duplications, */ /* then search the fact list for a duplicate fact. */ /*========================================================*/ hashValue = HandleFactDuplication(theFact); if (hashValue < 0) return(NULL); /*==========================================================*/ /* If necessary, add logical dependency links between the */ /* fact and the partial match which is its logical support. */ /*==========================================================*/ #if LOGICAL_DEPENDENCIES if (AddLogicalDependencies((struct patternEntity *) theFact,FALSE) == FALSE) { ReturnFact(theFact); return(NULL); } #endif /*======================================*/ /* Add the fact to the fact hash table. */ /*======================================*/ AddHashedFact(theFact,hashValue); /*================================*/ /* Add the fact to the fact list. */ /*================================*/ theFact->nextFact = NULL; theFact->list = NULL; theFact->previousFact = LastFact; if (LastFact == NULL) { FactList = theFact; } else { LastFact->nextFact = theFact; } LastFact = theFact; /*==================================*/ /* Set the fact index and time tag. */ /*==================================*/ theFact->factIndex = NextFactIndex++; theFact->factHeader.timeTag = CurrentEntityTimeTag++; /*=====================*/ /* Update busy counts. */ /*=====================*/ FactInstall(theFact); /*==========================*/ /* Print assert output if */ /* facts are being watched. */ /*==========================*/ #if DEBUGGING_FUNCTIONS if (theFact->whichDeftemplate->watch) { PrintRouter(WTRACE,"==> "); PrintFactWithIdentifier(WTRACE,theFact); PrintRouter(WTRACE,"\n"); } #endif /*==================================*/ /* Set the change flag to indicate */ /* the fact-list has been modified. */ /*==================================*/ ChangeToFactList = TRUE; /*==========================================*/ /* Check for constraint errors in the fact. */ /*==========================================*/ CheckTemplateFact(theFact); /*===================================================*/ /* Reset the evaluation error flag since expressions */ /* will be evaluated as part of the assert . */ /*===================================================*/ SetEvaluationError(FALSE); /*=============================================*/ /* Pattern match the fact using the associated */ /* deftemplate's pattern network. */ /*=============================================*/ JoinOperationInProgress = TRUE; FactPatternMatch(theFact,theFact->whichDeftemplate->patternNetwork,0,NULL,NULL); JoinOperationInProgress = FALSE; /*===================================================*/ /* Retract other facts that were logically dependent */ /* on the non-existence of the fact just asserted. */ /*===================================================*/ #if LOGICAL_DEPENDENCIES ForceLogicalRetractions(); #endif /*=========================================*/ /* Free partial matches that were released */ /* by the assertion of the fact. */ /*=========================================*/ if (ExecutingRule == NULL) FlushGarbagePartialMatches(); /*==========================================*/ /* Force periodic cleanup if the assert was */ /* executed from an embedded application. */ /*==========================================*/ if ((CurrentEvaluationDepth == 0) && (! EvaluatingTopLevelCommand) && (CurrentExpression == NULL)) { PeriodicCleanup(TRUE,FALSE); } /*===============================*/ /* Return a pointer to the fact. */ /*===============================*/ return((void *) theFact); }