Type System Dreams
Project: SmallForth
Although this version of forth is fun, it doesn't yet support strings. Strings in Forth normally rely on having two words on the stack, one a pter and the second a character count. These strings can store binary values, including zeros.
They are stored in the pad, which is a transient buffer unused by system words. Some implementations apparently have two buffers to store strings whilst they are being manipulated. Ultimately, there are stored in word, variables or constants.
As this version of Forth does not (yet) have a strong memory model, relying on C++ for memory allocation, I haven't yet implemented standard strings. Instead I have implemented a more complex type system that allows objects to be defined, constructed, and removed from memory.
Currently the type is an enumeration called ElementType. This contains things like StackElement_Char,StackElement_Int and StackElement_Bool.
This to be extended so that the lower 10 bits (up to incl-1022 actually) are value types (including the already-defined ones in the ElementType enumeration), 1024->32767 are system-defined objects such as string and files, and 32768->65535 are user-defined object types.
The top 16 bits is the indirection count. For example, an integer would be type 0x00000002, whereas a pointer to an integer would be 0x00010002.
The way to get a pointer to an entity (value/object/pter) is to create a variable to it.
The class TypeSystem has a lot of the functionality to deal with these types. The RefCountedObject encompasses functionality for anything over type 1023.
The class UserDefinedObject> provides functionality for user-defined objects. This takes data from the stack to define the types, name and default values for a user-defined object. It also defines a type word that should be used to construct an object of the new type.
The reference counted object implements garbage collection via reference count - whenever the reference count reaches 0 the object is deleted. The reference count represents how many root objects (stack elements or words) can reach the object (either directly, or via series of indirect pointers.
Although circular references are not yet possible, as an object needs to be already defined to include a reference to it in another definition, the reference counting code should prevent circular references from keeping objects alives. This is because a flag is set when reference counts are being increased (recursively) - as the recursion backs out the flag is reset. When increasing a reference count, loops are prevents by checking if the object to be incremented already has its flag set.