1 /*******************************************************/
2 /* "C" Language Integrated Production System */
4 /* CLIPS Version 6.30 01/13/15 */
6 /* OBJECT MESSAGE DISPATCH CODE */
7 /*******************************************************/
9 /*************************************************************/
12 /* Principal Programmer(s): */
15 /* Contributing Programmer(s): */
17 /* Revision History: */
19 /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
21 /* 6.24: Removed IMPERATIVE_MESSAGE_HANDLERS and */
22 /* AUXILIARY_MESSAGE_HANDLERS compilation flags. */
24 /* Renamed BOOLEAN macro type to intBool. */
26 /* 6.30: The return value of DirectMessage indicates */
27 /* whether an execution error has occurred. */
29 /* Removed conditional code for unsupported */
30 /* compilers/operating systems (IBM_MCW, */
31 /* MAC_MCW, and IBM_TBC). */
33 /* Changed garbage collection algorithm. */
35 /* Added const qualifiers to remove C++ */
36 /* deprecation warnings. */
38 /* Converted API macros to function calls. */
40 /* It's no longer necessary for a defclass to be */
41 /* in scope in order to sent a message to an */
42 /* instance of that class. */
44 /*************************************************************/
46 /* =========================================
47 *****************************************
49 =========================================
50 ***************************************** */
55 #ifndef _STDIO_INCLUDED_
57 #define _STDIO_INCLUDED_
80 #define _MSGPASS_SOURCE_
85 /* =========================================
86 *****************************************
87 INTERNALLY VISIBLE FUNCTION HEADERS
88 =========================================
89 ***************************************** */
91 static intBool PerformMessage(void *,DATA_OBJECT *,EXPRESSION *,SYMBOL_HN *);
92 static HANDLER_LINK *FindApplicableHandlers(void *,DEFCLASS *,SYMBOL_HN *);
93 static void CallHandlers(void *,DATA_OBJECT *);
94 static void EarlySlotBindError(void *,INSTANCE_TYPE *,DEFCLASS *,unsigned);
96 /* =========================================
97 *****************************************
98 EXTERNALLY VISIBLE FUNCTIONS
99 =========================================
100 ***************************************** */
102 /*****************************************************
104 DESCRIPTION : Plugs in given instance and
105 performs specified message
106 INPUTS : 1) Message symbolic name
107 2) The instance address
108 3) Address of DATA_OBJECT buffer
110 4) Message argument expressions
111 RETURNS : Returns FALSE is an execution error occurred
112 or execution is halted, otherwise TRUE
113 SIDE EFFECTS : Side effects of message execution
115 *****************************************************/
116 globle intBool DirectMessage(
120 DATA_OBJECT *resultbuf,
126 if (resultbuf == NULL)
128 args.nextArg = remargs;
130 args.type = INSTANCE_ADDRESS;
131 args.value = (void *) ins;
132 return PerformMessage(theEnv,resultbuf,&args,msg);
135 /***************************************************
137 DESCRIPTION : C Interface for sending messages to
139 INPUTS : 1) The data object of the instance
140 2) The message name-string
141 3) The message arguments string
143 4) Caller's buffer for result
144 RETURNS : Nothing useful
145 SIDE EFFECTS : Executes message and stores result
148 ***************************************************/
160 if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
161 (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
163 CleanCurrentGarbageFrame(theEnv,NULL);
164 CallPeriodicTasks(theEnv);
167 SetEvaluationError(theEnv,FALSE);
168 result->type = SYMBOL;
169 result->value = EnvFalseSymbol(theEnv);
170 msym = FindSymbolHN(theEnv,msg);
173 PrintNoHandlerError(theEnv,msg);
174 SetEvaluationError(theEnv,TRUE);
177 iexp = GenConstant(theEnv,idata->type,idata->value);
178 iexp->nextArg = ParseConstantArguments(theEnv,args,&error);
181 ReturnExpression(theEnv,iexp);
182 SetEvaluationError(theEnv,TRUE);
185 PerformMessage(theEnv,result,iexp,msym);
186 ReturnExpression(theEnv,iexp);
189 /*****************************************************
190 NAME : DestroyHandlerLinks
191 DESCRIPTION : Iteratively deallocates handler-links
192 INPUTS : The handler-link list
193 RETURNS : Nothing useful
194 SIDE EFFECTS : Deallocation of links
196 *****************************************************/
197 globle void DestroyHandlerLinks(
203 while (mhead != NULL)
208 DecrementDefclassBusyCount(theEnv,(void *) tmp->hnd->cls);
209 rtn_struct(theEnv,messageHandlerLink,tmp);
213 /***********************************************************************
215 DESCRIPTION : Determines the applicable handler(s) and sets up the
216 core calling frame. Then calls the core frame.
217 INPUTS : Caller's space for storing the result of the handler(s)
218 RETURNS : Nothing useful
219 SIDE EFFECTS : Any side-effects caused by the execution of handlers in
221 NOTES : H/L Syntax : (send <instance> <hnd> <args>*)
222 ***********************************************************************/
223 globle void SendCommand(
231 result->type = SYMBOL;
232 result->value = EnvFalseSymbol(theEnv);
233 if (EnvArgTypeCheck(theEnv,"send",2,SYMBOL,&temp) == FALSE)
235 msg = (SYMBOL_HN *) temp.value;
237 /* =============================================
238 Get the instance or primitive for the message
239 ============================================= */
240 args.type = GetFirstArgument()->type;
241 args.value = GetFirstArgument()->value;
242 args.argList = GetFirstArgument()->argList;
243 args.nextArg = GetFirstArgument()->nextArg->nextArg;
245 PerformMessage(theEnv,result,&args,msg);
248 /***************************************************
249 NAME : GetNthMessageArgument
250 DESCRIPTION : Returns the address of the nth
251 (starting at 1) which is an
252 argument of the current message
255 RETURNS : The message argument
257 NOTES : The active instance is always
258 stored as the first argument (0) in
259 the call frame of the message
260 ***************************************************/
261 globle DATA_OBJECT *GetNthMessageArgument(
265 return(&ProceduralPrimitiveData(theEnv)->ProcParamArray[n]);
268 /*****************************************************
269 NAME : NextHandlerAvailable
270 DESCRIPTION : Determines if there the currently
271 executing handler can call a
273 Used before calling call-next-handler
275 RETURNS : TRUE if shadow ready, FALSE otherwise
277 NOTES : H/L Syntax: (next-handlerp)
278 *****************************************************/
279 globle int NextHandlerAvailable(
282 if (MessageHandlerData(theEnv)->CurrentCore == NULL)
284 if (MessageHandlerData(theEnv)->CurrentCore->hnd->type == MAROUND)
285 return((MessageHandlerData(theEnv)->NextInCore != NULL) ? TRUE : FALSE);
286 if ((MessageHandlerData(theEnv)->CurrentCore->hnd->type == MPRIMARY) && (MessageHandlerData(theEnv)->NextInCore != NULL))
287 return((MessageHandlerData(theEnv)->NextInCore->hnd->type == MPRIMARY) ? TRUE : FALSE);
291 /********************************************************
292 NAME : CallNextHandler
293 DESCRIPTION : This function allows around-handlers
294 to execute the rest of the core frame.
295 It also allows primary handlers
296 to execute shadowed primaries.
298 The original handler arguments are
300 INPUTS : The caller's result-value buffer
301 RETURNS : Nothing useful
302 SIDE EFFECTS : The core frame is called and any
303 appropriate changes are made when
304 used in an around handler
306 But when call-next-handler is called
307 from a primary, the same shadowed
308 primary is called over and over
309 again for repeated calls to
311 NOTES : H/L Syntax: (call-next-handler) OR
312 (override-next-handler <arg> ...)
313 ********************************************************/
314 globle void CallNextHandler(
320 HANDLER_LINK *oldNext,*oldCurrent;
321 #if PROFILING_FUNCTIONS
322 struct profileFrameInfo profileFrame;
325 SetpType(result,SYMBOL);
326 SetpValue(result,EnvFalseSymbol(theEnv));
327 EvaluationData(theEnv)->EvaluationError = FALSE;
328 if (EvaluationData(theEnv)->HaltExecution)
330 if (NextHandlerAvailable(theEnv) == FALSE)
332 PrintErrorID(theEnv,"MSGPASS",1,FALSE);
333 EnvPrintRouter(theEnv,WERROR,"Shadowed message-handlers not applicable in current context.\n");
334 SetEvaluationError(theEnv,TRUE);
337 if (EvaluationData(theEnv)->CurrentExpression->value == (void *) FindFunction(theEnv,"override-next-handler"))
340 args.type = ProceduralPrimitiveData(theEnv)->ProcParamArray[0].type;
341 if (args.type != MULTIFIELD)
342 args.value = (void *) ProceduralPrimitiveData(theEnv)->ProcParamArray[0].value;
344 args.value = (void *) &ProceduralPrimitiveData(theEnv)->ProcParamArray[0];
345 args.nextArg = GetFirstArgument();
347 PushProcParameters(theEnv,&args,CountArguments(&args),
348 ValueToString(MessageHandlerData(theEnv)->CurrentMessageName),"message",
350 if (EvaluationData(theEnv)->EvaluationError)
352 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
358 oldNext = MessageHandlerData(theEnv)->NextInCore;
359 oldCurrent = MessageHandlerData(theEnv)->CurrentCore;
360 if (MessageHandlerData(theEnv)->CurrentCore->hnd->type == MAROUND)
362 if (MessageHandlerData(theEnv)->NextInCore->hnd->type == MAROUND)
364 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore;
365 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
366 #if DEBUGGING_FUNCTIONS
367 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
368 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
370 if (CheckHandlerArgCount(theEnv))
372 #if PROFILING_FUNCTIONS
373 StartProfile(theEnv,&profileFrame,
374 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
375 ProfileFunctionData(theEnv)->ProfileConstructs);
378 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
379 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
380 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
381 result,UnboundHandlerErr);
382 #if PROFILING_FUNCTIONS
383 EndProfile(theEnv,&profileFrame);
386 #if DEBUGGING_FUNCTIONS
387 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
388 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
392 CallHandlers(theEnv,result);
396 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore;
397 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
398 #if DEBUGGING_FUNCTIONS
399 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
400 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
402 if (CheckHandlerArgCount(theEnv))
404 #if PROFILING_FUNCTIONS
405 StartProfile(theEnv,&profileFrame,
406 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
407 ProfileFunctionData(theEnv)->ProfileConstructs);
410 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
411 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
412 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
413 result,UnboundHandlerErr);
414 #if PROFILING_FUNCTIONS
415 EndProfile(theEnv,&profileFrame);
419 #if DEBUGGING_FUNCTIONS
420 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
421 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
424 MessageHandlerData(theEnv)->NextInCore = oldNext;
425 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
427 PopProcParameters(theEnv);
428 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
431 /*************************************************************************
432 NAME : FindApplicableOfName
433 DESCRIPTION : Groups all handlers of all types of the specified
434 class of the specified name into the applicable handler
436 INPUTS : 1) The class address
437 2-3) The tops and bottoms of the four handler type lists:
438 around, before, primary and after
439 4) The message name symbol
440 RETURNS : Nothing useful
441 SIDE EFFECTS : Modifies the handler lists to include applicable handlers
443 *************************************************************************/
444 globle void FindApplicableOfName(
447 HANDLER_LINK *tops[4],
448 HANDLER_LINK *bots[4],
457 i = FindHandlerNameGroup(cls,mname);
460 e = ((int) cls->handlerCount) - 1;
462 arr = cls->handlerOrderMap;
463 for ( ; i <= e ; i++)
465 if (hnd[arr[i]].name != mname)
468 tmp = get_struct(theEnv,messageHandlerLink);
470 IncrementDefclassBusyCount(theEnv,(void *) hnd[arr[i]].cls);
471 tmp->hnd = &hnd[arr[i]];
472 if (tops[tmp->hnd->type] == NULL)
475 tops[tmp->hnd->type] = bots[tmp->hnd->type] = tmp;
478 else if (tmp->hnd->type == MAFTER)
480 tmp->nxt = tops[tmp->hnd->type];
481 tops[tmp->hnd->type] = tmp;
486 bots[tmp->hnd->type]->nxt = tmp;
487 bots[tmp->hnd->type] = tmp;
493 /*************************************************************************
494 NAME : JoinHandlerLinks
495 DESCRIPTION : Joins the queues of different handlers together
496 INPUTS : 1-2) The tops and bottoms of the four handler type lists:
497 around, before, primary and after
498 3) The message name symbol
499 RETURNS : The top of the joined lists, NULL on errors
500 SIDE EFFECTS : Links all the handler type lists together, or all the
501 lists are destroyed if there are no primary handlers
503 *************************************************************************/
504 globle HANDLER_LINK *JoinHandlerLinks(
506 HANDLER_LINK *tops[4],
507 HANDLER_LINK *bots[4],
513 if (tops[MPRIMARY] == NULL)
515 PrintNoHandlerError(theEnv,ValueToString(mname));
516 for (i = MAROUND ; i <= MAFTER ; i++)
517 DestroyHandlerLinks(theEnv,tops[i]);
518 SetEvaluationError(theEnv,TRUE);
522 mlink = tops[MPRIMARY];
524 if (tops[MBEFORE] != NULL)
526 bots[MBEFORE]->nxt = mlink;
527 mlink = tops[MBEFORE];
530 if (tops[MAROUND] != NULL)
532 bots[MAROUND]->nxt = mlink;
533 mlink = tops[MAROUND];
536 bots[MPRIMARY]->nxt = tops[MAFTER];
541 /***************************************************
542 NAME : PrintHandlerSlotGetFunction
543 DESCRIPTION : Developer access function for
544 printing direct slot references
546 INPUTS : 1) The logical name of the output
547 2) The bitmap expression
548 RETURNS : Nothing useful
549 SIDE EFFECTS : Expression printed
551 ***************************************************/
552 globle void PrintHandlerSlotGetFunction(
554 const char *logicalName,
558 HANDLER_SLOT_REFERENCE *theReference;
559 DEFCLASS *theDefclass;
562 theReference = (HANDLER_SLOT_REFERENCE *) ValueToBitMap(theValue);
563 EnvPrintRouter(theEnv,logicalName,"?self:[");
564 theDefclass = DefclassData(theEnv)->ClassIDMap[theReference->classID];
565 EnvPrintRouter(theEnv,logicalName,ValueToString(theDefclass->header.name));
566 EnvPrintRouter(theEnv,logicalName,"]");
567 sd = theDefclass->instanceTemplate[theDefclass->slotNameMap[theReference->slotID] - 1];
568 EnvPrintRouter(theEnv,logicalName,ValueToString(sd->slotName->name));
571 #pragma unused(theEnv)
572 #pragma unused(logicalName)
573 #pragma unused(theValue)
578 /***************************************************
579 NAME : HandlerSlotGetFunction
580 DESCRIPTION : Access function for handling the
581 statically-bound direct slot
582 references in message-handlers
583 INPUTS : 1) The bitmap expression
584 2) A data object buffer
585 RETURNS : TRUE if OK, FALSE
587 SIDE EFFECTS : Data object buffer gets value of
588 slot. On errors, buffer gets
589 symbol FALSE, EvaluationError
590 is set and error messages are
592 NOTES : It is possible for a handler
593 (attached to a superclass of
594 the currently active instance)
595 containing these static references
596 to be called for an instance
597 which does not contain the slots
598 (e.g., an instance of a subclass
599 where the original slot was
600 no-inherit or the subclass
601 overrode the original slot)
602 ***************************************************/
603 globle intBool HandlerSlotGetFunction(
606 DATA_OBJECT *theResult)
608 HANDLER_SLOT_REFERENCE *theReference;
609 DEFCLASS *theDefclass;
610 INSTANCE_TYPE *theInstance;
612 unsigned instanceSlotIndex;
614 theReference = (HANDLER_SLOT_REFERENCE *) ValueToBitMap(theValue);
615 theInstance = (INSTANCE_TYPE *) ProceduralPrimitiveData(theEnv)->ProcParamArray[0].value;
616 theDefclass = DefclassData(theEnv)->ClassIDMap[theReference->classID];
618 if (theInstance->garbage)
620 StaleInstanceAddress(theEnv,"for slot get",0);
621 theResult->type = SYMBOL;
622 theResult->value = EnvFalseSymbol(theEnv);
623 SetEvaluationError(theEnv,TRUE);
627 if (theInstance->cls == theDefclass)
629 instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
630 sp = theInstance->slotAddresses[instanceSlotIndex - 1];
634 if (theReference->slotID > theInstance->cls->maxSlotNameID)
635 goto HandlerGetError;
636 instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
637 if (instanceSlotIndex == 0)
638 goto HandlerGetError;
640 sp = theInstance->slotAddresses[instanceSlotIndex];
641 if (sp->desc->cls != theDefclass)
642 goto HandlerGetError;
644 theResult->type = (unsigned short) sp->type;
645 theResult->value = sp->value;
646 if (sp->type == MULTIFIELD)
648 theResult->begin = 0;
649 SetpDOEnd(theResult,GetInstanceSlotLength(sp));
654 EarlySlotBindError(theEnv,theInstance,theDefclass,theReference->slotID);
655 theResult->type = SYMBOL;
656 theResult->value = EnvFalseSymbol(theEnv);
657 SetEvaluationError(theEnv,TRUE);
661 /***************************************************
662 NAME : PrintHandlerSlotPutFunction
663 DESCRIPTION : Developer access function for
664 printing direct slot bindings
666 INPUTS : 1) The logical name of the output
667 2) The bitmap expression
668 RETURNS : Nothing useful
669 SIDE EFFECTS : Expression printed
671 ***************************************************/
672 globle void PrintHandlerSlotPutFunction(
674 const char *logicalName,
678 HANDLER_SLOT_REFERENCE *theReference;
679 DEFCLASS *theDefclass;
682 theReference = (HANDLER_SLOT_REFERENCE *) ValueToBitMap(theValue);
683 EnvPrintRouter(theEnv,logicalName,"(bind ?self:[");
684 theDefclass = DefclassData(theEnv)->ClassIDMap[theReference->classID];
685 EnvPrintRouter(theEnv,logicalName,ValueToString(theDefclass->header.name));
686 EnvPrintRouter(theEnv,logicalName,"]");
687 sd = theDefclass->instanceTemplate[theDefclass->slotNameMap[theReference->slotID] - 1];
688 EnvPrintRouter(theEnv,logicalName,ValueToString(sd->slotName->name));
689 if (GetFirstArgument() != NULL)
691 EnvPrintRouter(theEnv,logicalName," ");
692 PrintExpression(theEnv,logicalName,GetFirstArgument());
694 EnvPrintRouter(theEnv,logicalName,")");
697 #pragma unused(theEnv)
698 #pragma unused(logicalName)
699 #pragma unused(theValue)
704 /***************************************************
705 NAME : HandlerSlotPutFunction
706 DESCRIPTION : Access function for handling the
707 statically-bound direct slot
708 bindings in message-handlers
709 INPUTS : 1) The bitmap expression
710 2) A data object buffer
711 RETURNS : TRUE if OK, FALSE
713 SIDE EFFECTS : Data object buffer gets symbol
714 TRUE and slot is set. On errors,
715 buffer gets symbol FALSE,
716 EvaluationError is set and error
718 NOTES : It is possible for a handler
719 (attached to a superclass of
720 the currently active instance)
721 containing these static references
722 to be called for an instance
723 which does not contain the slots
724 (e.g., an instance of a subclass
725 where the original slot was
726 no-inherit or the subclass
727 overrode the original slot)
728 ***************************************************/
729 globle intBool HandlerSlotPutFunction(
732 DATA_OBJECT *theResult)
734 HANDLER_SLOT_REFERENCE *theReference;
735 DEFCLASS *theDefclass;
736 INSTANCE_TYPE *theInstance;
738 unsigned instanceSlotIndex;
739 DATA_OBJECT theSetVal;
741 theReference = (HANDLER_SLOT_REFERENCE *) ValueToBitMap(theValue);
742 theInstance = (INSTANCE_TYPE *) ProceduralPrimitiveData(theEnv)->ProcParamArray[0].value;
743 theDefclass = DefclassData(theEnv)->ClassIDMap[theReference->classID];
745 if (theInstance->garbage)
747 StaleInstanceAddress(theEnv,"for slot put",0);
748 theResult->type = SYMBOL;
749 theResult->value = EnvFalseSymbol(theEnv);
750 SetEvaluationError(theEnv,TRUE);
754 if (theInstance->cls == theDefclass)
756 instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
757 sp = theInstance->slotAddresses[instanceSlotIndex - 1];
761 if (theReference->slotID > theInstance->cls->maxSlotNameID)
762 goto HandlerPutError;
763 instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
764 if (instanceSlotIndex == 0)
765 goto HandlerPutError;
767 sp = theInstance->slotAddresses[instanceSlotIndex];
768 if (sp->desc->cls != theDefclass)
769 goto HandlerPutError;
772 /* =======================================================
773 The slot has already been verified not to be read-only.
774 However, if it is initialize-only, we need to make sure
775 that we are initializing the instance (something we
776 could not verify at parse-time)
777 ======================================================= */
778 if (sp->desc->initializeOnly && (!theInstance->initializeInProgress))
780 SlotAccessViolationError(theEnv,ValueToString(sp->desc->slotName->name),
781 TRUE,(void *) theInstance);
782 goto HandlerPutError2;
785 /* ======================================
786 No arguments means to use the
787 special NoParamValue to reset the slot
789 ====================================== */
790 if (GetFirstArgument())
792 if (EvaluateAndStoreInDataObject(theEnv,(int) sp->desc->multiple,
793 GetFirstArgument(),&theSetVal,TRUE) == FALSE)
794 goto HandlerPutError2;
798 SetDOBegin(theSetVal,1);
799 SetDOEnd(theSetVal,0);
800 SetType(theSetVal,MULTIFIELD);
801 SetValue(theSetVal,ProceduralPrimitiveData(theEnv)->NoParamValue);
803 if (PutSlotValue(theEnv,theInstance,sp,&theSetVal,theResult,NULL) == FALSE)
804 goto HandlerPutError2;
808 EarlySlotBindError(theEnv,theInstance,theDefclass,theReference->slotID);
811 theResult->type = SYMBOL;
812 theResult->value = EnvFalseSymbol(theEnv);
813 SetEvaluationError(theEnv,TRUE);
818 /*****************************************************
819 NAME : DynamicHandlerGetSlot
820 DESCRIPTION : Directly references a slot's value
821 (uses dynamic binding to lookup slot)
822 INPUTS : The caller's result buffer
823 RETURNS : Nothing useful
824 SIDE EFFECTS : Caller's result buffer set
825 NOTES : H/L Syntax: (get <slot>)
826 *****************************************************/
827 globle void DynamicHandlerGetSlot(
835 result->type = SYMBOL;
836 result->value = EnvFalseSymbol(theEnv);
837 if (CheckCurrentMessage(theEnv,"dynamic-get",TRUE) == FALSE)
839 EvaluateExpression(theEnv,GetFirstArgument(),&temp);
840 if (temp.type != SYMBOL)
842 ExpectedTypeError1(theEnv,"dynamic-get",1,"symbol");
843 SetEvaluationError(theEnv,TRUE);
846 ins = GetActiveInstance(theEnv);
847 sp = FindInstanceSlot(theEnv,ins,(SYMBOL_HN *) temp.value);
850 SlotExistError(theEnv,ValueToString(temp.value),"dynamic-get");
853 if ((sp->desc->publicVisibility == 0) &&
854 (MessageHandlerData(theEnv)->CurrentCore->hnd->cls != sp->desc->cls))
856 SlotVisibilityViolationError(theEnv,sp->desc,MessageHandlerData(theEnv)->CurrentCore->hnd->cls);
857 SetEvaluationError(theEnv,TRUE);
860 result->type = (unsigned short) sp->type;
861 result->value = sp->value;
862 if (sp->type == MULTIFIELD)
865 SetpDOEnd(result,GetInstanceSlotLength(sp));
869 /***********************************************************
870 NAME : DynamicHandlerPutSlot
871 DESCRIPTION : Directly puts a slot's value
872 (uses dynamic binding to lookup slot)
873 INPUTS : Data obejct buffer for holding slot value
874 RETURNS : Nothing useful
875 SIDE EFFECTS : Slot modified - and caller's buffer set
876 to value (or symbol FALSE on errors)
877 NOTES : H/L Syntax: (put <slot> <value>*)
878 ***********************************************************/
879 globle void DynamicHandlerPutSlot(
881 DATA_OBJECT *theResult)
887 theResult->type = SYMBOL;
888 theResult->value = EnvFalseSymbol(theEnv);
889 if (CheckCurrentMessage(theEnv,"dynamic-put",TRUE) == FALSE)
891 EvaluateExpression(theEnv,GetFirstArgument(),&temp);
892 if (temp.type != SYMBOL)
894 ExpectedTypeError1(theEnv,"dynamic-put",1,"symbol");
895 SetEvaluationError(theEnv,TRUE);
898 ins = GetActiveInstance(theEnv);
899 sp = FindInstanceSlot(theEnv,ins,(SYMBOL_HN *) temp.value);
902 SlotExistError(theEnv,ValueToString(temp.value),"dynamic-put");
905 if ((sp->desc->noWrite == 0) ? FALSE :
906 ((sp->desc->initializeOnly == 0) || (!ins->initializeInProgress)))
908 SlotAccessViolationError(theEnv,ValueToString(sp->desc->slotName->name),
910 SetEvaluationError(theEnv,TRUE);
913 if ((sp->desc->publicVisibility == 0) &&
914 (MessageHandlerData(theEnv)->CurrentCore->hnd->cls != sp->desc->cls))
916 SlotVisibilityViolationError(theEnv,sp->desc,MessageHandlerData(theEnv)->CurrentCore->hnd->cls);
917 SetEvaluationError(theEnv,TRUE);
920 if (GetFirstArgument()->nextArg)
922 if (EvaluateAndStoreInDataObject(theEnv,(int) sp->desc->multiple,
923 GetFirstArgument()->nextArg,&temp,TRUE) == FALSE)
928 SetpDOBegin(&temp,1);
930 SetpType(&temp,MULTIFIELD);
931 SetpValue(&temp,ProceduralPrimitiveData(theEnv)->NoParamValue);
933 PutSlotValue(theEnv,ins,sp,&temp,theResult,NULL);
936 /* =========================================
937 *****************************************
938 INTERNALLY VISIBLE FUNCTIONS
939 =========================================
940 ***************************************** */
942 /*****************************************************
943 NAME : PerformMessage
944 DESCRIPTION : Calls core framework for a message
945 INPUTS : 1) Caller's result buffer
946 2) Message argument expressions
947 (including implicit object)
949 RETURNS : Returns FALSE is an execution error occurred
950 or execution is halted, otherwise TRUE
951 SIDE EFFECTS : Any side-effects of message execution
952 and caller's result buffer set
953 NOTES : It's no longer necessary for a defclass
954 to be in scope in order to sent a message
955 to an instance of that class.
956 *****************************************************/
957 static intBool PerformMessage(
964 /* HANDLER_LINK *oldCore; */
965 DEFCLASS *cls = NULL;
966 INSTANCE_TYPE *ins = NULL;
968 #if PROFILING_FUNCTIONS
969 struct profileFrameInfo profileFrame;
971 struct garbageFrame newGarbageFrame;
972 struct garbageFrame *oldGarbageFrame;
974 result->type = SYMBOL;
975 result->value = EnvFalseSymbol(theEnv);
976 EvaluationData(theEnv)->EvaluationError = FALSE;
977 if (EvaluationData(theEnv)->HaltExecution)
980 oldGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame;
981 memset(&newGarbageFrame,0,sizeof(struct garbageFrame));
982 UtilityData(theEnv)->CurrentGarbageFrame = &newGarbageFrame;
984 oldce = ExecutingConstruct(theEnv);
985 SetExecutingConstruct(theEnv,TRUE);
986 oldName = MessageHandlerData(theEnv)->CurrentMessageName;
987 MessageHandlerData(theEnv)->CurrentMessageName = mname;
988 EvaluationData(theEnv)->CurrentEvaluationDepth++;
990 PushProcParameters(theEnv,args,CountArguments(args),
991 ValueToString(MessageHandlerData(theEnv)->CurrentMessageName),"message",
995 if (EvaluationData(theEnv)->EvaluationError)
997 EvaluationData(theEnv)->CurrentEvaluationDepth--;
998 MessageHandlerData(theEnv)->CurrentMessageName = oldName;
1000 RestorePriorGarbageFrame(theEnv,&newGarbageFrame,oldGarbageFrame,result);
1001 CallPeriodicTasks(theEnv);
1003 SetExecutingConstruct(theEnv,oldce);
1007 if (ProceduralPrimitiveData(theEnv)->ProcParamArray->type == INSTANCE_ADDRESS)
1009 ins = (INSTANCE_TYPE *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value;
1010 if (ins->garbage == 1)
1012 StaleInstanceAddress(theEnv,"send",0);
1013 SetEvaluationError(theEnv,TRUE);
1015 //else if (DefclassInScope(theEnv,ins->cls,(struct defmodule *) EnvGetCurrentModule(theEnv)) == FALSE)
1016 // NoInstanceError(theEnv,ValueToString(ins->name),"send");
1023 else if (ProceduralPrimitiveData(theEnv)->ProcParamArray->type == INSTANCE_NAME)
1025 ins = FindInstanceBySymbol(theEnv,(SYMBOL_HN *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value);
1028 PrintErrorID(theEnv,"MSGPASS",2,FALSE);
1029 EnvPrintRouter(theEnv,WERROR,"No such instance ");
1030 EnvPrintRouter(theEnv,WERROR,ValueToString((SYMBOL_HN *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value));
1031 EnvPrintRouter(theEnv,WERROR," in function send.\n");
1032 SetEvaluationError(theEnv,TRUE);
1036 ProceduralPrimitiveData(theEnv)->ProcParamArray->value = (void *) ins;
1037 ProceduralPrimitiveData(theEnv)->ProcParamArray->type = INSTANCE_ADDRESS;
1042 else if ((cls = DefclassData(theEnv)->PrimitiveClassMap[ProceduralPrimitiveData(theEnv)->ProcParamArray->type]) == NULL)
1044 SystemError(theEnv,"MSGPASS",1);
1045 EnvExitRouter(theEnv,EXIT_FAILURE);
1047 if (EvaluationData(theEnv)->EvaluationError)
1049 PopProcParameters(theEnv);
1050 EvaluationData(theEnv)->CurrentEvaluationDepth--;
1051 MessageHandlerData(theEnv)->CurrentMessageName = oldName;
1053 RestorePriorGarbageFrame(theEnv,&newGarbageFrame,oldGarbageFrame,result);
1054 CallPeriodicTasks(theEnv);
1056 SetExecutingConstruct(theEnv,oldce);
1060 /* oldCore = MessageHandlerData(theEnv)->TopOfCore; */
1062 if (MessageHandlerData(theEnv)->TopOfCore != NULL)
1063 { MessageHandlerData(theEnv)->TopOfCore->nxtInStack = MessageHandlerData(theEnv)->OldCore; }
1064 MessageHandlerData(theEnv)->OldCore = MessageHandlerData(theEnv)->TopOfCore;
1066 MessageHandlerData(theEnv)->TopOfCore = FindApplicableHandlers(theEnv,cls,mname);
1068 if (MessageHandlerData(theEnv)->TopOfCore != NULL)
1070 HANDLER_LINK *oldCurrent,*oldNext;
1072 oldCurrent = MessageHandlerData(theEnv)->CurrentCore;
1073 oldNext = MessageHandlerData(theEnv)->NextInCore;
1075 if (MessageHandlerData(theEnv)->TopOfCore->hnd->type == MAROUND)
1077 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->TopOfCore;
1078 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->TopOfCore->nxt;
1079 #if DEBUGGING_FUNCTIONS
1080 if (MessageHandlerData(theEnv)->WatchMessages)
1081 WatchMessage(theEnv,WTRACE,BEGIN_TRACE);
1082 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1083 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
1085 if (CheckHandlerArgCount(theEnv))
1087 #if PROFILING_FUNCTIONS
1088 StartProfile(theEnv,&profileFrame,
1089 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
1090 ProfileFunctionData(theEnv)->ProfileConstructs);
1094 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
1095 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
1096 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
1097 result,UnboundHandlerErr);
1100 #if PROFILING_FUNCTIONS
1101 EndProfile(theEnv,&profileFrame);
1105 #if DEBUGGING_FUNCTIONS
1106 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1107 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
1108 if (MessageHandlerData(theEnv)->WatchMessages)
1109 WatchMessage(theEnv,WTRACE,END_TRACE);
1114 MessageHandlerData(theEnv)->CurrentCore = NULL;
1115 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->TopOfCore;
1116 #if DEBUGGING_FUNCTIONS
1117 if (MessageHandlerData(theEnv)->WatchMessages)
1118 WatchMessage(theEnv,WTRACE,BEGIN_TRACE);
1120 CallHandlers(theEnv,result);
1121 #if DEBUGGING_FUNCTIONS
1122 if (MessageHandlerData(theEnv)->WatchMessages)
1123 WatchMessage(theEnv,WTRACE,END_TRACE);
1127 DestroyHandlerLinks(theEnv,MessageHandlerData(theEnv)->TopOfCore);
1128 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1129 MessageHandlerData(theEnv)->NextInCore = oldNext;
1132 /* MessageHandlerData(theEnv)->TopOfCore = oldCore; */
1133 MessageHandlerData(theEnv)->TopOfCore = MessageHandlerData(theEnv)->OldCore;
1134 if (MessageHandlerData(theEnv)->OldCore != NULL)
1135 { MessageHandlerData(theEnv)->OldCore = MessageHandlerData(theEnv)->OldCore->nxtInStack; }
1137 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
1142 /* ==================================
1143 Restore the original calling frame
1144 ================================== */
1145 PopProcParameters(theEnv);
1146 EvaluationData(theEnv)->CurrentEvaluationDepth--;
1147 MessageHandlerData(theEnv)->CurrentMessageName = oldName;
1149 RestorePriorGarbageFrame(theEnv,&newGarbageFrame,oldGarbageFrame,result);
1150 CallPeriodicTasks(theEnv);
1152 SetExecutingConstruct(theEnv,oldce);
1154 if (EvaluationData(theEnv)->EvaluationError)
1156 result->type = SYMBOL;
1157 result->value = EnvFalseSymbol(theEnv);
1164 /*****************************************************************************
1165 NAME : FindApplicableHandlers
1166 DESCRIPTION : Given a message name, this routine forms the "core frame"
1167 for the message : a list of all applicable class handlers.
1168 An applicable class handler is one whose name matches
1169 the message and whose class matches the instance.
1171 The list is in the following order :
1173 All around handlers (from most specific to most general)
1174 All before handlers (from most specific to most general)
1175 All primary handlers (from most specific to most general)
1176 All after handlers (from most general to most specific)
1178 INPUTS : 1) The class of the instance (or primitive) for the message
1180 RETURNS : NULL if no applicable handlers or errors,
1181 the list of handlers otherwise
1182 SIDE EFFECTS : Links are allocated for the list
1183 NOTES : The instance is the first thing on the ProcParamArray
1184 The number of arguments is in ProcParamArraySize
1185 *****************************************************************************/
1186 static HANDLER_LINK *FindApplicableHandlers(
1192 HANDLER_LINK *tops[4],*bots[4];
1194 for (i = MAROUND ; i <= MAFTER ; i++)
1195 tops[i] = bots[i] = NULL;
1197 for (i = 0 ; i < cls->allSuperclasses.classCount ; i++)
1198 FindApplicableOfName(theEnv,cls->allSuperclasses.classArray[i],tops,bots,mname);
1199 return(JoinHandlerLinks(theEnv,tops,bots,mname));
1202 /***************************************************************
1204 DESCRIPTION : Moves though the current message frame
1205 for a send-message as follows :
1207 Call all before handlers and ignore their
1209 Call the first primary handler and
1210 ignore the rest. The return value
1211 of the handler frame is this message's value.
1212 Call all after handlers and ignore their
1214 INPUTS : Caller's buffer for the return value of
1216 RETURNS : Nothing useful
1217 SIDE EFFECTS : The handlers are evaluated.
1218 NOTES : IMPORTANT : The global NextInCore should be
1219 pointing to the first handler to be executed.
1220 ***************************************************************/
1221 static void CallHandlers(
1223 DATA_OBJECT *result)
1225 HANDLER_LINK *oldCurrent = NULL,*oldNext = NULL; /* prevents warning */
1227 #if PROFILING_FUNCTIONS
1228 struct profileFrameInfo profileFrame;
1231 if (EvaluationData(theEnv)->HaltExecution)
1234 oldCurrent = MessageHandlerData(theEnv)->CurrentCore;
1235 oldNext = MessageHandlerData(theEnv)->NextInCore;
1237 while (MessageHandlerData(theEnv)->NextInCore->hnd->type == MBEFORE)
1239 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore;
1240 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
1241 #if DEBUGGING_FUNCTIONS
1242 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1243 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
1245 if (CheckHandlerArgCount(theEnv))
1247 #if PROFILING_FUNCTIONS
1248 StartProfile(theEnv,&profileFrame,
1249 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
1250 ProfileFunctionData(theEnv)->ProfileConstructs);
1253 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
1254 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
1255 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
1256 &temp,UnboundHandlerErr);
1259 #if PROFILING_FUNCTIONS
1260 EndProfile(theEnv,&profileFrame);
1264 #if DEBUGGING_FUNCTIONS
1265 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1266 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
1268 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
1269 if ((MessageHandlerData(theEnv)->NextInCore == NULL) || EvaluationData(theEnv)->HaltExecution)
1271 MessageHandlerData(theEnv)->NextInCore = oldNext;
1272 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1276 if (MessageHandlerData(theEnv)->NextInCore->hnd->type == MPRIMARY)
1278 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore;
1279 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
1280 #if DEBUGGING_FUNCTIONS
1281 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1282 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
1284 if (CheckHandlerArgCount(theEnv))
1286 #if PROFILING_FUNCTIONS
1287 StartProfile(theEnv,&profileFrame,
1288 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
1289 ProfileFunctionData(theEnv)->ProfileConstructs);
1293 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
1294 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
1295 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
1296 result,UnboundHandlerErr);
1298 #if PROFILING_FUNCTIONS
1299 EndProfile(theEnv,&profileFrame);
1304 #if DEBUGGING_FUNCTIONS
1305 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1306 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
1308 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
1310 if ((MessageHandlerData(theEnv)->NextInCore == NULL) || EvaluationData(theEnv)->HaltExecution)
1312 MessageHandlerData(theEnv)->NextInCore = oldNext;
1313 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1316 while (MessageHandlerData(theEnv)->NextInCore->hnd->type == MPRIMARY)
1318 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
1319 if (MessageHandlerData(theEnv)->NextInCore == NULL)
1321 MessageHandlerData(theEnv)->NextInCore = oldNext;
1322 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1327 while (MessageHandlerData(theEnv)->NextInCore->hnd->type == MAFTER)
1329 MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore;
1330 MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;
1331 #if DEBUGGING_FUNCTIONS
1332 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1333 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,BEGIN_TRACE);
1335 if (CheckHandlerArgCount(theEnv))
1337 #if PROFILING_FUNCTIONS
1338 StartProfile(theEnv,&profileFrame,
1339 &MessageHandlerData(theEnv)->CurrentCore->hnd->usrData,
1340 ProfileFunctionData(theEnv)->ProfileConstructs);
1344 EvaluateProcActions(theEnv,MessageHandlerData(theEnv)->CurrentCore->hnd->cls->header.whichModule->theModule,
1345 MessageHandlerData(theEnv)->CurrentCore->hnd->actions,
1346 MessageHandlerData(theEnv)->CurrentCore->hnd->localVarCount,
1347 &temp,UnboundHandlerErr);
1349 #if PROFILING_FUNCTIONS
1350 EndProfile(theEnv,&profileFrame);
1355 #if DEBUGGING_FUNCTIONS
1356 if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
1357 WatchHandler(theEnv,WTRACE,MessageHandlerData(theEnv)->CurrentCore,END_TRACE);
1359 ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
1360 if ((MessageHandlerData(theEnv)->NextInCore == NULL) || EvaluationData(theEnv)->HaltExecution)
1362 MessageHandlerData(theEnv)->NextInCore = oldNext;
1363 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1368 MessageHandlerData(theEnv)->NextInCore = oldNext;
1369 MessageHandlerData(theEnv)->CurrentCore = oldCurrent;
1373 /********************************************************
1374 NAME : EarlySlotBindError
1375 DESCRIPTION : Prints out an error message when
1376 a message-handler from a superclass
1377 which contains a static-bind
1378 slot access is not valid for the
1379 currently active instance (i.e.
1380 the instance is not using the
1382 INPUTS : 1) The currently active instance
1383 2) The defclass holding the invalid slot
1384 3) The canonical id of the slot
1385 RETURNS : Nothing useful
1386 SIDE EFFECTS : Error message printed
1388 ********************************************************/
1389 static void EarlySlotBindError(
1391 INSTANCE_TYPE *theInstance,
1392 DEFCLASS *theDefclass,
1397 sd = theDefclass->instanceTemplate[theDefclass->slotNameMap[slotID] - 1];
1398 PrintErrorID(theEnv,"MSGPASS",3,FALSE);
1399 EnvPrintRouter(theEnv,WERROR,"Static reference to slot ");
1400 EnvPrintRouter(theEnv,WERROR,ValueToString(sd->slotName->name));
1401 EnvPrintRouter(theEnv,WERROR," of class ");
1402 PrintClassName(theEnv,WERROR,theDefclass,FALSE);
1403 EnvPrintRouter(theEnv,WERROR," does not apply to ");
1404 PrintInstanceNameAndClass(theEnv,WERROR,theInstance,TRUE);
1407 /*#####################################*/
1408 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
1409 /*#####################################*/
1411 #if ALLOW_ENVIRONMENT_GLOBALS
1417 DATA_OBJECT *result)
1419 EnvSend(GetCurrentEnvironment(),idata,msg,args,result);
1422 #endif /* ALLOW_ENVIRONMENT_GLOBALS */
1424 #endif /* OBJECT_SYSTEM */