Possible inconsistent lazy evaluation of instances compared to Java runtime.
ams-tschoening opened this issue · comments
I've found the following because I wondered about some wrong output in the Ruby visualizer, but I believe that the underlying problem is in the runtime.
I have a structure consisting of an arbitrary length of blocks and implemented a look-ahead approach to check if another block is following or not. It's simply a list of blocks where the last read block tells if there's a next block coming or not. This works, the data is parsed as expected and the data itself is shown in the right way in the visualizer. The following code is used to implement the look-ahead in KSY and is called in a repeat-until
:
look_ahead_next_byte:
pos: _io.pos
type: u1
next_isnt_vdb:
value: _io.eof or
(
(look_ahead_next_byte == 0x0F) or
(look_ahead_next_byte == 0x1F)
)
The problem in the visualizer is that next_isnt_vdb
is always shown as true
, even for those blocks were it is false on runtime. And it must be false on runtime, because else it wouldn't work AND because only if _io.eof
is false the byte is actually read and that is shown in the visualizer as well. Only at the very last element that byte is not shown, simply because _io.eof
is correctly true
in that case.
Look at the following screenshot, where element 19 should print false
, one can see that a byte has been read and that's not the case for element 20. Whenever I try to open look_ahead_next_byte
of element 20 an error message is shown that 1 byte couldn't be read. That's expected behaviour, because the stream is already at eof
when I'm doing this, the true
of element 19 and less is not.
The Ruby runtime generates the following code:
def next_isnt_vdb
return @next_isnt_vdb if @next_isnt_vdb
@next_isnt_vdb = _io.eof? || look_ahead_next_byte == 15 || look_ahead_next_byte == 31
@next_isnt_vdb
end
I don't know Ruby, but from my Perl background this is very likely caching the value only in case it's true
, not if it has been evaluated to false
successfully before. There's most likely a difference between a defined variable with a false
value and and undefined one. Pretty much the same like with null
vs. a Boolean
object evaluating to true
or false
in Java.
So the current implementation in Ruby simply always evaluates that instance until true
is reached, which is the case when I'm browsing the structure in the visualizer. This doesn't seem to be inline with your behaviour in Java and simply shows wrong data in the visualizer.
SO says that there's an explicit check for undefined or such in Ruby as well using defined?
. So in theory this could be fixed unless there's a reason for this behaviour I'm not aware of. If so, how to deal with the wrong data shown in the visualizer?
You're really amazing on how you find all that bugs! Thanks!
Indeed, this one stems from a long time ago, where we had no idea of having boolean type at all, so it is completely missed. I'll fix it asap.
I guess it should be fixed now, please take a look. Stupid GitHub has only 2 states for the issue, so it opted to close it already :(