1 /*******************************************************/
2 /* "C" Language Integrated Production System */
4 /* CLIPS Version 6.30 08/22/14 */
7 /*******************************************************/
9 /*************************************************************/
11 /* Provides functionality for examining, manipulating, */
12 /* adding, and removing activations from the agenda. */
14 /* Principal Programmer(s): */
17 /* Contributing Programmer(s): */
20 /* Revision History: */
21 /* 6.23: Corrected compilation errors for files */
22 /* generated by constructs-to-c. DR0861 */
24 /* 6.24: Removed CONFLICT_RESOLUTION_STRATEGIES */
25 /* and DYNAMIC_SALIENCE compilation flags. */
27 /* Renamed BOOLEAN macro type to intBool. */
29 /* Added EnvGetActivationBasisPPForm function. */
31 /* 6.30: Added salience groups to improve performance */
32 /* with large numbers of activations of different */
35 /* Borland C (IBM_TBC) and Metrowerks CodeWarrior */
36 /* (MAC_MCW, IBM_MCW) are no longer supported. */
38 /* Support for long long integers. */
40 /* Added const qualifiers to remove C++ */
41 /* deprecation warnings. */
43 /* Converted API macros to function calls. */
45 /*************************************************************/
47 #define _AGENDA_SOURCE_
50 #define _STDIO_INCLUDED_
78 /***************************************/
79 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
80 /***************************************/
82 static void PrintActivation(void *,const char *,void *);
83 static void AgendaClearFunction(void *);
84 static const char *SalienceEvaluationName(int);
85 static int EvaluateSalience(void *,void *);
86 static struct salienceGroup *ReuseOrCreateSalienceGroup(void *,struct defruleModule *,int);
87 static struct salienceGroup *FindSalienceGroup(struct defruleModule *,int);
88 static void RemoveActivationFromGroup(void *,struct activation *,struct defruleModule *);
90 /*************************************************/
91 /* InitializeAgenda: Initializes the activations */
92 /* watch item and the H/L commands for */
93 /* manipulating the agenda. */
94 /*************************************************/
95 globle void InitializeAgenda(
98 AllocateEnvironmentData(theEnv,AGENDA_DATA,sizeof(struct agendaData),NULL);
100 AgendaData(theEnv)->SalienceEvaluation = WHEN_DEFINED;
102 AgendaData(theEnv)->Strategy = DEFAULT_STRATEGY;
104 EnvAddClearFunction(theEnv,"agenda",AgendaClearFunction,0);
105 #if DEBUGGING_FUNCTIONS
106 AddWatchItem(theEnv,"activations",1,&AgendaData(theEnv)->WatchActivations,40,DefruleWatchAccess,DefruleWatchPrint);
109 EnvDefineFunction2(theEnv,"refresh", 'v', PTIEF RefreshCommand, "RefreshCommand", "11w");
111 EnvDefineFunction2(theEnv,"refresh-agenda",'v',
112 PTIEF RefreshAgendaCommand,"RefreshAgendaCommand", "01w");
113 EnvDefineFunction2(theEnv,"get-salience-evaluation",'w',
114 PTIEF GetSalienceEvaluationCommand,
115 "GetSalienceEvaluationCommand", "00");
116 EnvDefineFunction2(theEnv,"set-salience-evaluation",'w',
117 PTIEF SetSalienceEvaluationCommand,
118 "SetSalienceEvaluationCommand",
121 #if DEBUGGING_FUNCTIONS
122 EnvDefineFunction2(theEnv,"agenda", 'v', PTIEF AgendaCommand, "AgendaCommand", "01w");
127 /*****************************************************************/
128 /* AddActivation: Creates a rule activation to be added to the */
129 /* Agenda and links the activation with its associated partial */
130 /* match. The function PlaceActivation is then called to place */
131 /* the activation on the Agenda. Typically called when all */
132 /* patterns on the LHS of a rule have been satisfied. */
133 /*****************************************************************/
134 globle void AddActivation(
139 struct activation *newActivation;
140 struct defrule *theRule = (struct defrule *) vTheRule;
141 struct partialMatch *binds = (struct partialMatch *) vBinds;
142 struct defruleModule *theModuleItem;
143 struct salienceGroup *theGroup;
145 /*=======================================*/
146 /* Focus on the module if the activation */
147 /* is from an auto-focus rule. */
148 /*=======================================*/
150 if (theRule->autoFocus)
151 { EnvFocus(theEnv,(void *) theRule->header.whichModule->theModule); }
153 /*=======================================================*/
154 /* Create the activation. The activation stores pointers */
155 /* to its associated partial match and defrule. The */
156 /* activation is given a time tag, its salience is */
157 /* evaluated, and it is assigned a random number for use */
158 /* with the random conflict resolution strategy. */
159 /*=======================================================*/
161 newActivation = get_struct(theEnv,activation);
162 newActivation->theRule = theRule;
163 newActivation->basis = binds;
164 newActivation->timetag = AgendaData(theEnv)->CurrentTimetag++;
165 newActivation->salience = EvaluateSalience(theEnv,theRule);
167 newActivation->randomID = genrand();
168 newActivation->prev = NULL;
169 newActivation->next = NULL;
171 AgendaData(theEnv)->NumberOfActivations++;
173 /*=======================================================*/
174 /* Point the partial match to the activation to complete */
175 /* the link between the join network and the agenda. */
176 /*=======================================================*/
178 binds->marker = (void *) newActivation;
180 /*====================================================*/
181 /* If activations are being watch, display a message. */
182 /*====================================================*/
184 #if DEBUGGING_FUNCTIONS
185 if (newActivation->theRule->watchActivation)
187 EnvPrintRouter(theEnv,WTRACE,"==> Activation ");
188 PrintActivation(theEnv,WTRACE,(void *) newActivation);
189 EnvPrintRouter(theEnv,WTRACE,"\n");
193 /*=====================================*/
194 /* Place the activation on the agenda. */
195 /*=====================================*/
197 theModuleItem = (struct defruleModule *) theRule->header.whichModule;
199 theGroup = ReuseOrCreateSalienceGroup(theEnv,theModuleItem,newActivation->salience);
201 PlaceActivation(theEnv,&(theModuleItem->agenda),newActivation,theGroup);
204 /***************************************************************/
205 /* ReuseOrCreateSalienceGroup: */
206 /***************************************************************/
207 static struct salienceGroup *ReuseOrCreateSalienceGroup(
209 struct defruleModule *theRuleModule,
212 struct salienceGroup *theGroup, *lastGroup, *newGroup;
214 for (lastGroup = NULL, theGroup = theRuleModule->groupings;
216 lastGroup = theGroup, theGroup = theGroup->next)
218 if (theGroup->salience == salience)
219 { return(theGroup); }
221 if (theGroup->salience < salience)
225 newGroup = get_struct(theEnv,salienceGroup);
226 newGroup->salience = salience;
227 newGroup->first = NULL;
228 newGroup->last = NULL;
229 newGroup->next = theGroup;
230 newGroup->prev = lastGroup;
232 if (newGroup->next != NULL)
233 { newGroup->next->prev = newGroup; }
235 if (newGroup->prev != NULL)
236 { newGroup->prev->next = newGroup; }
238 if (lastGroup == NULL)
239 { theRuleModule->groupings = newGroup; }
244 /***************************************************************/
245 /* FindSalienceGroup: */
246 /***************************************************************/
247 static struct salienceGroup *FindSalienceGroup(
248 struct defruleModule *theRuleModule,
251 struct salienceGroup *theGroup;
253 for (theGroup = theRuleModule->groupings;
255 theGroup = theGroup->next)
257 if (theGroup->salience == salience)
258 { return(theGroup); }
260 if (theGroup->salience < salience)
267 /***************************************************************/
268 /* ClearRuleFromAgenda: Clears the agenda of a specified rule. */
269 /***************************************************************/
270 globle void ClearRuleFromAgenda(
274 struct defrule *theRule = (struct defrule *) vTheRule;
275 struct defrule *tempRule;
276 struct activation *agendaPtr, *agendaNext;
278 /*============================================*/
279 /* Get a pointer to the agenda for the module */
280 /* in which the rule is contained. */
281 /*============================================*/
283 agendaPtr = ((struct defruleModule *) theRule->header.whichModule)->agenda;
285 /*==============================================*/
286 /* Loop through every activation on the agenda. */
287 /*==============================================*/
289 while (agendaPtr != NULL)
291 agendaNext = agendaPtr->next;
293 /*========================================================*/
294 /* Check each disjunct of the rule against the activation */
295 /* to determine if the activation points to the rule. If */
296 /* it does, then remove the activation from the agenda. */
297 /*========================================================*/
299 for (tempRule = theRule;
301 tempRule = tempRule->disjunct)
303 if (agendaPtr->theRule == tempRule)
305 RemoveActivation(theEnv,agendaPtr,TRUE,TRUE);
310 agendaPtr = agendaNext;
314 /****************************************************************/
315 /* EnvGetNextActivation: Returns an activation from the Agenda. */
316 /* If its argument is NULL, then the first activation on the */
317 /* Agenda is returned. If its argument is not NULL, the next */
318 /* activation after the argument is returned. */
319 /****************************************************************/
320 globle void *EnvGetNextActivation(
324 struct defruleModule *theModuleItem;
328 theModuleItem = (struct defruleModule *) GetModuleItem(theEnv,NULL,DefruleData(theEnv)->DefruleModuleIndex);
329 if (theModuleItem == NULL) return(NULL);
330 return((void *) theModuleItem->agenda);
333 { return((void *) (((struct activation *) actPtr)->next)); }
336 /***********************************************/
337 /* EnvGetActivationBasis: Returns the basis of */
338 /* the rule associated with an activation. */
339 /***********************************************/
340 globle struct partialMatch *EnvGetActivationBasis(
345 #pragma unused(theEnv)
347 return ((struct activation *) actPtr)->basis;
350 /*********************************************/
351 /* EnvGetActivationName: Returns the name of */
352 /* the rule associated with an activation. */
353 /*********************************************/
354 globle const char *EnvGetActivationName(
359 #pragma unused(theEnv)
362 return(ValueToString(((struct activation *) actPtr)->theRule->header.name));
365 /******************************************/
366 /* EnvGetActivationRule: Returns the rule */
367 /* associated with an activation. */
368 /******************************************/
369 globle struct defrule *EnvGetActivationRule(
374 #pragma unused(theEnv)
376 return ((struct activation *) actPtr)->theRule;
379 /**************************************************/
380 /* EnvGetActivationSalience: Returns the salience */
381 /* of the rule associated with an activation. */
382 /**************************************************/
383 globle int EnvGetActivationSalience(
388 #pragma unused(theEnv)
390 return ((struct activation *) actPtr)->salience;
393 /**************************************/
394 /* EnvSetActivationSalience: Sets the */
395 /* salience value of an activation. */
396 /**************************************/
397 globle int EnvSetActivationSalience(
404 #pragma unused(theEnv)
407 temp = ((struct activation *) actPtr)->salience;
408 ((struct activation *) actPtr)->salience = value;
412 /**********************************************/
413 /* EnvGetActivationPPForm: Returns the pretty */
414 /* print representation of an activation. */
415 /**********************************************/
416 globle void EnvGetActivationPPForm(
422 OpenStringDestination(theEnv,"ActPPForm",buffer,bufferLength);
423 PrintActivation(theEnv,"ActPPForm",(void *) theActivation);
424 CloseStringDestination(theEnv,"ActPPForm");
427 /****************************************************/
428 /* EnvGetActivationBasisPPForm: Returns the pretty */
429 /* print representation of an activation's basis. */
430 /****************************************************/
431 globle void EnvGetActivationBasisPPForm(
435 void *vTheActivation)
437 struct activation *theActivation = (struct activation *) vTheActivation;
439 OpenStringDestination(theEnv,"ActPPForm",buffer,bufferLength);
440 PrintPartialMatch(theEnv,"ActPPForm",theActivation->basis);
441 CloseStringDestination(theEnv,"ActPPForm");
444 /********************************************/
445 /* MoveActivationToTop: Moves the specified */
446 /* activation to the top of the agenda. */
447 /********************************************/
448 globle intBool MoveActivationToTop(
450 void *vtheActivation)
452 struct activation *prevPtr;
453 struct activation *theActivation = (struct activation *) vtheActivation;
454 struct defruleModule *theModuleItem;
456 /*====================================*/
457 /* Determine the module of the agenda */
458 /* in which the activation is stored. */
459 /*====================================*/
461 theModuleItem = (struct defruleModule *) theActivation->theRule->header.whichModule;
463 /*============================================*/
464 /* If the activation is already at the top of */
465 /* the agenda, then nothing needs to be done. */
466 /*============================================*/
468 if (theActivation == theModuleItem->agenda) return(FALSE);
470 /*=================================================*/
471 /* Update the pointers of the activation preceding */
472 /* and following the activation being moved. */
473 /*=================================================*/
475 prevPtr = theActivation->prev;
476 prevPtr->next = theActivation->next;
477 if (theActivation->next != NULL) theActivation->next->prev = prevPtr;
479 /*=======================================================*/
480 /* Move the activation and then update its pointers, the */
481 /* pointers of the activation following it, and the */
482 /* module pointer to the top activation on the agenda. */
483 /*=======================================================*/
485 theActivation->next = theModuleItem->agenda;
486 theModuleItem->agenda->prev = theActivation;
487 theActivation->prev = NULL;
488 theModuleItem->agenda = theActivation;
490 /*=============================*/
491 /* Mark the agenda as changed. */
492 /*=============================*/
494 AgendaData(theEnv)->AgendaChanged = TRUE;
499 /**********************************************/
500 /* EnvDeleteActivation: Removes the specified */
501 /* activation from the agenda. */
502 /**********************************************/
503 globle intBool EnvDeleteActivation(
507 if (theActivation == NULL) RemoveAllActivations(theEnv);
508 else RemoveActivation(theEnv,(struct activation *) theActivation,TRUE,TRUE);
513 /*******************************************************/
514 /* DetachActivation: Detaches the specified activation */
515 /* from the list of activations on the Agenda. */
516 /*******************************************************/
517 globle intBool DetachActivation(
519 void *vTheActivation)
521 struct defruleModule *theModuleItem;
522 struct activation *theActivation = (struct activation *) vTheActivation;
524 /*============================*/
525 /* A NULL pointer is invalid. */
526 /*============================*/
528 if (theActivation == NULL) SystemError(theEnv,"AGENDA",1);
530 /*====================================*/
531 /* Determine the module of the agenda */
532 /* in which the activation is stored. */
533 /*====================================*/
535 theModuleItem = (struct defruleModule *) theActivation->theRule->header.whichModule;
537 RemoveActivationFromGroup(theEnv,theActivation,theModuleItem);
539 /*========================================================*/
540 /* If the activation is the top activation on the agenda, */
541 /* then update the module pointer to agenda. */
542 /*========================================================*/
544 if (theActivation == theModuleItem->agenda)
545 { theModuleItem->agenda = theActivation->next; }
547 /*==================================================*/
548 /* Update the pointers in the preceding activation. */
549 /*==================================================*/
551 if (theActivation->prev != NULL)
552 { theActivation->prev->next = theActivation->next; }
554 /*==================================================*/
555 /* Update the pointers in the following activation. */
556 /*==================================================*/
558 if (theActivation->next != NULL)
559 { theActivation->next->prev = theActivation->prev; }
561 /*=================================================*/
562 /* Update the pointers in the detached activation. */
563 /*=================================================*/
565 theActivation->prev = NULL;
566 theActivation->next = NULL;
568 /*=============================*/
569 /* Mark the agenda as changed. */
570 /*=============================*/
572 AgendaData(theEnv)->AgendaChanged = TRUE;
577 /****************************************************************************/
578 /* PrintActivation: Prints an activation in a "pretty" format. Salience, */
579 /* rule name, and the partial match which activated the rule are printed. */
580 /****************************************************************************/
581 static void PrintActivation(
583 const char *logicalName,
584 void *vTheActivation)
586 struct activation *theActivation = (struct activation *) vTheActivation;
589 gensprintf(printSpace,"%-6d ",theActivation->salience);
590 EnvPrintRouter(theEnv,logicalName,printSpace);
591 EnvPrintRouter(theEnv,logicalName,ValueToString(theActivation->theRule->header.name));
592 EnvPrintRouter(theEnv,logicalName,": ");
593 PrintPartialMatch(theEnv,logicalName,theActivation->basis);
596 /*******************************/
597 /* EnvAgenda: C access routine */
598 /* for the agenda command. */
599 /*******************************/
600 globle void EnvAgenda(
602 const char *logicalName,
605 struct defmodule *theModule = (struct defmodule *) vTheModule;
607 ListItemsDriver(theEnv,logicalName,theModule,"activation","activations",
608 EnvGetNextActivation,NULL,PrintActivation,NULL);
611 /*******************************************************************/
612 /* RemoveActivation: Returns an activation and its associated data */
613 /* structures to the Memory Manager. Links to other activations */
614 /* and partial matches may also be updated. */
615 /*******************************************************************/
616 globle void RemoveActivation(
618 void *vTheActivation,
622 struct defruleModule *theModuleItem;
623 struct activation *theActivation = (struct activation *) vTheActivation;
625 /*====================================*/
626 /* Determine the module of the agenda */
627 /* in which the activation is stored. */
628 /*====================================*/
630 theModuleItem = (struct defruleModule *) theActivation->theRule->header.whichModule;
632 /*=================================*/
633 /* Update the agenda if necessary. */
634 /*=================================*/
636 if (updateAgenda == TRUE)
638 RemoveActivationFromGroup(theEnv,theActivation,theModuleItem);
640 /*===============================================*/
641 /* Update the pointer links between activations. */
642 /*===============================================*/
644 if (theActivation->prev == NULL)
646 theModuleItem->agenda = theModuleItem->agenda->next;
647 if (theModuleItem->agenda != NULL) theModuleItem->agenda->prev = NULL;
651 theActivation->prev->next = theActivation->next;
652 if (theActivation->next != NULL)
653 { theActivation->next->prev = theActivation->prev; }
656 /*===================================*/
657 /* Indicate removal of activation if */
658 /* activations are being watched. */
659 /*===================================*/
661 #if DEBUGGING_FUNCTIONS
662 if (theActivation->theRule->watchActivation)
664 EnvPrintRouter(theEnv,WTRACE,"<== Activation ");
665 PrintActivation(theEnv,WTRACE,(void *) theActivation);
666 EnvPrintRouter(theEnv,WTRACE,"\n");
670 /*=============================*/
671 /* Mark the agenda as changed. */
672 /*=============================*/
674 AgendaData(theEnv)->AgendaChanged = TRUE;
677 /*============================================*/
678 /* Update join and agenda links if necessary. */
679 /*============================================*/
681 if ((updateLinks == TRUE) && (theActivation->basis != NULL))
682 { theActivation->basis->marker = NULL; }
684 /*================================================*/
685 /* Return the activation to the free memory pool. */
686 /*================================================*/
688 AgendaData(theEnv)->NumberOfActivations--;
690 rtn_struct(theEnv,activation,theActivation);
693 /**************************************************************/
694 /* RemoveActivationFromGroup: */
695 /**************************************************************/
696 static void RemoveActivationFromGroup(
698 struct activation *theActivation,
699 struct defruleModule *theRuleModule)
701 struct salienceGroup *theGroup;
703 theGroup = FindSalienceGroup(theRuleModule,theActivation->salience);
704 if (theGroup == NULL) return;
706 if (theActivation == theGroup->first)
708 /*====================================================*/
709 /* If the activation is the only remaining activation */
710 /* in the group, then the group needs to be removed. */
711 /*====================================================*/
713 if (theActivation == theGroup->last)
715 if (theGroup->prev == NULL)
716 { theRuleModule->groupings = theGroup->next; }
718 { theGroup->prev->next = theGroup->next; }
720 if (theGroup->next != NULL)
721 { theGroup->next->prev = theGroup->prev; }
723 rtn_struct(theEnv,salienceGroup,theGroup);
726 /*======================================================*/
727 /* Otherwise this is the first activation in the group, */
728 /* but there are other activations which follow. */
729 /*======================================================*/
732 { theGroup->first = theActivation->next; }
736 /*====================================================*/
737 /* Otherwise if the activation isn't the first in the */
738 /* group, then check to see if it's the last. */
739 /*====================================================*/
741 if (theActivation == theGroup->last)
742 { theGroup->last = theActivation->prev; }
744 /*==================================================*/
745 /* Otherwise the activation is in the middle of the */
746 /* group and no first/last updates are needed. */
747 /*==================================================*/
754 /**************************************************************/
755 /* AgendaClearFunction: Agenda clear routine for use with the */
756 /* clear command. Resets the current time tag to zero. */
757 /**************************************************************/
758 static void AgendaClearFunction(
761 AgendaData(theEnv)->CurrentTimetag = 0;
764 /*************************************************/
765 /* RemoveAllActivations: Removes all activations */
766 /* from the agenda of the current module. */
767 /*************************************************/
768 globle void RemoveAllActivations(
771 struct activation *tempPtr, *theActivation;
772 struct salienceGroup *theGroup, *tempGroup;
774 theActivation = GetDefruleModuleItem(theEnv,NULL)->agenda;
775 while (theActivation != NULL)
777 tempPtr = theActivation->next;
778 RemoveActivation(theEnv,theActivation,TRUE,TRUE);
779 theActivation = tempPtr;
782 theGroup = GetDefruleModuleItem(theEnv,NULL)->groupings;
783 while (theGroup != NULL)
785 tempGroup = theGroup->next;
786 rtn_struct(theEnv,salienceGroup,theGroup);
787 theGroup = tempGroup;
791 /*********************************************************/
792 /* EnvGetAgendaChanged: Returns the value of the boolean */
793 /* flag which indicates whether any changes have been */
794 /* made to the agenda. */
795 /*********************************************************/
796 globle int EnvGetAgendaChanged(
799 return(AgendaData(theEnv)->AgendaChanged);
802 /*****************************************************************/
803 /* EnvSetAgendaChanged: Sets the value of the boolean flag which */
804 /* indicates whether any changes have been made to the agenda. */
805 /*****************************************************************/
806 globle void EnvSetAgendaChanged(
810 AgendaData(theEnv)->AgendaChanged = value;
813 /**********************************************************/
814 /* EnvReorderAgenda: Completely reorders the agenda based */
815 /* on the current conflict resolution strategy. */
816 /**********************************************************/
817 globle void EnvReorderAgenda(
821 struct activation *theActivation, *tempPtr;
822 struct defmodule *theModule = (struct defmodule *) vTheModule;
823 int allModules = FALSE;
824 struct defruleModule *theModuleItem;
825 struct salienceGroup *theGroup, *tempGroup;
827 /*=============================================*/
828 /* If the module specified is a NULL pointer, */
829 /* then every module has its agenda reordered. */
830 /*=============================================*/
832 if (theModule == NULL)
835 theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
838 /*========================*/
839 /* Reorder the agenda(s). */
840 /*========================*/
844 theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
846 /*=================================*/
847 /* Get the list of activations and */
848 /* remove them from the agenda. */
849 /*=================================*/
851 theModuleItem = GetDefruleModuleItem(theEnv,theModule);
852 theActivation = theModuleItem->agenda;
853 theModuleItem->agenda = NULL;
855 theGroup = theModuleItem->groupings;
856 while (theGroup != NULL)
858 tempGroup = theGroup->next;
859 rtn_struct(theEnv,salienceGroup,theGroup);
860 theGroup = tempGroup;
863 theModuleItem->groupings = NULL;
865 /*=========================================*/
866 /* Reorder the activations by placing them */
867 /* back on the agenda one by one. */
868 /*=========================================*/
870 while (theActivation != NULL)
872 tempPtr = theActivation->next;
873 theActivation->next = NULL;
874 theActivation->prev = NULL;
875 theGroup = ReuseOrCreateSalienceGroup(theEnv,theModuleItem,theActivation->salience);
876 PlaceActivation(theEnv,&(theModuleItem->agenda),theActivation,theGroup);
877 theActivation = tempPtr;
880 /*===============================================*/
881 /* Return if only one agenda is being reordered. */
882 /*===============================================*/
884 if (! allModules) return;
888 /****************************************************/
889 /* GetNumberOfActivations: Returns the value of the */
890 /* total number of activations on all agendas. */
891 /****************************************************/
892 globle unsigned long GetNumberOfActivations(
895 return(AgendaData(theEnv)->NumberOfActivations);
898 /******************************************************/
899 /* RefreshCommand: H/L Command for refreshing a rule. */
900 /* Syntax: (refresh <defrule-name>) */
901 /******************************************************/
902 globle void RefreshCommand(
905 const char *ruleName;
908 /*===========================*/
909 /* Get the name of the rule. */
910 /*===========================*/
912 ruleName = GetConstructName(theEnv,"refresh","rule name");
913 if (ruleName == NULL) return;
915 /*===============================*/
916 /* Determine if the rule exists. */
917 /*===============================*/
919 rulePtr = EnvFindDefrule(theEnv,ruleName);
922 CantFindItemErrorMessage(theEnv,"defrule",ruleName);
926 /*===================*/
927 /* Refresh the rule. */
928 /*===================*/
930 EnvRefresh(theEnv,rulePtr);
933 /************************************************************/
934 /* EnvRefresh: Refreshes a defrule. Activations of the rule */
935 /* that have already been fired are added to the agenda. */
936 /************************************************************/
937 globle intBool EnvRefresh(
941 struct defrule *rulePtr;
942 struct partialMatch *listOfMatches;
945 /*====================================*/
946 /* Refresh each disjunct of the rule. */
947 /*====================================*/
949 for (rulePtr = (struct defrule *) theRule;
951 rulePtr = rulePtr->disjunct)
953 /*================================*/
954 /* Check each partial match that */
955 /* satisfies the LHS of the rule. */
956 /*================================*/
958 for (b = 0; b < rulePtr->lastJoin->leftMemory->size; b++)
960 for (listOfMatches = rulePtr->lastJoin->leftMemory->beta[b];
961 listOfMatches != NULL;
962 listOfMatches = listOfMatches->nextInMemory)
964 /*=======================================================*/
965 /* If the partial match is associated with an activation */
966 /* (which it should always be), then place a new */
967 /* activation on the agenda if this partial matchdoesn't */
968 /* have an activation associated with it. */
969 /*=======================================================*/
971 if (((struct joinNode *) listOfMatches->owner)->ruleToActivate != NULL)
973 if (listOfMatches->marker == NULL)
974 { AddActivation(theEnv,rulePtr,listOfMatches); }
983 /**********************************************/
984 /* RefreshAgendaCommand: H/L access routine */
985 /* for the refresh-agenda command. */
986 /**********************************************/
987 globle void RefreshAgendaCommand(
991 struct defmodule *theModule;
993 /*==============================================*/
994 /* This function can have at most one argument. */
995 /*==============================================*/
997 if ((numArgs = EnvArgCountCheck(theEnv,"refresh-agenda",NO_MORE_THAN,1)) == -1) return;
999 /*===============================================================*/
1000 /* If a module name is specified, then the agenda of that module */
1001 /* is refreshed. Otherwise, the agenda of the current module is */
1003 /*===============================================================*/
1007 theModule = GetModuleName(theEnv,"refresh-agenda",1,&error);
1011 { theModule = ((struct defmodule *) EnvGetCurrentModule(theEnv)); }
1013 /*===============================================*/
1014 /* Refresh the agenda of the appropriate module. */
1015 /*===============================================*/
1017 EnvRefreshAgenda(theEnv,theModule);
1020 /**************************************/
1021 /* EnvRefreshAgenda: C access routine */
1022 /* for the refresh-agenda command. */
1023 /**************************************/
1024 globle void EnvRefreshAgenda(
1028 struct activation *theActivation;
1029 struct defmodule *theModule = (struct defmodule *) vTheModule;
1031 int allModules = FALSE;
1033 /*==========================*/
1034 /* Save the current module. */
1035 /*==========================*/
1037 SaveCurrentModule(theEnv);
1039 /*=============================================*/
1040 /* If the module specified is a NULL pointer, */
1041 /* then every module has its agenda refreshed. */
1042 /*=============================================*/
1044 if (theModule == NULL)
1047 theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
1050 /*=======================================================*/
1051 /* Remember the current setting for salience evaluation. */
1052 /* To perform the refresh, the when activated setting is */
1053 /* used to recompute the salience values. */
1054 /*=======================================================*/
1056 oldValue = EnvGetSalienceEvaluation(theEnv);
1057 EnvSetSalienceEvaluation(theEnv,WHEN_ACTIVATED);
1059 /*========================*/
1060 /* Refresh the agenda(s). */
1061 /*========================*/
1065 theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
1067 /*=========================================*/
1068 /* Change the current module to the module */
1069 /* of the agenda being refreshed. */
1070 /*=========================================*/
1072 EnvSetCurrentModule(theEnv,(void *) theModule);
1074 /*================================================================*/
1075 /* Recompute the salience values for the current module's agenda. */
1076 /*================================================================*/
1078 for (theActivation = (struct activation *) EnvGetNextActivation(theEnv,NULL);
1079 theActivation != NULL;
1080 theActivation = (struct activation *) EnvGetNextActivation(theEnv,theActivation))
1081 { theActivation->salience = EvaluateSalience(theEnv,theActivation->theRule); }
1083 /*======================================================*/
1084 /* Reorder the agenda based on the new salience values. */
1085 /*======================================================*/
1087 EnvReorderAgenda(theEnv,theModule);
1089 /*===============================================*/
1090 /* Return if only one agenda is being refreshed. */
1091 /*===============================================*/
1095 EnvSetSalienceEvaluation(theEnv,oldValue);
1096 RestoreCurrentModule(theEnv);
1101 /*==========================================*/
1102 /* Restore the salience evaluation setting. */
1103 /*==========================================*/
1105 EnvSetSalienceEvaluation(theEnv,oldValue);
1107 /*=============================*/
1108 /* Restore the current module. */
1109 /*=============================*/
1111 RestoreCurrentModule(theEnv);
1114 /*********************************************************/
1115 /* SetSalienceEvaluationCommand: H/L Command for setting */
1116 /* the salience evaluation behavior. */
1117 /* Syntax: (set-salience-evaluation-behavior <symbol>) */
1118 /*********************************************************/
1119 globle void *SetSalienceEvaluationCommand(
1123 const char *argument;
1124 const char *oldValue;
1126 /*==================================================*/
1127 /* Get the current setting for salience evaluation. */
1128 /*==================================================*/
1130 oldValue = SalienceEvaluationName(EnvGetSalienceEvaluation(theEnv));
1132 /*=========================================*/
1133 /* This function expects a single argument */
1134 /* which must be a symbol. */
1135 /*=========================================*/
1137 if (EnvArgCountCheck(theEnv,"set-salience-evaluation",EXACTLY,1) == -1)
1138 { return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue)); }
1140 if (EnvArgTypeCheck(theEnv,"set-salience-evaluation",1,SYMBOL,&argPtr) == FALSE)
1141 { return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue)); }
1143 /*=============================================================*/
1144 /* The allowed symbols to pass as an argument to this function */
1145 /* are when-defined, when-activated, and every-cycle. */
1146 /*=============================================================*/
1148 argument = DOToString(argPtr);
1150 if (strcmp(argument,"when-defined") == 0)
1151 { EnvSetSalienceEvaluation(theEnv,WHEN_DEFINED); }
1152 else if (strcmp(argument,"when-activated") == 0)
1153 { EnvSetSalienceEvaluation(theEnv,WHEN_ACTIVATED); }
1154 else if (strcmp(argument,"every-cycle") == 0)
1155 { EnvSetSalienceEvaluation(theEnv,EVERY_CYCLE); }
1158 ExpectedTypeError1(theEnv,"set-salience-evaluation",1,
1159 "symbol with value when-defined, when-activated, or every-cycle");
1160 return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
1163 /*=================================================*/
1164 /* Return the old setting for salience evaluation. */
1165 /*=================================================*/
1167 return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
1170 /*********************************************************/
1171 /* GetSalienceEvaluationCommand: H/L Command for getting */
1172 /* the salience evaluation behavior. */
1173 /* Syntax: (get-salience-evaluation-behavior) */
1174 /*********************************************************/
1175 globle void *GetSalienceEvaluationCommand(
1178 EnvArgCountCheck(theEnv,"get-salience-evaluation",EXACTLY,0);
1180 return((SYMBOL_HN *) EnvAddSymbol(theEnv,SalienceEvaluationName(EnvGetSalienceEvaluation(theEnv))));
1183 /*****************************************************************/
1184 /* SalienceEvaluationName: Given the integer value corresponding */
1185 /* to a specified salience evaluation behavior, returns a */
1186 /* character string of the behavior's name. */
1187 /*****************************************************************/
1188 static const char *SalienceEvaluationName(
1196 sname = "when-defined";
1198 case WHEN_ACTIVATED:
1199 sname = "when-activated";
1202 sname = "every-cycle";
1212 /****************************************************************/
1213 /* EnvGetSalienceEvaluation: Returns the value of current type */
1214 /* of salience evaluation (e.g., when defined, when activated, */
1215 /* or every cycle). */
1216 /****************************************************************/
1217 globle intBool EnvGetSalienceEvaluation(
1220 return(AgendaData(theEnv)->SalienceEvaluation);
1223 /***********************************************/
1224 /* EnvSetSalienceEvaluation: Sets the value of */
1225 /* the current type of salience evaluation. */
1226 /***********************************************/
1227 globle intBool EnvSetSalienceEvaluation(
1233 ov = AgendaData(theEnv)->SalienceEvaluation;
1234 AgendaData(theEnv)->SalienceEvaluation = value;
1238 /*****************************************************************/
1239 /* EvaluateSalience: Returns the salience value of the specified */
1240 /* defrule. If salience evaluation is currently set to */
1241 /* when-defined, then the current value of the rule's salience */
1242 /* is returned. Otherwise the salience expression associated */
1243 /* with the rule is reevaluated, the value is stored as the */
1244 /* rule's current salience, and it is then returned. */
1245 /*****************************************************************/
1246 static int EvaluateSalience(
1250 struct defrule *rPtr = (struct defrule *) vPtr;
1251 DATA_OBJECT salienceValue;
1254 /*==================================================*/
1255 /* If saliences are only being evaluated when rules */
1256 /* are defined, then just return the last salience */
1257 /* value evaluated for the rule. */
1258 /*==================================================*/
1260 if (EnvGetSalienceEvaluation(theEnv) == WHEN_DEFINED)
1261 { return(rPtr->salience); }
1263 /*=================================================================*/
1264 /* If the rule's salience value was defined as an integer constant */
1265 /* (i.e., not an expression or global variable which could change */
1266 /* on reevaluation), then just return the salience value computed */
1267 /* for the rule when it was defined. */
1268 /*=================================================================*/
1270 if (rPtr->dynamicSalience == NULL) return(rPtr->salience);
1272 /*====================================================*/
1273 /* Reevaluate the rule's salience. If an error occurs */
1274 /* during evaluation, print an error message. */
1275 /*====================================================*/
1277 SetEvaluationError(theEnv,FALSE);
1278 if (EvaluateExpression(theEnv,rPtr->dynamicSalience,&salienceValue))
1280 SalienceInformationError(theEnv,"defrule",ValueToString(rPtr->header.name));
1281 return(rPtr->salience);
1284 /*========================================*/
1285 /* The salience value must be an integer. */
1286 /*========================================*/
1288 if (salienceValue.type != INTEGER)
1290 SalienceNonIntegerError(theEnv);
1291 SalienceInformationError(theEnv,"defrule",ValueToString(rPtr->header.name));
1292 SetEvaluationError(theEnv,TRUE);
1293 return(rPtr->salience);
1296 /*==========================================*/
1297 /* The salience value must fall between the */
1298 /* minimum and maximum allowed values. */
1299 /*==========================================*/
1301 salience = (int) ValueToLong(salienceValue.value);
1303 if ((salience > MAX_DEFRULE_SALIENCE) || (salience < MIN_DEFRULE_SALIENCE))
1305 SalienceRangeError(theEnv,MIN_DEFRULE_SALIENCE,MAX_DEFRULE_SALIENCE);
1306 SetEvaluationError(theEnv,TRUE);
1307 SalienceInformationError(theEnv,"defrule",ValueToString(((struct defrule *) rPtr)->header.name));
1308 return(rPtr->salience);
1311 /*===================================*/
1312 /* Store the new salience value with */
1313 /* the rule and return this value. */
1314 /*===================================*/
1316 rPtr->salience = salience;
1317 return(rPtr->salience);
1320 #if DEBUGGING_FUNCTIONS
1322 /***********************************************/
1323 /* AgendaCommand: Prints out the agenda of the */
1324 /* rules that are ready to fire. */
1325 /* Syntax: (agenda) */
1326 /***********************************************/
1327 globle void AgendaCommand(
1331 struct defmodule *theModule;
1333 /*==============================================*/
1334 /* This function can have at most one argument. */
1335 /*==============================================*/
1337 if ((numArgs = EnvArgCountCheck(theEnv,"agenda",NO_MORE_THAN,1)) == -1) return;
1339 /*===============================================================*/
1340 /* If a module name is specified, then the agenda of that module */
1341 /* is displayed. Otherwise, the agenda of the current module is */
1343 /*===============================================================*/
1347 theModule = GetModuleName(theEnv,"agenda",1,&error);
1351 { theModule = ((struct defmodule *) EnvGetCurrentModule(theEnv)); }
1353 /*===============================================*/
1354 /* Display the agenda of the appropriate module. */
1355 /*===============================================*/
1357 EnvAgenda(theEnv,WDISPLAY,theModule);
1360 #endif /* DEBUGGING_FUNCTIONS */
1362 /*#####################################*/
1363 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
1364 /*#####################################*/
1366 #if ALLOW_ENVIRONMENT_GLOBALS
1369 const char *logicalName,
1372 EnvAgenda(GetCurrentEnvironment(),logicalName,vTheModule);
1375 globle intBool DeleteActivation(
1376 void *theActivation)
1378 return EnvDeleteActivation(GetCurrentEnvironment(),theActivation);
1381 globle struct partialMatch *GetActivationBasis(
1384 return EnvGetActivationBasis(GetCurrentEnvironment(),actPtr);
1387 globle const char *GetActivationName(
1390 return EnvGetActivationName(GetCurrentEnvironment(),actPtr);
1393 globle void GetActivationPPForm(
1395 unsigned bufferLength,
1396 void *theActivation)
1398 EnvGetActivationPPForm(GetCurrentEnvironment(),buffer,bufferLength,theActivation);
1401 globle struct defrule *GetActivationRule(
1404 return EnvGetActivationRule(GetCurrentEnvironment(),actPtr);
1407 globle int GetActivationSalience(
1410 return EnvGetActivationSalience(GetCurrentEnvironment(),actPtr);
1413 globle int GetAgendaChanged()
1415 return EnvGetAgendaChanged(GetCurrentEnvironment());
1418 globle void *GetNextActivation(
1421 return EnvGetNextActivation(GetCurrentEnvironment(),actPtr);
1424 globle intBool Refresh(
1427 return EnvRefresh(GetCurrentEnvironment(),theRule);
1430 globle void RefreshAgenda(
1433 EnvRefreshAgenda(GetCurrentEnvironment(),vTheModule);
1436 globle void ReorderAgenda(
1439 EnvReorderAgenda(GetCurrentEnvironment(),vTheModule);
1442 globle void SetAgendaChanged(
1445 EnvSetAgendaChanged(GetCurrentEnvironment(),value);
1448 globle int SetActivationSalience(
1452 return EnvSetActivationSalience(GetCurrentEnvironment(),actPtr,value);
1455 globle intBool GetSalienceEvaluation()
1457 return EnvGetSalienceEvaluation(GetCurrentEnvironment());
1460 globle intBool SetSalienceEvaluation(
1463 return EnvSetSalienceEvaluation(GetCurrentEnvironment(),value);
1468 #endif /* DEFRULE_CONSTRUCT */