home *** CD-ROM | disk | FTP | other *** search
- /* Kevo -- a prototype-based object-oriented language */
- /* (c) Antero Taivalsaari 1991-1993 */
- /* Some parts (c) Antero Taivalsaari 1986-1988 */
- /* context.c: Name space (context) management internals */
-
- #include "global.h"
- #include "portGlobal.h"
-
- /*--------------------------------------------------------------------------*/
- /* Context management operations */
-
- PAIR* LatestPair; /* Pointer to the latest name in the dictionary */
- /* Needed only for setting flags after 'addPair' */
-
- /* hash(): hash function */
-
- /* inlined for speed (see the header file 'context.h')
- int hash(identifier)
- char* identifier;
- {
- return((int)*identifier % CONTEXTSIZE);
- }
- */
-
-
- /* lowCreateContext(): low-level context creation */
-
- CONTEXT* lowCreateContext()
- {
- return((CONTEXT*)mycalloc(1, sizeof(CONTEXT)));
- }
-
-
- /* xCreateContext(): another low-level context creation */
- /* which is needed only in root context initialization */
- /* Since 'dummyContext' and (=context) have not been defined */
- /* when initializing root contexts, we cannot initialize */
- /* the clone families of these contexts (using createList) */
-
- CONTEXT* xCreateContext()
- {
- CONTEXT* newContext = lowCreateContext();
-
- /* Attach the context to the end of the global context list */
- if (lastContext) {
- lastContext->nextContext = newContext;
- lastContext = newContext;
- }
-
- return(newContext);
- }
-
-
- /* createContext(): create and initialize a new context (high-level) */
-
- CONTEXT* createContext()
- {
- CONTEXT* newContext = xCreateContext();
-
- /* Initialize the family lists */
- newContext->cloneFamily = createList();
- newContext->parentFamilies = createList();
- newContext->childFamilies = createList();
-
- return(newContext);
- }
-
-
- /* copyContext(): duplicate an existing context with all its names */
- /* this operation is needed internally when new clone families are */
- /* being derived. Note that family lists are not copied (shallow copy) */
-
- CONTEXT* copyContext(oldC)
- CONTEXT* oldC;
- {
- CONTEXT* newC;
- PAIR* oldPair = oldC->firstPair;
- PAIR* newPair;
-
- newC = createContext();
- while (oldPair) {
- newPair = addPair(newC, oldPair->nfa, oldPair->ofa);
- newPair->ffa = oldPair->ffa; /* Duplicate flag field too */
- oldPair = oldPair->sfa;
- }
-
- return(newC);
- }
-
-
- /* This operation is needed only internally in the next operation */
- /* to find the previous context in the context list */
-
- CONTEXT* findPrevContext(context)
- CONTEXT* context;
- {
- /* The first context in the context list is always 'rootContext' */
- CONTEXT* thisContext = rootContext;
-
- while (thisContext) {
- if (thisContext->nextContext == context) return(thisContext);
- thisContext = thisContext->nextContext;
- }
-
- fprintf(confile, "== Integrity error detected: context link damaged (no prev ctxt found) ==\n");
- reportIntegrityError();
- ownLongJmp();
- }
-
-
- /* deleteContext(): delete an existing context with all its names. */
- /* Note that family lists are not deleted (must be done separately) */
- /* Remember that contexts are linked in a singly-linked list so as */
- /* to allow type name lookup, so we must remove the context from */
- /* that list too */
-
- void deleteContext(context)
- CONTEXT* context;
- {
- CONTEXT* prevCtxt = findPrevContext(context);
- CONTEXT* nextCtxt = context->nextContext;
- PAIR* thisPair = context->firstPair;
-
- /* Remove the context from the context list */
- if (prevCtxt) {
- prevCtxt->nextContext = nextCtxt;
- if (lastContext == context) lastContext = prevCtxt;
- }
- else {
- fprintf(confile, "== Integrity error detected: attempt to remove 'rootContext' ==\n");
- reportIntegrityError();
- ownLongJmp();
- }
-
- /* Deallocate the pairs */
- while (thisPair) {
- PAIR* tempPair = thisPair->sfa;
- free(thisPair);
- thisPair = tempPair;
- }
-
- /* Deallocate the context itself */
- free(context);
- }
-
-
- /* comparePairs(): compare if two pairs are equivalent.
- The comparison is based on the equivalence of names,
- encapsulation flags, and operations.
-
- The equality of operations is based simply on the identity
- of the operations (physically same code) rather than behavioral
- comparison. More clever schemes should be examined later.
-
- The operation returns TRUE if the pairs are equal.
- */
- int comparePairs(pair1, pair2)
- PAIR* pair1;
- PAIR* pair2;
- {
- if (!pair1) return(FALSE);
- if (!pair2) return(FALSE);
- if (pair1->ofa != pair2->ofa) return(FALSE);
- if (strcmp(pair1->nfa, pair2->nfa) != 0) return(FALSE);
- if (pair1->ffa != pair2->ffa) return(FALSE);
- return(TRUE);
- }
-
-
- /* compareContexts(): compare if two contexts are equivalent.
- The operation returns TRUE if the contexts are equal.
- */
- int compareContexts(context1, context2)
- CONTEXT* context1;
- CONTEXT* context2;
- {
- PAIR* thisPair1 = context1->firstPair;
- PAIR* thisPair2 = context2->firstPair;
-
- while (thisPair1) {
- /* Any incompatible pair will cause the comparison to fail */
- if (!comparePairs(thisPair1, thisPair2)) return(FALSE);
-
- thisPair1 = thisPair1->sfa;
- thisPair2 = thisPair2->sfa;
- }
-
- if (thisPair2) return(FALSE);
- else return(TRUE);
- }
-
-
- /* compareContextResemblance(): compare if two context
- have at least something in common (at least one of
- the properties in them is exactly the same)
- */
- int compareContextResemblance(context1, context2)
- CONTEXT* context1;
- CONTEXT* context2;
- {
- PAIR* thisPair1 = context1->firstPair;
- PAIR* thisPair2;
-
- while (thisPair1) {
- thisPair2 = context2->firstPair;
- while (thisPair2) {
- /* Any compatible pair will cause the comparison to succeed */
- if (comparePairs(thisPair1, thisPair2)) return(TRUE);
- thisPair2 = thisPair2->sfa;
- }
- thisPair1 = thisPair1->sfa;
- }
- return(FALSE);
- }
-
-
- /* isContextObject(): check if a given object is */
- /* a proper OOP object with its own context */
- /* This operation is fairly slow, and is used mainly in the browser */
-
- int isContextObject(object)
- OBJECT* object;
- {
- if (maskedFetch((int*)object) && maskedFetch((int*)object->mfa))
- return(object->mfa->efa == (int*)oContext ? TRUE : FALSE);
- else return(FALSE);
- }
-
-
- /* getContext(): given an OOP object, return the corresponding context */
- /* Inlined for speed (see the header file 'global.h'
- CONTEXT* getContext(object)
- OBJECT* object;
- {
- return((CONTEXT*)object->mfa->pfa);
- }
- */
-
-
- /* initRootContexts(): initialize the root context. */
- /* This operation is needed in 'main.c' */
-
- void initRootContexts()
- {
- /* Create an "empty" dummy context. This is useful for some objects */
- /* so that we can view them as objects from the browser */
- dummyContext = lowCreateContext();
-
- /* Create a root context for system primitives */
- /* This is known as 'SystemRoot' in the high-level Kevo */
- rootContext = lastContext = xCreateContext();
-
- /* Create a root context for user-given definitions */
- /* This is known as 'Root' in the high-level Kevo */
- userContext = xCreateContext();
- }
-
-
- /* initRootFamilies(): initialize the clone family lists */
- /* of basic contexts. These could not be initialized property */
- /* earlier, because '(=context)' and dummyContext were not */
- /* declared when calling 'createList()' */
- void initRootFamilies()
- {
- dummyContext->cloneFamily = createList();
- dummyContext->parentFamilies = createList();
- dummyContext->childFamilies = createList();
-
- rootContext->cloneFamily = createList();
- rootContext->parentFamilies = createList();
- rootContext->childFamilies = createList();
-
- userContext->cloneFamily = createList();
- userContext->parentFamilies = createList();
- userContext->childFamilies = createList();
- }
-
-
- /*--------------------------------------------------------------------------*/
- /* Pair (name) specific context operations */
-
- /* addPair(): add a new pair to an existing context */
-
- PAIR* addPair(context, identifier, referent)
- CONTEXT* context;
- char* identifier;
- OBJECT* referent;
- {
- int thread = hash(identifier);
-
- /* Allocate a new pair */
- PAIR* newPair = (PAIR*)mymalloc(sizeof(PAIR));
-
- /* Initialize fields */
- newPair->nfa = identifier; /* Note that the string is not copied */
- newPair->ofa = referent; /* The object */
- newPair->cfa = context; /* Pair contains a backpointer to the context */
- newPair->ffa = 0; /* Flags are all down at first */
-
- /* Add the new pair to the end of the correct thread in context */
- newPair->lfa = context->lastPair[thread];
- context->lastPair[thread] = newPair;
-
- /* Set also the reverse link */
- if (context->latestPair) context->latestPair->sfa = newPair;
- else context->firstPair = newPair;
-
- context->latestPair = newPair;
- newPair->sfa = NIL;
-
- /* Set the global variable to point to the latest pair */
- LatestPair = newPair;
-
- return(newPair);
- }
-
-
- /* findSurroundings: find the surrounding four pairs for the given pair.
- This operation is used only internally in some dictionary manipulation
- operations to allow easy link manipulation.
- */
- void findSurroundings(thePair, theThread, prevPair, succPair, prevInThread, succInThread)
- PAIR* thePair;
- int theThread;
- PAIR** prevPair; /* Previous pair in the context before 'thePair' */
- PAIR** succPair; /* Next pair in the context after 'thePair' */
- PAIR** prevInThread; /* Previous pair in 'theThread' before 'thePair' */
- PAIR** succInThread; /* Next pair in 'theThread' after 'thePair' */
- {
- CONTEXT* context = thePair->cfa;
- PAIR* thisPair = context->firstPair;
-
- /* Initialize the return values */
- *prevPair = NIL;
- *succPair = thePair->sfa;
- *prevInThread = NIL;
- *succInThread = NIL;
-
- while (thisPair) {
- if (thisPair == thePair) goto forward;
- if (hash(thisPair->nfa) == theThread) *prevInThread = thisPair;
- *prevPair = thisPair;
- thisPair = thisPair->sfa;
- }
-
- /* 'thePair' was not found in the context -> serious error */
- fprintf(confile, "== Integrity error detected: pair not found in 'findSurroundings' ==\n");
- reportIntegrityError();
- ownLongJmp();
-
- forward:
- /* Find the next pair in the requested thread */
- while ((thisPair = thisPair->sfa) != NIL) {
- if (hash(thisPair->nfa) == theThread) {
- *succInThread = thisPair;
- break;
- }
- }
- }
-
-
- /* unlinkPair(): remove a pair from a context */
- /*
- Remember that we must unlink the pair from both directions.
- This is a bit problematic, since to the other direction
- dictionary is hashed (multi-linked), and to the other there is
- only a singly linked list.
- */
-
- void unlinkPair(pair)
- PAIR* pair;
- {
- CONTEXT* context = pair->cfa;
- int thread = hash(pair->nfa);
- PAIR* prevPair;
- PAIR* succPair;
- PAIR* prevInThread;
- PAIR* succInThread;
-
- findSurroundings(pair, thread, &prevPair, &succPair, &prevInThread, &succInThread);
-
- /* Remove the pair from the successor link */
- if (prevPair)
- prevPair->sfa = pair->sfa;
- else context->firstPair = pair->sfa;
-
- if (succPair == NIL) context->latestPair = prevPair;
-
- /* Remove the pair from the predecessor link */
- if (succInThread)
- succInThread->lfa = pair->lfa;
- else context->lastPair[thread] = pair->lfa;
- }
-
-
- /* renamePair(): rename a pair in a context */
- /*
- This operation is also a bit problematic to implement owing
- to the hashed (multi-linked) structure of the dictionary.
- */
-
- void renamePair(oldPair, newName)
- PAIR* oldPair;
- char* newName;
- {
- CONTEXT* context = oldPair->cfa;
- int oldThread = hash(oldPair->nfa);
- int newThread = hash(newName);
- PAIR* newPair;
- PAIR* thisPair;
- PAIR* succInThread;
-
- /*
- If the new name hashes to the same link than the previous one,
- things are simple, and we can directly change the name field.
- */
- if (oldThread == newThread) {
- oldPair->nfa = newName;
- return;
- }
-
- /*
- Otherwise, things get a bit more complicated.
- Fortunately, the pairs are linked together also to the other
- direction. The successor link is only singly linked (unhashed),
- so we know the exact definition order of pairs.
- */
-
- /* Allocate a new pair */
- newPair = (PAIR*)mymalloc(sizeof(PAIR));
-
- /* Initialize/copy the fields */
- newPair->nfa = newName;
- newPair->ofa = oldPair->ofa;
- newPair->cfa = oldPair->cfa;
- newPair->ffa = oldPair->ffa;
-
- /* New pair will be added right after the old one in the successor link */
- /* Locate the next pair in the new thread after 'oldPair' */
-
- thisPair = oldPair;
- succInThread = NIL;
-
- while (thisPair) {
- if (hash(thisPair->nfa) == newThread) {
- succInThread = thisPair;
- break;
- }
- thisPair = thisPair->sfa;
- }
-
- /* Insert the new pair to the insertion point */
- newPair->sfa = oldPair->sfa;
- oldPair->sfa = newPair;
-
- if (succInThread) {
- newPair->lfa = succInThread->lfa;
- succInThread->lfa = newPair;
- }
- else {
- newPair->lfa = context->lastPair[newThread];
- context->lastPair[newThread] = newPair;
- }
-
- if (context->latestPair == oldPair)
- context->latestPair = newPair;
-
- /* Finally, remove the old pair from the context */
- unlinkPair(oldPair);
- free(oldPair);
- }
-
-
- /* hide(): make the latest pair "hidden" */
-
- void hide()
- {
- LatestPair->ffa |= HiddenFlag;
- }
-
-
- /* copyPair(): make a copy of a pair */
- /* This operation is needed for the user interface (CUT, COPY, PASTE) */
-
- PAIR* copyPair(oldPair)
- PAIR* oldPair;
- {
- PAIR* newPair = (PAIR*)mymalloc(sizeof(PAIR));
-
- /* Copy fields */
- *newPair = *oldPair;
- return(newPair);
- }
-
-
- /* addBeforePair(): link the given pair in front of the requested pair */
- /*
- This operation allows new properties to be added to arbitrary
- points within objects, and it is needed for the user interface
- (CUT, COPY, PASTE).
-
- Different cases:
- 1) if the context is empty before addition (should not happen)
- 2) if added before the first pair in the context
- 3) if added before the first pair in a thread
- 4) other
- */
- PAIR* addBeforePair(beforePair, newPair)
- PAIR* beforePair; /* The pair before which the new pair is added */
- PAIR* newPair; /* The pair to be added */
- {
- CONTEXT* context = beforePair->cfa;
- int beforeThread = hash(beforePair->nfa);
- int newThread = hash(newPair->nfa);
- PAIR* prevPair;
- PAIR* succPair;
- PAIR* prevInThread;
- PAIR* succInThread;
-
- findSurroundings(beforePair, newThread, &prevPair, &succPair, &prevInThread, &succInThread);
-
- /* Add the pair to the successor link */
- newPair->sfa = beforePair;
-
- if (prevPair)
- prevPair->sfa = newPair;
- else context->firstPair = newPair;
-
- /* Add the pair to the predecessor link */
- newPair->lfa = prevInThread;
-
- /*
- If we are adding to the same thread, then the successor
- is the 'beforePair' rather than its successor.
- */
- if (beforeThread == newThread) succInThread = beforePair;
-
- if (succInThread)
- succInThread->lfa = newPair;
- else context->lastPair[newThread] = newPair;
-
- /* Finally, change the new pair's context field to 'context' */
- newPair->cfa = context;
-
- return(newPair);
- }
-
-
- /*--------------------------------------------------------------------------*/
- /* Finding operations (used in searching names and objects from contexts) */
-
- /* findPairInThis(): find a pair from a specific context given a string */
-
- PAIR* findPairInThis(context, identifier)
- CONTEXT* context;
- char* identifier;
- {
- int thread = hash(identifier);
- register PAIR* tempPair = context->lastPair[thread];
-
- while (tempPair) {
- if (!(tempPair->ffa & SmudgeFlag) &&
- strcmp(tempPair->nfa, identifier) == 0)
- return(tempPair);
- tempPair = tempPair->lfa;
- }
- return(NIL);
- }
-
-
- /* findPairBackward(): find a pair using a certain search order. */
- /* First the current context (self) will be searched, then 'Root' */
- /* (user-level root) and finally 'SystemRoot' (system primitives). */
-
- PAIR* findPairBackward(identifier)
- char* identifier;
- {
- register PAIR* thisPair;
-
- if (thisPair = findPairInThis(getContext((OBJECT*)topContext), identifier))
- return(thisPair);
-
- if (thisPair = findPairInThis(userContext, identifier))
- return(thisPair);
-
- if (thisPair = findPairInThis(rootContext, identifier))
- return(thisPair);
-
- return(NIL);
- }
-
-
- /* findNameInThis(): find a matching pair for a given object in a specific context */
-
- PAIR* findNameInThis(context, object)
- CONTEXT* context;
- OBJECT* object;
- {
- int thread;
-
- for (thread = 0; thread < CONTEXTSIZE; thread++) {
- PAIR* tempPair = context->lastPair[thread];
-
- while (tempPair) {
- if (!(tempPair->ffa & SmudgeFlag) && tempPair->ofa == object)
- return(tempPair);
- tempPair = tempPair->lfa;
- }
- }
- return(NIL);
- }
-
-
- /* findNameBackward(): find a matching pair using a backward search order */
- /* see 'findPairBackward' above */
-
- PAIR* findNameBackward(object)
- OBJECT* object;
- {
- PAIR* thisPair;
-
- if (!maskedFetch((int*)object)) return(NIL);
-
- if (thisPair = findNameInThis(getContext((OBJECT*)topContext), object))
- return(thisPair);
-
- if (thisPair = findNameInThis(userContext, object))
- return(thisPair);
-
- if (thisPair = findNameInThis(rootContext, object))
- return(thisPair);
-
- return(NIL);
- }
-
-
- /* findNameForward(): find a matching pair by searching all the contexts */
- /* in the first-defined-first order */
-
- PAIR* findNameForward(object)
- OBJECT* object;
- {
- CONTEXT* thisContext = rootContext;
- PAIR* thisPair;
-
- if (!maskedFetch((int*)object)) return(NIL);
-
- while (thisContext) {
- if (thisPair = findNameInThis(thisContext, object)) return(thisPair);
- thisContext = thisContext->nextContext;
- }
-
- return(NIL);
- }
-
-
- /* findTypeInThis(): find a matching object for a given context object */
- /* This object is the "type" of that context */
- /*
- This operation is needed for object-oriented programming to print the
- types of objects automatically. Compared to other finding operations,
- the search order in this operation is backwards (from the earlier defined
- things towards later defined ones).
-
- Due to the very indirect nature of objects in our system, this operation
- is admittedly rather complicated. Furthermore, possible bus errors caused
- by high memory references must be avoided, causing extra complexity.
- */
-
- PAIR* findTypeInThis(context, ctxtObject)
- CONTEXT* context;
- OBJECT* ctxtObject;
- {
- CONTEXT* desiredCtxt;
- PAIR* tempPair;
-
- desiredCtxt = getContext(ctxtObject);
- tempPair = context->firstPair;
-
- while (tempPair) {
- if (!(tempPair->ffa & SmudgeFlag)) {
- OBJECT* object = tempPair->ofa;
-
- /* We search mainly for REF objects */
- if (object && object->sfa == DATAOFFSET &&
- (object = (OBJECT*)object->mfa->pfa)) {
- if (maskedFetch((int*)object) &&
- object->sfa > 0 &&
- object->mfa->efa == (int*)oContext &&
- object->mfa->pfa == (int*)desiredCtxt) return(tempPair);
- }
- }
- tempPair = tempPair->sfa; /* get next pair */
- }
- return(NIL);
- }
-
-
- /* findTypeForward(): this is the generalization of 'findTypeInThis()' */
- /* Search through all the contexts using their definition order list */
-
- PAIR* findTypeForward(ctxtObject)
- OBJECT* ctxtObject;
- {
- CONTEXT* thisContext = userContext;
- PAIR* thisPair;
-
- if (!isContextObject(ctxtObject)) return(NIL);
-
- while(thisContext) {
- if (thisPair = findTypeInThis(thisContext, ctxtObject)) return(thisPair);
- thisContext = thisContext->nextContext;
- }
-
- return(NIL);
- }
-
-
-
- /* findPrimName(): find the name part of a primitive function. */
- /* It is assumed that C primitives reside only in the system root context, */
- /* so we search only that context. */
-
- PAIR* findPrimName(prim)
- int* prim;
- {
- int thread;
-
- for (thread = 0; thread < CONTEXTSIZE; thread++) {
- PAIR* tempPair = rootContext->lastPair[thread];
-
- while (tempPair) {
- if (tempPair->ofa && tempPair->ofa->mfa == (STORE*)prim) return(tempPair);
- tempPair = tempPair->lfa;
- }
- }
- return(NIL);
- }
-
-
- /* ------------------------------------------------------------------------ */
- /* Context operations for object-oriented programming */
-
- /* nonSelfLookUp(): find a matching pair in the context starting */
- /* from a given pair, but accept only the non-hidden properties. */
-
- PAIR* nonSelfLookUp(thisPair, identifier)
- PAIR* thisPair;
- char* identifier;
- {
- while (thisPair) {
- if (strcmp(thisPair->nfa, identifier) == 0 && !(thisPair->ffa & HiddenFlag))
- return(thisPair);
- thisPair = thisPair->lfa;
- }
- return(NIL);
- }
-
-
- /* selfLookUp(): find a matching pair in the context starting */
- /* from a given pair, accepting also the hidden properties. */
-
- PAIR* selfLookUp(thisPair, identifier)
- PAIR* thisPair;
- char* identifier;
- {
- while (thisPair) {
- if (strcmp(thisPair->nfa, identifier) == 0) return(thisPair);
- thisPair = thisPair->lfa;
- }
- return(NIL);
- }
-
-
- /* messageLookUp(): basic lookup routine for object-oriented programming. */
- /* find a matching pair in the given context object, but search the non-hidden */
- /* (not encapsulated) properties only if the message comes from outside 'self' */
-
- PAIR* messageLookUp(object, identifier)
- OBJECT* object;
- char* identifier;
- {
- CONTEXT* context = getContext(object);
- int thread = hash(identifier);
- PAIR* thisPair = context->lastPair[thread];
-
- if (object == (OBJECT*)topContext) {
- /* 'selfLookUp() "inlined" for speed */
- while (thisPair) {
- if (strcmp(thisPair->nfa, identifier) == 0) return(thisPair);
- thisPair = thisPair->lfa;
- }
- }
- else {
- /* nonSelfLookUp() "inlined" for speed */
- while (thisPair) {
- if (strcmp(thisPair->nfa, identifier) == 0 && !(thisPair->ffa & HiddenFlag))
- return(thisPair);
- thisPair = thisPair->lfa;
- }
- return(NIL);
- }
- }
-
-
- /* respondsTo(): test if a certain object responds to a certain message */
- /* This operation does not refer to context stack, so it can invoked also */
- /* by the user interface */
-
- PAIR* respondsTo(object, identifier)
- OBJECT* object;
- char* identifier;
- {
- CONTEXT* context = getContext(object);
- int thread = hash(identifier);
- PAIR* startPair = context->lastPair[thread];
-
- return nonSelfLookUp(startPair, identifier);
- }
-
-
- /* getREFslot(): gets the storage address of a REF (SHAREDVAR) or CONST slot */
-
- OBJECT** getREFslot(thisPair)
- PAIR* thisPair;
- {
- STORE* store;
-
- if (thisPair->ofa && (store = thisPair->ofa->mfa))
- return((OBJECT**)&store->pfa);
- else return(NIL);
- }
-
-
- /* getVARoffset(): gets the offset of a VAR slot */
- /* Remember: data slots are offseted with DATAOFFSET */
- /* (i.e., the offset to the first data slot is 2, second = 3, ...) */
-
- int getVARoffset(thisPair)
- PAIR* thisPair;
- {
- OBJECT** offsetAddr = getREFslot(thisPair);
-
- if (offsetAddr)
- return((int)*offsetAddr);
- else return(0);
- }
-
-
- /* getVARslot(): gets the storage address of a VAR slot */
-
- OBJECT** getVARslot(ctxtObject, thisPair)
- OBJECT* ctxtObject;
- PAIR* thisPair;
- {
- int offset = getVARoffset(thisPair);
-
- return((OBJECT**)((int**)ctxtObject->mfa + offset));
- }
-
-
- /* countAllPairs(): count all the pairs in the given context */
-
- int countAllPairs(context)
- CONTEXT* context;
- {
- PAIR* thisPair = context->firstPair;
- int count = 0;
-
- while (thisPair) {
- count++;
- thisPair = thisPair->sfa;
- }
-
- return(count);
- }
-
-
- /* countDataPairs(): count the data pairs in the given context */
- /* (REF, VAR, SHAREDVAR, CONST) */
-
- int countDataPairs(context)
- CONTEXT* context;
- {
- PAIR* thisPair = context->firstPair;
- int count = 0;
-
- while (thisPair) {
- if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
- case REF:
- case VAR:
- case CONST:
- count++;
- break;
- }
- thisPair = thisPair->sfa;
- }
- return(count);
- }
-
-
- /* countOperPairs(): count the method pairs in the given context */
-
- int countOperPairs(context)
- CONTEXT* context;
- {
- PAIR* thisPair = context->firstPair;
- int count = 0;
-
- while (thisPair) {
- if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
- case PRIMITIVE:
- case METHOD:
- count++;
- break;
- }
- thisPair = thisPair->sfa;
- }
- return(count);
- }
-
-
- /* findAllAsIndexed(): find the n'th pair in the given context */
-
- PAIR* findAllAsIndexed(context, index)
- CONTEXT* context;
- int index;
- {
- PAIR* tempPair = context->firstPair;
-
- while (--index && tempPair) tempPair = tempPair->sfa;
-
- return(tempPair);
- }
-
-
- /* findDataAsIndexed(): find the n'th data pair in the given context */
-
- PAIR* findDataAsIndexed(context, index)
- CONTEXT* context;
- int index;
- {
- PAIR* tempPair = context->firstPair;
-
- while (tempPair) {
- if (tempPair->ofa) switch(recognizeObject(tempPair->ofa)) {
- case REF:
- case VAR:
- case CONST:
- if (--index == 0) return(tempPair);
- break;
- }
- tempPair = tempPair->sfa;
- }
- return(NIL);
- }
-
-
- /* findOperAsIndexed(): find the n'th method pair in the given context */
-
- PAIR* findOperAsIndexed(context, index)
- CONTEXT* context;
- int index;
- {
- PAIR* tempPair = context->firstPair;
-
- while (tempPair) {
- if (tempPair->ofa) switch(recognizeObject(tempPair->ofa)) {
- case PRIMITIVE:
- case METHOD:
- if (--index == 0) return(tempPair);
- break;
- }
- tempPair = tempPair->sfa;
- }
- return(NIL);
- }
-
-
- /* Check the integrity of the given context by performing several checks */
-
- void checkIntegrity(context)
- CONTEXT* context;
- {
- int fwdCount = countAllPairs(context);
- int bwdCount = 0;
- int thread;
- int error = FALSE;
-
- for (thread = 0; thread < CONTEXTSIZE; thread++) {
- PAIR* thisPair = context->lastPair[thread];
- PAIR* tempPair;
-
- while (thisPair) {
- bwdCount++;
-
- if (hash(thisPair->nfa) != thread) {
- fprintf(confile, "== Integrity error detected: name in wrong thread ==\n");
- error = TRUE;
- }
-
- if (thisPair->cfa != context) {
- fprintf(confile, "== Integrity error detected: name in wrong context ==\n");
- error = TRUE;
- }
-
- tempPair = context->firstPair;
- while (tempPair) {
- if (tempPair == thisPair) goto forw1;
- tempPair = tempPair->sfa;
- }
- fprintf(confile, "== Integrity error detected: name not found in successor link ==\n");
- error = TRUE;
-
- forw1:
- thisPair = thisPair->lfa;
- }
- }
-
- if (fwdCount != bwdCount) {
- fprintf(confile, "== Integrity error detected: link counts do no match ==\n");
- error = TRUE;
- }
-
- if (fwdCount) {
- if (context->latestPair == NIL) {
- fprintf(confile, "== Integrity error detected: latest pair is NIL although context isn't empty ==\n");
- error = TRUE;
- }
- }
-
- if (bwdCount) {
- if (context->firstPair == NIL) {
- fprintf(confile, "== Integrity error detected: first pair is NIL although context isn't empty == \n");
- error = TRUE;
- }
- }
-
- if (context->latestPair != NIL) {
- for (thread = 0; thread < CONTEXTSIZE; thread++) {
- if (context->lastPair[thread] == context->latestPair) goto forw2;
- }
- fprintf(confile, "== Integrity error detected: latest pair not found among last pairs ==\n");
- error = TRUE;
- }
-
- if (!checkFamilyIntegrity(context)) error = TRUE;
-
- forw2:
- if (error) reportIntegrityError();
- }
-