From: Rick M. <obj...@gm...> - 2007-04-14 12:25:00
|
I was doing some simple testing of how array handled suppliers, and I ran into a nasty bit of a problem with the array makestring method. Here's the sequence I ran: a = .array~new(2, 2, 2) a[1,1,1] = a a[1,2,1] = b s = a~supplier do while s~available; say s~index; say s~item; s~next; end and here's the result of running it: 1,1,1 8 *-* say s~item; Error 11 running C:\ORexxDev\oorexx\testsupplier.rex line 8: Control stack full Error 11.1: Insufficient control stack space; cannot continue execution What the .....????????? The problem here was in this line: a[1,1,1] = a by not quoting the value 'a', I created a recursive reference with the array. The array makestring method just concatentates the string values of the elements together into a single string, and when it requests the string value of the element at position 1,2,1, it gets into a recursion loop. Now when this function was originally added by the Boeblingen developers, they didn't complete the implementation in that say a originally resulted in an "An Array", which is a violation of the language definition, since a~REQUEST('STRING') should be returning the value of the MAKESTRING since the array object clearly has a MAKESTRING method. This was one of the earliest bugs I fixed, and I'm now regretting it :-) The real problem here was this should never have been a MAKESTRING method, but rather something like "TOSTRING", so it didn't get hooked into the automatic string coercion mechanisms. The second assumption was that all of the elements in the array were going to be strings in the first place. Also, adding options to MAKESTRING really shouldn't have been done. The MAKE* methods are really intended for the automatic REQUEST processing and are not expected to have arguments. This really should have been something like a "TOSTRING" method instead. Rony, MAKEARRAY on CircularQueue has a similar problem. Note that even a simple direct recursion check would not eliminate the problem. There's still indirect reference loops possible: a = .array~new b = .array~new a[1] = b b[1] = a say a would produce the same result, but is something not directly detectable in the context of the array string method. The other thing that makes me feel uneasy here is that the implicit coercion could be pretty disastrous when working with large arrays....particularly if you turn on "trace i" and you're working with a large array. As a short term fix, I'm going to default any value in the array that is not a string to a "" value. We can debate other replacement values later, but right now I want to avoid the recursion problems. I'm also going to revert my "fix" to the makestring problem back to the original behavior to avoid the accidental behavior that could be very bad. I'd really like to "deprecate" MAKESTRING and introduce TOSTRING, which supports the same options. Then, I'd also like to cap the length of the value returned by the no-argument form of MAKESTRING to some "reasonable" value. To get everything converted to a string, you need to be explicit about what you want. Once that's done, I'll convert the REQUEST stuff back to the "proper" behavior of calling the MAKESTRING method. Rick |