📄 classpsr.c
字号:
/*******************************************************
NAME : BuildSubclassLinks
DESCRIPTION : Follows the list of superclasses
for a class and puts the class in
each of the superclasses' subclass
list.
INPUTS : The address of the class
RETURNS : Nothing useful
SIDE EFFECTS : The subclass lists for every superclass
are modified.
NOTES : Assumes the superclass list is formed.
*******************************************************/
static void BuildSubclassLinks(
void *theEnv,
DEFCLASS *cls)
{
register unsigned i;
for (i = 0 ; i < cls->directSuperclasses.classCount ; i++)
AddClassLink(theEnv,&cls->directSuperclasses.classArray[i]->directSubclasses,cls,-1);
}
/**********************************************************
NAME : FormInstanceTemplate
DESCRIPTION : Forms a contiguous array of instance
slots for use in creating instances later
Also used in determining instance slot
indices a priori during handler defns
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Contiguous array of instance slots formed
NOTES : None
**********************************************************/
static void FormInstanceTemplate(
void *theEnv,
DEFCLASS *cls)
{
TEMP_SLOT_LINK *islots = NULL,*stmp;
unsigned scnt = 0;
register unsigned i;
/* ========================
Get direct class's slots
======================== */
islots = MergeSlots(theEnv,islots,cls,&scnt,DIRECT);
/* ===================================================================
Get all inherited slots - a more specific slot takes precedence
over more general, i.e. the first class in the precedence list with
a particular slot gets to specify its default value
=================================================================== */
for (i = 1 ; i < cls->allSuperclasses.classCount ; i++)
islots = MergeSlots(theEnv,islots,cls->allSuperclasses.classArray[i],&scnt,INHERIT);
/* ===================================================
Allocate a contiguous array to store all the slots.
=================================================== */
cls->instanceSlotCount = scnt;
cls->localInstanceSlotCount = 0;
if (scnt > 0)
cls->instanceTemplate = (SLOT_DESC **) gm2(theEnv,(scnt * sizeof(SLOT_DESC *)));
for (i = 0 ; i < scnt ; i++)
{
stmp = islots;
islots = islots->nxt;
cls->instanceTemplate[i] = stmp->desc;
if (stmp->desc->shared == 0)
cls->localInstanceSlotCount++;
rtn_struct(theEnv,tempSlotLink,stmp);
}
}
/**********************************************************
NAME : FormSlotNameMap
DESCRIPTION : Forms a mapping of the slot name ids into
the instance template. Given the slot
name id, this map provides a much faster
lookup of a slot. The id is stored
statically in object patterns and can
be looked up via a hash table at runtime
as well.
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Contiguous array of integers formed
The position in the array corresponding
to a slot name id holds an the index
into the instance template array holding
the slot
The max slot name id for the class is
also stored to make deletion of the slots
easier
NOTES : Assumes the instance template has already
been formed
**********************************************************/
static void FormSlotNameMap(
void *theEnv,
DEFCLASS *cls)
{
register unsigned i;
cls->maxSlotNameID = 0;
cls->slotNameMap = NULL;
if (cls->instanceSlotCount == 0)
return;
for (i = 0 ; i < cls->instanceSlotCount ; i++)
if (cls->instanceTemplate[i]->slotName->id > cls->maxSlotNameID)
cls->maxSlotNameID = cls->instanceTemplate[i]->slotName->id;
cls->slotNameMap = (unsigned *) gm2(theEnv,(sizeof(unsigned) * (cls->maxSlotNameID + 1)));
for (i = 0 ; i <= cls->maxSlotNameID ; i++)
cls->slotNameMap[i] = 0;
for (i = 0 ; i < cls->instanceSlotCount ; i++)
cls->slotNameMap[cls->instanceTemplate[i]->slotName->id] = i + 1;
}
/********************************************************************
NAME : MergeSlots
DESCRIPTION : Adds non-duplicate slots to list and increments
slot count for the class instance template
INPUTS : 1) The old slot list
2) The address of class containing new slots
3) Caller's buffer for # of slots
4) A flag indicating whether the new list of slots
is from the direct parent-class or not.
RETURNS : The address of the new expanded list, or NULL
for an empty list
SIDE EFFECTS : The list is expanded
Caller's slot count is adjusted.
NOTES : Lists are assumed to contain no duplicates
*******************************************************************/
static TEMP_SLOT_LINK *MergeSlots(
void *theEnv,
TEMP_SLOT_LINK *old,
DEFCLASS *cls,
unsigned *scnt,
int src)
{
TEMP_SLOT_LINK *cur,*tmp;
register int i;
SLOT_DESC *newSlot;
/* ======================================
Process the slots in reverse order
since we are pushing them onto a stack
====================================== */
for (i = (int) (cls->slotCount - 1) ; i >= 0 ; i--)
{
newSlot = &cls->slots[i];
/* ==========================================
A class can prevent it slots from being
propagated to all but its direct instances
========================================== */
if ((newSlot->noInherit == 0) ? TRUE : (src == DIRECT))
{
cur = old;
while ((cur != NULL) ? (newSlot->slotName != cur->desc->slotName) : FALSE)
cur = cur->nxt;
if (cur == NULL)
{
tmp = get_struct(theEnv,tempSlotLink);
tmp->desc = newSlot;
tmp->nxt = old;
old = tmp;
(*scnt)++;
}
}
}
return(old);
}
/***********************************************************************
NAME : PackSlots
DESCRIPTION : Groups class-slots into a contiguous array
"slots" field points to array
"slotCount" field set
INPUTS : 1) The class
2) The list of slots
RETURNS : Nothing useful
SIDE EFFECTS : Temporary list deallocated, contiguous array allocated,
and nxt pointers linked
Class pointer set for slots
NOTES : Assumes class->slotCount == 0 && class->slots == NULL
***********************************************************************/
static void PackSlots(
void *theEnv,
DEFCLASS *cls,
TEMP_SLOT_LINK *slots)
{
TEMP_SLOT_LINK *stmp,*sprv;
register unsigned i;
stmp = slots;
while (stmp != NULL)
{
stmp->desc->cls = cls;
cls->slotCount++;
stmp = stmp->nxt;
}
cls->slots = (SLOT_DESC *) gm2(theEnv,(sizeof(SLOT_DESC) * cls->slotCount));
stmp = slots;
for (i = 0 ; i < cls->slotCount ; i++)
{
sprv = stmp;
stmp = stmp->nxt;
GenCopyMemory(SLOT_DESC,1,&(cls->slots[i]),sprv->desc);
cls->slots[i].sharedValue.desc = &(cls->slots[i]);
cls->slots[i].sharedValue.value = NULL;
rtn_struct(theEnv,slotDescriptor,sprv->desc);
rtn_struct(theEnv,tempSlotLink,sprv);
}
}
#if DEFMODULE_CONSTRUCT
/********************************************************
NAME : CreateClassScopeMap
DESCRIPTION : Creates a bitmap where each bit position
corresponds to a module id. If the bit
is set, the class is in scope for that
module, otherwise it is not.
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Scope bitmap created and attached
NOTES : Uses FindImportedConstruct()
********************************************************/
static void CreateClassScopeMap(
void *theEnv,
DEFCLASS *theDefclass)
{
unsigned scopeMapSize;
char *scopeMap;
char *className;
struct defmodule *matchModule,
*theModule;
int moduleID,count;
className = ValueToString(theDefclass->header.name);
matchModule = theDefclass->header.whichModule->theModule;
scopeMapSize = (sizeof(char) * ((GetNumberOfDefmodules(theEnv) / BITS_PER_BYTE) + 1));
scopeMap = (char *) gm2(theEnv,scopeMapSize);
ClearBitString((void *) scopeMap,scopeMapSize);
SaveCurrentModule(theEnv);
for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL) ;
theModule != NULL ;
theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,(void *) theModule))
{
EnvSetCurrentModule(theEnv,(void *) theModule);
moduleID = (int) theModule->bsaveID;
if (FindImportedConstruct(theEnv,"defclass",matchModule,
className,&count,TRUE,NULL) != NULL)
SetBitMap(scopeMap,moduleID);
}
RestoreCurrentModule(theEnv);
theDefclass->scopeMap = (BITMAP_HN *) AddBitMap(theEnv,scopeMap,scopeMapSize);
IncrementBitMapCount(theDefclass->scopeMap);
rm(theEnv,(void *) scopeMap,scopeMapSize);
}
#endif
/*****************************************************************************
NAME : CreatePublicSlotMessageHandlers
DESCRIPTION : Creates a get-<slot-name> and
put-<slot-name> handler for every
public slot in a class.
The syntax of the message-handlers
created are:
(defmessage-handler <class> get-<slot-name> primary ()
?self:<slot-name>)
For single-field slots:
(defmessage-handler <class> put-<slot-name> primary (?value)
(bind ?self:<slot-name> ?value))
For multifield slots:
(defmessage-handler <class> put-<slot-name> primary ($?value)
(bind ?self:<slot-name> ?value))
INPUTS : The defclass
RETURNS : Nothing useful
SIDE EFFECTS : Message-handlers created
NOTES : None
******************************************************************************/
static void CreatePublicSlotMessageHandlers(
void *theEnv,
DEFCLASS *theDefclass)
{
register unsigned i;
register SLOT_DESC *sd;
for (i = 0 ; i < theDefclass->slotCount ; i++)
{
sd = &theDefclass->slots[i];
CreateGetAndPutHandlers(theEnv,sd);
}
for (i = 0 ; i < theDefclass->handlerCount ; i++)
theDefclass->handlers[i].system = TRUE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -