New semantics for the integer 'for' loop
The numerical 'for' loop over integers now uses a precomputed counter to control its number of iteractions. This change eliminates several weird cases caused by overflows (wrap-around) in the control variable. (It also ensures that every integer loop halts.) Also, the special opcodes for the usual case of step==1 were removed. (The new code is already somewhat complex for the usual case, but efficient.)
This commit is contained in:
@@ -76,7 +76,7 @@ while a < lim do
|
||||
a = math.ceil(a*1.3)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function check (t, na, nh)
|
||||
local a, h = T.querytab(t)
|
||||
if a ~= na or h ~= nh then
|
||||
@@ -100,7 +100,7 @@ local s = 'return {'
|
||||
for i=1,lim do
|
||||
s = s..i..','
|
||||
local s = s
|
||||
for k=0,lim do
|
||||
for k=0,lim do
|
||||
local t = load(s..'}', '')()
|
||||
assert(#t == i)
|
||||
check(t, fb(i), mp2(k))
|
||||
@@ -279,7 +279,7 @@ do -- clear global table
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
--
|
||||
|
||||
local function checknext (a)
|
||||
local b = {}
|
||||
@@ -500,7 +500,7 @@ else --[
|
||||
mt.__newindex = nil
|
||||
mt.__len = nil
|
||||
local tab2 = {}
|
||||
local u2 = T.newuserdata(0)
|
||||
local u2 = T.newuserdata(0)
|
||||
debug.setmetatable(u2, {__newindex = function (_, k, v) tab2[k] = v end})
|
||||
table.move(u, 1, 4, 1, u2)
|
||||
assert(#tab2 == 4 and tab2[1] == tab[1] and tab2[4] == tab[4])
|
||||
@@ -601,6 +601,69 @@ do -- checking types
|
||||
|
||||
end
|
||||
|
||||
|
||||
do -- testing other strange cases for numeric 'for'
|
||||
|
||||
local function checkfor (from, to, step, t)
|
||||
local c = 0
|
||||
for i = from, to, step do
|
||||
c = c + 1
|
||||
assert(i == t[c])
|
||||
end
|
||||
assert(c == #t)
|
||||
end
|
||||
|
||||
local maxi = math.maxinteger
|
||||
local mini = math.mininteger
|
||||
|
||||
checkfor(mini, maxi, maxi, {mini, -1, maxi - 1})
|
||||
|
||||
checkfor(mini, math.huge, maxi, {mini, -1, maxi - 1})
|
||||
|
||||
checkfor(maxi, mini, mini, {maxi, -1})
|
||||
|
||||
checkfor(maxi, mini, -maxi, {maxi, 0, -maxi})
|
||||
|
||||
checkfor(maxi, -math.huge, mini, {maxi, -1})
|
||||
|
||||
checkfor(maxi, mini, 1, {})
|
||||
checkfor(mini, maxi, -1, {})
|
||||
|
||||
checkfor(maxi - 6, maxi, 3, {maxi - 6, maxi - 3, maxi})
|
||||
checkfor(mini + 4, mini, -2, {mini + 4, mini + 2, mini})
|
||||
|
||||
local step = maxi // 10
|
||||
local c = mini
|
||||
for i = mini, maxi, step do
|
||||
assert(i == c)
|
||||
c = c + step
|
||||
end
|
||||
|
||||
c = maxi
|
||||
for i = maxi, mini, -step do
|
||||
assert(i == c)
|
||||
c = c - step
|
||||
end
|
||||
|
||||
checkfor(maxi, maxi, maxi, {maxi})
|
||||
checkfor(maxi, maxi, mini, {maxi})
|
||||
checkfor(mini, mini, maxi, {mini})
|
||||
checkfor(mini, mini, mini, {mini})
|
||||
end
|
||||
|
||||
|
||||
checkerror("'for' step is zero", function ()
|
||||
for i = 1, 10, 0 do end
|
||||
end)
|
||||
|
||||
checkerror("'for' step is zero", function ()
|
||||
for i = 1, -10, 0 do end
|
||||
end)
|
||||
|
||||
checkerror("'for' step is zero", function ()
|
||||
for i = 1.0, -10, 0.0 do end
|
||||
end)
|
||||
|
||||
collectgarbage()
|
||||
|
||||
|
||||
@@ -657,7 +720,7 @@ a[3] = 30
|
||||
-- testing ipairs with metamethods
|
||||
a = {n=10}
|
||||
setmetatable(a, { __index = function (t,k)
|
||||
if k <= t.n then return k * 10 end
|
||||
if k <= t.n then return k * 10 end
|
||||
end})
|
||||
i = 0
|
||||
for k,v in ipairs(a) do
|
||||
|
||||
Reference in New Issue
Block a user