interfaces -- a proposal for a Spin2 extension

I've been experimenting with a Spin2 extension to make writing generic objects that interact with other objects easier. This adds "interfaces", which are kind of like structs but which only have methods (no variables). The syntax is like structs:
CON %interface io( PUB tx(c) PUB rx(): r ) PUB printstr(^io f, s) | c repeat while (c:=byte[s++]) f.tx(c)
The idea of an interface is that it can match any object which provides all of the methods specified in the interface. So for example, if you have two objects Serial and LCD which both provide tx
and rx
methods, you could do:
printstr(@serial, @"Hello on Serial") printstr(@lcd, @"Hello on LCD")
That is, the printstr
method from above can accept a pointer to any object that implements tx
and rx
.
IMPLEMENTATION
This is the tricky part, of course. I'm not sure how best to do this in PNut, but in Flexspin (for now) the interface objects are basically just collections of method pointers. When an object parameter has to match an interface, the compiler checks to see if it has an interface skeleton corresponding to that object, and if necessary builds one. Then it inserts runtime code to convert that skeleton, plus the object pointer, into a new object pointer to the interface.
ALTERNATIVE IMPLEMENTATION
Another way to implement interfaces would be to make the interface pointer itself a method pointer, which takes as argument a method index, and returns a new method pointer which should be invoked for the given method. That is, the call:
f.tx(c) ' f is an interface pointer
would actually be translated like
(f(TX_INDEX))(c)
Where f(TX_INDEX)
returns the method pointer for tx
of whatever object f
originally was.
Then for each object that has to implement an interface we'd add a function that just switches on its argument and returns the new method pointer, like:
Serial GetInterface_Io(idx) : r case idx TX_INDEX: return @tx RX_INDEX: return @rx
In some cases it may be possible to optimize this further, by arranging the original object's method dispatch table in a way that makes finding the interface equivalent trivial.
Comments
Great, this is better than pointer to objects which is one my wish list.
How far away is all of this from being a C++ style "class"?
Maybe can work with FlexProp C style limitations on the class?