18 May 2011

Hash passing to a subroutine (I) - The bug

As mentioned in the (English) help file the handling of a Hash type argument is erroneous. The compiler produces incorrect code when the local Hash parameter is used in Hash commands like Hash Add, Hash Remove, etc. As far as I know all Hash Xxx commands suffer from the compiler bug. In contradiction with this behavior is the handling of the Hash–operator code. When a Hash data type is passed to a subroutine the compiler produces correct code for all [ ] hash-operator code. The following code illustrates the situation:
Sub q(hs As Hash String)
  ' Errorneous:
  Hash Add hs["mykey"], "Entry1"
  Hash Add hs[2], "Entry2"
  ' OK:
  hs[3] = "Entry3"
  Print hs[%]
EndSub

What is happening?
Due to the implicit Sub by-reference passing the compiler puts the address of the Hash argument on the stack when invoking q( Hs[] ). This is the first step performed by the compiler when a call to q() must be produced and it turns out to be ok. The second step performed by the compiler is when the subroutine q() is compiled. Due to the by-ref passing the compiler must set the local hs variable to the address put on the stack by the code that invoked the call. That way the local variable hs points to the same data as the hash passed to q().
However, somehow the compiler messes up with the Hash Xxx commands. When inspecting the assembly code for q() it can be seen that for the hash-operator instructions the correct Hash address is passed to the runtime library functions. Also, it is clear that the compiler passes the incorrect address in case the Hash Xxx commands are used.

What is to be done?
At this moment this bug cannot be fixed, so we either need a workaround or we avoid the use of Hash variables as a subroutine argument at all. The second option isn't the worst of both, because due to their nature Hash tables are mostly used globally and don't need to be passed to subroutines at all. Of course, a hash table could be used to store temporary results (regular expression commands), but in that case the Hash is usually declared locally and not passed to any subroutine.
Advise: Don't pass Hash variables to subroutines.
In the next post I will discuss a workaround together with the layout of the GFA-BASIC 32 Hash data type.

No comments:

Post a Comment