Files

39 lines
1.6 KiB
Lua

-- A tail call must close captured registers before reusing their frame.
local saved = {}
local function descend(n, ...)
if n == 0 then return ... end
if n % 1000 == 0 then saved[#saved+1] = function() return n end end
return descend(n-1, ...)
end
local function pack(...) return {n = select('#', ...), ...} end
local results = pack(descend(100000, nil, 'middle', nil))
assert(results.n == 3 and results[2] == 'middle')
assert(saved[1]() == 100000 and saved[#saved]() == 1000)
-- Resume a yielded C call with open results across a Lua tail call.
local thread = coroutine.create(function(...)
return descend(10, coroutine.yield(...))
end)
local ok, first = coroutine.resume(thread, 7)
assert(ok and first == 7)
results = pack(coroutine.resume(thread, false, nil, 9))
assert(results.n == 4 and results[1] and results[2] == false and results[4] == 9)
-- Metamethods can call Lua and grow the stack in the middle of an opcode.
local function grow(n)
if n == 0 then collectgarbage(); return 0 end
return 1 + grow(n-1)
end
local obj = setmetatable({}, {__index = function(_, key) return grow(300) + key end})
assert(obj[4] == 304)
-- Exercise the extra page word for a list wider than the SETLIST C field.
local wide = assert(loadstring('return {' .. string.rep('1,', 26000) .. '42}'))()
assert(#wide == 26001 and wide[26001] == 42)
local f, syntax = loadstring('local =')
assert(not f and type(syntax) == 'string')
local ok, err = pcall(assert(loadstring('local x\nreturn x.missing', '@bad.lua')))
assert(not ok and err:match('bad.lua:2:'))
print('VM regression tests passed')