1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 02/04/15 */
5 /* */
6 /* FACT MANAGER MODULE */
7 /*******************************************************/
8
9 /*************************************************************/
10 /* Purpose: Provides core routines for maintaining the fact */
11 /* list including assert/retract operations, data */
12 /* structure creation/deletion, printing, slot access, */
13 /* and other utility functions. */
14 /* */
15 /* Principal Programmer(s): */
16 /* Gary D. Riley */
17 /* */
18 /* Contributing Programmer(s): */
19 /* Brian L. Dantes */
20 /* */
21 /* Revision History: */
22 /* */
23 /* 6.23: Added support for templates maintaining their */
24 /* own list of facts. */
25 /* */
26 /* 6.24: Removed LOGICAL_DEPENDENCIES compilation flag. */
27 /* */
28 /* Renamed BOOLEAN macro type to intBool. */
29 /* */
30 /* AssignFactSlotDefaults function does not */
31 /* properly handle defaults for multifield slots. */
32 /* DR0869 */
33 /* */
34 /* Support for ppfact command. */
35 /* */
36 /* 6.30: Callback function support for assertion, */
37 /* retraction, and modification of facts. */
38 /* */
39 /* Updates to fact pattern entity record. */
40 /* */
41 /* Changed integer type/precision. */
42 /* */
43 /* Changed garbage collection algorithm. */
44 /* */
45 /* Removed conditional code for unsupported */
46 /* compilers/operating systems (IBM_MCW, */
47 /* MAC_MCW, and IBM_TBC). */
48 /* */
49 /* Added const qualifiers to remove C++ */
50 /* deprecation warnings. */
51 /* */
52 /* Converted API macros to function calls. */
53 /* */
54 /* Removed unused global variables. */
55 /* */
56 /* Added code to prevent a clear command from */
57 /* being executed during fact assertions via */
58 /* JoinOperationInProgress mechanism. */
59 /* */
60 /* Added code to keep track of pointers to */
61 /* constructs that are contained externally to */
62 /* to constructs, DanglingConstructs. */
63 /* */
64 /*************************************************************/
65
66
67 #define _FACTMNGR_SOURCE_
68
69 #include <stdio.h>
70 #define _STDIO_INCLUDED_
71
72 #include "setup.h"
73
74 #if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
75
76 #include "constant.h"
77 #include "symbol.h"
78 #include "memalloc.h"
79 #include "exprnpsr.h"
80 #include "argacces.h"
81 #include "scanner.h"
82 #include "router.h"
83 #include "strngrtr.h"
84 #include "match.h"
85 #include "factbld.h"
86 #include "factqury.h"
87 #include "reteutil.h"
88 #include "retract.h"
89 #include "factcmp.h"
90 #include "filecom.h"
91 #include "factfun.h"
92 #include "factcom.h"
93 #include "constrct.h"
94 #include "factrhs.h"
95 #include "factmch.h"
96 #include "watch.h"
97 #include "utility.h"
98 #include "factbin.h"
99 #include "factmngr.h"
100 #include "facthsh.h"
101 #include "default.h"
102 #include "commline.h"
103 #include "envrnmnt.h"
104 #include "sysdep.h"
105
106 #include "engine.h"
107 #include "lgcldpnd.h"
108 #include "drive.h"
109 #include "ruledlt.h"
110
111 #include "tmpltbsc.h"
112 #include "tmpltdef.h"
113 #include "tmpltutl.h"
114 #include "tmpltfun.h"
115
116 /***************************************/
117 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
118 /***************************************/
119
120 static void ResetFacts(void *);
121 static int ClearFactsReady(void *);
122 static void RemoveGarbageFacts(void *);
123 static void DeallocateFactData(void *);
124
125 /**************************************************************/
126 /* InitializeFacts: Initializes the fact data representation. */
127 /* Facts are only available when both the defrule and */
128 /* deftemplate constructs are available. */
129 /**************************************************************/
InitializeFacts(void * theEnv)130 globle void InitializeFacts(
131 void *theEnv)
132 {
133 struct patternEntityRecord factInfo = { { "FACT_ADDRESS", FACT_ADDRESS,1,0,0,
134 PrintFactIdentifier,
135 PrintFactIdentifierInLongForm,
136 EnvRetract,
137 NULL,
138 EnvGetNextFact,
139 EnvDecrementFactCount,
140 EnvIncrementFactCount,NULL,NULL,NULL,NULL,NULL
141 },
142 DecrementFactBasisCount,
143 IncrementFactBasisCount,
144 MatchFactFunction,
145 NULL,
146 FactIsDeleted
147 };
148
149 struct fact dummyFact = { { NULL, NULL, 0, 0L }, NULL, NULL, -1L, 0, 1,
150 NULL, NULL, NULL, NULL, { 1, 0UL, NULL, { { 0, NULL } } } };
151
152 AllocateEnvironmentData(theEnv,FACTS_DATA,sizeof(struct factsData),DeallocateFactData);
153
154 memcpy(&FactData(theEnv)->FactInfo,&factInfo,sizeof(struct patternEntityRecord));
155 dummyFact.factHeader.theInfo = &FactData(theEnv)->FactInfo;
156 memcpy(&FactData(theEnv)->DummyFact,&dummyFact,sizeof(struct fact));
157 FactData(theEnv)->LastModuleIndex = -1;
158
159 /*=========================================*/
160 /* Initialize the fact hash table (used to */
161 /* quickly determine if a fact exists). */
162 /*=========================================*/
163
164 InitializeFactHashTable(theEnv);
165
166 /*============================================*/
167 /* Initialize the fact callback functions for */
168 /* use with the reset and clear commands. */
169 /*============================================*/
170
171 EnvAddResetFunction(theEnv,"facts",ResetFacts,60);
172 AddClearReadyFunction(theEnv,"facts",ClearFactsReady,0);
173
174 /*=============================*/
175 /* Initialize periodic garbage */
176 /* collection for facts. */
177 /*=============================*/
178
179 AddCleanupFunction(theEnv,"facts",RemoveGarbageFacts,0);
180
181 /*===================================*/
182 /* Initialize fact pattern matching. */
183 /*===================================*/
184
185 InitializeFactPatterns(theEnv);
186
187 /*==================================*/
188 /* Initialize the facts keyword for */
189 /* use with the watch command. */
190 /*==================================*/
191
192 #if DEBUGGING_FUNCTIONS
193 AddWatchItem(theEnv,"facts",0,&FactData(theEnv)->WatchFacts,80,DeftemplateWatchAccess,DeftemplateWatchPrint);
194 #endif
195
196 /*=========================================*/
197 /* Initialize fact commands and functions. */
198 /*=========================================*/
199
200 FactCommandDefinitions(theEnv);
201 FactFunctionDefinitions(theEnv);
202
203 /*==============================*/
204 /* Initialize fact set queries. */
205 /*==============================*/
206
207 #if FACT_SET_QUERIES
208 SetupFactQuery(theEnv);
209 #endif
210
211 /*==================================*/
212 /* Initialize fact patterns for use */
213 /* with the bload/bsave commands. */
214 /*==================================*/
215
216 #if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME)
217 FactBinarySetup(theEnv);
218 #endif
219
220 /*===================================*/
221 /* Initialize fact patterns for use */
222 /* with the constructs-to-c command. */
223 /*===================================*/
224
225 #if CONSTRUCT_COMPILER && (! RUN_TIME)
226 FactPatternsCompilerSetup(theEnv);
227 #endif
228 }
229
230 /***********************************/
231 /* DeallocateFactData: Deallocates */
232 /* environment data for facts. */
233 /***********************************/
DeallocateFactData(void * theEnv)234 static void DeallocateFactData(
235 void *theEnv)
236 {
237 struct factHashEntry *tmpFHEPtr, *nextFHEPtr;
238 struct fact *tmpFactPtr, *nextFactPtr;
239 unsigned long i;
240 struct patternMatch *theMatch, *tmpMatch;
241
242 for (i = 0; i < FactData(theEnv)->FactHashTableSize; i++)
243 {
244 tmpFHEPtr = FactData(theEnv)->FactHashTable[i];
245
246 while (tmpFHEPtr != NULL)
247 {
248 nextFHEPtr = tmpFHEPtr->next;
249 rtn_struct(theEnv,factHashEntry,tmpFHEPtr);
250 tmpFHEPtr = nextFHEPtr;
251 }
252 }
253
254 rm3(theEnv,FactData(theEnv)->FactHashTable,
255 sizeof(struct factHashEntry *) * FactData(theEnv)->FactHashTableSize);
256
257 tmpFactPtr = FactData(theEnv)->FactList;
258 while (tmpFactPtr != NULL)
259 {
260 nextFactPtr = tmpFactPtr->nextFact;
261
262 theMatch = (struct patternMatch *) tmpFactPtr->list;
263 while (theMatch != NULL)
264 {
265 tmpMatch = theMatch->next;
266 rtn_struct(theEnv,patternMatch,theMatch);
267 theMatch = tmpMatch;
268 }
269
270 ReturnEntityDependencies(theEnv,(struct patternEntity *) tmpFactPtr);
271
272 ReturnFact(theEnv,tmpFactPtr);
273 tmpFactPtr = nextFactPtr;
274 }
275
276 tmpFactPtr = FactData(theEnv)->GarbageFacts;
277 while (tmpFactPtr != NULL)
278 {
279 nextFactPtr = tmpFactPtr->nextFact;
280
281 ReturnFact(theEnv,tmpFactPtr);
282 tmpFactPtr = nextFactPtr;
283 }
284
285 DeallocateCallListWithArg(theEnv,FactData(theEnv)->ListOfAssertFunctions);
286 DeallocateCallListWithArg(theEnv,FactData(theEnv)->ListOfRetractFunctions);
287 DeallocateCallListWithArg(theEnv,FactData(theEnv)->ListOfModifyFunctions);
288 }
289
290 /**********************************************/
291 /* PrintFactWithIdentifier: Displays a single */
292 /* fact preceded by its fact identifier. */
293 /**********************************************/
PrintFactWithIdentifier(void * theEnv,const char * logicalName,struct fact * factPtr)294 globle void PrintFactWithIdentifier(
295 void *theEnv,
296 const char *logicalName,
297 struct fact *factPtr)
298 {
299 char printSpace[20];
300
301 gensprintf(printSpace,"f-%-5lld ",factPtr->factIndex);
302 EnvPrintRouter(theEnv,logicalName,printSpace);
303 PrintFact(theEnv,logicalName,factPtr,FALSE,FALSE);
304 }
305
306 /****************************************************/
307 /* PrintFactIdentifier: Displays a fact identifier. */
308 /****************************************************/
PrintFactIdentifier(void * theEnv,const char * logicalName,void * factPtr)309 globle void PrintFactIdentifier(
310 void *theEnv,
311 const char *logicalName,
312 void *factPtr)
313 {
314 char printSpace[20];
315
316 gensprintf(printSpace,"f-%lld",((struct fact *) factPtr)->factIndex);
317 EnvPrintRouter(theEnv,logicalName,printSpace);
318 }
319
320 /********************************************/
321 /* PrintFactIdentifierInLongForm: Display a */
322 /* fact identifier in a longer format. */
323 /********************************************/
PrintFactIdentifierInLongForm(void * theEnv,const char * logicalName,void * factPtr)324 globle void PrintFactIdentifierInLongForm(
325 void *theEnv,
326 const char *logicalName,
327 void *factPtr)
328 {
329 if (PrintUtilityData(theEnv)->AddressesToStrings) EnvPrintRouter(theEnv,logicalName,"\"");
330 if (factPtr != (void *) &FactData(theEnv)->DummyFact)
331 {
332 EnvPrintRouter(theEnv,logicalName,"<Fact-");
333 PrintLongInteger(theEnv,logicalName,((struct fact *) factPtr)->factIndex);
334 EnvPrintRouter(theEnv,logicalName,">");
335 }
336 else
337 { EnvPrintRouter(theEnv,logicalName,"<Dummy Fact>"); }
338
339 if (PrintUtilityData(theEnv)->AddressesToStrings) EnvPrintRouter(theEnv,logicalName,"\"");
340 }
341
342 /*******************************************/
343 /* DecrementFactBasisCount: Decrements the */
344 /* partial match busy count of a fact */
345 /*******************************************/
DecrementFactBasisCount(void * theEnv,void * vFactPtr)346 globle void DecrementFactBasisCount(
347 void *theEnv,
348 void *vFactPtr)
349 {
350 struct fact *factPtr = (struct fact *) vFactPtr;
351 struct multifield *theSegment;
352 int i;
353
354 EnvDecrementFactCount(theEnv,factPtr);
355
356 theSegment = &factPtr->theProposition;
357
358 for (i = 0 ; i < (int) theSegment->multifieldLength ; i++)
359 {
360 AtomDeinstall(theEnv,theSegment->theFields[i].type,theSegment->theFields[i].value);
361 }
362 }
363
364 /*******************************************/
365 /* IncrementFactBasisCount: Increments the */
366 /* partial match busy count of a fact. */
367 /*******************************************/
IncrementFactBasisCount(void * theEnv,void * vFactPtr)368 globle void IncrementFactBasisCount(
369 void *theEnv,
370 void *vFactPtr)
371 {
372 struct fact *factPtr = (struct fact *) vFactPtr;
373 struct multifield *theSegment;
374 int i;
375
376 EnvIncrementFactCount(theEnv,factPtr);
377
378 theSegment = &factPtr->theProposition;
379
380 for (i = 0 ; i < (int) theSegment->multifieldLength ; i++)
381 {
382 AtomInstall(theEnv,theSegment->theFields[i].type,theSegment->theFields[i].value);
383 }
384 }
385
386 /******************/
387 /* FactIsDeleted: */
388 /******************/
FactIsDeleted(void * theEnv,void * theFact)389 globle intBool FactIsDeleted(
390 void *theEnv,
391 void *theFact)
392 {
393 #if MAC_XCD
394 #pragma unused(theEnv)
395 #endif
396
397 return(((struct fact *) theFact)->garbage);
398 }
399
400 /**************************************************/
401 /* PrintFact: Displays the printed representation */
402 /* of a fact containing the relation name and */
403 /* all of the fact's slots or fields. */
404 /**************************************************/
PrintFact(void * theEnv,const char * logicalName,struct fact * factPtr,int seperateLines,int ignoreDefaults)405 globle void PrintFact(
406 void *theEnv,
407 const char *logicalName,
408 struct fact *factPtr,
409 int seperateLines,
410 int ignoreDefaults)
411 {
412 struct multifield *theMultifield;
413
414 /*=========================================*/
415 /* Print a deftemplate (non-ordered) fact. */
416 /*=========================================*/
417
418 if (factPtr->whichDeftemplate->implied == FALSE)
419 {
420 PrintTemplateFact(theEnv,logicalName,factPtr,seperateLines,ignoreDefaults);
421 return;
422 }
423
424 /*==============================*/
425 /* Print an ordered fact (which */
426 /* has an implied deftemplate). */
427 /*==============================*/
428
429 EnvPrintRouter(theEnv,logicalName,"(");
430
431 EnvPrintRouter(theEnv,logicalName,factPtr->whichDeftemplate->header.name->contents);
432
433 theMultifield = (struct multifield *) factPtr->theProposition.theFields[0].value;
434 if (theMultifield->multifieldLength != 0)
435 {
436 EnvPrintRouter(theEnv,logicalName," ");
437 PrintMultifield(theEnv,logicalName,theMultifield,0,
438 (long) (theMultifield->multifieldLength - 1),
439 FALSE);
440 }
441
442 EnvPrintRouter(theEnv,logicalName,")");
443 }
444
445 /*********************************************/
446 /* MatchFactFunction: Filters a fact through */
447 /* the appropriate fact pattern network. */
448 /*********************************************/
MatchFactFunction(void * theEnv,void * vTheFact)449 globle void MatchFactFunction(
450 void *theEnv,
451 void *vTheFact)
452 {
453 struct fact *theFact = (struct fact *) vTheFact;
454
455 FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,NULL,NULL);
456 }
457
458 /*********************************************************/
459 /* EnvRetract: C access routine for the retract command. */
460 /*********************************************************/
EnvRetract(void * theEnv,void * vTheFact)461 globle intBool EnvRetract(
462 void *theEnv,
463 void *vTheFact)
464 {
465 struct fact *theFact = (struct fact *) vTheFact;
466 struct deftemplate *theTemplate = theFact->whichDeftemplate;
467 struct callFunctionItemWithArg *theRetractFunction;
468
469 /*===========================================*/
470 /* A fact can not be retracted while another */
471 /* fact is being asserted or retracted. */
472 /*===========================================*/
473
474 if (EngineData(theEnv)->JoinOperationInProgress)
475 {
476 PrintErrorID(theEnv,"FACTMNGR",1,TRUE);
477 EnvPrintRouter(theEnv,WERROR,"Facts may not be retracted during pattern-matching\n");
478 return(FALSE);
479 }
480
481 /*====================================*/
482 /* A NULL fact pointer indicates that */
483 /* all facts should be retracted. */
484 /*====================================*/
485
486 if (theFact == NULL)
487 {
488 RemoveAllFacts(theEnv);
489 return(TRUE);
490 }
491
492 /*======================================================*/
493 /* Check to see if the fact has already been retracted. */
494 /*======================================================*/
495
496 if (theFact->garbage) return(FALSE);
497
498 /*==========================================*/
499 /* Execute the list of functions that are */
500 /* to be called before each fact assertion. */
501 /*==========================================*/
502
503 for (theRetractFunction = FactData(theEnv)->ListOfRetractFunctions;
504 theRetractFunction != NULL;
505 theRetractFunction = theRetractFunction->next)
506 {
507 SetEnvironmentCallbackContext(theEnv,theRetractFunction->context);
508 if (theRetractFunction->environmentAware)
509 { (*theRetractFunction->func)(theEnv,theFact); }
510 else
511 { ((void (*)(void *))(*theRetractFunction->func))(theFact); }
512 }
513
514 /*============================*/
515 /* Print retraction output if */
516 /* facts are being watched. */
517 /*============================*/
518
519 #if DEBUGGING_FUNCTIONS
520 if (theFact->whichDeftemplate->watch)
521 {
522 EnvPrintRouter(theEnv,WTRACE,"<== ");
523 PrintFactWithIdentifier(theEnv,WTRACE,theFact);
524 EnvPrintRouter(theEnv,WTRACE,"\n");
525 }
526 #endif
527
528 /*==================================*/
529 /* Set the change flag to indicate */
530 /* the fact-list has been modified. */
531 /*==================================*/
532
533 FactData(theEnv)->ChangeToFactList = TRUE;
534
535 /*===============================================*/
536 /* Remove any links between the fact and partial */
537 /* matches in the join network. These links are */
538 /* used to keep track of logical dependencies. */
539 /*===============================================*/
540
541 RemoveEntityDependencies(theEnv,(struct patternEntity *) theFact);
542
543 /*===========================================*/
544 /* Remove the fact from the fact hash table. */
545 /*===========================================*/
546
547 RemoveHashedFact(theEnv,theFact);
548
549 /*=========================================*/
550 /* Remove the fact from its template list. */
551 /*=========================================*/
552
553 if (theFact == theTemplate->lastFact)
554 { theTemplate->lastFact = theFact->previousTemplateFact; }
555
556 if (theFact->previousTemplateFact == NULL)
557 {
558 theTemplate->factList = theTemplate->factList->nextTemplateFact;
559 if (theTemplate->factList != NULL)
560 { theTemplate->factList->previousTemplateFact = NULL; }
561 }
562 else
563 {
564 theFact->previousTemplateFact->nextTemplateFact = theFact->nextTemplateFact;
565 if (theFact->nextTemplateFact != NULL)
566 { theFact->nextTemplateFact->previousTemplateFact = theFact->previousTemplateFact; }
567 }
568
569 /*=====================================*/
570 /* Remove the fact from the fact list. */
571 /*=====================================*/
572
573 if (theFact == FactData(theEnv)->LastFact)
574 { FactData(theEnv)->LastFact = theFact->previousFact; }
575
576 if (theFact->previousFact == NULL)
577 {
578 FactData(theEnv)->FactList = FactData(theEnv)->FactList->nextFact;
579 if (FactData(theEnv)->FactList != NULL)
580 { FactData(theEnv)->FactList->previousFact = NULL; }
581 }
582 else
583 {
584 theFact->previousFact->nextFact = theFact->nextFact;
585 if (theFact->nextFact != NULL)
586 { theFact->nextFact->previousFact = theFact->previousFact; }
587 }
588
589 /*========================================*/
590 /* Add the fact to the fact garbage list. */
591 /*========================================*/
592
593 theFact->nextFact = FactData(theEnv)->GarbageFacts;
594 FactData(theEnv)->GarbageFacts = theFact;
595 theFact->garbage = TRUE;
596 UtilityData(theEnv)->CurrentGarbageFrame->dirty = TRUE;
597
598 /*===================================================*/
599 /* Reset the evaluation error flag since expressions */
600 /* will be evaluated as part of the retract. */
601 /*===================================================*/
602
603 SetEvaluationError(theEnv,FALSE);
604
605 /*===========================================*/
606 /* Loop through the list of all the patterns */
607 /* that matched the fact and process the */
608 /* retract operation for each one. */
609 /*===========================================*/
610
611 EngineData(theEnv)->JoinOperationInProgress = TRUE;
612 NetworkRetract(theEnv,(struct patternMatch *) theFact->list);
613 EngineData(theEnv)->JoinOperationInProgress = FALSE;
614
615 /*=========================================*/
616 /* Free partial matches that were released */
617 /* by the retraction of the fact. */
618 /*=========================================*/
619
620 if (EngineData(theEnv)->ExecutingRule == NULL)
621 { FlushGarbagePartialMatches(theEnv); }
622
623 /*=========================================*/
624 /* Retract other facts that were logically */
625 /* dependent on the fact just retracted. */
626 /*=========================================*/
627
628 ForceLogicalRetractions(theEnv);
629
630 /*===========================================*/
631 /* Force periodic cleanup if the retract was */
632 /* executed from an embedded application. */
633 /*===========================================*/
634
635 if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
636 (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
637 { CleanCurrentGarbageFrame(theEnv,NULL); }
638
639 /*==================================*/
640 /* Update busy counts and ephemeral */
641 /* garbage information. */
642 /*==================================*/
643
644 FactDeinstall(theEnv,theFact);
645
646 /*==================================*/
647 /* Return TRUE to indicate the fact */
648 /* was successfully retracted. */
649 /*==================================*/
650
651 return(TRUE);
652 }
653
654 /*******************************************************************/
655 /* RemoveGarbageFacts: Returns facts that have been retracted to */
656 /* the pool of available memory. It is necessary to postpone */
657 /* returning the facts to memory because RHS actions retrieve */
658 /* their variable bindings directly from the fact data structure */
659 /* and the facts may be in use in other data structures. */
660 /*******************************************************************/
RemoveGarbageFacts(void * theEnv)661 static void RemoveGarbageFacts(
662 void *theEnv)
663 {
664 struct fact *factPtr, *nextPtr, *lastPtr = NULL;
665
666 factPtr = FactData(theEnv)->GarbageFacts;
667
668 while (factPtr != NULL)
669 {
670 nextPtr = factPtr->nextFact;
671 if (factPtr->factHeader.busyCount == 0)
672 {
673 ReturnFact(theEnv,factPtr);
674 if (lastPtr == NULL) FactData(theEnv)->GarbageFacts = nextPtr;
675 else lastPtr->nextFact = nextPtr;
676 }
677 else
678 { lastPtr = factPtr; }
679
680 factPtr = nextPtr;
681 }
682 }
683
684 /********************************************************/
685 /* EnvAssert: C access routine for the assert function. */
686 /********************************************************/
EnvAssert(void * theEnv,void * vTheFact)687 globle void *EnvAssert(
688 void *theEnv,
689 void *vTheFact)
690 {
691 unsigned long hashValue;
692 unsigned long length, i;
693 struct field *theField;
694 struct fact *theFact = (struct fact *) vTheFact;
695 intBool duplicate;
696 struct callFunctionItemWithArg *theAssertFunction;
697
698 /*==========================================*/
699 /* A fact can not be asserted while another */
700 /* fact is being asserted or retracted. */
701 /*==========================================*/
702
703 if (EngineData(theEnv)->JoinOperationInProgress)
704 {
705 ReturnFact(theEnv,theFact);
706 PrintErrorID(theEnv,"FACTMNGR",2,TRUE);
707 EnvPrintRouter(theEnv,WERROR,"Facts may not be asserted during pattern-matching\n");
708 return(NULL);
709 }
710
711 /*=============================================================*/
712 /* Replace invalid data types in the fact with the symbol nil. */
713 /*=============================================================*/
714
715 length = theFact->theProposition.multifieldLength;
716 theField = theFact->theProposition.theFields;
717
718 for (i = 0; i < length; i++)
719 {
720 if (theField[i].type == RVOID)
721 {
722 theField[i].type = SYMBOL;
723 theField[i].value = (void *) EnvAddSymbol(theEnv,"nil");
724 }
725 }
726
727 /*========================================================*/
728 /* If fact assertions are being checked for duplications, */
729 /* then search the fact list for a duplicate fact. */
730 /*========================================================*/
731
732 hashValue = HandleFactDuplication(theEnv,theFact,&duplicate);
733 if (duplicate) return(NULL);
734
735 /*==========================================================*/
736 /* If necessary, add logical dependency links between the */
737 /* fact and the partial match which is its logical support. */
738 /*==========================================================*/
739
740 if (AddLogicalDependencies(theEnv,(struct patternEntity *) theFact,FALSE) == FALSE)
741 {
742 ReturnFact(theEnv,theFact);
743 return(NULL);
744 }
745
746 /*======================================*/
747 /* Add the fact to the fact hash table. */
748 /*======================================*/
749
750 AddHashedFact(theEnv,theFact,hashValue);
751
752 /*================================*/
753 /* Add the fact to the fact list. */
754 /*================================*/
755
756 theFact->nextFact = NULL;
757 theFact->list = NULL;
758 theFact->previousFact = FactData(theEnv)->LastFact;
759 if (FactData(theEnv)->LastFact == NULL)
760 { FactData(theEnv)->FactList = theFact; }
761 else
762 { FactData(theEnv)->LastFact->nextFact = theFact; }
763 FactData(theEnv)->LastFact = theFact;
764
765 /*====================================*/
766 /* Add the fact to its template list. */
767 /*====================================*/
768
769 theFact->previousTemplateFact = theFact->whichDeftemplate->lastFact;
770 theFact->nextTemplateFact = NULL;
771
772 if (theFact->whichDeftemplate->lastFact == NULL)
773 { theFact->whichDeftemplate->factList = theFact; }
774 else
775 { theFact->whichDeftemplate->lastFact->nextTemplateFact = theFact; }
776
777 theFact->whichDeftemplate->lastFact = theFact;
778
779 /*==================================*/
780 /* Set the fact index and time tag. */
781 /*==================================*/
782
783 theFact->factIndex = FactData(theEnv)->NextFactIndex++;
784 theFact->factHeader.timeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
785
786 /*=====================*/
787 /* Update busy counts. */
788 /*=====================*/
789
790 FactInstall(theEnv,theFact);
791
792 /*==========================================*/
793 /* Execute the list of functions that are */
794 /* to be called before each fact assertion. */
795 /*==========================================*/
796
797 for (theAssertFunction = FactData(theEnv)->ListOfAssertFunctions;
798 theAssertFunction != NULL;
799 theAssertFunction = theAssertFunction->next)
800 {
801 SetEnvironmentCallbackContext(theEnv,theAssertFunction->context);
802 if (theAssertFunction->environmentAware)
803 { (*theAssertFunction->func)(theEnv,theFact); }
804 else
805 { ((void (*)(void *))(*theAssertFunction->func))(theFact); }
806 }
807
808 /*==========================*/
809 /* Print assert output if */
810 /* facts are being watched. */
811 /*==========================*/
812
813 #if DEBUGGING_FUNCTIONS
814 if (theFact->whichDeftemplate->watch)
815 {
816 EnvPrintRouter(theEnv,WTRACE,"==> ");
817 PrintFactWithIdentifier(theEnv,WTRACE,theFact);
818 EnvPrintRouter(theEnv,WTRACE,"\n");
819 }
820 #endif
821
822 /*==================================*/
823 /* Set the change flag to indicate */
824 /* the fact-list has been modified. */
825 /*==================================*/
826
827 FactData(theEnv)->ChangeToFactList = TRUE;
828
829 /*==========================================*/
830 /* Check for constraint errors in the fact. */
831 /*==========================================*/
832
833 CheckTemplateFact(theEnv,theFact);
834
835 /*===================================================*/
836 /* Reset the evaluation error flag since expressions */
837 /* will be evaluated as part of the assert . */
838 /*===================================================*/
839
840 SetEvaluationError(theEnv,FALSE);
841
842 /*=============================================*/
843 /* Pattern match the fact using the associated */
844 /* deftemplate's pattern network. */
845 /*=============================================*/
846
847 EngineData(theEnv)->JoinOperationInProgress = TRUE;
848 FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,NULL,NULL);
849 EngineData(theEnv)->JoinOperationInProgress = FALSE;
850
851 /*===================================================*/
852 /* Retract other facts that were logically dependent */
853 /* on the non-existence of the fact just asserted. */
854 /*===================================================*/
855
856 ForceLogicalRetractions(theEnv);
857
858 /*=========================================*/
859 /* Free partial matches that were released */
860 /* by the assertion of the fact. */
861 /*=========================================*/
862
863 if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
864
865 /*==========================================*/
866 /* Force periodic cleanup if the assert was */
867 /* executed from an embedded application. */
868 /*==========================================*/
869
870 if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
871 (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
872 {
873 CleanCurrentGarbageFrame(theEnv,NULL);
874 CallPeriodicTasks(theEnv);
875 }
876
877 /*===============================*/
878 /* Return a pointer to the fact. */
879 /*===============================*/
880
881 return((void *) theFact);
882 }
883
884 /**************************************/
885 /* RemoveAllFacts: Loops through the */
886 /* fact-list and removes each fact. */
887 /**************************************/
RemoveAllFacts(void * theEnv)888 globle void RemoveAllFacts(
889 void *theEnv)
890 {
891 while (FactData(theEnv)->FactList != NULL)
892 { EnvRetract(theEnv,(void *) FactData(theEnv)->FactList); }
893 }
894
895 /************************************************/
896 /* EnvCreateFact: Creates a fact data structure */
897 /* of the specified deftemplate. */
898 /************************************************/
EnvCreateFact(void * theEnv,void * vTheDeftemplate)899 globle struct fact *EnvCreateFact(
900 void *theEnv,
901 void *vTheDeftemplate)
902 {
903 struct deftemplate *theDeftemplate = (struct deftemplate *) vTheDeftemplate;
904 struct fact *newFact;
905 int i;
906
907 /*=================================*/
908 /* A deftemplate must be specified */
909 /* in order to create a fact. */
910 /*=================================*/
911
912 if (theDeftemplate == NULL) return(NULL);
913
914 /*============================================*/
915 /* Create a fact for an explicit deftemplate. */
916 /*============================================*/
917
918 if (theDeftemplate->implied == FALSE)
919 {
920 newFact = CreateFactBySize(theEnv,theDeftemplate->numberOfSlots);
921 for (i = 0;
922 i < (int) theDeftemplate->numberOfSlots;
923 i++)
924 { newFact->theProposition.theFields[i].type = RVOID; }
925 }
926
927 /*===========================================*/
928 /* Create a fact for an implied deftemplate. */
929 /*===========================================*/
930
931 else
932 {
933 newFact = CreateFactBySize(theEnv,1);
934 newFact->theProposition.theFields[0].type = MULTIFIELD;
935 newFact->theProposition.theFields[0].value = CreateMultifield2(theEnv,0L);
936 }
937
938 /*===============================*/
939 /* Return a pointer to the fact. */
940 /*===============================*/
941
942 newFact->whichDeftemplate = theDeftemplate;
943
944 return(newFact);
945 }
946
947 /******************************************/
948 /* EnvGetFactSlot: Returns the slot value */
949 /* from the specified slot of a fact. */
950 /******************************************/
EnvGetFactSlot(void * theEnv,void * vTheFact,const char * slotName,DATA_OBJECT * theValue)951 globle intBool EnvGetFactSlot(
952 void *theEnv,
953 void *vTheFact,
954 const char *slotName,
955 DATA_OBJECT *theValue)
956 {
957 struct fact *theFact = (struct fact *) vTheFact;
958 struct deftemplate *theDeftemplate;
959 short whichSlot;
960
961 /*===============================================*/
962 /* Get the deftemplate associated with the fact. */
963 /*===============================================*/
964
965 theDeftemplate = theFact->whichDeftemplate;
966
967 /*==============================================*/
968 /* Handle retrieving the slot value from a fact */
969 /* having an implied deftemplate. An implied */
970 /* facts has a single multifield slot. */
971 /*==============================================*/
972
973 if (theDeftemplate->implied)
974 {
975 if (slotName != NULL) return(FALSE);
976 theValue->type = theFact->theProposition.theFields[0].type;
977 theValue->value = theFact->theProposition.theFields[0].value;
978 SetpDOBegin(theValue,1);
979 SetpDOEnd(theValue,((struct multifield *) theValue->value)->multifieldLength);
980 return(TRUE);
981 }
982
983 /*===================================*/
984 /* Make sure the slot name requested */
985 /* corresponds to a valid slot name. */
986 /*===================================*/
987
988 if (FindSlot(theDeftemplate,(SYMBOL_HN *) EnvAddSymbol(theEnv,slotName),&whichSlot) == NULL)
989 { return(FALSE); }
990
991 /*======================================================*/
992 /* Return the slot value. If the slot value wasn't set, */
993 /* then return FALSE to indicate that an appropriate */
994 /* slot value wasn't available. */
995 /*======================================================*/
996
997 theValue->type = theFact->theProposition.theFields[whichSlot-1].type;
998 theValue->value = theFact->theProposition.theFields[whichSlot-1].value;
999 if (theValue->type == MULTIFIELD)
1000 {
1001 SetpDOBegin(theValue,1);
1002 SetpDOEnd(theValue,((struct multifield *) theValue->value)->multifieldLength);
1003 }
1004
1005 if (theValue->type == RVOID) return(FALSE);
1006
1007 return(TRUE);
1008 }
1009
1010 /***************************************/
1011 /* EnvPutFactSlot: Sets the slot value */
1012 /* of the specified slot of a fact. */
1013 /***************************************/
EnvPutFactSlot(void * theEnv,void * vTheFact,const char * slotName,DATA_OBJECT * theValue)1014 globle intBool EnvPutFactSlot(
1015 void *theEnv,
1016 void *vTheFact,
1017 const char *slotName,
1018 DATA_OBJECT *theValue)
1019 {
1020 struct fact *theFact = (struct fact *) vTheFact;
1021 struct deftemplate *theDeftemplate;
1022 struct templateSlot *theSlot;
1023 short whichSlot;
1024
1025 /*===============================================*/
1026 /* Get the deftemplate associated with the fact. */
1027 /*===============================================*/
1028
1029 theDeftemplate = theFact->whichDeftemplate;
1030
1031 /*============================================*/
1032 /* Handle setting the slot value of a fact */
1033 /* having an implied deftemplate. An implied */
1034 /* facts has a single multifield slot. */
1035 /*============================================*/
1036
1037 if (theDeftemplate->implied)
1038 {
1039 if ((slotName != NULL) || (theValue->type != MULTIFIELD))
1040 { return(FALSE); }
1041
1042 if (theFact->theProposition.theFields[0].type == MULTIFIELD)
1043 { ReturnMultifield(theEnv,(struct multifield *) theFact->theProposition.theFields[0].value); }
1044
1045 theFact->theProposition.theFields[0].type = theValue->type;
1046 theFact->theProposition.theFields[0].value = DOToMultifield(theEnv,theValue);
1047
1048 return(TRUE);
1049 }
1050
1051 /*===================================*/
1052 /* Make sure the slot name requested */
1053 /* corresponds to a valid slot name. */
1054 /*===================================*/
1055
1056 if ((theSlot = FindSlot(theDeftemplate,(SYMBOL_HN *) EnvAddSymbol(theEnv,slotName),&whichSlot)) == NULL)
1057 { return(FALSE); }
1058
1059 /*=============================================*/
1060 /* Make sure a single field value is not being */
1061 /* stored in a multifield slot or vice versa. */
1062 /*=============================================*/
1063
1064 if (((theSlot->multislot == 0) && (theValue->type == MULTIFIELD)) ||
1065 ((theSlot->multislot == 1) && (theValue->type != MULTIFIELD)))
1066 { return(FALSE); }
1067
1068 /*=====================*/
1069 /* Set the slot value. */
1070 /*=====================*/
1071
1072 if (theFact->theProposition.theFields[whichSlot-1].type == MULTIFIELD)
1073 { ReturnMultifield(theEnv,(struct multifield *) theFact->theProposition.theFields[whichSlot-1].value); }
1074
1075 theFact->theProposition.theFields[whichSlot-1].type = theValue->type;
1076
1077 if (theValue->type == MULTIFIELD)
1078 { theFact->theProposition.theFields[whichSlot-1].value = DOToMultifield(theEnv,theValue); }
1079 else
1080 { theFact->theProposition.theFields[whichSlot-1].value = theValue->value; }
1081
1082 return(TRUE);
1083 }
1084
1085 /********************************************************/
1086 /* EnvAssignFactSlotDefaults: Sets a fact's slot values */
1087 /* to its default value if the value of the slot has */
1088 /* not yet been set. */
1089 /********************************************************/
EnvAssignFactSlotDefaults(void * theEnv,void * vTheFact)1090 globle intBool EnvAssignFactSlotDefaults(
1091 void *theEnv,
1092 void *vTheFact)
1093 {
1094 struct fact *theFact = (struct fact *) vTheFact;
1095 struct deftemplate *theDeftemplate;
1096 struct templateSlot *slotPtr;
1097 int i;
1098 DATA_OBJECT theResult;
1099
1100 /*===============================================*/
1101 /* Get the deftemplate associated with the fact. */
1102 /*===============================================*/
1103
1104 theDeftemplate = theFact->whichDeftemplate;
1105
1106 /*================================================*/
1107 /* The value for the implied multifield slot of */
1108 /* an implied deftemplate is set to a multifield */
1109 /* of length zero when the fact is created. */
1110 /*================================================*/
1111
1112 if (theDeftemplate->implied) return(TRUE);
1113
1114 /*============================================*/
1115 /* Loop through each slot of the deftemplate. */
1116 /*============================================*/
1117
1118 for (i = 0, slotPtr = theDeftemplate->slotList;
1119 i < (int) theDeftemplate->numberOfSlots;
1120 i++, slotPtr = slotPtr->next)
1121 {
1122 /*===================================*/
1123 /* If the slot's value has been set, */
1124 /* then move on to the next slot. */
1125 /*===================================*/
1126
1127 if (theFact->theProposition.theFields[i].type != RVOID) continue;
1128
1129 /*======================================================*/
1130 /* Assign the default value for the slot if one exists. */
1131 /*======================================================*/
1132
1133 if (DeftemplateSlotDefault(theEnv,theDeftemplate,slotPtr,&theResult,FALSE))
1134 {
1135 theFact->theProposition.theFields[i].type = theResult.type;
1136 theFact->theProposition.theFields[i].value = theResult.value;
1137 }
1138 }
1139
1140 /*==========================================*/
1141 /* Return TRUE to indicate that the default */
1142 /* values have been successfully set. */
1143 /*==========================================*/
1144
1145 return(TRUE);
1146 }
1147
1148 /********************************************************/
1149 /* DeftemplateSlotDefault: Determines the default value */
1150 /* for the specified slot of a deftemplate. */
1151 /********************************************************/
DeftemplateSlotDefault(void * theEnv,struct deftemplate * theDeftemplate,struct templateSlot * slotPtr,DATA_OBJECT * theResult,int garbageMultifield)1152 globle intBool DeftemplateSlotDefault(
1153 void *theEnv,
1154 struct deftemplate *theDeftemplate,
1155 struct templateSlot *slotPtr,
1156 DATA_OBJECT *theResult,
1157 int garbageMultifield)
1158 {
1159 /*================================================*/
1160 /* The value for the implied multifield slot of an */
1161 /* implied deftemplate does not have a default. */
1162 /*=================================================*/
1163
1164 if (theDeftemplate->implied) return(FALSE);
1165
1166 /*===============================================*/
1167 /* If the (default ?NONE) attribute was declared */
1168 /* for the slot, then return FALSE to indicate */
1169 /* the default values for the fact couldn't be */
1170 /* supplied since this attribute requires that a */
1171 /* default value can't be used for the slot. */
1172 /*===============================================*/
1173
1174 if (slotPtr->noDefault) return(FALSE);
1175
1176 /*==============================================*/
1177 /* Otherwise if a static default was specified, */
1178 /* use this as the default value. */
1179 /*==============================================*/
1180
1181 else if (slotPtr->defaultPresent)
1182 {
1183 if (slotPtr->multislot)
1184 {
1185 StoreInMultifield(theEnv,theResult,slotPtr->defaultList,garbageMultifield);
1186 }
1187 else
1188 {
1189 theResult->type = slotPtr->defaultList->type;
1190 theResult->value = slotPtr->defaultList->value;
1191 }
1192 }
1193
1194 /*================================================*/
1195 /* Otherwise if a dynamic-default was specified, */
1196 /* evaluate it and use this as the default value. */
1197 /*================================================*/
1198
1199 else if (slotPtr->defaultDynamic)
1200 {
1201 if (! EvaluateAndStoreInDataObject(theEnv,(int) slotPtr->multislot,
1202 (EXPRESSION *) slotPtr->defaultList,
1203 theResult,garbageMultifield))
1204 { return(FALSE); }
1205 }
1206
1207 /*====================================*/
1208 /* Otherwise derive the default value */
1209 /* from the slot's constraints. */
1210 /*====================================*/
1211
1212 else
1213 {
1214 DeriveDefaultFromConstraints(theEnv,slotPtr->constraints,theResult,
1215 (int) slotPtr->multislot,garbageMultifield);
1216 }
1217
1218 /*==========================================*/
1219 /* Return TRUE to indicate that the default */
1220 /* values have been successfully set. */
1221 /*==========================================*/
1222
1223 return(TRUE);
1224 }
1225
1226 /***************************************************************/
1227 /* CopyFactSlotValues: Copies the slot values from one fact to */
1228 /* another. Both facts must have the same relation name. */
1229 /***************************************************************/
CopyFactSlotValues(void * theEnv,void * vTheDestFact,void * vTheSourceFact)1230 globle intBool CopyFactSlotValues(
1231 void *theEnv,
1232 void *vTheDestFact,
1233 void *vTheSourceFact)
1234 {
1235 struct fact *theDestFact = (struct fact *) vTheDestFact;
1236 struct fact *theSourceFact = (struct fact *) vTheSourceFact;
1237 struct deftemplate *theDeftemplate;
1238 struct templateSlot *slotPtr;
1239 int i;
1240
1241 /*===================================*/
1242 /* Both facts must be the same type. */
1243 /*===================================*/
1244
1245 theDeftemplate = theSourceFact->whichDeftemplate;
1246 if (theDestFact->whichDeftemplate != theDeftemplate)
1247 { return(FALSE); }
1248
1249 /*===================================================*/
1250 /* Loop through each slot of the deftemplate copying */
1251 /* the source fact value to the destination fact. */
1252 /*===================================================*/
1253
1254 for (i = 0, slotPtr = theDeftemplate->slotList;
1255 i < (int) theDeftemplate->numberOfSlots;
1256 i++, slotPtr = slotPtr->next)
1257 {
1258 theDestFact->theProposition.theFields[i].type =
1259 theSourceFact->theProposition.theFields[i].type;
1260 if (theSourceFact->theProposition.theFields[i].type != MULTIFIELD)
1261 {
1262 theDestFact->theProposition.theFields[i].value =
1263 theSourceFact->theProposition.theFields[i].value;
1264 }
1265 else
1266 {
1267 theDestFact->theProposition.theFields[i].value =
1268 CopyMultifield(theEnv,(struct multifield *) theSourceFact->theProposition.theFields[i].value);
1269 }
1270 }
1271
1272 /*========================================*/
1273 /* Return TRUE to indicate that fact slot */
1274 /* values were successfully copied. */
1275 /*========================================*/
1276
1277 return(TRUE);
1278 }
1279
1280 /*********************************************/
1281 /* CreateFactBySize: Allocates a fact data */
1282 /* structure based on the number of slots. */
1283 /*********************************************/
CreateFactBySize(void * theEnv,unsigned size)1284 globle struct fact *CreateFactBySize(
1285 void *theEnv,
1286 unsigned size)
1287 {
1288 struct fact *theFact;
1289 unsigned newSize;
1290
1291 if (size <= 0) newSize = 1;
1292 else newSize = size;
1293
1294 theFact = get_var_struct(theEnv,fact,sizeof(struct field) * (newSize - 1));
1295
1296 theFact->garbage = FALSE;
1297 theFact->factIndex = 0LL;
1298 theFact->factHeader.busyCount = 0;
1299 theFact->factHeader.theInfo = &FactData(theEnv)->FactInfo;
1300 theFact->factHeader.dependents = NULL;
1301 theFact->whichDeftemplate = NULL;
1302 theFact->nextFact = NULL;
1303 theFact->previousFact = NULL;
1304 theFact->previousTemplateFact = NULL;
1305 theFact->nextTemplateFact = NULL;
1306 theFact->list = NULL;
1307
1308 theFact->theProposition.multifieldLength = size;
1309 theFact->theProposition.busyCount = 0;
1310
1311 return(theFact);
1312 }
1313
1314 /*********************************************/
1315 /* ReturnFact: Returns a fact data structure */
1316 /* to the pool of free memory. */
1317 /*********************************************/
ReturnFact(void * theEnv,struct fact * theFact)1318 globle void ReturnFact(
1319 void *theEnv,
1320 struct fact *theFact)
1321 {
1322 struct multifield *theSegment, *subSegment;
1323 long newSize, i;
1324
1325 theSegment = &theFact->theProposition;
1326
1327 for (i = 0; i < theSegment->multifieldLength; i++)
1328 {
1329 if (theSegment->theFields[i].type == MULTIFIELD)
1330 {
1331 subSegment = (struct multifield *) theSegment->theFields[i].value;
1332 if (subSegment->busyCount == 0)
1333 { ReturnMultifield(theEnv,subSegment); }
1334 else
1335 { AddToMultifieldList(theEnv,subSegment); }
1336 }
1337 }
1338
1339 if (theFact->theProposition.multifieldLength == 0) newSize = 1;
1340 else newSize = theFact->theProposition.multifieldLength;
1341
1342 rtn_var_struct(theEnv,fact,sizeof(struct field) * (newSize - 1),theFact);
1343 }
1344
1345 /*************************************************************/
1346 /* FactInstall: Increments the fact, deftemplate, and atomic */
1347 /* data value busy counts associated with the fact. */
1348 /*************************************************************/
FactInstall(void * theEnv,struct fact * newFact)1349 globle void FactInstall(
1350 void *theEnv,
1351 struct fact *newFact)
1352 {
1353 struct multifield *theSegment;
1354 int i;
1355
1356 FactData(theEnv)->NumberOfFacts++;
1357 newFact->whichDeftemplate->busyCount++;
1358 theSegment = &newFact->theProposition;
1359
1360 for (i = 0 ; i < (int) theSegment->multifieldLength ; i++)
1361 {
1362 AtomInstall(theEnv,theSegment->theFields[i].type,theSegment->theFields[i].value);
1363 }
1364
1365 newFact->factHeader.busyCount++;
1366 }
1367
1368 /***************************************************************/
1369 /* FactDeinstall: Decrements the fact, deftemplate, and atomic */
1370 /* data value busy counts associated with the fact. */
1371 /***************************************************************/
FactDeinstall(void * theEnv,struct fact * newFact)1372 globle void FactDeinstall(
1373 void *theEnv,
1374 struct fact *newFact)
1375 {
1376 struct multifield *theSegment;
1377 int i;
1378
1379 FactData(theEnv)->NumberOfFacts--;
1380 theSegment = &newFact->theProposition;
1381 newFact->whichDeftemplate->busyCount--;
1382
1383 for (i = 0 ; i < (int) theSegment->multifieldLength ; i++)
1384 {
1385 AtomDeinstall(theEnv,theSegment->theFields[i].type,theSegment->theFields[i].value);
1386 }
1387
1388 newFact->factHeader.busyCount--;
1389 }
1390
1391 /************************************************/
1392 /* EnvIncrementFactCount: Increments the number */
1393 /* of references to a specified fact. */
1394 /************************************************/
EnvIncrementFactCount(void * theEnv,void * factPtr)1395 globle void EnvIncrementFactCount(
1396 void *theEnv,
1397 void *factPtr)
1398 {
1399 #if MAC_XCD
1400 #pragma unused(theEnv)
1401 #endif
1402
1403 ((struct fact *) factPtr)->factHeader.busyCount++;
1404 }
1405
1406 /************************************************/
1407 /* EnvDecrementFactCount: Decrements the number */
1408 /* of references to a specified fact. */
1409 /************************************************/
EnvDecrementFactCount(void * theEnv,void * factPtr)1410 globle void EnvDecrementFactCount(
1411 void *theEnv,
1412 void *factPtr)
1413 {
1414 #if MAC_XCD
1415 #pragma unused(theEnv)
1416 #endif
1417
1418 ((struct fact *) factPtr)->factHeader.busyCount--;
1419 }
1420
1421 /*********************************************************/
1422 /* EnvGetNextFact: If passed a NULL pointer, returns the */
1423 /* first fact in the fact-list. Otherwise returns the */
1424 /* next fact following the fact passed as an argument. */
1425 /*********************************************************/
EnvGetNextFact(void * theEnv,void * factPtr)1426 globle void *EnvGetNextFact(
1427 void *theEnv,
1428 void *factPtr)
1429 {
1430 if (factPtr == NULL)
1431 { return((void *) FactData(theEnv)->FactList); }
1432
1433 if (((struct fact *) factPtr)->garbage) return(NULL);
1434
1435 return((void *) ((struct fact *) factPtr)->nextFact);
1436 }
1437
1438 /**************************************************/
1439 /* GetNextFactInScope: Returns the next fact that */
1440 /* is in scope of the current module. Works in */
1441 /* a similar fashion to GetNextFact, but skips */
1442 /* facts that are out of scope. */
1443 /**************************************************/
GetNextFactInScope(void * theEnv,void * vTheFact)1444 globle void *GetNextFactInScope(
1445 void *theEnv,
1446 void *vTheFact)
1447 {
1448 struct fact *theFact = (struct fact *) vTheFact;
1449
1450 /*=======================================================*/
1451 /* If fact passed as an argument is a NULL pointer, then */
1452 /* we're just beginning a traversal of the fact list. If */
1453 /* the module index has changed since that last time the */
1454 /* fact list was traversed by this routine, then */
1455 /* determine all of the deftemplates that are in scope */
1456 /* of the current module. */
1457 /*=======================================================*/
1458
1459 if (theFact == NULL)
1460 {
1461 theFact = FactData(theEnv)->FactList;
1462 if (FactData(theEnv)->LastModuleIndex != DefmoduleData(theEnv)->ModuleChangeIndex)
1463 {
1464 UpdateDeftemplateScope(theEnv);
1465 FactData(theEnv)->LastModuleIndex = DefmoduleData(theEnv)->ModuleChangeIndex;
1466 }
1467 }
1468
1469 /*==================================================*/
1470 /* Otherwise, if the fact passed as an argument has */
1471 /* been retracted, then there's no way to determine */
1472 /* the next fact, so return a NULL pointer. */
1473 /*==================================================*/
1474
1475 else if (((struct fact *) theFact)->garbage)
1476 { return(NULL); }
1477
1478 /*==================================================*/
1479 /* Otherwise, start the search for the next fact in */
1480 /* scope with the fact immediately following the */
1481 /* fact passed as an argument. */
1482 /*==================================================*/
1483
1484 else
1485 { theFact = theFact->nextFact; }
1486
1487 /*================================================*/
1488 /* Continue traversing the fact-list until a fact */
1489 /* is found that's associated with a deftemplate */
1490 /* that's in scope. */
1491 /*================================================*/
1492
1493 while (theFact != NULL)
1494 {
1495 if (theFact->whichDeftemplate->inScope) return((void *) theFact);
1496
1497 theFact = theFact->nextFact;
1498 }
1499
1500 return(NULL);
1501 }
1502
1503 /****************************************/
1504 /* EnvGetFactPPForm: Returns the pretty */
1505 /* print representation of a fact. */
1506 /****************************************/
EnvGetFactPPForm(void * theEnv,char * buffer,size_t bufferLength,void * theFact)1507 globle void EnvGetFactPPForm(
1508 void *theEnv,
1509 char *buffer,
1510 size_t bufferLength,
1511 void *theFact)
1512 {
1513 OpenStringDestination(theEnv,"FactPPForm",buffer,bufferLength);
1514 PrintFactWithIdentifier(theEnv,"FactPPForm",(struct fact *) theFact);
1515 CloseStringDestination(theEnv,"FactPPForm");
1516 }
1517
1518 /**********************************/
1519 /* EnvFactIndex: C access routine */
1520 /* for the fact-index function. */
1521 /**********************************/
EnvFactIndex(void * theEnv,void * factPtr)1522 globle long long EnvFactIndex(
1523 void *theEnv,
1524 void *factPtr)
1525 {
1526 #if MAC_XCD
1527 #pragma unused(theEnv)
1528 #endif
1529
1530 return(((struct fact *) factPtr)->factIndex);
1531 }
1532
1533 /*************************************/
1534 /* EnvAssertString: C access routine */
1535 /* for the assert-string function. */
1536 /*************************************/
EnvAssertString(void * theEnv,const char * theString)1537 globle void *EnvAssertString(
1538 void *theEnv,
1539 const char *theString)
1540 {
1541 struct fact *theFact;
1542 int danglingConstructs;
1543 danglingConstructs = ConstructData(theEnv)->DanglingConstructs;
1544
1545 if ((theFact = StringToFact(theEnv,theString)) == NULL) return(NULL);
1546
1547 if ((! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
1548 (EvaluationData(theEnv)->CurrentExpression == NULL))
1549 { ConstructData(theEnv)->DanglingConstructs = danglingConstructs; }
1550
1551 return((void *) EnvAssert(theEnv,(void *) theFact));
1552 }
1553
1554 /******************************************************/
1555 /* EnvGetFactListChanged: Returns the flag indicating */
1556 /* whether a change to the fact-list has been made. */
1557 /******************************************************/
EnvGetFactListChanged(void * theEnv)1558 globle int EnvGetFactListChanged(
1559 void *theEnv)
1560 {
1561 return(FactData(theEnv)->ChangeToFactList);
1562 }
1563
1564 /***********************************************************/
1565 /* EnvSetFactListChanged: Sets the flag indicating whether */
1566 /* a change to the fact-list has been made. */
1567 /***********************************************************/
EnvSetFactListChanged(void * theEnv,int value)1568 globle void EnvSetFactListChanged(
1569 void *theEnv,
1570 int value)
1571 {
1572 FactData(theEnv)->ChangeToFactList = value;
1573 }
1574
1575 /****************************************/
1576 /* GetNumberOfFacts: Returns the number */
1577 /* of facts in the fact-list. */
1578 /****************************************/
GetNumberOfFacts(void * theEnv)1579 globle unsigned long GetNumberOfFacts(
1580 void *theEnv)
1581 {
1582 return(FactData(theEnv)->NumberOfFacts);
1583 }
1584
1585 /***********************************************************/
1586 /* ResetFacts: Reset function for facts. Sets the starting */
1587 /* fact index to zero and removes all facts. */
1588 /***********************************************************/
ResetFacts(void * theEnv)1589 static void ResetFacts(
1590 void *theEnv)
1591 {
1592 /*====================================*/
1593 /* Initialize the fact index to zero. */
1594 /*====================================*/
1595
1596 FactData(theEnv)->NextFactIndex = 0L;
1597
1598 /*======================================*/
1599 /* Remove all facts from the fact list. */
1600 /*======================================*/
1601
1602 RemoveAllFacts(theEnv);
1603 }
1604
1605 /************************************************************/
1606 /* ClearFactsReady: Clear ready function for facts. Returns */
1607 /* TRUE if facts were successfully removed and the clear */
1608 /* command can continue, otherwise FALSE. */
1609 /************************************************************/
ClearFactsReady(void * theEnv)1610 static int ClearFactsReady(
1611 void *theEnv)
1612 {
1613 /*======================================*/
1614 /* Facts can not be deleted when a join */
1615 /* operation is already in progress. */
1616 /*======================================*/
1617
1618 if (EngineData(theEnv)->JoinOperationInProgress) return(FALSE);
1619
1620 /*====================================*/
1621 /* Initialize the fact index to zero. */
1622 /*====================================*/
1623
1624 FactData(theEnv)->NextFactIndex = 0L;
1625
1626 /*======================================*/
1627 /* Remove all facts from the fact list. */
1628 /*======================================*/
1629
1630 RemoveAllFacts(theEnv);
1631
1632 /*==============================================*/
1633 /* If for some reason there are any facts still */
1634 /* remaining, don't continue with the clear. */
1635 /*==============================================*/
1636
1637 if (EnvGetNextFact(theEnv,NULL) != NULL) return(FALSE);
1638
1639 /*=============================*/
1640 /* Return TRUE to indicate the */
1641 /* clear command can continue. */
1642 /*=============================*/
1643
1644 return(TRUE);
1645 }
1646
1647 /***************************************************/
1648 /* FindIndexedFact: Returns a pointer to a fact in */
1649 /* the fact list with the specified fact index. */
1650 /***************************************************/
FindIndexedFact(void * theEnv,long long factIndexSought)1651 globle struct fact *FindIndexedFact(
1652 void *theEnv,
1653 long long factIndexSought)
1654 {
1655 struct fact *theFact;
1656
1657 for (theFact = (struct fact *) EnvGetNextFact(theEnv,NULL);
1658 theFact != NULL;
1659 theFact = (struct fact *) EnvGetNextFact(theEnv,theFact))
1660 {
1661 if (theFact->factIndex == factIndexSought)
1662 { return(theFact); }
1663 }
1664
1665 return(NULL);
1666 }
1667
1668 /*****************************************/
1669 /* EnvAddAssertFunction: Adds a function */
1670 /* to the ListOfAssertFunctions. */
1671 /*****************************************/
EnvAddAssertFunction(void * theEnv,const char * name,void (* functionPtr)(void *,void *),int priority)1672 globle intBool EnvAddAssertFunction(
1673 void *theEnv,
1674 const char *name,
1675 void (*functionPtr)(void *, void *),
1676 int priority)
1677 {
1678 FactData(theEnv)->ListOfAssertFunctions =
1679 AddFunctionToCallListWithArg(theEnv,name,priority,
1680 functionPtr,
1681 FactData(theEnv)->ListOfAssertFunctions,TRUE);
1682 return(1);
1683 }
1684
1685 /********************************************/
1686 /* EnvAddAssertFunctionWithContext: Adds a */
1687 /* function to the ListOfAssertFunctions. */
1688 /********************************************/
EnvAddAssertFunctionWithContext(void * theEnv,const char * name,void (* functionPtr)(void *,void *),int priority,void * context)1689 globle intBool EnvAddAssertFunctionWithContext(
1690 void *theEnv,
1691 const char *name,
1692 void (*functionPtr)(void *, void *),
1693 int priority,
1694 void *context)
1695 {
1696 FactData(theEnv)->ListOfAssertFunctions =
1697 AddFunctionToCallListWithArgWithContext(theEnv,name,priority,functionPtr,
1698 FactData(theEnv)->ListOfAssertFunctions,
1699 TRUE,context);
1700 return(1);
1701 }
1702
1703 /***********************************************/
1704 /* EnvRemoveAssertFunction: Removes a function */
1705 /* from the ListOfAssertFunctions. */
1706 /***********************************************/
EnvRemoveAssertFunction(void * theEnv,const char * name)1707 globle intBool EnvRemoveAssertFunction(
1708 void *theEnv,
1709 const char *name)
1710 {
1711 int found;
1712
1713 FactData(theEnv)->ListOfAssertFunctions =
1714 RemoveFunctionFromCallListWithArg(theEnv,name,FactData(theEnv)->ListOfAssertFunctions,&found);
1715
1716 if (found) return(TRUE);
1717
1718 return(FALSE);
1719 }
1720
1721 /******************************************/
1722 /* EnvAddRetractFunction: Adds a function */
1723 /* to the ListOfRetractFunctions. */
1724 /******************************************/
EnvAddRetractFunction(void * theEnv,const char * name,void (* functionPtr)(void *,void *),int priority)1725 globle intBool EnvAddRetractFunction(
1726 void *theEnv,
1727 const char *name,
1728 void (*functionPtr)(void *, void *),
1729 int priority)
1730 {
1731 FactData(theEnv)->ListOfRetractFunctions =
1732 AddFunctionToCallListWithArg(theEnv,name,priority,
1733 functionPtr,
1734 FactData(theEnv)->ListOfRetractFunctions,TRUE);
1735 return(1);
1736 }
1737
1738 /*********************************************/
1739 /* EnvAddRetractFunctionWithContext: Adds a */
1740 /* function to the ListOfRetractFunctions. */
1741 /*********************************************/
EnvAddRetractFunctionWithContext(void * theEnv,const char * name,void (* functionPtr)(void *,void *),int priority,void * context)1742 globle intBool EnvAddRetractFunctionWithContext(
1743 void *theEnv,
1744 const char *name,
1745 void (*functionPtr)(void *, void *),
1746 int priority,
1747 void *context)
1748 {
1749 FactData(theEnv)->ListOfRetractFunctions =
1750 AddFunctionToCallListWithArgWithContext(theEnv,name,priority,functionPtr,
1751 FactData(theEnv)->ListOfRetractFunctions,
1752 TRUE,context);
1753 return(1);
1754 }
1755
1756 /************************************************/
1757 /* EnvRemoveRetractFunction: Removes a function */
1758 /* from the ListOfRetractFunctions. */
1759 /************************************************/
EnvRemoveRetractFunction(void * theEnv,const char * name)1760 globle intBool EnvRemoveRetractFunction(
1761 void *theEnv,
1762 const char *name)
1763 {
1764 int found;
1765
1766 FactData(theEnv)->ListOfRetractFunctions =
1767 RemoveFunctionFromCallListWithArg(theEnv,name,FactData(theEnv)->ListOfRetractFunctions,&found);
1768
1769 if (found) return(TRUE);
1770
1771 return(FALSE);
1772 }
1773
1774 /*****************************************/
1775 /* EnvAddModifyFunction: Adds a function */
1776 /* to the ListOfModifyFunctions. */
1777 /*****************************************/
EnvAddModifyFunction(void * theEnv,const char * name,void (* functionPtr)(void *,void *,void *),int priority)1778 globle intBool EnvAddModifyFunction(
1779 void *theEnv,
1780 const char *name,
1781 void (*functionPtr)(void *, void *, void *),
1782 int priority)
1783 {
1784 FactData(theEnv)->ListOfModifyFunctions =
1785 AddFunctionToCallListWithArg(theEnv,name,priority,
1786 (void (*)(void *, void *)) functionPtr,
1787 FactData(theEnv)->ListOfModifyFunctions,TRUE);
1788 return(1);
1789 }
1790
1791 /********************************************/
1792 /* EnvAddModifyFunctionWithContext: Adds a */
1793 /* function to the ListOfModifyFunctions. */
1794 /********************************************/
EnvAddModifyFunctionWithContext(void * theEnv,const char * name,void (* functionPtr)(void *,void *,void *),int priority,void * context)1795 globle intBool EnvAddModifyFunctionWithContext(
1796 void *theEnv,
1797 const char *name,
1798 void (*functionPtr)(void *, void *, void *),
1799 int priority,
1800 void *context)
1801 {
1802 FactData(theEnv)->ListOfModifyFunctions =
1803 AddFunctionToCallListWithArgWithContext(theEnv,name,priority,
1804 (void (*)(void *, void *)) functionPtr,
1805 FactData(theEnv)->ListOfModifyFunctions,
1806 TRUE,context);
1807 return(1);
1808 }
1809
1810 /***********************************************/
1811 /* EnvRemoveModifyFunction: Removes a function */
1812 /* from the ListOfModifyFunctions. */
1813 /***********************************************/
EnvRemoveModifyFunction(void * theEnv,const char * name)1814 globle intBool EnvRemoveModifyFunction(
1815 void *theEnv,
1816 const char *name)
1817 {
1818 int found;
1819
1820 FactData(theEnv)->ListOfModifyFunctions =
1821 RemoveFunctionFromCallListWithArg(theEnv,name,FactData(theEnv)->ListOfModifyFunctions,&found);
1822
1823 if (found) return(TRUE);
1824
1825 return(FALSE);
1826 }
1827
1828 /*#####################################*/
1829 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
1830 /*#####################################*/
1831
1832 #if ALLOW_ENVIRONMENT_GLOBALS
1833
AddAssertFunction(const char * name,void (* functionPtr)(void *,void *),int priority)1834 globle intBool AddAssertFunction(
1835 const char *name,
1836 void (*functionPtr)(void *,void *),
1837 int priority)
1838 {
1839 void *theEnv;
1840
1841 theEnv = GetCurrentEnvironment();
1842
1843 FactData(theEnv)->ListOfAssertFunctions =
1844 AddFunctionToCallListWithArg(theEnv,name,priority,(void (*)(void *, void *)) functionPtr,
1845 FactData(theEnv)->ListOfAssertFunctions,TRUE);
1846 return(1);
1847 }
1848
AddModifyFunction(const char * name,void (* functionPtr)(void *,void *,void *),int priority)1849 globle intBool AddModifyFunction(
1850 const char *name,
1851 void (*functionPtr)(void *,void *,void *),
1852 int priority)
1853 {
1854 void *theEnv;
1855
1856 theEnv = GetCurrentEnvironment();
1857
1858 FactData(theEnv)->ListOfModifyFunctions =
1859 AddFunctionToCallListWithArg(theEnv,name,priority,(void (*)(void *, void *)) functionPtr,
1860 FactData(theEnv)->ListOfModifyFunctions,TRUE);
1861 return(1);
1862 }
1863
AddRetractFunction(const char * name,void (* functionPtr)(void *,void *),int priority)1864 globle intBool AddRetractFunction(
1865 const char *name,
1866 void (*functionPtr)(void *,void *),
1867 int priority)
1868 {
1869 void *theEnv;
1870
1871 theEnv = GetCurrentEnvironment();
1872
1873 FactData(theEnv)->ListOfRetractFunctions =
1874 AddFunctionToCallListWithArg(theEnv,name,priority,(void (*)(void *, void *)) functionPtr,
1875 FactData(theEnv)->ListOfRetractFunctions,TRUE);
1876 return(1);
1877 }
1878
Assert(void * vTheFact)1879 globle void *Assert(
1880 void *vTheFact)
1881 {
1882 return EnvAssert(GetCurrentEnvironment(),vTheFact);
1883 }
1884
AssertString(const char * theString)1885 globle void *AssertString(
1886 const char *theString)
1887 {
1888 return EnvAssertString(GetCurrentEnvironment(),theString);
1889 }
1890
AssignFactSlotDefaults(void * vTheFact)1891 globle intBool AssignFactSlotDefaults(
1892 void *vTheFact)
1893 {
1894 return EnvAssignFactSlotDefaults(GetCurrentEnvironment(),vTheFact);
1895 }
1896
CreateFact(void * vTheDeftemplate)1897 globle struct fact *CreateFact(
1898 void *vTheDeftemplate)
1899 {
1900 return EnvCreateFact(GetCurrentEnvironment(),vTheDeftemplate);
1901 }
1902
DecrementFactCount(void * factPtr)1903 globle void DecrementFactCount(
1904 void *factPtr)
1905 {
1906 EnvDecrementFactCount(GetCurrentEnvironment(),factPtr);
1907 }
1908
FactIndex(void * factPtr)1909 globle long long FactIndex(
1910 void *factPtr)
1911 {
1912 return(EnvFactIndex(GetCurrentEnvironment(),factPtr));
1913 }
1914
GetFactListChanged()1915 globle int GetFactListChanged()
1916 {
1917 return EnvGetFactListChanged(GetCurrentEnvironment());
1918 }
1919
GetFactPPForm(char * buffer,unsigned bufferLength,void * theFact)1920 globle void GetFactPPForm(
1921 char *buffer,
1922 unsigned bufferLength,
1923 void *theFact)
1924 {
1925 EnvGetFactPPForm(GetCurrentEnvironment(),buffer,bufferLength,theFact);
1926 }
1927
GetFactSlot(void * vTheFact,const char * slotName,DATA_OBJECT * theValue)1928 globle intBool GetFactSlot(
1929 void *vTheFact,
1930 const char *slotName,
1931 DATA_OBJECT *theValue)
1932 {
1933 return(EnvGetFactSlot(GetCurrentEnvironment(),vTheFact,slotName,theValue));
1934 }
1935
GetNextFact(void * factPtr)1936 globle void *GetNextFact(
1937 void *factPtr)
1938 {
1939 return EnvGetNextFact(GetCurrentEnvironment(),factPtr);
1940 }
1941
IncrementFactCount(void * factPtr)1942 globle void IncrementFactCount(
1943 void *factPtr)
1944 {
1945 EnvIncrementFactCount(GetCurrentEnvironment(),factPtr);
1946 }
1947
PutFactSlot(void * vTheFact,const char * slotName,DATA_OBJECT * theValue)1948 globle intBool PutFactSlot(
1949 void *vTheFact,
1950 const char *slotName,
1951 DATA_OBJECT *theValue)
1952 {
1953 return EnvPutFactSlot(GetCurrentEnvironment(),vTheFact,slotName,theValue);
1954 }
1955
RemoveAssertFunction(const char * name)1956 globle intBool RemoveAssertFunction(
1957 const char *name)
1958 {
1959 return EnvRemoveAssertFunction(GetCurrentEnvironment(),name);
1960 }
1961
RemoveModifyFunction(const char * name)1962 globle intBool RemoveModifyFunction(
1963 const char *name)
1964 {
1965 return EnvRemoveModifyFunction(GetCurrentEnvironment(),name);
1966 }
1967
RemoveRetractFunction(const char * name)1968 globle intBool RemoveRetractFunction(
1969 const char *name)
1970 {
1971 return EnvRemoveRetractFunction(GetCurrentEnvironment(),name);
1972 }
1973
Retract(void * vTheFact)1974 globle intBool Retract(
1975 void *vTheFact)
1976 {
1977 return EnvRetract(GetCurrentEnvironment(),vTheFact);
1978 }
1979
SetFactListChanged(int value)1980 globle void SetFactListChanged(
1981 int value)
1982 {
1983 EnvSetFactListChanged(GetCurrentEnvironment(),value);
1984 }
1985
1986 #endif /* ALLOW_ENVIRONMENT_GLOBALS */
1987
1988 #endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
1989
1990