home *** CD-ROM | disk | FTP | other *** search
- /*
- Little Smalltalk, version 2
- Written by Tim Budd, Oregon State University, July 1987
- */
-
- # define streq(a,b) (strcmp(a,b) == 0)
-
- /*
- The first major decision to be made in the memory manager is what
- an entity of type object really is. Two obvious choices are a pointer (to
- the actual object memory) or an index into an object table. We decided to
- use the latter, although either would work.
- Similarly, one can either define the token object using a typedef,
- or using a define statement. Either one will work (check this?)
- */
-
- typedef short object;
-
- /*
- The memory module itself is defined by over a dozen routines.
- All of these could be defined by procedures, and indeed this was originally
- done. However, for efficiency reasons, many of these procedures can be
- replaced by macros generating in-line code. For the latter approach
- to work, the structure of the object table must be known. For this reason,
- it is given here. Note, however, that ONLY the macros described in this
- file make use of this structure: therefore modifications or even complete
- replacement is possible as long as the interface remains consistent
-
- */
-
- struct objectStruct {
- object class;
- short referenceCount;
- byte size;
- byte type;
- object *memory;
- };
-
- extern struct objectStruct objectTable[];
-
- /* types of object memory */
- # define objectMemory 0
- # define byteMemory 1
- # define charMemory 2
- # define floatMemory 3
-
- # define isString(x) ((objectTable[x>>1].type == charMemory) || (objectTable[x>>1].type == byteMemory))
- # define isFloat(x) (objectTable[x>>1].type == floatMemory)
-
- /*
- The most basic routines to the memory manager are incr and decr,
- which increment and decrement reference counts in objects. By separating
- decrement from memory freeing, we could replace these as procedure calls
- by using the following macros:
- extern object incrobj;
- # define incr(x) if ((incrobj=(x))&&!isInteger(incrobj)) \
- objectTable[incrobj>>1].referenceCount++
- # define decr(x) if (((incrobj=x)&&!isInteger(incrobj))&&\
- (--objectTable[incrobj>>1].referenceCount<=0)) sysDecr(incrobj);*/
- /*
- notice that the argument x is first assigned to a global variable; this is
- in case evaluation of x results in side effects (such as assignment) which
- should not be repeated. */
-
- extern noreturn sysDecr(OBJ);
-
- # ifndef incr
- extern void incr(OBJ);
- # endif
- # ifndef decr
- extern void decr(OBJ);
- # endif
-
- /*
- The next most basic routines in the memory module are those that
- allocate blocks of storage. There are three routines:
- allocObject(size) - allocate an array of objects
- allocByte(size) - allocate an array of bytes
- allocChar(size) - allocate an array of character values
- allocSymbol(value) - allocate a string value
- allocInt(value) - allocate an integer value
- allocFloat(value) - allocate a floating point object
- again, these may be macros, or they may be actual procedure calls
- */
-
- extern object alcObject(INT X INT); /* the actual routine */
- # define allocObject(size) alcObject(size, objectMemory)
- # define allocByte(size) alcObject(((size)+1)/2, byteMemory)
- # define allocChar(size) alcObject(((size)+1)/2, charMemory)
- extern object allocSymbol(STR);
- # define allocInt(value) ((value<0)?value:(value<<1)+1)
- extern object allocFloat(FLOAT);
-
- /*
- integer objects are (but need not be) treated specially.
- In this memory manager, negative integers are just left as is, but
- positive integers are changed to x*2+1. Either a negative or an odd
- number is therefore an integer, while a nonzero even number is an
- object pointer (multiplied by two). Zero is reserved for the object ``nil''
- Since newInteger does not fill in the class field, it can be given here.
- If it was required to use the class field, it would have to be deferred
- until names.h
- */
-
- extern object intobj;
- # define isInteger(x) ((x) & 0x8001)
- # define newInteger(x) ( (intobj = x)<0 ? intobj : (intobj<<1)+1 )
- # define intValue(x) ( (intobj = x)<0 ? intobj : (intobj>>1) )
-
- /*
- in addition to alloc floating point routine given above,
- another routine must be provided to go the other way. Note that
- the routine newFloat, which fills in the class field as well, must
- wait until the global name table is known, in names.h
- */
- extern double floatValue(OBJ);
-
- /*
- there are four routines used to access fields within an object.
- Again, some of these could be replaced by macros, for efficiency
- basicAt(x, i) - ith field (start at 1) of object x
- basicAtPut(x, i, v) - put value v in object x
- byteAt(x, i) - ith field (start at 0) of object x
- byteAtPut(x, i, v) - put value v in object x
-
- # define basicAt(x,i) (sysMemPtr(x)[i-1])
- */
- # define byteAt(x, i) (charPtr(x)[i-1])
-
- # ifndef basicAt
- extern object basicAt(OBJ X INT);
- # endif
- # ifndef basicAtPut
- extern void basicAtPut(OBJ X INT X OBJ);
- # endif
- # ifndef byteAt
- extern int byteAt(OBJ X INT);
- # endif
- # ifndef byteAtPut
- extern void byteAtPut(OBJ X INT X INT);
- # endif
-
- /*
- Finally, a few routines (or macros) are used to access or set
- class fields and size fields of objects
- */
-
- # define classField(x) objectTable[x>>1].class
- # define setClass(x,y) incr(classField(x)=y)
-
- # define objectSize(x) byteToInt(objectTable[x>>1].size)
-
- # define sysMemPtr(x) objectTable[x>>1].memory
- extern object sysobj;
- # define memoryPtr(x) (isInteger(sysobj = x)?(object *) 0:sysMemPtr(sysobj))
- # define bytePtr(x) ((byte *) memoryPtr(x))
- # define charPtr(x) ((char *) memoryPtr(x))
-
- # define nilobj (object) 0
-
- /*
- these two objects are the source of all objects in the system
- */
- extern object symbols;
- extern object globalNames;
-
- extern noreturn sysError (STR X STR);
- extern boolean debugging;
- extern noreturn initMemoryManager(NOARGS);
- extern noreturn imageRead(FILEP);
- extern noreturn imageWrite(FILEP);
-