Spin Objects
Chad George
Posts: 138
I've used the Propeller on several projects now and have come to like the mix of high level SPIN code and low level assembly language. There's one thing that I still get hung up on. I know spin objects are more of a static compiler construct than a real object. And they provide a useful way of encapsulating data and code which is good for alot of things. But I run into alot of situations where I wish that I could share access to the same instance of an object. It seems like this should be possible, but I don't think there is any syntax to specify it. I generally have to pass memory addresses around, but then the code degenerates to using things like long[noparse][[/noparse]ptr + 16] which quickly becomes impossible to read.
Here some things that I wish I could do and maybe some people out there have come across elegant ways of getting around them. Or maybe there's a really good reason not to have them available.
1. Access to object variables through the object instance name like we can access object constants. ie. obj#var_name
Not even real OO languages require you to wrap every single public variable access in a get/set method. I understand the reasons for encapsulation, but the compiler KNOWs the address of the variable why can't we take advantage it for better syntax and smaller code.
2. A mechanism for globally sharing a single instance of an object.
There may be alot of good reasons against this, and it could be argued that a good design won't need it. But I'm always working on some file and wishing I had access to that variable (or function) that I'm using in some other spin object. This of course doesn't promote building standalong object modules, but again the compiler KNOWs exactly where that variable or function code will be. Why do I have to pass around memory addresses and access everything using byte offsets.
3. As an alternative to #2 some syntax for accessing any particular object instance in the project tree. Maybe some dotted name notation.
4. Indirect function calls in SPIN would be useful. I know this is trivial to do in assembly, but its really useful for state machines.
-Chad
Here some things that I wish I could do and maybe some people out there have come across elegant ways of getting around them. Or maybe there's a really good reason not to have them available.
1. Access to object variables through the object instance name like we can access object constants. ie. obj#var_name
Not even real OO languages require you to wrap every single public variable access in a get/set method. I understand the reasons for encapsulation, but the compiler KNOWs the address of the variable why can't we take advantage it for better syntax and smaller code.
2. A mechanism for globally sharing a single instance of an object.
There may be alot of good reasons against this, and it could be argued that a good design won't need it. But I'm always working on some file and wishing I had access to that variable (or function) that I'm using in some other spin object. This of course doesn't promote building standalong object modules, but again the compiler KNOWs exactly where that variable or function code will be. Why do I have to pass around memory addresses and access everything using byte offsets.
3. As an alternative to #2 some syntax for accessing any particular object instance in the project tree. Maybe some dotted name notation.
4. Indirect function calls in SPIN would be useful. I know this is trivial to do in assembly, but its really useful for state machines.
-Chad
Comments
1) If I understand the interpretive code right, the variable references are all relative to the particular instance of the object. I suppose the compiler could determine the absolute address of the object's variables and refer to them that way, but there's no current mechanism for that.
2) Yeah! There's a very natural use of objects to implement abstractions where you need an internal state that's common to all references to the object. Spin doesn't allow this. In the Propeller OS, I had to go to dynamically allocated global areas accessed inefficiently via pointers and offsets. An example might be an I/O device (keyboard or display) that's used throughout a project, all by one execution thread so there's not a problem with simultaneous access by more than one cog. You can't naturally do it.
3) I'm not sure you need this. I see two cases: 1) Each instance of an object requires the allocation of a unique variable instance. 2) All instances of an object use the same variable instance.
4) Yes, this would allow the implementation of many useful things like coroutines for I/O formatting for example. I'm not sure the interpreter can handle this. Since that's in ROM, it would be difficult to extend it.
I wrote SerialMirror (as a replacement for FullDuplexSerial) to address exactly this problem. I've done something similar for other objects - although using DAT variables instead of VAR variables can raise its own issues.
See SerialMirror at : http://forums.parallax.com/showthread.php?p=649541
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
It's not all that hard to count the number of grains of sand on the beach. The hardest part is making a start - after that it just takes time.·· Mirror - 15 May 2007
Thank you for the well documented solution to #2. That is a rather effective way to share variables between instances of the same object.
Now if we just had a Spin-language solution for #1 (besides using known addresses which is somewhat of a hack)
Just wanted to provide some positive feedback.
Mike
PUB set(n)
classAttribute1 := n
PUB get
return classAttribute1
DAT
classAttribute1 long 5
Though the DAT area is supposed to be used inside a COG it is also located in the RAM (as a template so to speak) and can be altered before beeing loaded into a COG (as a means of parametrization e.g.).
As the "Object Model" of SPIN allows no direct access to "attributes" you have to include setters and getters as shown in the example, which however is VERY inefficient...