ObjectSharing

Permit objects to be shared between other objects.

Define "template" objects to permit such sharing.

For example, let's say that I want to write a program consisting of an object hierarchy where A is my top-level object, and it uses objects B and C and D. All of A, B, C, and D want to do general I/O using a keyboard/screen or serial terminal or whatnot. But it's critical that they all share the same I/O object (in the physical sense).

At the same time, the flexibility to change from a serial interface to a keyboard/TV or keyboard/VGA interface, with only one or two lines of code, is important.

To make this work, we add the ability to define an object template. An object template is just like any other object, containing public methods, but the actual code and data of that object is typically just simple stubs. For instance, a generic I/O genio.spin object might just be

PUB getchar repeat ' do nothing PUB putchar(n) PUB charready return 0

The idea here is that any object that has methods with these three signatures can be "plugged in" where the template object is used. The substitution of the objects is done at the object instantiation.

So for instance objects B, C, and D all might use

OBJ generic_io : "genio"

A will create B, C, and D normally with code like

OBJ My_b_obj : "B" My_c_obj : "C" My_d_obj : "D"

But, A also has the option of "rebinding" or "renaming" the objects accessed by sub-objects. For instance, it might say

OBJ RealIO : "KeyboardPlusVGA" My_b_obj : "B"("genio"/RealIO) My_c_obj : "C"("genio"/RealIO) My_d_obj : "D"("genio"/RealIO)

which means, when including the "A" object, replace any occurrence of "genio" throughout B, C, or D with the specific RealIO object that is created at the top level of A. In this case we only instantiate RealIO *once*, but it is accessible to B, C, and D.

In addition, the B, C, and D objects are all separately usable using whatever I/O they may have defined.

Note that we do not "check" anywhere that RealIO contains all the methods defined in genio; that is done when the top-level object is compiled (and it will recompile the subobjects, with the appropriate substitution of "objects").

Problem: what do we do with the genio.start lines in B, C, and D?  Clearly we don't want to start the object multiple times. I suggest for the moment just magically eliminating any calls to "start" or "stop" associated with objects that are rebound in this manner. This is ugly, but since we don't have explicit constructors/destructors I'm not sure we'll be able to come up with anything better. Another option is to not do such substitution, and assume that any starting/stopping is done always at the top-level (which means that B, C, and D no longer are completely standalone, but this I think is a minor problem; they still *compile* standalone and that's the important thing).