📄 insmngr.c
字号:
InstanceData(theEnv)->InstanceTable[hashTableIndex]->prvHash = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->InstanceTable[hashTableIndex] = InstanceData(theEnv)->CurrentInstance;
}
else
{
InstanceData(theEnv)->CurrentInstance->nxtHash = iprv->nxtHash;
if (iprv->nxtHash != NULL)
iprv->nxtHash->prvHash = InstanceData(theEnv)->CurrentInstance;
iprv->nxtHash = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->CurrentInstance->prvHash = iprv;
}
/* ======================================
Put instance in global and class lists
====================================== */
if (InstanceData(theEnv)->CurrentInstance->cls->instanceList == NULL)
InstanceData(theEnv)->CurrentInstance->cls->instanceList = InstanceData(theEnv)->CurrentInstance;
else
InstanceData(theEnv)->CurrentInstance->cls->instanceListBottom->nxtClass = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->CurrentInstance->prvClass = InstanceData(theEnv)->CurrentInstance->cls->instanceListBottom;
InstanceData(theEnv)->CurrentInstance->cls->instanceListBottom = InstanceData(theEnv)->CurrentInstance;
if (InstanceData(theEnv)->InstanceList == NULL)
InstanceData(theEnv)->InstanceList = InstanceData(theEnv)->CurrentInstance;
else
InstanceData(theEnv)->InstanceListBottom->nxtList = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->CurrentInstance->prvList = InstanceData(theEnv)->InstanceListBottom;
InstanceData(theEnv)->InstanceListBottom = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->ChangesToInstances = TRUE;
/* ==============================================================================
Install the instance's name and slot-value symbols (prevent them from becoming
ephemeral) - the class name and slot names are accounted for by the class
============================================================================== */
InstallInstance(theEnv,InstanceData(theEnv)->CurrentInstance,TRUE);
ins = InstanceData(theEnv)->CurrentInstance;
InstanceData(theEnv)->CurrentInstance = NULL;
if (InstanceData(theEnv)->MkInsMsgPass)
{ DirectMessage(theEnv,MessageHandlerData(theEnv)->CREATE_SYMBOL,ins,&temp,NULL); }
#if DEFRULE_CONSTRUCT
if (ins->cls->reactive)
ObjectNetworkAction(theEnv,OBJECT_ASSERT,(INSTANCE_TYPE *) ins,-1);
#endif
return(ins);
}
/*****************************************************************************
NAME : InitSlotsCommand
DESCRIPTION : Calls Kernel Expression Evaluator EvaluateExpression
for each expression-value of an instance expression
Evaluates default slots only - slots that were specified
by overrides (sp->override == 1) are ignored)
INPUTS : 1) Instance address
RETURNS : Nothing useful
SIDE EFFECTS : Each DATA_OBJECT slot in the instance's slot array is replaced
by the evaluation (by EvaluateExpression) of the expression
in the slot list. The old expression-values
are deleted.
NOTES : H/L Syntax: (init-slots <instance>)
*****************************************************************************/
globle void InitSlotsCommand(
void *theEnv,
DATA_OBJECT *result)
{
SetpType(result,SYMBOL);
SetpValue(result,EnvFalseSymbol(theEnv));
EvaluationData(theEnv)->EvaluationError = FALSE;
if (CheckCurrentMessage(theEnv,"init-slots",TRUE) == FALSE)
return;
EvaluateClassDefaults(theEnv,GetActiveInstance(theEnv));
if (! EvaluationData(theEnv)->EvaluationError)
{
SetpType(result,INSTANCE_ADDRESS);
SetpValue(result,(void *) GetActiveInstance(theEnv));
}
}
/******************************************************
NAME : QuashInstance
DESCRIPTION : Deletes an instance if it is not in
use, otherwise sticks it on the
garbage list
INPUTS : The instance
RETURNS : 1 if successful, 0 otherwise
SIDE EFFECTS : Instance deleted or added to garbage
NOTES : Even though the instance is removed
from the class list, hash table and
instance list, its links remain
unchanged so that outside loops
can still determine where the next
node in the list is (assuming the
instance was garbage collected).
******************************************************/
globle intBool QuashInstance(
void *theEnv,
INSTANCE_TYPE *ins)
{
register int iflag;
IGARBAGE *gptr;
#if DEFRULE_CONSTRUCT
if (EngineData(theEnv)->JoinOperationInProgress && ins->cls->reactive)
{
PrintErrorID(theEnv,"INSMNGR",12,FALSE);
EnvPrintRouter(theEnv,WERROR,"Cannot delete instances of reactive classes while\n");
EnvPrintRouter(theEnv,WERROR," pattern-matching is in process.\n");
SetEvaluationError(theEnv,TRUE);
return(0);
}
#endif
if (ins->garbage == 1)
return(0);
if (ins->installed == 0)
{
PrintErrorID(theEnv,"INSMNGR",6,FALSE);
EnvPrintRouter(theEnv,WERROR,"Cannot delete instance ");
EnvPrintRouter(theEnv,WERROR,ValueToString(ins->name));
EnvPrintRouter(theEnv,WERROR," during initialization.\n");
SetEvaluationError(theEnv,TRUE);
return(0);
}
#if DEBUGGING_FUNCTIONS
if (ins->cls->traceInstances)
PrintInstanceWatch(theEnv,UNMAKE_TRACE,ins);
#endif
#if DEFRULE_CONSTRUCT
RemoveEntityDependencies(theEnv,(struct patternEntity *) ins);
if (ins->cls->reactive)
ObjectNetworkAction(theEnv,OBJECT_RETRACT,(INSTANCE_TYPE *) ins,-1);
#endif
if (ins->prvHash != NULL)
ins->prvHash->nxtHash = ins->nxtHash;
else
InstanceData(theEnv)->InstanceTable[ins->hashTableIndex] = ins->nxtHash;
if (ins->nxtHash != NULL)
ins->nxtHash->prvHash = ins->prvHash;
if (ins->prvClass != NULL)
ins->prvClass->nxtClass = ins->nxtClass;
else
ins->cls->instanceList = ins->nxtClass;
if (ins->nxtClass != NULL)
ins->nxtClass->prvClass = ins->prvClass;
else
ins->cls->instanceListBottom = ins->prvClass;
if (ins->prvList != NULL)
ins->prvList->nxtList = ins->nxtList;
else
InstanceData(theEnv)->InstanceList = ins->nxtList;
if (ins->nxtList != NULL)
ins->nxtList->prvList = ins->prvList;
else
InstanceData(theEnv)->InstanceListBottom = ins->prvList;
iflag = ins->installed;
InstallInstance(theEnv,ins,FALSE);
/* ==============================================
If the instance is the basis for an executing
rule, don't bother deleting its slots yet, for
they may still be needed by pattern variables
============================================== */
if ((iflag == 1)
#if DEFRULE_CONSTRUCT
&& (ins->header.busyCount == 0)
#endif
)
RemoveInstanceData(theEnv,ins);
if ((ins->busy == 0) && (ins->depth > EvaluationData(theEnv)->CurrentEvaluationDepth) &&
(InstanceData(theEnv)->MaintainGarbageInstances == FALSE)
#if DEFRULE_CONSTRUCT
&& (ins->header.busyCount == 0)
#endif
)
{
DecrementSymbolCount(theEnv,ins->name);
rtn_struct(theEnv,instance,ins);
}
else
{
gptr = get_struct(theEnv,igarbage);
ins->garbage = 1;
gptr->ins = ins;
gptr->nxt = InstanceData(theEnv)->InstanceGarbageList;
InstanceData(theEnv)->InstanceGarbageList = gptr;
UtilityData(theEnv)->EphemeralItemCount += 2;
UtilityData(theEnv)->EphemeralItemSize += InstanceSizeHeuristic(ins) + sizeof(IGARBAGE);
}
InstanceData(theEnv)->ChangesToInstances = TRUE;
return(1);
}
#if DEFRULE_CONSTRUCT
/****************************************************
NAME : InactiveInitializeInstance
DESCRIPTION : Initializes an instance of a class
Pattern-matching is automatically
delayed until the instance is
completely initialized
INPUTS : The address of the result value
RETURNS : Nothing useful
SIDE EFFECTS : Instance intialized
NOTES : H/L Syntax:
(initialize-instance <instance-name>
<slot-override>*)
****************************************************/
globle void InactiveInitializeInstance(
void *theEnv,
DATA_OBJECT *result)
{
int ov;
ov = SetDelayObjectPatternMatching(theEnv,TRUE);
InitializeInstanceCommand(theEnv,result);
SetDelayObjectPatternMatching(theEnv,ov);
}
/**************************************************************
NAME : InactiveMakeInstance
DESCRIPTION : Creates and initializes an instance of a class
Pattern-matching is automatically
delayed until the instance is
completely initialized
INPUTS : The address of the result value
RETURNS : Nothing useful
SIDE EFFECTS : Instance intialized
NOTES : H/L Syntax:
(make-instance <instance-name> of <class>
<slot-override>*)
**************************************************************/
globle void InactiveMakeInstance(
void *theEnv,
DATA_OBJECT *result)
{
int ov;
ov = SetDelayObjectPatternMatching(theEnv,TRUE);
MakeInstanceCommand(theEnv,result);
SetDelayObjectPatternMatching(theEnv,ov);
}
#endif
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/********************************************************
NAME : NewInstance
DESCRIPTION : Allocates and initializes a new instance
INPUTS : None
RETURNS : The address of the new instance
SIDE EFFECTS : None
NOTES : None
********************************************************/
static INSTANCE_TYPE *NewInstance(
void *theEnv)
{
INSTANCE_TYPE *instance;
instance = get_struct(theEnv,instance);
#if DEFRULE_CONSTRUCT
instance->header.theInfo = &InstanceData(theEnv)->InstanceInfo;
instance->header.dependents = NULL;
instance->header.busyCount = 0;
instance->header.timeTag = 0L;
instance->partialMatchList = NULL;
instance->basisSlots = NULL;
instance->reteSynchronized = FALSE;
#endif
instance->busy = 0;
instance->installed = 0;
instance->garbage = 0;
instance->initSlotsCalled = 0;
instance->initializeInProgress = 0;
instance->depth = EvaluationData(theEnv)->CurrentEvaluationDepth;
instance->name = NULL;
instance->hashTableIndex = 0;
instance->cls = NULL;
instance->slots = NULL;
instance->slotAddresses = NULL;
instance->prvClass = NULL;
instance->nxtClass = NULL;
instance->prvHash = NULL;
instance->nxtHash = NULL;
instance->prvList = NULL;
instance->nxtList = NULL;
return(instance);
}
/*****************************************************************
NAME : InstanceLocationInfo
DESCRIPTION : Determines where a specified instance belongs
in the instance hash table
INPUTS : 1) The class of the new instance
2) The symbol for the name of the instance
3) Caller's buffer for previous node address
4) Caller's buffer for hash value
RETURNS : The address of the found instance, NULL otherwise
SIDE EFFECTS : None
NOTES : Instance names only have to be unique within
a module
*****************************************************************/
static INSTANCE_TYPE *InstanceLocationInfo(
void *theEnv,
DEFCLASS *cls,
SYMBOL_HN *iname,
INSTANCE_TYPE **prv,
unsigned *hashTableIndex)
{
INSTANCE_TYPE *ins;
*hashTableIndex = HashInstance(iname);
ins = InstanceData(theEnv)->InstanceTable[*hashTableIndex];
/* ========================================
Make sure all instances of the same name
are grouped together regardless of what
module their classes are in
======================================== */
*prv = NULL;
while ((ins != NULL) ? (ins->name != iname) : FALSE)
{
*prv = ins;
ins = ins->nxtHash;
}
while ((ins != NULL) ? (ins->name == iname) : FALSE)
{
if (ins->cls->header.whichModule->theModule ==
cls->header.whichModule->theModule)
return(ins);
*prv = ins;
ins = ins->nxtHash;
}
return(NULL);
}
/********************************************************
NAME : InstallInstance
DESCRIPTION : Prevent name and slot value symbols
from being ephemeral (all others
taken care of by class defn)
INPUTS : 1) The address of the instance
2) A flag indicating whether to
install or deinstall
RETURNS : Nothing useful
SIDE EFFECTS : Symbol counts incremented or decremented
NOTES : Slot symbol installations are handled
by PutSlotValue
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -