mirror of
https://github.com/lua/lua
synced 2025-03-27 16:12:52 +03:00
Fixed bug in tail calls of __call chains
A tail call of a __call chain (a __call metamethod that itself is also not a function) was being perfomed as a regular call.
This commit is contained in:
parent
c12983cf8a
commit
7d526e75a7
3
lvm.c
3
lvm.c
@ -1549,9 +1549,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
luaF_close(L, base, NOCLOSINGMETH);
|
||||
lua_assert(base == ci->func + 1);
|
||||
}
|
||||
if (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||
while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||
b++; /* there is now one extra argument */
|
||||
checkstackp(L, 1, ra);
|
||||
}
|
||||
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||
luaD_call(L, ra, LUA_MULTRET); /* call it */
|
||||
|
@ -107,7 +107,9 @@ end
|
||||
deep(10)
|
||||
deep(180)
|
||||
|
||||
-- testing tail calls
|
||||
|
||||
print"testing tail calls"
|
||||
|
||||
function deep (n) if n>0 then return deep(n-1) else return 101 end end
|
||||
assert(deep(30000) == 101)
|
||||
a = {}
|
||||
@ -148,6 +150,27 @@ do -- tail calls x varargs
|
||||
assert(X == 10 and Y == 20 and #A == 1 and A[1] == 30)
|
||||
end
|
||||
|
||||
|
||||
|
||||
do -- tail calls x chain of __call
|
||||
local n = 10000 -- depth
|
||||
|
||||
local function foo ()
|
||||
if n == 0 then return 1023
|
||||
else n = n - 1; return foo()
|
||||
end
|
||||
end
|
||||
|
||||
-- build a chain of __call metamethods ending in function 'foo'
|
||||
for i = 1, 100 do
|
||||
foo = setmetatable({}, {__call = foo})
|
||||
end
|
||||
|
||||
-- call the first one as a tail call in a new coroutine
|
||||
-- (to ensure stack is not preallocated)
|
||||
assert(coroutine.wrap(function() return foo() end)() == 1023)
|
||||
end
|
||||
|
||||
print('+')
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user