📄 msgpass.c
字号:
}
/***************************************************
NAME : HandlerSlotPutFunction
DESCRIPTION : Access function for handling the
statically-bound direct slot
bindings in message-handlers
INPUTS : 1) The bitmap expression
2) A data object buffer
RETURNS : TRUE if OK, FALSE
on errors
SIDE EFFECTS : Data object buffer gets symbol
TRUE and slot is set. On errors,
buffer gets symbol FALSE,
EvaluationError is set and error
messages are printed
NOTES : It is possible for a handler
(attached to a superclass of
the currently active instance)
containing these static references
to be called for an instance
which does not contain the slots
(e.g., an instance of a subclass
where the original slot was
no-inherit or the subclass
overrode the original slot)
***************************************************/
globle intBool HandlerSlotPutFunction(
void *theEnv,
void *theValue,
DATA_OBJECT *theResult)
{
HANDLER_SLOT_REFERENCE *theReference;
DEFCLASS *theDefclass;
INSTANCE_TYPE *theInstance;
INSTANCE_SLOT *sp;
unsigned instanceSlotIndex;
DATA_OBJECT theSetVal;
theReference = (HANDLER_SLOT_REFERENCE *) ValueToBitMap(theValue);
theInstance = (INSTANCE_TYPE *) ProceduralPrimitiveData(theEnv)->ProcParamArray[0].value;
theDefclass = DefclassData(theEnv)->ClassIDMap[theReference->classID];
if (theInstance->garbage)
{
StaleInstanceAddress(theEnv,"for slot put",0);
theResult->type = SYMBOL;
theResult->value = EnvFalseSymbol(theEnv);
SetEvaluationError(theEnv,TRUE);
return(FALSE);
}
if (theInstance->cls == theDefclass)
{
instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
sp = theInstance->slotAddresses[instanceSlotIndex - 1];
}
else
{
if (theReference->slotID > theInstance->cls->maxSlotNameID)
goto HandlerPutError;
instanceSlotIndex = theInstance->cls->slotNameMap[theReference->slotID];
if (instanceSlotIndex == 0)
goto HandlerPutError;
instanceSlotIndex--;
sp = theInstance->slotAddresses[instanceSlotIndex];
if (sp->desc->cls != theDefclass)
goto HandlerPutError;
}
/* =======================================================
The slot has already been verified not to be read-only.
However, if it is initialize-only, we need to make sure
that we are initializing the instance (something we
could not verify at parse-time)
======================================================= */
if (sp->desc->initializeOnly && (!theInstance->initializeInProgress))
{
SlotAccessViolationError(theEnv,ValueToString(sp->desc->slotName->name),
TRUE,(void *) theInstance);
goto HandlerPutError2;
}
/* ======================================
No arguments means to use the
special NoParamValue to reset the slot
to its default value
====================================== */
if (GetFirstArgument())
{
if (EvaluateAndStoreInDataObject(theEnv,(int) sp->desc->multiple,
GetFirstArgument(),&theSetVal,TRUE) == FALSE)
goto HandlerPutError2;
}
else
{
SetDOBegin(theSetVal,1);
SetDOEnd(theSetVal,0);
SetType(theSetVal,MULTIFIELD);
SetValue(theSetVal,ProceduralPrimitiveData(theEnv)->NoParamValue);
}
if (PutSlotValue(theEnv,theInstance,sp,&theSetVal,theResult,NULL) == FALSE)
goto HandlerPutError2;
return(TRUE);
HandlerPutError:
EarlySlotBindError(theEnv,theInstance,theDefclass,theReference->slotID);
HandlerPutError2:
theResult->type = SYMBOL;
theResult->value = EnvFalseSymbol(theEnv);
SetEvaluationError(theEnv,TRUE);
return(FALSE);
}
/*****************************************************
NAME : DynamicHandlerGetSlot
DESCRIPTION : Directly references a slot's value
(uses dynamic binding to lookup slot)
INPUTS : The caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : Caller's result buffer set
NOTES : H/L Syntax: (get <slot>)
*****************************************************/
globle void DynamicHandlerGetSlot(
void *theEnv,
DATA_OBJECT *result)
{
INSTANCE_SLOT *sp;
INSTANCE_TYPE *ins;
DATA_OBJECT temp;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
if (CheckCurrentMessage(theEnv,"dynamic-get",TRUE) == FALSE)
return;
EvaluateExpression(theEnv,GetFirstArgument(),&temp);
if (temp.type != SYMBOL)
{
ExpectedTypeError1(theEnv,"dynamic-get",1,"symbol");
SetEvaluationError(theEnv,TRUE);
return;
}
ins = GetActiveInstance(theEnv);
sp = FindInstanceSlot(theEnv,ins,(SYMBOL_HN *) temp.value);
if (sp == NULL)
{
SlotExistError(theEnv,ValueToString(temp.value),"dynamic-get");
return;
}
if ((sp->desc->publicVisibility == 0) &&
(MessageHandlerData(theEnv)->CurrentCore->hnd->cls != sp->desc->cls))
{
SlotVisibilityViolationError(theEnv,sp->desc,MessageHandlerData(theEnv)->CurrentCore->hnd->cls);
SetEvaluationError(theEnv,TRUE);
return;
}
result->type = (unsigned short) sp->type;
result->value = sp->value;
if (sp->type == MULTIFIELD)
{
result->begin = 0;
SetpDOEnd(result,GetInstanceSlotLength(sp));
}
}
/***********************************************************
NAME : DynamicHandlerPutSlot
DESCRIPTION : Directly puts a slot's value
(uses dynamic binding to lookup slot)
INPUTS : Data obejct buffer for holding slot value
RETURNS : Nothing useful
SIDE EFFECTS : Slot modified - and caller's buffer set
to value (or symbol FALSE on errors)
NOTES : H/L Syntax: (put <slot> <value>*)
***********************************************************/
globle void DynamicHandlerPutSlot(
void *theEnv,
DATA_OBJECT *theResult)
{
INSTANCE_SLOT *sp;
INSTANCE_TYPE *ins;
DATA_OBJECT temp;
theResult->type = SYMBOL;
theResult->value = EnvFalseSymbol(theEnv);
if (CheckCurrentMessage(theEnv,"dynamic-put",TRUE) == FALSE)
return;
EvaluateExpression(theEnv,GetFirstArgument(),&temp);
if (temp.type != SYMBOL)
{
ExpectedTypeError1(theEnv,"dynamic-put",1,"symbol");
SetEvaluationError(theEnv,TRUE);
return;
}
ins = GetActiveInstance(theEnv);
sp = FindInstanceSlot(theEnv,ins,(SYMBOL_HN *) temp.value);
if (sp == NULL)
{
SlotExistError(theEnv,ValueToString(temp.value),"dynamic-put");
return;
}
if ((sp->desc->noWrite == 0) ? FALSE :
((sp->desc->initializeOnly == 0) || (!ins->initializeInProgress)))
{
SlotAccessViolationError(theEnv,ValueToString(sp->desc->slotName->name),
TRUE,(void *) ins);
SetEvaluationError(theEnv,TRUE);
return;
}
if ((sp->desc->publicVisibility == 0) &&
(MessageHandlerData(theEnv)->CurrentCore->hnd->cls != sp->desc->cls))
{
SlotVisibilityViolationError(theEnv,sp->desc,MessageHandlerData(theEnv)->CurrentCore->hnd->cls);
SetEvaluationError(theEnv,TRUE);
return;
}
if (GetFirstArgument()->nextArg)
{
if (EvaluateAndStoreInDataObject(theEnv,(int) sp->desc->multiple,
GetFirstArgument()->nextArg,&temp,TRUE) == FALSE)
return;
}
else
{
SetpDOBegin(&temp,1);
SetpDOEnd(&temp,0);
SetpType(&temp,MULTIFIELD);
SetpValue(&temp,ProceduralPrimitiveData(theEnv)->NoParamValue);
}
PutSlotValue(theEnv,ins,sp,&temp,theResult,NULL);
}
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/*****************************************************
NAME : PerformMessage
DESCRIPTION : Calls core framework for a message
INPUTS : 1) Caller's result buffer
2) Message argument expressions
(including implicit object)
3) Message name
RETURNS : Nothing useful
SIDE EFFECTS : Any side-effects of message execution
and caller's result buffer set
NOTES : None
*****************************************************/
static void PerformMessage(
void *theEnv,
DATA_OBJECT *result,
EXPRESSION *args,
SYMBOL_HN *mname)
{
int oldce;
HANDLER_LINK *oldCore;
DEFCLASS *cls = NULL;
INSTANCE_TYPE *ins = NULL;
SYMBOL_HN *oldName;
#if PROFILING_FUNCTIONS
struct profileFrameInfo profileFrame;
#endif
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
EvaluationData(theEnv)->EvaluationError = FALSE;
if (EvaluationData(theEnv)->HaltExecution)
return;
oldce = ExecutingConstruct(theEnv);
SetExecutingConstruct(theEnv,TRUE);
oldName = MessageHandlerData(theEnv)->CurrentMessageName;
MessageHandlerData(theEnv)->CurrentMessageName = mname;
EvaluationData(theEnv)->CurrentEvaluationDepth++;
PushProcParameters(theEnv,args,CountArguments(args),
ValueToString(MessageHandlerData(theEnv)->CurrentMessageName),"message",
UnboundHandlerErr);
if (EvaluationData(theEnv)->EvaluationError)
{
EvaluationData(theEnv)->CurrentEvaluationDepth--;
MessageHandlerData(theEnv)->CurrentMessageName = oldName;
PeriodicCleanup(theEnv,FALSE,TRUE);
SetExecutingConstruct(theEnv,oldce);
return;
}
if (ProceduralPrimitiveData(theEnv)->ProcParamArray->type == INSTANCE_ADDRESS)
{
ins = (INSTANCE_TYPE *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value;
if (ins->garbage == 1)
{
StaleInstanceAddress(theEnv,"send",0);
SetEvaluationError(theEnv,TRUE);
}
else if (DefclassInScope(theEnv,ins->cls,(struct defmodule *) EnvGetCurrentModule(theEnv)) == FALSE)
NoInstanceError(theEnv,ValueToString(ins->name),"send");
else
{
cls = ins->cls;
ins->busy++;
}
}
else if (ProceduralPrimitiveData(theEnv)->ProcParamArray->type == INSTANCE_NAME)
{
ins = FindInstanceBySymbol(theEnv,(SYMBOL_HN *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value);
if (ins == NULL)
{
PrintErrorID(theEnv,"MSGPASS",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"No such instance ");
EnvPrintRouter(theEnv,WERROR,ValueToString((SYMBOL_HN *) ProceduralPrimitiveData(theEnv)->ProcParamArray->value));
EnvPrintRouter(theEnv,WERROR," in function send.\n");
SetEvaluationError(theEnv,TRUE);
}
else
{
ProceduralPrimitiveData(theEnv)->ProcParamArray->value = (void *) ins;
ProceduralPrimitiveData(theEnv)->ProcParamArray->type = INSTANCE_ADDRESS;
cls = ins->cls;
ins->busy++;
}
}
else if ((cls = DefclassData(theEnv)->PrimitiveClassMap[ProceduralPrimitiveData(theEnv)->ProcParamArray->type]) == NULL)
{
SystemError(theEnv,"MSGPASS",1);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
if (EvaluationData(theEnv)->EvaluationError)
{
PopProcParameters(theEnv);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
MessageHandlerData(theEnv)->CurrentMessageName = oldName;
PeriodicCleanup(theEnv,FALSE,TRUE);
SetExecutingConstruct(theEnv,oldce);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -