"NoW" means "Nitpicking on Wednesdays"
(unimportant questions about Lua design and implementation)
Let's start with two simple examples:
for x = -2^53, -2^53 do print(x) end
for x = 1e100, 1e100 do print(x) end
Did you expect such results?
There is a problem in numeric "for"-loop: Lua internally exceeds the range of values specified by user.
The loop
for x = a, b, c do ... end
is currently executed as follows:
y = a - c
while true do
y = y + c
if y <?= b then
set x = y and execute the loop body
else
break
end
end
The range specified by user is: a <= x <= b
Lua exceeds it in the beginning (first value of y = a-c)
and in the end (the last value of y might be b+c).
It might happen that a-c+c ~= a
It might also happen that b+c == b
User intuitively implies the correctness of addition and comparison operators for values inside the range a <= x <= b
He might not expect that Lua performs calculations beyond this range.
Another not-a-good-thing is that Lua uses subtraction in numeric "for"-loop (the loop is supposed to always add and never subtract).
This would prevent generalization of numeric "for"-loop (Sony L. some time ago asked for this useful feature).
Addition and comparison metamethods should be enough to perform generalized numeric "for"-loop with arbitrary user objects.
Such objects must implement operations "obj+obj", "obj==obj", "obj<obj" and "obj<0".
The last one is needed to determine whether the loop is "increasing" (step>0) or "decreasing" (step<0).
My suggestion is to implement numeric "for"-loop in more accurate way:
- don't use subtraction;
- don't make addition when upper limit is already reached.
The loop
for x = a, b, c do ... end
should be executed as follows:
y = a
while y <? b do
set x = y and execute the loop body
y = y + c
end
if y == b then
set x = y and execute the loop body
end
Lua VM instructions would be the following:
[1] FORPREP
[2] loop body
[3] FORLOOP
[4] next instruction after the loop
R(A) = index
R(A+1) = limit
R(A+2) = step
R(A+3) = user loop variable
R(A), R(A+1) and R(A+2) might contain user objects instead of Lua numbers.
Operator ">?=" implies comparison of R(A+2) with number 0 to be resolved:
to ">=" for increasing loop, to "<=" for decreasing loop.
A trick is used here:
when the index R(A) reaches the limit R(A+1), the step R(A+2) is set to nil to mark the current iteration as final.
No addition is made after the final iteration.
function FORPREP(A, sBx)
if R(A) >?= R(A+1) then
if R(A) == R(A+1) then
R(A+2) = nil -- set step to nil (the next iteration will be final)
else
pc+=sBx -- jump to [4]
return
end
end
R(A+3)=R(A)
end
function FORLOOP(A, sBx)
if R(A+2) then -- if step is not nil (if not after the final iteration)
R(A)+=R(A+2)
if R(A) >?= R(A+1) then
if R(A) == R(A+1) then
R(A+2) = nil -- set step to nil (the next iteration will be final)
else
return
end
end
R(A+3)=R(A)
pc+=sBx -- jump to [2]
end
end
This would involve unnoticeable decrease of performance of usual numeric "for"-loops.