Shop OBEX P1 Docs P2 Docs Learn Events
@@@ operator — Parallax Forums

@@@ operator

Roy ElthamRoy Eltham Posts: 3,000
edited 2013-08-28 12:44 in Propeller 1
So, the documentation on the @@@ operator in BSTC is very sparse. It's not clear to me what Symbols you can use it on and where. Can it be used in SPIN code or PASM or only one of the two? Is it only usable on VARs? Or does it also work on DATs?

I'm not sure how it can know at compile time the absolute address of any symbol anywhere in HUB, especially when some are not known until runtime. So it must be limited to global symbols. If you have two instances of an object with VAR/DAT stuff which one will the @@@ resolve to?

I still don't really understand why it's needed other than as a shortcut. Can someone give me some examples of using it that aren't just contrived? Also, can someone explain a case where this gives you something you can't get another way with @ and/or @@?

I need to know all the details so that I can properly add this operator to OpenSpin.
«1

Comments

  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 02:55
    In a DAT section you might want to initialize a LONG with the address of some other data in that section.
    DAT
    x LONG 0
    y LONG 0
    z LONG 0
    
    y_ptr LONG @@@y
    

    You cannot do that nicely with @.

    I have used this in Z80 emulation code some time.

    Given that an objects DAT section only exists once and is shared by all instances of the object then the compiler should be able to get it's real address in HUB at build time.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 07:08
    Roy Eltham wrote:
    I'm not sure how it can know at compile time the absolute address of any symbol anywhere in HUB, especially when some are not known until runtime.
    One way is to create a relocation table in the compiler with pointers to the places that use @@@. That way, the @values temporarily stored in those places can be updated from their base addresses after the program's objects have been linked together. But, no, you can't expect to use @@@ in the DAT section, when it points to a VAR.

    BTW, @@@ seems rather ugly. It's too bad, invoking the principle of least surp[rise, that @ can't simply do what new users expect in such situations.

    -Phil
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 08:09
    I've used @@@ in BST for SpinLMM, and I believe PropBASIC depends on it. I also have several programs that I compile under the Prop Tool where I use something like "@variable+16" when I want to store the absolute address. However, this only works in the top object. The source for pfth contains probably a hundred or more places where I have to add the object offset. I know I have at least one program where I have absolute addresses in a child object, and I have to fix up the addresses when the program first starts up. The @@@ operator would be a nice addition to OpenSpin.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-08-21 10:27
    Heater,
    In your example, I believe you could have used @ and @@. If you used: 'y_ptr LONG @y' then use @@y_ptr and you get the absolute address as a result. The Propeller Manual describes this case.

    Phil,
    I understand how to go about implementing @@@ for Symbols that have known addresses during compile time. My questions here are more about what are the limitations on it from BSTC. What does BSTC do when you use @@@ on a VAR and have multiple instances of the object? It's not documented well at all.

    Dave Hein,
    I think you need to read the section in the Prop Manual about @@ again, because I think it does what you want. On other other hand, I might be wrong about that?
  • AribaAriba Posts: 2,690
    edited 2013-08-21 10:42
    Roy Eltham wrote: »
    So, the documentation on the @@@ operator in BSTC is very sparse. It's not clear to me what Symbols you can use it on and where. Can it be used in SPIN code or PASM or only one of the two? Is it only usable on VARs? Or does it also work on DATs?
    It's only used for DAT symbols and only inside DAT sections. Actually it's 99.9% used in a LONG directive only.
    I'm not sure how it can know at compile time the absolute address of any symbol anywhere in HUB, especially when some are not known until runtime. So it must be limited to global symbols. If you have two instances of an object with VAR/DAT stuff which one will the @@@ resolve to?
    You need an additional compiler pass after all objects are placed in the hubram. You nee to identify the locations and add the object-base.
    I still don't really understand why it's needed other than as a shortcut. Can someone give me some examples of using it that aren't just contrived? Also, can someone explain a case where this gives you something you can't get another way with @ and/or @@?

    I need to know all the details so that I can properly add this operator to OpenSpin.
    As already said it is manly used for LMM code. You need the absolute address to access a table or jump to a subroutine and so on. In a Spin section @ gives the absolute address (I think the object-offset is added at runtime) and @@ gives you the object-offset alone. Both is not available in DAT/PASM sections, with @ you only get a relative offset to the begin of the object.

    Andy
  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 11:18
    Has anyone ever used "@@"? If it "gives you the object-offset alone" as Ariba says it seems pretty useless.

    Meanwhile @ gives you different results depending where you use it.

    It's chaos.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 11:40
    Roy Eltham wrote: »
    Dave Hein,
    I think you need to read the section in the Prop Manual about @@ again, because I think it does what you want. On other other hand, I might be wrong about that?
    Roy, I understand exactly how @, @@ and @@@ work. @@ does not do what I want.

    Heater, I've used the @@ operator. It adds the object offset to a value, and can only be used within a Spin method. The value @@0 will give you the absolute starting address of the object that it is executed from.
  • jazzedjazzed Posts: 11,803
    edited 2013-08-21 11:40
    Dave Hein wrote: »
    I've used @@@ in BST for SpinLMM, and I believe PropBASIC depends on it.
    Yes, at the moment PropBASIC uses @@@. That's where I noticed it. We don't use it in PropellerGCC.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 11:51
    Roy Eltham wrote:
    What does BSTC do when you use @@@ on a VAR and have multiple instances of the object?
    I should hope that @@@[var] gives you an error, since it's unresolvable. 'Shouldn't even be allowed with single instances, since it can't be generalized to multiple instances.

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 11:57
    Dave Hein.
    I've used the @@ operator. It adds the object offset to a value, and can only be used within a Spin method.
    Yes I know. So what on earth did you use it for?
    The value @@0 will give you the absolute starting address of the object that it is executed from.
    Is that documented anywhere?
    It sounds insane. In FORTRAN you could get the address of literal constants because it kept them in a "literal pool". Spin does not do that and any kind of address of zero (or 1 or 2 or ... n) makes no sense.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 11:59
    Phil,
    I should hope that @@@[var] gives you an error
    Indeed it does in BSTC.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 13:21
    I use @@0 to get the value of PBASE. It's used in the MethodPtr object. In general, I've used the @@ operator to fix up address pointers that are stored in DAT space. One example where I have to fix up the addresses is in the spinit Spin compiler that runs under Spinix. I have an array of strings that contains the Spin operators, and it was defined in C as:
    char *ops[] = {"++", "+=", "+", "--", "-=", ... };
    
    This was converted to Spin using cspin, which automatically adds the top object offset of 16. However, this code resides in a child object, so I have a start method that fixes up the addresses. It looks like this:
    DAT
      datstr byte "++", 0, "+=", 0, "+", 0, "--", 0, "-=", 0
      byte "-", 0, ">>=", 0, ">>", 0, ">-=", 0, ">-", 0, "><=", 0
      byte "><", 0, ">|", 0, ">=", 0, ">", 0, "<<=", 0, "<<", 0
      byte "<-=", 0, "<-", 0, "<#=", 0, "<#", 0, "<>=", 0, "<>", 0
      byte "<=", 0, "<", 0, "**=", 0, "**", 0, "*=", 0, "*", 0
      byte "//=", 0, "//", 0, "/=", 0, "/", 0, "||", 0, "|<", 0
      byte "|=", 0, "|", 0, "@@", 0, "@", 0, "#>=", 0, "#>", 0
      byte "^^", 0, "^=", 0, "^", 0, "=>=", 0, "=>", 0, "=<=", 0
      byte "=<", 0, "!", 0, "~~", 0, "~>=", 0, "~>", 0, "~", 0
      byte "?", 0, "===", 0, "==", 0
      ops long @datstr + 16, @datstr + 19, @datstr + 22, @datstr + 24
      long @datstr + 27, @datstr + 30, @datstr + 32, @datstr + 36
      long @datstr + 39, @datstr + 43, @datstr + 46, @datstr + 50
      long @datstr + 53, @datstr + 56, @datstr + 59, @datstr + 61
      long @datstr + 65, @datstr + 68, @datstr + 72, @datstr + 75
      long @datstr + 79, @datstr + 82, @datstr + 86, @datstr + 89
      long @datstr + 92, @datstr + 94, @datstr + 98, @datstr + 101
      long @datstr + 104, @datstr + 106, @datstr + 110, @datstr + 113
      long @datstr + 116, @datstr + 118, @datstr + 121, @datstr + 124
      long @datstr + 127, @datstr + 129, @datstr + 132, @datstr + 134
      long @datstr + 138, @datstr + 141, @datstr + 144, @datstr + 147
      long @datstr + 149, @datstr + 153, @datstr + 156, @datstr + 160
      long @datstr + 163, @datstr + 165, @datstr + 168, @datstr + 172
      long @datstr + 175, @datstr + 177, @datstr + 179, @datstr + 183
      long 0
    
    PUB start | ptr
      ptr := @ops
      repeat while long[ptr]
        long[ptr] += @@0 - 16
        ptr += 4
    
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-08-21 14:13
    Dave Hein,
    Sorry if I came off poorly towards you there. I think I just misunderstood the situation.

    All,
    So from what you are all saying, @@@ can only be used for DAT symbols and it's only used in PASM code, is that correct? This is the case that makes the most sense to me. I was primarily wondering how this would work on VAR variables, and why it was needed for SPIN code.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 14:35
    @Roy,

    Yeah, it cannot be used for VAR variables.

    @Dave,

    Exactly, you used the abomination that is "@@0", which as far as I know is undocumented and meaningless to fix up for the failure of @ or @@ to do the right thing in your DAT sections.
    long[ptr] += @@0 - 16
    

    And by the way, what is that magic number 16 doingin there?

    This shows exactly why we need @@@ (Or fix @ so that it works, which can never happen now without breaking so much existing code).
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 15:04
    heater wrote:
    Or fix @ so that it works, which can never happen now without breaking so much existing code.
    I'd vote for breaking code. Those who used @ in their DAT sections successfully will be savvy enough to deal with it. Those who used it unsuccessfully will achieve instant success because it will do what they meant it to do in the first place.

    @@ is bad enough, but @@@ is a syntactic kludge and just plain ugly.

    Also for addresses that are knowable at link time, @ should be allowed inside the constant pseudo-operator. 'No point computing the absolute address every time. (For that matter, constant should be abolished in favor of constant folding during compile time, but that's another issue that we don't need to discuss here.)

    -Phil
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 16:54
    Heater. wrote: »
    @Dave,

    Exactly, you used the abomination that is "@@0", which as far as I know is undocumented and meaningless to fix up for the failure of @ or @@ to do the right thing in your DAT sections.
    long[ptr] += @@0 - 16
    

    And by the way, what is that magic number 16 doingin there?
    The @@ operator translates into a load-object-address Spin bytecode, which is applied to the value on the Spin interpreters stack. The Spin compiler doesn't care how you got the value, it just applies the load-object-address, which just add the objects absolute starting address to the value. Normally, the @@ operator would precede a variable containing a DAT offset, but it could be applied to anything. So you could do something like this:
    DAT
    buffer  long 0[64] ' 64-long buffer
    offset @buffer  ' Offset of buffer from the start of the object
    
    PUB main
      result := GetAbsoluteAddress(offset)
    
    PUB GetAbsoluteAddress(parm)
     return @@parm
    
    Of course, in this case it's easier to get the absolute address of the buffer by using @buffer in the main method. The unfortunate thing is that @ means different things when used in a DAT section than it does when used in a method.

    EDIT: The magic number 16 is the absolute address for the top object. The table in my example was generated assuming it would be used in the top object so that no further adjustment was necessary. However, I ended up using it in a child object, so I needed to subtract 16 and add @@0 to it. If I didn't already have the +16 in the numbers I could have adjusted them by doing long[ptr] := @@long[ptr]. Now that I think of it, I could have just add @@(-16), or it might even work without the parens -- @@-16. Now that's really ugly!
  • Cluso99Cluso99 Posts: 18,069
    edited 2013-08-21 17:02
    Roy,
    Yes, my understanding is that @@@ is only refers to DAT section from PASM. There was no way to get an absolute hub address into the pasm code without resorting to either:-
    1. Getting a list of addresses passed via PAR and plugging these into PASM using PASM. Extremely wasteful of PASM code space.
    2. Plugging the addresses into the PASM hub code via spin before launching the cog. Very messy and frowned upon.

    I disagree with Phil for breaking the existing code. However, perhaps it is time (or in the future) to fix this @, @@, @@@ mess up with a new operator that just works correctly - such as &label which means indirect in some other languages.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 17:27
    Cluso,

    Normally, I would not suggest breaking existing code. However, in this case, I doubt that there will have been many uses of @ in DAT sections that weren't put there in error. So the collateral damage will be minimal, and we end up with pleasing and consistent syntax and semantics. And those who have already used @@@ can easily revert to @ if they wish to use the OpenSpin compiler.

    -Phil
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-08-21 17:35
    Thanks everyone! So next question, should I just go with using @@@ for OpenSpin? Or, since @@ isn't currently legal in PASM code, it could be @@ instead of @@@. I don't think & would work because it would cause ambiguity in compiling with the existing & operator.

    I'm not sure if making just @ work "as you want" in PASM is feasable. How would you know if the coder intended to get the cog address or the hub address of a given DAT symbol? If you did it based on the DAT symbol being in the same org space as the PASM code, then you couldn't get the HUB address of those symbols which I think could be useful.
  • Cluso99Cluso99 Posts: 18,069
    edited 2013-08-21 18:04
    Roy, yes, perhaps @@ when used in PASM might replace @@ usage...

    1. SPIN @@ means the absolute address of the current object (is this correct Dave?)
    2. PASM @@ means the absolute hub address of the label (replaces @@@ operator in bst/homespun)

    In PASM @@label may be used in these cases (or similar)...
            rdlong  count, hubptr
            rdlong  count, #@@hublabel    ' where hublabel is hub $0000-$00FF ($00FC is used in the case of a long)
    hubptr  long    @@hublabel
    count   long    0
    

    But what would happen in SPIN with these, and are they valid???
    PUB/PRI xxxx
            count := hublabel
            count := @@hublabel
            count := hubptr
            count := @@hubptr
    DAT
    hubptr  long    @@hublabel
    count   long    0
    

    Would the hubprt long @@hublabel be set the same in both SPIN & PASM cases???
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 18:34
    Roy Eltham wrote:
    How would you know if the coder intended to get the cog address or the hub address of a given DAT symbol?
    To get the cog address, you leave off the prefix entirely, viz:
    Label   mov  a,b
    ...
    CogAdr  long Label  'Extant
    HubAdr  long @Label 'Proposed
    

    This is already part of PASM. (But you knew that! :) )

    -Phil
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 18:45
    I would suggest keeping the functionality of the current operators the same, and use @@@ to get the absolute address. This is compatible with the way BST does it. Changing the way the current operators work will cause problems with existing code that depends on the current functionality. It will have an impact on code that is expected to be relocatable, and depends on the @ operator to produce an object offset rather than an absolute address.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 18:56
    Cluso99 wrote: »
    1. SPIN @@ means the absolute address of the current object (is this correct Dave?)
    In Spin, @@ means compute the sum of the absolute address of the current object and the value that follows. So functionally, @@temp is equal to (temp + PBASE), where PBASE is the absolute address of the object.

    This code compiles under the Prop Tool
    dat
      offset long @variable
      variable long 0
    
    pub main
      result := @@offset
      result := @@0
      result := @@result
      result := @@(1 + 2 + 3)
      result := @@ComputeSomething
    
    pub ComputeSomething
      return 1984 + 2001
    
    Of course, @@offset is the intended use of the @@ operator. However, @@0 is useful for getting the address of the beginning of the object when doing things like examining the method table.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 19:06
    Dave Hein wrote:
    It will have an impact on code that is expected to be relocatable, and depends on the @ operator to produce an object offset rather than an absolute address.
    'Still possible:
    RelAdr  long  @Label - @@0
    

    -Phil
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-08-21 19:46
    I don't see any advantage to changing the old operators. I think implementing @@@ like in BST is the best approach at this point. It seems like a no-brainer to me, but maybe there's something I'm not getting. Roy, let me know if you implement Phil's suggestion so that I can rewrite my old code to work with OpenSpin. I guess I'll also have to maintain two sets of code so that I can compile it under both OpenSpin and the Prop Tool.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 20:45
    I don't mean for my suggestion to cause any pain for those who have already used @ in DAT, and I don't take breaking backwards compatibility lightly. I made the suggestion since the proposed semantics are what most programmers expect if they're new to Spin/PASM (i.e. the principle of least surprise). Moreover, it's a change that will, AFAIK, affect but a small minority of the extant codebase. I might further suggest that @@@ be allowed. provisionally, but with a compile-time warning that it's deprecated and will raise an error in future releases of the compiler. That should help to ease the transition and give people a chance to bring their code up to date.

    Eventually, the existing Prop Tool is going away, and OpenSpin will define the lingua franca for Spin. It's easier to take a leadership role in Spin's definition early on than to let ugly syntax and bad semantics linger until it really is too late to correct them.

    I so wish the same could be done with => and =<, but that train left the station years ago.

    -Phil
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-08-21 21:50
    As of right now, I am just going to implement @@@ and leave the other stuff alone. I'll also make it so you need a command line option to enable @@@ support.
  • Heater.Heater. Posts: 21,230
    edited 2013-08-21 21:59
    I imagine that fixing the behavior of @ is not something we can do without the say so of Chip as he is the language standards body.

    Using "&" would be great but in order to continue the tradition Spin being designed to trip up C programmers it should really be some other symbol, using "*" would be perfect:)

    How about using "¤". That has been on my keyboards for decades and I have never ever had to use it. It's about time some programming language did.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-08-21 23:08
    Roy Eltham wrote:
    As of right now, ...
    'Sorry, Roy, but you can't use that dodge. You're on the cusp of destiny, man, and "as of right now" means forever. You can either seize the opportunity now to keep Spin elegant, or leave us with Brad's very effective but ugly kludge. Please, before you pick the blue pill, give it some more thought. :)

    Thanks,
    -Phil
    heater wrote:
    I imagine that fixing the behavior of @ is not something we can do without the say so of Chip as he is the language standards body.
    I suspect that the current behavior of @ arose because he didn't want to add another pass to the compiler, not because of any philosophical preference. But it woul;dn't hurt to ask him about it.
  • AribaAriba Posts: 2,690
    edited 2013-08-22 01:50
    ...
    I so wish the same could be done with => and =<, but that train left the station years ago.
    I'm pretty sure @ and @@ were in the same train as >= and <=.

    There are Manuals, Tutorials, Books and many Forum posts that describe the @ and @@ operators.
    All the Spin code that does it right according these descriptions will be broken.
    All the tricks that were used to solve the not expected behavior will be broken (@Label+16 and such).

    One possible solution may be to support a new section, which changes the behavior of @ inside that section.
    For example:
    DAT
    x     long 0
    offs  long @x       'offset to object-begin
    ptr   long @@@x     'absolute address
    
    
    DAT@@
    x     long 0
    ptr   long @x       'absolute address
    
    Andy
Sign In or Register to comment.