globle void RetractCommand( void *theEnv) { long long factIndex; struct fact *ptr; struct expr *theArgument; DATA_OBJECT theResult; int argNumber; /*================================*/ /* Iterate through each argument. */ /*================================*/ for (theArgument = GetFirstArgument(), argNumber = 1; theArgument != NULL; theArgument = GetNextArgument(theArgument), argNumber++) { /*========================*/ /* Evaluate the argument. */ /*========================*/ EvaluateExpression(theEnv,theArgument,&theResult); /*===============================================*/ /* If the argument evaluates to an integer, then */ /* it's assumed to be the fact index of the fact */ /* to be retracted. */ /*===============================================*/ if (theResult.type == INTEGER) { /*==========================================*/ /* A fact index must be a positive integer. */ /*==========================================*/ factIndex = ValueToLong(theResult.value); if (factIndex < 0) { ExpectedTypeError1(theEnv,(char*)"retract",argNumber,(char*)"fact-address, fact-index, or the symbol *"); return; } /*================================================*/ /* See if a fact with the specified index exists. */ /*================================================*/ ptr = FindIndexedFact(theEnv,factIndex); /*=====================================*/ /* If the fact exists then retract it, */ /* otherwise print an error message. */ /*=====================================*/ if (ptr != NULL) { EnvRetract(theEnv,(void *) ptr); } else { char tempBuffer[20]; gensprintf(tempBuffer,"f-%lld",factIndex); CantFindItemErrorMessage(theEnv,(char*)"fact",tempBuffer); } } /*===============================================*/ /* Otherwise if the argument evaluates to a fact */ /* address, we can directly retract it. */ /*===============================================*/ else if (theResult.type == FACT_ADDRESS) { EnvRetract(theEnv,theResult.value); } /*============================================*/ /* Otherwise if the argument evaluates to the */ /* symbol *, then all facts are retracted. */ /*============================================*/ else if ((theResult.type == SYMBOL) ? (strcmp(ValueToString(theResult.value),"*") == 0) : FALSE) { RemoveAllFacts(theEnv); return; } /*============================================*/ /* Otherwise the argument has evaluated to an */ /* illegal value for the retract command. */ /*============================================*/ else { ExpectedTypeError1(theEnv,(char*)"retract",argNumber,(char*)"fact-address, fact-index, or the symbol *"); SetEvaluationError(theEnv,TRUE); } } }
bool Fact::retract( ) { if ( !m_cobj ) return false; return EnvRetract( m_environment.cobj(), m_cobj ); }
static void DuplicateModifyCommand( void *theEnv, int retractIt, DATA_OBJECT_PTR returnValue) { long int factNum; struct fact *oldFact, *newFact, *theFact; struct expr *testPtr; DATA_OBJECT computeResult; struct deftemplate *templatePtr; struct templateSlot *slotPtr; int i, position, found; /*===================================================*/ /* Set the default return value to the symbol FALSE. */ /*===================================================*/ SetpType(returnValue,SYMBOL); SetpValue(returnValue,SymbolData(theEnv)->FalseSymbol); /*==================================================*/ /* Evaluate the first argument which is used to get */ /* a pointer to the fact to be modified/duplicated. */ /*==================================================*/ testPtr = GetFirstArgument(); EvaluateExpression(theEnv,testPtr,&computeResult); /*==============================================================*/ /* If an integer is supplied, then treat it as a fact-index and */ /* search the fact-list for the fact with that fact-index. */ /*==============================================================*/ if (computeResult.type == INTEGER) { factNum = ValueToLong(computeResult.value); if (factNum < 0) { if (retractIt) ExpectedTypeError2(theEnv,"modify",1); else ExpectedTypeError2(theEnv,"duplicate",1); SetEvaluationError(theEnv,TRUE); return; } oldFact = (struct fact *) EnvGetNextFact(theEnv,NULL); while (oldFact != NULL) { if (oldFact->factIndex == factNum) { break; } else { oldFact = oldFact->nextFact; } } if (oldFact == NULL) { char tempBuffer[20]; sprintf(tempBuffer,"f-%ld",factNum); CantFindItemErrorMessage(theEnv,"fact",tempBuffer); return; } } /*==========================================*/ /* Otherwise, if a pointer is supplied then */ /* no lookup is required. */ /*==========================================*/ else if (computeResult.type == FACT_ADDRESS) { oldFact = (struct fact *) computeResult.value; } /*===========================================*/ /* Otherwise, the first argument is invalid. */ /*===========================================*/ else { if (retractIt) ExpectedTypeError2(theEnv,"modify",1); else ExpectedTypeError2(theEnv,"duplicate",1); SetEvaluationError(theEnv,TRUE); return; } /*==================================*/ /* See if it is a deftemplate fact. */ /*==================================*/ templatePtr = oldFact->whichDeftemplate; if (templatePtr->implied) return; /*================================================================*/ /* Duplicate the values from the old fact (skipping multifields). */ /*================================================================*/ newFact = (struct fact *) CreateFactBySize(theEnv,oldFact->theProposition.multifieldLength); newFact->whichDeftemplate = templatePtr; for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { newFact->theProposition.theFields[i].type = oldFact->theProposition.theFields[i].type; if (newFact->theProposition.theFields[i].type != MULTIFIELD) { newFact->theProposition.theFields[i].value = oldFact->theProposition.theFields[i].value; } else { newFact->theProposition.theFields[i].value = NULL; } } /*========================*/ /* Start replacing slots. */ /*========================*/ testPtr = testPtr->nextArg; while (testPtr != NULL) { /*============================================================*/ /* If the slot identifier is an integer, then the slot was */ /* previously identified and its position within the template */ /* was stored. Otherwise, the position of the slot within the */ /* deftemplate has to be determined by comparing the name of */ /* the slot against the list of slots for the deftemplate. */ /*============================================================*/ if (testPtr->type == INTEGER) { position = (int) ValueToLong(testPtr->value); } else { found = FALSE; position = 0; slotPtr = templatePtr->slotList; while (slotPtr != NULL) { if (slotPtr->slotName == (SYMBOL_HN *) testPtr->value) { found = TRUE; slotPtr = NULL; } else { slotPtr = slotPtr->next; position++; } } if (! found) { InvalidDeftemplateSlotMessage(theEnv,ValueToString(testPtr->value), ValueToString(templatePtr->header.name)); SetEvaluationError(theEnv,TRUE); ReturnFact(theEnv,newFact); return; } } /*===================================================*/ /* If a single field slot is being replaced, then... */ /*===================================================*/ if (newFact->theProposition.theFields[position].type != MULTIFIELD) { /*======================================================*/ /* If the list of values to store in the slot is empty */ /* or contains more than one member than an error has */ /* occured because a single field slot can only contain */ /* a single value. */ /*======================================================*/ if ((testPtr->argList == NULL) ? TRUE : (testPtr->argList->nextArg != NULL)) { MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr); ReturnFact(theEnv,newFact); return; } /*===================================================*/ /* Evaluate the expression to be stored in the slot. */ /*===================================================*/ EvaluateExpression(theEnv,testPtr->argList,&computeResult); SetEvaluationError(theEnv,FALSE); /*====================================================*/ /* If the expression evaluated to a multifield value, */ /* then an error occured since a multifield value can */ /* not be stored in a single field slot. */ /*====================================================*/ if (computeResult.type == MULTIFIELD) { ReturnFact(theEnv,newFact); MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr); return; } /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } /*=================================*/ /* Else replace a multifield slot. */ /*=================================*/ else { /*======================================*/ /* Determine the new value of the slot. */ /*======================================*/ StoreInMultifield(theEnv,&computeResult,testPtr->argList,FALSE); SetEvaluationError(theEnv,FALSE); /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } testPtr = testPtr->nextArg; } /*=====================================*/ /* Copy the multifield values from the */ /* old fact that were not replaced. */ /*=====================================*/ for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { if ((newFact->theProposition.theFields[i].type == MULTIFIELD) && (newFact->theProposition.theFields[i].value == NULL)) { newFact->theProposition.theFields[i].value = CopyMultifield(theEnv,(struct multifield *) oldFact->theProposition.theFields[i].value); } } /*======================================*/ /* Perform the duplicate/modify action. */ /*======================================*/ if (retractIt) EnvRetract(theEnv,oldFact); theFact = (struct fact *) EnvAssert(theEnv,newFact); /*========================================*/ /* The asserted fact is the return value. */ /*========================================*/ if (theFact != NULL) { SetpDOBegin(returnValue,1); SetpDOEnd(returnValue,theFact->theProposition.multifieldLength); SetpType(returnValue,FACT_ADDRESS); SetpValue(returnValue,(void *) theFact); } return; }
//madianyi End globle void UpdateCommand( void *theEnv, DATA_OBJECT_PTR rv) { long long factIndex; struct fact *oldFact, *newFact, *theFact; struct defrule *ExecutingRule = NULL; struct expr *testPtr; DATA_OBJECT computeResult; /*===================================================*/ /* Set the default return value to the symbol FALSE. */ /*===================================================*/ SetpType(rv,SYMBOL); SetpValue(rv,EnvFalseSymbol(theEnv)); /*==================================================*/ /* Evaluate the first argument which is used to get */ /* a pointer to the fact to be updated. */ /*==================================================*/ testPtr = GetFirstArgument(); EnvIncrementClearReadyLocks(theEnv); EvaluateExpression(theEnv,testPtr,&computeResult); EnvDecrementClearReadyLocks(theEnv); /*==============================================================*/ /* If an integer is supplied, then treat it as a fact-index and */ /* search the fact-list for the fact with that fact-index. */ /*==============================================================*/ if (computeResult.type == INTEGER) { factIndex = ValueToLong(computeResult.value); if (factIndex < 0) { ExpectedTypeError1(theEnv,"update",1,"fact-address, fact-index, or the symbol *"); return; } /*================================================*/ /* See if a fact with the specified index exists. */ /*================================================*/ oldFact = FindIndexedFact(theEnv,factIndex); if (oldFact == NULL) { char tempBuffer[20]; gensprintf(tempBuffer,"f-%lld",factIndex); CantFindItemErrorMessage(theEnv,"fact",tempBuffer); return; } } /*==========================================*/ /* Otherwise, if a pointer is supplied then */ /* no lookup is required. */ /*==========================================*/ else if (computeResult.type == FACT_ADDRESS) { oldFact = (struct fact *) computeResult.value; } /*============================================*/ /* Otherwise the argument has evaluated to an */ /* illegal value for the retract command. */ /*============================================*/ else { ExpectedTypeError1(theEnv,"update",1,"fact-address, fact-index, or the symbol *"); SetEvaluationError(theEnv,TRUE); } /*============================================*/ /* Retract oldFact and Assert newFact */ /*============================================*/ if (oldFact->localFact != NULL) { newFact = oldFact->localFact; //Remove oldFact from localFactList of ExecutingRule ExecutingRule = EngineData(theEnv)->ExecutingRule; if (oldFact == ExecutingRule->lastLocalFact) { ExecutingRule->lastLocalFact = oldFact->previousLocalFact; } if (oldFact->previousLocalFact == NULL) { ExecutingRule->localFactList = ExecutingRule->localFactList->nextLocalFact; if (ExecutingRule->localFactList != NULL) { ExecutingRule->localFactList->previousLocalFact = NULL; } } else { oldFact->previousLocalFact->nextLocalFact = oldFact->nextLocalFact; if (oldFact->nextLocalFact != NULL) { oldFact->nextLocalFact->previousLocalFact = oldFact->previousLocalFact; } } EnvRetract(theEnv,oldFact); theFact = (struct fact *) EnvAssert(theEnv,(void *) newFact); if (theFact != NULL) { SetpType(rv,FACT_ADDRESS); SetpValue(rv,(void *) theFact); } return; } else { ExpectedTypeError1(theEnv,"update",1,"been set before *"); SetEvaluationError(theEnv,TRUE); } }