lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




Le sam. 14 mai 2022 à 04:27, Gé Weijers <ge@weijers.org> a écrit :

repeat
    if math.random() ~= 0.1 then
        goto continue
    end
    local finished = true
::continue::
until finished

Adding "continue" would not add any problem that adding "goto" did not already introduce.

That code gives unpredictable result: what is the value of the "finished" variable when jumping to the ::continue:: label from a "goto" statement where that "finished" variable was not even in scope, and so has no initial value and was still not initialized?

That "goto" statement jumps into an inner scope, so even the validity of the "goto" itself is questionable (and in my opinion it should be invalid too: "goto" is a bad statement here and I don't see any valid use of any "continue" statement or jump from inside any "repeat..until" loop, where only a "break" or jump to outside is semantically valid).

The following code would also be invalid for the same reason:

if math.random() ~= 0.1 then
   goto A
else
   goto B
end
local x=10
::A:: print('A', x); goto exit
local x=11
::B:: print('B', x); goto exit
::exit:: ;
Here you can get any output, not just "A 10", or "B 11", but as well "A 0", "A undefined", "A nil', "A (random string)", "B 10"... or even strange crashes caused by assertion checks made in the compiler about initialization states.

That's the major argument against "goto" which should absolutely never be used to jump to labels that are not in the current lexical scope: such use is clearly invalid (tolerated in C because local variables are allocated, but don't necessarily have to be initialized: their declaration is forward, they are "preallocated" on the stack but the initialization may have still not occured

Some C compilers enforce a initialization to binary zero for all local variables at entry of the function, even if there are later some initializers that may set (or reset) them explicitly and individually to 0.

But in Lua, this is not clear: does the compiler or interpreter have to initialize all variables in scope implicitly to zero? If so, the code above could print only "A 0" or "B 0", and explicit initializers (x=10 or x=11) would have no use, as they are not reachable, and could be safely discarded. But variables in Lua are not necessarily numbers and are polymorphic (like also in _javascript_ where all uninitialized variables have a default initialization to "undefined", which is a singleton type).

But Lua does not have a safe and well-defined singleton type for uninitialized variables, so we get unpredicatable results; and as a consequence, the "goto" statement is unsafe, it is ill-defined and this should be fixed (like in _javascript_), maybe by explicitly stating that ALL uninitialized variables implicitly have the "nil" value, and making sure that the compiler or interpreter will allocate all variables in lexical scopes with that default value, independantly of all other initializers. Only under this condition, that "goto" statement can be safe and have predictable results, even if they jump outside from current lexical scopes.