One of the purposes of my Homespun Spin compiler is to experiment with Spin language extensions. People are always bemoaning the inability to pass object pointers in Spin, so I implemented that functionality. However, I haven't heard of anyone who's actually tried it out, which I attribute to several possible causes:
1. No one knows about this Homespun feature
2. No one uses Homespun
3. Object-passing in Homespun doesn't do what people want
This post is intended to address point 1. Perhaps it will inspire people to get past point 2, and then maybe I'll find out about point 3, which is what I'm really interested in. Since this feature seems so important to people, I'd like to try to get it right. It's in an early stage of development (see caveats below) so there's plenty of room for improvement, but first I'd like to know if I'm on the right track. If the ability to pass object pointers is important to you, please let me know what works and what doesn't from your point of view.
The following totally contrived example involves a main object and a child object. The main object will be passing two kinds of object pointers to the child. The first is to a tv_text object, so that both main and child can print to the screen. The second type of object pointer implements the following two functions:
Code:' IWorker.spin pub FunctionFirst( a, b ) pub FunctionSecond( a, b )
IWorker is an interface, and the main object contains two worker objects that implement the IWorker interface (in other words, each worker contains public methods that match the description in IWorker.spin).
Here's the main object:
Code:' main.spin con _clkmode = xtal1+pll16x _xinfreq = 5_000_000 obj worker1 : "worker1" ' implements IWorker interface worker2 : "worker2" ' implements IWorker interface child : "child" debug : "tv_text" pub Main | r debug.start( 0 ) debug.str( string( "Object-passing test", 13 ) ) ' We want child to be able to print to the screen, so pass it a pointer to the debug object: child.Init( debug ) ' Now pass a pointer to worker1. child is expecting something that ' implements the the IWorker interface, which worker1 does. r := child.TestWorker( worker1, 654, 321 ) debug.dec( r ) debug.out( 13 ) ' Same thing with worker2. r := Child.TestWorker( worker2, 654, 321 ) debug.dec( r ) debug.out( 13 )
The child object:
Code:' child.spin obj worker : "IWorker" pointer debug : "tv_text" pointer pub Init( pDebug ) debug := pDebug pub TestWorker( pWorker, a, b ) | r1, r2 worker := pWorker r1 := worker.FunctionFirst( a, b ) debug.str( string( "r1 = " ) ) debug.dec( r1 ) debug.out( 13 ) r2 := worker.FunctionSecond( a, b ) debug.str( string( "r2 = " ) ) debug.dec( r2 ) debug.out( 13 ) return r1 + r2
The first worker object:
Code:' worker1.spin pri Sum( a, b ) return a + b pub FunctionFirst( a, b ) return Sum( a, b ) pri Multiply( a, b ) return a * b pub FunctionSecond( a, b ) return Multiply( a, b )
The second worker object:
Code:' worker2.spin pri Difference( a, b ) return a - b pub FunctionFirst( a, b ) return Difference( a, b ) pub FunctionSecond( a, b ) return a / b
Code:Object-passing test r1 = 975 r2 = 209934 210909 r1 = 333 r2 = 2 335
I know that third caveat did prevent one person from using object-passing, but I'm hoping that it's an unusual situation. But who knows, maybe it's more common than I think.
- There's no type-checking
- You can't dynamically create objects (but I have some ideas here).
- Things break if you have two or more child objects; i.e., obj child[ 2 ] : "child" -- passing an object pointer to child[ 0 ] messes up the corresponding pointer in child[ 1 ].