コード例 #1
0
ファイル: ruledlt.c プロジェクト: garydriley/FuzzyCLIPS631
globle void ReturnDefrule(
  void *theEnv,
  void *vWaste)
  {
#if (! RUN_TIME) && (! BLOAD_ONLY)
   struct defrule *waste = (struct defrule *) vWaste;
   int first = TRUE;
   struct defrule *nextPtr, *tmpPtr;

   if (waste == NULL) return;

   /*======================================*/
   /* If a rule is redefined, then we want */
   /* to save its breakpoint status.       */
   /*======================================*/

#if DEBUGGING_FUNCTIONS
   DefruleData(theEnv)->DeletedRuleDebugFlags = 0;
   if (waste->afterBreakpoint) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,0);
   if (waste->watchActivation) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,1);
   if (waste->watchFiring) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,2);
#endif

   /*================================*/
   /* Clear the agenda of all the    */
   /* activations added by the rule. */
   /*================================*/

   ClearRuleFromAgenda(theEnv,waste);

   /*======================*/
   /* Get rid of the rule. */
   /*======================*/

   while (waste != NULL)
     {
      /*================================================*/
      /* Remove the rule's joins from the join network. */
      /*================================================*/

      DetachJoinsDriver(theEnv,waste,FALSE);

      /*=============================================*/
      /* If this is the first disjunct, get rid of   */
      /* the dynamic salience and pretty print form. */
      /*=============================================*/

      if (first)
        {
         if (waste->dynamicSalience != NULL)
          {
           ExpressionDeinstall(theEnv,waste->dynamicSalience);
           ReturnPackedExpression(theEnv,waste->dynamicSalience);
           waste->dynamicSalience = NULL;
          }
#if CERTAINTY_FACTORS     /* changed 03-12-96 */
         if (waste->dynamicCF != NULL)
          {
           ExpressionDeinstall(theEnv,waste->dynamicCF);
           ReturnPackedExpression(theEnv,waste->dynamicCF);
           waste->dynamicCF = NULL;
          }
#endif
         if (waste->header.ppForm != NULL)
           {
            rm(theEnv,(void *) waste->header.ppForm,strlen(waste->header.ppForm) + 1);
            waste->header.ppForm = NULL;
            
            /*=======================================================*/
            /* All of the rule disjuncts share the same pretty print */
            /* form, so we want to avoid deleting it again.          */
            /*=======================================================*/
            
            for (tmpPtr = waste->disjunct; tmpPtr != NULL; tmpPtr = tmpPtr->disjunct)
              { tmpPtr->header.ppForm = NULL; }
           }

         first = FALSE;
        }

      /*===========================*/
      /* Get rid of any user data. */
      /*===========================*/
      
      if (waste->header.usrData != NULL)
        { ClearUserDataList(theEnv,waste->header.usrData); }
        
      /*===========================================*/
      /* Decrement the count for the defrule name. */
      /*===========================================*/

      DecrementSymbolCount(theEnv,waste->header.name);

      /*========================================*/
      /* Get rid of the the rule's RHS actions. */
      /*========================================*/

      if (waste->actions != NULL)
        {
         ExpressionDeinstall(theEnv,waste->actions);
         ReturnPackedExpression(theEnv,waste->actions);
        }

      /*===============================*/
      /* Move on to the next disjunct. */
      /*===============================*/

      nextPtr = waste->disjunct;
#if FUZZY_DEFTEMPLATES 
      if (waste != EngineData(theEnv)->ExecutingRule)
        {
         if (waste->numberOfFuzzySlots > 0)
         rm(theEnv,waste->pattern_fv_arrayPtr, sizeof(struct fzSlotLocator) * waste->numberOfFuzzySlots);
        }
#endif
      rtn_struct(theEnv,defrule,waste);
      waste = nextPtr;
     }

   /*==========================*/
   /* Free up partial matches. */
   /*==========================*/

   if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
#endif
  }
コード例 #2
0
ファイル: factmngr.c プロジェクト: OS2World/DEV-LISP-Clips
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);
  }
コード例 #3
0
ファイル: engine.c プロジェクト: femto/rbclips
globle long int EnvRun(
  void *theEnv,
  long int runLimit)
  {
   long int rulesFired = 0;
   DATA_OBJECT result;
   struct callFunctionItem *theRunFunction;
#if DEBUGGING_FUNCTIONS
   unsigned long maxActivations = 0, sumActivations = 0;
#if DEFTEMPLATE_CONSTRUCT
   unsigned long maxFacts = 0, sumFacts = 0;
#endif
#if OBJECT_SYSTEM
   unsigned long maxInstances = 0, sumInstances = 0;
#endif
   double endTime, startTime = 0.0;
   unsigned long tempValue;
#endif
   unsigned int i;
   struct patternEntity *theMatchingItem;
   struct partialMatch *theBasis;
   ACTIVATION *theActivation;
   char *ruleFiring;
#if PROFILING_FUNCTIONS
   struct profileFrameInfo profileFrame;
#endif

   /*=====================================================*/
   /* Make sure the run command is not already executing. */
   /*=====================================================*/

   if (EngineData(theEnv)->AlreadyRunning) return(0);
   EngineData(theEnv)->AlreadyRunning = TRUE;

   /*================================*/
   /* Set up statistics information. */
   /*================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
#if DEFTEMPLATE_CONSTRUCT
      maxFacts = GetNumberOfFacts(theEnv);
      sumFacts = maxFacts;
#endif
#if OBJECT_SYSTEM
      maxInstances = GetGlobalNumberOfInstances(theEnv);
      sumInstances = maxInstances;
#endif
      maxActivations = GetNumberOfActivations(theEnv);
      sumActivations = maxActivations;
      startTime = gentime();
     }
#endif

   /*=============================*/
   /* Set up execution variables. */
   /*=============================*/

   if (EvaluationData(theEnv)->CurrentEvaluationDepth == 0) SetHaltExecution(theEnv,FALSE);
   EngineData(theEnv)->HaltRules = FALSE;

   /*=====================================================*/
   /* Fire rules until the agenda is empty, the run limit */
   /* has been reached, or a rule execution error occurs. */
   /*=====================================================*/

   theActivation = NextActivationToFire(theEnv);
   while ((theActivation != NULL) &&
          (runLimit != 0) &&
          (EvaluationData(theEnv)->HaltExecution == FALSE) &&
          (EngineData(theEnv)->HaltRules == FALSE))
     {
      /*===========================================*/
      /* Detach the activation from the agenda and */
      /* determine which rule is firing.           */
      /*===========================================*/

      DetachActivation(theEnv,theActivation);
      ruleFiring = EnvGetActivationName(theEnv,theActivation);
      theBasis = (struct partialMatch *) GetActivationBasis(theActivation);
      EngineData(theEnv)->ExecutingRule = (struct defrule *) GetActivationRule(theActivation);

      /*=============================================*/
      /* Update the number of rules that have fired. */
      /*=============================================*/

      rulesFired++;
      if (runLimit > 0) { runLimit--; }

      /*==================================*/
      /* If rules are being watched, then */
      /* print an information message.    */
      /*==================================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->ExecutingRule->watchFiring)
        {
         char printSpace[60];

         sprintf(printSpace,"FIRE %4ld ",rulesFired);
         EnvPrintRouter(theEnv,WTRACE,printSpace);
         EnvPrintRouter(theEnv,WTRACE,ruleFiring);
         EnvPrintRouter(theEnv,WTRACE,": ");
         PrintPartialMatch(theEnv,WTRACE,theBasis);
         EnvPrintRouter(theEnv,WTRACE,"\n");
        }
#endif

      /*=================================================*/
      /* Remove the link between the activation and the  */
      /* completed match for the rule. Set the busy flag */
      /* for the completed match to TRUE (so the match   */
      /* upon which our RHS variables are dependent is   */
      /* not deleted while our rule is firing). Set up   */
      /* the global pointers to the completed match for  */
      /* routines which do variable extractions.         */
      /*=================================================*/

      theBasis->binds[theBasis->bcount].gm.theValue = NULL;
      theBasis->busy = TRUE;

      EngineData(theEnv)->GlobalLHSBinds = theBasis;
      EngineData(theEnv)->GlobalRHSBinds = NULL;

      /*===================================================================*/
      /* Increment the count for each of the facts/objects associated with */
      /* the rule activation so that the facts/objects cannot be deleted   */
      /* by garbage collection while the rule is executing.                */
      /*===================================================================*/

      for (i = 0; i < theBasis->bcount; i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->incrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*====================================================*/
      /* Execute the rule's right hand side actions. If the */
      /* rule has logical CEs, set up the pointer to the    */
      /* rules logical join so the assert command will      */
      /* attach the appropriate dependencies to the facts.  */
      /*====================================================*/

      EngineData(theEnv)->TheLogicalJoin = EngineData(theEnv)->ExecutingRule->logicalJoin;
      EvaluationData(theEnv)->CurrentEvaluationDepth++;
      SetEvaluationError(theEnv,FALSE);
      EngineData(theEnv)->ExecutingRule->executing = TRUE;

#if PROFILING_FUNCTIONS
      StartProfile(theEnv,&profileFrame,
                   &EngineData(theEnv)->ExecutingRule->header.usrData,
                   ProfileFunctionData(theEnv)->ProfileConstructs);
#endif

      EvaluateProcActions(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule,
                          EngineData(theEnv)->ExecutingRule->actions,EngineData(theEnv)->ExecutingRule->localVarCnt,
                          &result,NULL);

#if PROFILING_FUNCTIONS
      EndProfile(theEnv,&profileFrame);
#endif

      EngineData(theEnv)->ExecutingRule->executing = FALSE;
      SetEvaluationError(theEnv,FALSE);
      EvaluationData(theEnv)->CurrentEvaluationDepth--;
      EngineData(theEnv)->TheLogicalJoin = NULL;

      /*=====================================================*/
      /* If rule execution was halted, then print a message. */
      /*=====================================================*/

#if DEBUGGING_FUNCTIONS
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules && EngineData(theEnv)->ExecutingRule->watchFiring))
#else
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules))
#endif

        {
         PrintErrorID(theEnv,"PRCCODE",4,FALSE);
         EnvPrintRouter(theEnv,WERROR,"Execution halted during the actions of defrule ");
         EnvPrintRouter(theEnv,WERROR,ruleFiring);
         EnvPrintRouter(theEnv,WERROR,".\n");
        }

      /*===================================================================*/
      /* Decrement the count for each of the facts/objects associated with */
      /* the rule activation. If the last match for the activation         */
      /* is from a not CE, then we need to make sure that the last         */
      /* match is an actual match for the CE and not a counter.            */
      /*===================================================================*/

      theBasis->busy = FALSE;

      for (i = 0; i < (theBasis->bcount - 1); i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      i = (unsigned) (theBasis->bcount - 1);
      if (theBasis->counterf == FALSE)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*========================================*/
      /* Return the agenda node to free memory. */
      /*========================================*/

      RemoveActivation(theEnv,theActivation,FALSE,FALSE);

      /*======================================*/
      /* Get rid of partial matches discarded */
      /* while executing the rule's RHS.      */
      /*======================================*/

      FlushGarbagePartialMatches(theEnv);

      /*==================================*/
      /* Get rid of other garbage created */
      /* while executing the rule's RHS.  */
      /*==================================*/

      PeriodicCleanup(theEnv,FALSE,TRUE);

      /*==========================*/
      /* Keep up with statistics. */
      /*==========================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->WatchStatistics)
        {
#if DEFTEMPLATE_CONSTRUCT
         tempValue = GetNumberOfFacts(theEnv);
         if (tempValue > maxFacts) maxFacts = tempValue;
         sumFacts += tempValue;
#endif
#if OBJECT_SYSTEM
         tempValue = GetGlobalNumberOfInstances(theEnv);
         if (tempValue > maxInstances) maxInstances = tempValue;
         sumInstances += tempValue;
#endif
         tempValue = GetNumberOfActivations(theEnv);
         if (tempValue > maxActivations) maxActivations = tempValue;
         sumActivations += tempValue;
        }
#endif

      /*==================================*/
      /* Update saliences if appropriate. */
      /*==================================*/

      if (EnvGetSalienceEvaluation(theEnv) == EVERY_CYCLE) EnvRefreshAgenda(theEnv,NULL);

      /*========================================*/
      /* Execute the list of functions that are */
      /* to be called after each rule firing.   */
      /*========================================*/

      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }

      /*========================================*/
      /* If a return was issued on the RHS of a */
      /* rule, then remove *that* rule's module */
      /* from the focus stack                   */
      /*========================================*/

      if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
        { RemoveFocus(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule); }
      ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;

      /*========================================*/
      /* Determine the next activation to fire. */
      /*========================================*/

      theActivation = (struct activation *) NextActivationToFire(theEnv);

      /*==============================*/
      /* Check for a rule breakpoint. */
      /*==============================*/

      if (theActivation != NULL)
        {
         if (((struct defrule *) GetActivationRule(theActivation))->afterBreakpoint)
           {
            EngineData(theEnv)->HaltRules = TRUE;
            EnvPrintRouter(theEnv,WDIALOG,"Breaking on rule ");
            EnvPrintRouter(theEnv,WDIALOG,EnvGetActivationName(theEnv,theActivation));
            EnvPrintRouter(theEnv,WDIALOG,".\n");
           }
        }
     }

   /*=====================================================*/
   /* Make sure run functions are executed at least once. */
   /*=====================================================*/

   if (rulesFired == 0)
     {
      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }
     }

   /*======================================================*/
   /* If rule execution was halted because the rule firing */
   /* limit was reached, then print a message.             */
   /*======================================================*/

   if (runLimit == rulesFired)
     { EnvPrintRouter(theEnv,WDIALOG,"rule firing limit reached\n"); }

   /*==============================*/
   /* Restore execution variables. */
   /*==============================*/

   EngineData(theEnv)->ExecutingRule = NULL;
   EngineData(theEnv)->HaltRules = FALSE;

   /*=================================================*/
   /* Print out statistics if they are being watched. */
   /*=================================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
      char printSpace[60];

      endTime = gentime();

      PrintLongInteger(theEnv,WDIALOG,rulesFired);
      EnvPrintRouter(theEnv,WDIALOG," rules fired");

#if (! GENERIC)
      if (startTime != endTime)
        {
         EnvPrintRouter(theEnv,WDIALOG,"        Run time is ");
         PrintFloat(theEnv,WDIALOG,endTime - startTime);
         EnvPrintRouter(theEnv,WDIALOG," seconds.\n");
         PrintFloat(theEnv,WDIALOG,(double) rulesFired / (endTime - startTime));
         EnvPrintRouter(theEnv,WDIALOG," rules per second.\n");
        }
      else
        { EnvPrintRouter(theEnv,WDIALOG,"\n"); }
#endif

#if DEFTEMPLATE_CONSTRUCT
      sprintf(printSpace,"%ld mean number of facts (%ld maximum).\n",
                          (long) (((double) sumFacts / (rulesFired + 1)) + 0.5),
                          maxFacts);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

#if OBJECT_SYSTEM
      sprintf(printSpace,"%ld mean number of instances (%ld maximum).\n",
                          (long) (((double) sumInstances / (rulesFired + 1)) + 0.5),
                          maxInstances);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

      sprintf(printSpace,"%ld mean number of activations (%ld maximum).\n",
                          (long) (((double) sumActivations / (rulesFired + 1)) + 0.5),
                          maxActivations);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
     }
#endif

   /*==========================================*/
   /* The current module should be the current */
   /* focus when the run finishes.             */
   /*==========================================*/

   if (EngineData(theEnv)->CurrentFocus != NULL)
     {
      if (EngineData(theEnv)->CurrentFocus->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv)))
        { EnvSetCurrentModule(theEnv,(void *) EngineData(theEnv)->CurrentFocus->theModule); }
     }

   /*===================================*/
   /* Return the number of rules fired. */
   /*===================================*/

   EngineData(theEnv)->AlreadyRunning = FALSE;
   return(rulesFired);
  }
コード例 #4
0
ファイル: factmngr.c プロジェクト: OS2World/DEV-LISP-Clips
globle BOOLEAN Retract(
  void *vTheFact)
  {
   struct fact *theFact = (struct fact *) vTheFact;

   /*===========================================*/
   /* A fact can not be retracted while another */
   /* fact is being asserted or retracted.      */
   /*===========================================*/

   if (JoinOperationInProgress)
     {
      PrintErrorID("FACTMNGR",1,TRUE);
      PrintRouter(WERROR,"Facts may not be retracted during pattern-matching\n");
      return(FALSE);
     }

   /*====================================*/
   /* A NULL fact pointer indicates that */
   /* all facts should be retracted.     */
   /*====================================*/

   if (theFact == NULL)
     {
      RemoveAllFacts();
      return(TRUE);
     }

   /*======================================================*/
   /* Check to see if the fact has already been retracted. */
   /*======================================================*/

   if (theFact->garbage) return(FALSE);

   /*============================*/
   /* Print retraction 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;

   /*===============================================*/
   /* Remove any links between the fact and partial */
   /* matches in the join network. These links are  */
   /* used to keep track of logical dependencies.   */
   /*===============================================*/

#if LOGICAL_DEPENDENCIES
   RemoveEntityDependencies((struct patternEntity *) theFact);
#endif

   /*===========================================*/
   /* Remove the fact from the fact hash table. */
   /*===========================================*/

   RemoveHashedFact(theFact);

   /*=====================================*/
   /* Remove the fact from the fact list. */
   /*=====================================*/

   if (theFact == LastFact)
     { LastFact = theFact->previousFact; }

   if (theFact->previousFact == NULL)
     {
      FactList = FactList->nextFact;
      if (FactList != NULL)
        { FactList->previousFact = NULL; }
     }
   else
     {
      theFact->previousFact->nextFact = theFact->nextFact;
      if (theFact->nextFact != NULL)
        { theFact->nextFact->previousFact = theFact->previousFact; }
     }

   /*==================================*/
   /* Update busy counts and ephemeral */
   /* garbage information.             */
   /*==================================*/

   FactDeinstall(theFact);
   EphemeralItemCount++;
   EphemeralItemSize += sizeof(struct fact) + (sizeof(struct field) * theFact->theProposition.multifieldLength);

   /*========================================*/
   /* Add the fact to the fact garbage list. */
   /*========================================*/

   theFact->nextFact = GarbageFacts;
   GarbageFacts = theFact;
   theFact->garbage = TRUE;

   /*===================================================*/
   /* Reset the evaluation error flag since expressions */
   /* will be evaluated as part of the retract.         */
   /*===================================================*/

   SetEvaluationError(FALSE);

   /*===========================================*/
   /* Loop through the list of all the patterns */
   /* that matched the fact and process the     */
   /* retract operation for each one.           */
   /*===========================================*/

   JoinOperationInProgress = TRUE;
   NetworkRetract((struct patternMatch *) theFact->list);
   JoinOperationInProgress = FALSE;

   /*=========================================*/
   /* Free partial matches that were released */
   /* by the retraction of the fact.          */
   /*=========================================*/

   if (ExecutingRule == NULL)
     { FlushGarbagePartialMatches(); }

   /*=========================================*/
   /* Retract other facts that were logically */
   /* dependent on the fact just retracted.   */
   /*=========================================*/

#if LOGICAL_DEPENDENCIES
   ForceLogicalRetractions();
#endif

   /*===========================================*/
   /* Force periodic cleanup if the retract was */
   /* executed from an embedded application.    */
   /*===========================================*/

   if ((CurrentEvaluationDepth == 0) && (! EvaluatingTopLevelCommand) &&
       (CurrentExpression == NULL))
     { PeriodicCleanup(TRUE,FALSE); }

   /*==================================*/
   /* Return TRUE to indicate the fact */
   /* was successfully retracted.      */
   /*==================================*/

   return(TRUE);
  }
コード例 #5
0
globle void ReturnDefrule(
  void *theEnv,
  void *vWaste)
  {
#if (MAC_MCW || IBM_MCW) && (RUN_TIME || BLOAD_ONLY)
#pragma unused(theEnv,vWaste)
#endif

#if (! RUN_TIME) && (! BLOAD_ONLY)
   struct defrule *waste = (struct defrule *) vWaste;
   int first = TRUE;
   struct defrule *nextPtr;

   if (waste == NULL) return;

   /*======================================*/
   /* If a rule is redefined, then we want */
   /* to save its breakpoint status.       */
   /*======================================*/

#if DEBUGGING_FUNCTIONS
   DefruleData(theEnv)->DeletedRuleDebugFlags = 0;
   if (waste->afterBreakpoint) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,0);
   if (waste->watchActivation) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,1);
   if (waste->watchFiring) BitwiseSet(DefruleData(theEnv)->DeletedRuleDebugFlags,2);
#endif

   /*================================*/
   /* Clear the agenda of all the    */
   /* activations added by the rule. */
   /*================================*/

   ClearRuleFromAgenda(theEnv,waste);

   /*======================*/
   /* Get rid of the rule. */
   /*======================*/

   while (waste != NULL)
     {
      /*================================================*/
      /* Remove the rule's joins from the join network. */
      /*================================================*/

      DetachJoins(theEnv,waste,FALSE);

      /*=============================================*/
      /* If this is the first disjunct, get rid of   */
      /* the dynamic salience and pretty print form. */
      /*=============================================*/

      if (first)
        {
#if DYNAMIC_SALIENCE
         if (waste->dynamicSalience != NULL)
          {
           ExpressionDeinstall(theEnv,waste->dynamicSalience);
           ReturnPackedExpression(theEnv,waste->dynamicSalience);
           waste->dynamicSalience = NULL;
          }
#endif
         if (waste->header.ppForm != NULL)
           {
            rm(theEnv,waste->header.ppForm,strlen(waste->header.ppForm) + 1);
            waste->header.ppForm = NULL;
           }

         first = FALSE;
        }

      /*===========================*/
      /* Get rid of any user data. */
      /*===========================*/
      
      if (waste->header.usrData != NULL)
        { ClearUserDataList(theEnv,waste->header.usrData); }
        
      /*===========================================*/
      /* Decrement the count for the defrule name. */
      /*===========================================*/

      DecrementSymbolCount(theEnv,waste->header.name);

      /*========================================*/
      /* Get rid of the the rule's RHS actions. */
      /*========================================*/

      if (waste->actions != NULL)
        {
         ExpressionDeinstall(theEnv,waste->actions);
         ReturnPackedExpression(theEnv,waste->actions);
        }

      /*===============================*/
      /* Move on to the next disjunct. */
      /*===============================*/

      nextPtr = waste->disjunct;
      rtn_struct(theEnv,defrule,waste);
      waste = nextPtr;
     }

   /*==========================*/
   /* Free up partial matches. */
   /*==========================*/

   if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
#endif
  }