Shop OBEX P1 Docs P2 Docs Learn Events
Spin Feature Request — Parallax Forums

Spin Feature Request

darcodarco Posts: 86
edited 2008-04-01 23:50 in Propeller 1
After looking over the spin bytecode and the interpreter, I realize that with one small additional capability I will be able to much more easily write complex systems. After looking over the bytecode, I know this is possible.

The biggest problem with spin that I have is that object dependencies are always trees. If you have a serial object defined in the top level object, the only object which can use that specific instance of the serial object is the top level object. No other children can use it. Sure, I could define another serial object in those objects, but they would all be independent objects---which is not what was desired.

The child objects of an object are listed at the end of the method table. Each object is represented by two pointers: one to the method table of the child object and the other to the "variables". The only thing that is different between different instances of an object is that VAR pointer.

What I'm suggesting is a way to provide child objects with instances of certain objects.

Syntactically, it would look like this:

main.spin:
OBJ
  term : "TV_Text"
  subsys : "subsys" (term)   ' Share our instance of TV_Text with subsys

PUB init
  term.start(12)
  subsys.start
  term.str(@done)

DAT
done   byte    "Done!",13,0





subsys.spin:
OBJ
  *term : "TV_Text"    ' The actual instance of this object will be provided by whoever is instantiating us

PUB start
  term.str(@title)

DAT
title   byte    "Starting subsys... ",0




This would print the following on the TV:
Starting subsys... Done!




From this example, we can see that main.spin is sharing it's instance of term with subsys.spin. Subsys.spin has marked the term object with a asterisk (*) which lets the compiler know that the instance will be substituted.

Note that the only thing getting substituted is the instance, the "variable base" part of that object's entry in the method table.

This would make it much easier to add debugging code and design complex systems with lots of interdependencies. It is also 100% backward compatible with existing code.

Please, I'm begging you, consider this improvement for a future version of the propeller tool! My number one gripe with spin has been the inflexible object model, but this change will make it much more flexible.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

darco
www.deepdarc.com/
[url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]

Comments

  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-28 05:48
    I basically asked for this same thing. You can do it by only changing the compiler and not the interperter. In fact, you can even do it with the current compiler if you are willing to do some mucking around. Have a look at this thread http://forums.parallax.com/showthread.php?p=701497. I have also figured out a way of adding inheritance but haven't had time to implement it yet (need to finish the XOR version of graphics.spin first...). When we get an open source compiler done it will be easy to do things like this.

    Note that if you don't have an VAR sections than you will get the effect you desire as only the VAR sections are created for each new instance of an object. The PUB, PRI and DAT sections are shared by all instances.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-03-28 06:47
    It would even be better if the compiler allowed us to pass term as a parameter.
    The compiler then needs to distinguish between normal parameters and an object reference parameter.
    I like Darco's use of *.

    OBJ
    · term: "TV_TEXT"
    · subsys: "subsys"

    PUB entry
    · subsys.start(term)

    In subsys:
    PUB start(*tv)
    · tv.initialize
    'tv is used as placeholder for object reference term
    'because of the * the compiler knows to create an object reference field

    regards peter
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-28 08:44
    The * isn't a bad idea but I think that a better idea is to just indicate in the OBJ section that it is a object that will be decided at run time. What it really needs is a method of indicating that the object is to be determined at run time like Darco's orignal post like this in subsys
    OBJ
      DYN term: "TV_TEXT"
    
    PUB start(termPtr)
      term:=termPtr
      term.initialize
    


    The code in the main object would be something like this
    OBJ
      term:"TV_TEXT"
      subsys:"subsys"
    PUB start
      subsys.start(@term)
    



    This will need several changes to the compiler
    1. New keywork to indicate that an object should not actually be used but just allocate space for a pointer to an object.
    2. If you want to be able to change it at run time than the ":=" operator will need to have a different meaning it would need to generate something like this
    ----term:=(arg.word[noparse][[/noparse]0]-@thisObject.word[noparse][[/noparse]0])|(arg.word-@thisObjectFirstVAR.word) 'would need to check if these are the right way around
    3. The "@" operator would need to be changed so that it returns the start address of the object so it can be used like this
    ----startOfTerm:=@term

    However, you run into several problems depending on how you do it.
    1. If you want to make it truly dynamic than you run into problems when you are using more than one instance of the same object.
    2. Things would turn really bad if you made it dynamic and gave it either a wrong pointer or a pointer to the wrong kind of function.

    So to sum up. It should be fairly easy if you just want to make the links static. It is possible to make it dynamic but you run into a couple of problems that can be worked around by careful attention to detail.
  • hippyhippy Posts: 1,981
    edited 2008-03-28 14:51
    The simplest idea, ie that which should cause minimal effort for Parallax, would probably be to have a mechanism which allows the offsets of named objects and methods in an object's 'method call table' to be determined. The rest could then be left to end-programmer / hackers to create objects which can implement the function pointer calls etc.

    It would be nice for Parallax to add full support in an elegant way, but overcoming the obstacles that prevent easy hackery would be the second best.

    At the moment, the biggest problem is not being able to get at the required information to implement the hackery without looking at the generated object code. Then altering the code can easily break the hack.

    If the compiler could support "CallObj(varObjNum,varMethodNum,varArg1,varArg2...varArgN)" that would make life so much easier ...

        PUSH    varObjNum
        POP     X+1
        PUSH    varMethodNum
        POP     X+2
        PUSH    varArg1
        PUSH    varArg2
        :
        PUSH    varArgN
     
    X   CALLOBJ 0,0
    
    
    



    Calls to local methods "Call(varMethodNum,varArg1,varArg2...varArgN)" could be done in the same way. These can already be done, but it isn't easy and not being able to determine the values for varObjNum and varMethodNum is the core problem.
  • darcodarco Posts: 86
    edited 2008-03-28 17:10
    I just wanted to point out that what I was suggesting would all be calculated at buildtime, not runtime. That's why I chose the * syntax in the OBJ section instead of making it a parameter to the 'init' or 'start' method.

    Doing this at runtime would waste memory because the compiler would end up allocating variables for an instance which will never be used. Whereas at build time, the compiler can identify that it is a reference and not allocate variable memory for another instance.

    Very simple change.

    Being able to do it at runtime would be nice I suppose, but isn't necessary and is potentially wasteful. It would also require additional implementation work.

    I would love to hear Chip's opinion on this.

    EDIT: I'm suddenly having second thoughts about using the '*' character. A '&' would likely have been more appropriate symbol to indicate a reference, similar to C++. Not that it really matters, since spin has a tendency to do things its own way. Like the wacky <> operator. *cringe* >_<

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]

    Post Edited (darco) : 3/28/2008 5:28:06 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-03-28 18:30
    My earlier suggestion will not work because the object type referenced is unspecified.
    @Darco, if you specified 2 instances of TV_Text, which one should subsys then use in your approach?

    I think the following does allow for static building and solves for the above question:

    'main file
    OBJ
    · term: "TV_Text"
    · term2: "TV_Text"
    · subsys: "subsys"

    PUB main
    · subsys.start(@term2) 'pass address of object
    · 'or should we use subsys.start(term2) ??

    'subsys
    OBJ
    · tv: "TV_Text"

    PUB start(tv)

    Note that an object name as formal parameter instructs compiler
    to use a passed object reference rather than creating a new instance.
    The type of the object is known at compile time by using the object name.

    regards peter
  • darcodarco Posts: 86
    edited 2008-03-28 18:47
    Peter: If you take a closer look at my example, you'll see that I specify which specific object to use as a reference:

    main.spin:
    OBJ
      term : "TV_Text"
      subsys : "subsys" (term)   ' Share our instance of TV_Text with subsys
    
    



    Notice the parenthesis.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-03-28 19:10
    That wouldn't solve the problem of having 2 instances of TV_Text in your top object file.
    Objects are compiled seperately, so how does subsys know which to use when you compile subsys?

    regards peter
  • darcodarco Posts: 86
    edited 2008-03-28 20:16
    Objects being compiled separately isn't a problem, because all that needs to happen is for main.spin to patch the subsys.spin object's method table at compile time. The only forseeable problem is multiple "subsys" objects, not multiple "TV_Term" objects. Even that problem has a fairly simple solution: have more than one method table per "subsys" instance.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-28 22:01
    How about this. When including an object you do this
    OBJ
      term :"TV_Terminal"
      other:"OtherObject"
      subsys(term,other):"subSys"
    


    The question then becomes where to put these in subsys? Maybe a new section something like this?
    POBJ 'for passed objects
      terminal :"TV_Terminal"
      anObj :"OtherObject" 'etc
    


    The compiler would allow only one POBJ section to avoid confusion and potentially bad situations like getting the objects out of order (or it could be solved by using objectiveC style messages where each argument can have a namesmile.gif ).

    The object table gets patched during compile time at the moment so it shouldn't be too hard to add. If parallax doesn't add it we can always add it to the open source compiler.
  • darcodarco Posts: 86
    edited 2008-03-28 22:15
    I would be quite happy with such a scheme!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]
  • darcodarco Posts: 86
    edited 2008-03-28 22:44
    While we are at it, the ability to define the value of certain constants at instantiation would be useful as well, although not critical.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-28 23:36
    This will be very difficult as constants are actually embedded in the spin byte-code and there is only one copy of the code for all instances. To do this you would need to pre-initialise the VAR section. This would have possible benefits. This could also be a bit hard but it would be possible.
  • darcodarco Posts: 86
    edited 2008-04-01 23:03
    Any chance someone at Parallax could comment on the possibility of my original suggestion making it into a future version of the propeller tool?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    darco
    www.deepdarc.com/
    [url=mailto:xmpp:darco@deepdarc.com]xmpp:darco@deepdarc.com[/url]
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-04-01 23:50
    We will consider it when we get to the point of revising the compiler for the next chip.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
Sign In or Register to comment.