diff options
| author | Philipp Janda <siffiejoe@gmx.net> | 2015-01-20 11:35:16 +0100 |
|---|---|---|
| committer | Philipp Janda <siffiejoe@gmx.net> | 2015-01-20 11:35:16 +0100 |
| commit | 866cb79f65c844b3fcfa99d2caa4bf19930dbc6d (patch) | |
| tree | 338699b9df9b2c99cec053321790e9a5960c4b3b /compat53.lua | |
| parent | e52c3c4e7af665acd23e63fd3ae85f2c8ae87e49 (diff) | |
| download | lua-compat-5.3-866cb79f65c844b3fcfa99d2caa4bf19930dbc6d.tar.gz lua-compat-5.3-866cb79f65c844b3fcfa99d2caa4bf19930dbc6d.tar.bz2 lua-compat-5.3-866cb79f65c844b3fcfa99d2caa4bf19930dbc6d.zip | |
luajit already has yieldable (x)pcall, add tests for code from compat52
Diffstat (limited to 'compat53.lua')
| -rw-r--r-- | compat53.lua | 318 |
1 files changed, 162 insertions, 156 deletions
diff --git a/compat53.lua b/compat53.lua index 5f88e8b..67a8c8f 100644 --- a/compat53.lua +++ b/compat53.lua | |||
| @@ -336,12 +336,12 @@ if lua_version < "5.3" then | |||
| 336 | function debug.setuservalue(obj, value) | 336 | function debug.setuservalue(obj, value) |
| 337 | if type(obj) ~= "userdata" then | 337 | if type(obj) ~= "userdata" then |
| 338 | error("bad argument #1 to 'setuservalue' (userdata expected, got ".. | 338 | error("bad argument #1 to 'setuservalue' (userdata expected, got ".. |
| 339 | type(obj)..")", 0) | 339 | type(obj)..")", 2) |
| 340 | end | 340 | end |
| 341 | if value == nil then value = _G end | 341 | if value == nil then value = _G end |
| 342 | if type(value) ~= "table" then | 342 | if type(value) ~= "table" then |
| 343 | error("bad argument #2 to 'setuservalue' (table expected, got ".. | 343 | error("bad argument #2 to 'setuservalue' (table expected, got ".. |
| 344 | type(value)..")", 0) | 344 | type(value)..")", 2) |
| 345 | end | 345 | end |
| 346 | return debug_setfenv(obj, value) | 346 | return debug_setfenv(obj, value) |
| 347 | end | 347 | end |
| @@ -366,96 +366,98 @@ if lua_version < "5.3" then | |||
| 366 | end | 366 | end |
| 367 | end -- not luajit with compat52 enabled | 367 | end -- not luajit with compat52 enabled |
| 368 | 368 | ||
| 369 | local debug_getinfo = debug.getinfo | 369 | if not is_luajit then |
| 370 | local function calculate_trace_level(co, level) | 370 | local debug_getinfo = debug.getinfo |
| 371 | if level ~= nil then | 371 | local function calculate_trace_level(co, level) |
| 372 | for out = 1, 1/0 do | 372 | if level ~= nil then |
| 373 | local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") | 373 | for out = 1, 1/0 do |
| 374 | if info == nil then | 374 | local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") |
| 375 | local max = out-1 | 375 | if info == nil then |
| 376 | if level <= max then | 376 | local max = out-1 |
| 377 | return level | 377 | if level <= max then |
| 378 | return level | ||
| 379 | end | ||
| 380 | return nil, level-max | ||
| 378 | end | 381 | end |
| 379 | return nil, level-max | ||
| 380 | end | 382 | end |
| 381 | end | 383 | end |
| 384 | return 1 | ||
| 382 | end | 385 | end |
| 383 | return 1 | ||
| 384 | end | ||
| 385 | 386 | ||
| 386 | local stack_pattern = "\nstack traceback:" | 387 | local stack_pattern = "\nstack traceback:" |
| 387 | local stack_replace = "" | 388 | local stack_replace = "" |
| 388 | local debug_traceback = debug.traceback | 389 | local debug_traceback = debug.traceback |
| 389 | function debug.traceback(co, msg, level) | 390 | function debug.traceback(co, msg, level) |
| 390 | local lvl | 391 | local lvl |
| 391 | local nilmsg | 392 | local nilmsg |
| 392 | if type(co) ~= "thread" then | 393 | if type(co) ~= "thread" then |
| 393 | co, msg, level = coroutine_running(), co, msg | 394 | co, msg, level = coroutine_running(), co, msg |
| 394 | end | 395 | end |
| 395 | if msg == nil then | 396 | if msg == nil then |
| 396 | msg = "" | 397 | msg = "" |
| 397 | nilmsg = true | 398 | nilmsg = true |
| 398 | elseif type(msg) ~= "string" then | 399 | elseif type(msg) ~= "string" then |
| 399 | return msg | 400 | return msg |
| 400 | end | 401 | end |
| 401 | if co == nil then | 402 | if co == nil then |
| 402 | msg = debug_traceback(msg, level or 1) | 403 | msg = debug_traceback(msg, level or 1) |
| 403 | else | ||
| 404 | local xpco = xpcall_running[co] | ||
| 405 | if xpco ~= nil then | ||
| 406 | lvl, level = calculate_trace_level(xpco, level) | ||
| 407 | if lvl then | ||
| 408 | msg = debug_traceback(xpco, msg, lvl) | ||
| 409 | else | ||
| 410 | msg = msg..stack_pattern | ||
| 411 | end | ||
| 412 | lvl, level = calculate_trace_level(co, level) | ||
| 413 | if lvl then | ||
| 414 | local trace = debug_traceback(co, "", lvl) | ||
| 415 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 416 | end | ||
| 417 | else | 404 | else |
| 418 | co = pcall_callOf[co] or co | 405 | local xpco = xpcall_running[co] |
| 419 | lvl, level = calculate_trace_level(co, level) | 406 | if xpco ~= nil then |
| 420 | if lvl then | 407 | lvl, level = calculate_trace_level(xpco, level) |
| 421 | msg = debug_traceback(co, msg, lvl) | 408 | if lvl then |
| 409 | msg = debug_traceback(xpco, msg, lvl) | ||
| 410 | else | ||
| 411 | msg = msg..stack_pattern | ||
| 412 | end | ||
| 413 | lvl, level = calculate_trace_level(co, level) | ||
| 414 | if lvl then | ||
| 415 | local trace = debug_traceback(co, "", lvl) | ||
| 416 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 417 | end | ||
| 422 | else | 418 | else |
| 423 | msg = msg..stack_pattern | 419 | co = pcall_callOf[co] or co |
| 424 | end | 420 | lvl, level = calculate_trace_level(co, level) |
| 425 | end | 421 | if lvl then |
| 426 | co = pcall_previous[co] | 422 | msg = debug_traceback(co, msg, lvl) |
| 427 | while co ~= nil do | 423 | else |
| 428 | lvl, level = calculate_trace_level(co, level) | 424 | msg = msg..stack_pattern |
| 429 | if lvl then | 425 | end |
| 430 | local trace = debug_traceback(co, "", lvl) | ||
| 431 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 432 | end | 426 | end |
| 433 | co = pcall_previous[co] | 427 | co = pcall_previous[co] |
| 428 | while co ~= nil do | ||
| 429 | lvl, level = calculate_trace_level(co, level) | ||
| 430 | if lvl then | ||
| 431 | local trace = debug_traceback(co, "", lvl) | ||
| 432 | msg = msg..trace:gsub(stack_pattern, stack_replace) | ||
| 433 | end | ||
| 434 | co = pcall_previous[co] | ||
| 435 | end | ||
| 436 | end | ||
| 437 | if nilmsg then | ||
| 438 | msg = msg:gsub("^\n", "") | ||
| 434 | end | 439 | end |
| 440 | msg = msg:gsub("\n\t%(tail call%): %?", "\000") | ||
| 441 | msg = msg:gsub("\n\t%.%.%.\n", "\001\n") | ||
| 442 | msg = msg:gsub("\n\t%.%.%.$", "\001") | ||
| 443 | msg = msg:gsub("(%z+)\001(%z+)", function(some, other) | ||
| 444 | return "\n\t(..."..#some+#other.."+ tail call(s)...)" | ||
| 445 | end) | ||
| 446 | msg = msg:gsub("\001(%z+)", function(zeros) | ||
| 447 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 448 | end) | ||
| 449 | msg = msg:gsub("(%z+)\001", function(zeros) | ||
| 450 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 451 | end) | ||
| 452 | msg = msg:gsub("%z+", function(zeros) | ||
| 453 | return "\n\t(..."..#zeros.." tail call(s)...)" | ||
| 454 | end) | ||
| 455 | msg = msg:gsub("\001", function(zeros) | ||
| 456 | return "\n\t..." | ||
| 457 | end) | ||
| 458 | return msg | ||
| 435 | end | 459 | end |
| 436 | if nilmsg then | 460 | end -- is not luajit |
| 437 | msg = msg:gsub("^\n", "") | ||
| 438 | end | ||
| 439 | msg = msg:gsub("\n\t%(tail call%): %?", "\000") | ||
| 440 | msg = msg:gsub("\n\t%.%.%.\n", "\001\n") | ||
| 441 | msg = msg:gsub("\n\t%.%.%.$", "\001") | ||
| 442 | msg = msg:gsub("(%z+)\001(%z+)", function(some, other) | ||
| 443 | return "\n\t(..."..#some+#other.."+ tail call(s)...)" | ||
| 444 | end) | ||
| 445 | msg = msg:gsub("\001(%z+)", function(zeros) | ||
| 446 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 447 | end) | ||
| 448 | msg = msg:gsub("(%z+)\001", function(zeros) | ||
| 449 | return "\n\t(..."..#zeros.."+ tail call(s)...)" | ||
| 450 | end) | ||
| 451 | msg = msg:gsub("%z+", function(zeros) | ||
| 452 | return "\n\t(..."..#zeros.." tail call(s)...)" | ||
| 453 | end) | ||
| 454 | msg = msg:gsub("\001", function(zeros) | ||
| 455 | return "\n\t..." | ||
| 456 | end) | ||
| 457 | return msg | ||
| 458 | end | ||
| 459 | end -- debug table available | 461 | end -- debug table available |
| 460 | 462 | ||
| 461 | 463 | ||
| @@ -501,7 +503,7 @@ if lua_version < "5.3" then | |||
| 501 | local ld_type = type(ld) | 503 | local ld_type = type(ld) |
| 502 | if ld_type ~= "function" then | 504 | if ld_type ~= "function" then |
| 503 | error("bad argument #1 to 'load' (function expected, got ".. | 505 | error("bad argument #1 to 'load' (function expected, got ".. |
| 504 | ld_type..")", 0) | 506 | ld_type..")", 2) |
| 505 | end | 507 | end |
| 506 | if mode ~= "bt" then | 508 | if mode ~= "bt" then |
| 507 | local checked, merr = false, nil | 509 | local checked, merr = false, nil |
| @@ -564,7 +566,7 @@ if lua_version < "5.3" then | |||
| 564 | function rawlen(v) | 566 | function rawlen(v) |
| 565 | local t = type(v) | 567 | local t = type(v) |
| 566 | if t ~= "string" and t ~= "table" then | 568 | if t ~= "string" and t ~= "table" then |
| 567 | error("bad argument #1 to 'rawlen' (table or string expected)", 0) | 569 | error("bad argument #1 to 'rawlen' (table or string expected)", 2) |
| 568 | end | 570 | end |
| 569 | return #v | 571 | return #v |
| 570 | end | 572 | end |
| @@ -622,92 +624,94 @@ if lua_version < "5.3" then | |||
| 622 | 624 | ||
| 623 | local coroutine_yield = coroutine.yield | 625 | local coroutine_yield = coroutine.yield |
| 624 | function coroutine.yield(...) | 626 | function coroutine.yield(...) |
| 625 | local co = coroutine_running() | 627 | local co, flag = coroutine_running() |
| 626 | if co then | 628 | if co and not flag then |
| 627 | return coroutine_yield(...) | 629 | return coroutine_yield(...) |
| 628 | else | 630 | else |
| 629 | error("attempt to yield from outside a coroutine", 0) | 631 | error("attempt to yield from outside a coroutine", 0) |
| 630 | end | 632 | end |
| 631 | end | 633 | end |
| 632 | 634 | ||
| 633 | local coroutine_resume = coroutine.resume | 635 | if not is_luajit then |
| 634 | function coroutine.resume(co, ...) | 636 | local coroutine_resume = coroutine.resume |
| 635 | if co == main_coroutine then | 637 | function coroutine.resume(co, ...) |
| 636 | return false, "cannot resume non-suspended coroutine" | 638 | if co == main_coroutine then |
| 637 | else | 639 | return false, "cannot resume non-suspended coroutine" |
| 638 | return coroutine_resume(co, ...) | 640 | else |
| 641 | return coroutine_resume(co, ...) | ||
| 642 | end | ||
| 639 | end | 643 | end |
| 640 | end | ||
| 641 | 644 | ||
| 642 | local coroutine_status = coroutine.status | 645 | local coroutine_status = coroutine.status |
| 643 | function coroutine.status(co) | 646 | function coroutine.status(co) |
| 644 | local notmain = coroutine_running() | 647 | local notmain = coroutine_running() |
| 645 | if co == main_coroutine then | 648 | if co == main_coroutine then |
| 646 | return notmain and "normal" or "running" | 649 | return notmain and "normal" or "running" |
| 647 | else | 650 | else |
| 648 | return coroutine_status(co) | 651 | return coroutine_status(co) |
| 652 | end | ||
| 649 | end | 653 | end |
| 650 | end | ||
| 651 | 654 | ||
| 652 | local function pcall_results(current, call, success, ...) | 655 | local function pcall_results(current, call, success, ...) |
| 653 | if coroutine_status(call) == "suspended" then | 656 | if coroutine_status(call) == "suspended" then |
| 654 | return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) | 657 | return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) |
| 658 | end | ||
| 659 | if pcall_previous then | ||
| 660 | pcall_previous[call] = nil | ||
| 661 | local main = pcall_mainOf[call] | ||
| 662 | if main == current then current = nil end | ||
| 663 | pcall_callOf[main] = current | ||
| 664 | end | ||
| 665 | pcall_mainOf[call] = nil | ||
| 666 | return success, ... | ||
| 655 | end | 667 | end |
| 656 | if pcall_previous then | 668 | local function pcall_exec(current, call, ...) |
| 657 | pcall_previous[call] = nil | 669 | local main = pcall_mainOf[current] or current |
| 658 | local main = pcall_mainOf[call] | 670 | pcall_mainOf[call] = main |
| 659 | if main == current then current = nil end | 671 | if pcall_previous then |
| 660 | pcall_callOf[main] = current | 672 | pcall_previous[call] = current |
| 673 | pcall_callOf[main] = call | ||
| 674 | end | ||
| 675 | return pcall_results(current, call, coroutine_resume(call, ...)) | ||
| 661 | end | 676 | end |
| 662 | pcall_mainOf[call] = nil | 677 | local coroutine_create52 = coroutine.create |
| 663 | return success, ... | 678 | local function pcall_coroutine(func) |
| 664 | end | 679 | if type(func) ~= "function" then |
| 665 | local function pcall_exec(current, call, ...) | 680 | local callable = func |
| 666 | local main = pcall_mainOf[current] or current | 681 | func = function (...) return callable(...) end |
| 667 | pcall_mainOf[call] = main | 682 | end |
| 668 | if pcall_previous then | 683 | return coroutine_create52(func) |
| 669 | pcall_previous[call] = current | ||
| 670 | pcall_callOf[main] = call | ||
| 671 | end | 684 | end |
| 672 | return pcall_results(current, call, coroutine_resume(call, ...)) | 685 | function pcall(func, ...) |
| 673 | end | 686 | local current = coroutine_running() |
| 674 | local coroutine_create52 = coroutine.create | 687 | if not current then return _pcall(func, ...) end |
| 675 | local function pcall_coroutine(func) | 688 | return pcall_exec(current, pcall_coroutine(func), ...) |
| 676 | if type(func) ~= "function" then | ||
| 677 | local callable = func | ||
| 678 | func = function (...) return callable(...) end | ||
| 679 | end | 689 | end |
| 680 | return coroutine_create52(func) | ||
| 681 | end | ||
| 682 | function pcall(func, ...) | ||
| 683 | local current = coroutine_running() | ||
| 684 | if not current then return _pcall(func, ...) end | ||
| 685 | return pcall_exec(current, pcall_coroutine(func), ...) | ||
| 686 | end | ||
| 687 | 690 | ||
| 688 | local function xpcall_catch(current, call, msgh, success, ...) | 691 | local function xpcall_catch(current, call, msgh, success, ...) |
| 689 | if not success then | 692 | if not success then |
| 690 | xpcall_running[current] = call | 693 | xpcall_running[current] = call |
| 691 | local ok, result = _pcall(msgh, ...) | 694 | local ok, result = _pcall(msgh, ...) |
| 692 | xpcall_running[current] = nil | 695 | xpcall_running[current] = nil |
| 693 | if not ok then | 696 | if not ok then |
| 694 | return false, "error in error handling ("..tostring(result)..")" | 697 | return false, "error in error handling ("..tostring(result)..")" |
| 698 | end | ||
| 699 | return false, result | ||
| 695 | end | 700 | end |
| 696 | return false, result | 701 | return true, ... |
| 697 | end | 702 | end |
| 698 | return true, ... | 703 | local _xpcall = xpcall |
| 699 | end | 704 | local _unpack = unpack |
| 700 | local _xpcall = xpcall | 705 | function xpcall(f, msgh, ...) |
| 701 | local _unpack = unpack | 706 | local current = coroutine_running() |
| 702 | function xpcall(f, msgh, ...) | 707 | if not current then |
| 703 | local current = coroutine_running() | 708 | local args, n = { ... }, select('#', ...) |
| 704 | if not current then | 709 | return _xpcall(function() return f(_unpack(args, 1, n)) end, msgh) |
| 705 | local args, n = { ... }, select('#', ...) | 710 | end |
| 706 | return _xpcall(function() return f(_unpack(args, 1, n)) end, msgh) | 711 | local call = pcall_coroutine(f) |
| 712 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) | ||
| 707 | end | 713 | end |
| 708 | local call = pcall_coroutine(f) | 714 | end -- not luajit |
| 709 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) | ||
| 710 | end | ||
| 711 | 715 | ||
| 712 | 716 | ||
| 713 | if not is_luajit then | 717 | if not is_luajit then |
| @@ -806,6 +810,7 @@ if lua_version < "5.3" then | |||
| 806 | return addqt[c] or string_format("\\%03d", c:byte()) | 810 | return addqt[c] or string_format("\\%03d", c:byte()) |
| 807 | end | 811 | end |
| 808 | 812 | ||
| 813 | local _unpack = unpack | ||
| 809 | function string.format(fmt, ...) | 814 | function string.format(fmt, ...) |
| 810 | local args, n = { ... }, select('#', ...) | 815 | local args, n = { ... }, select('#', ...) |
| 811 | local i = 0 | 816 | local i = 0 |
| @@ -846,12 +851,13 @@ if lua_version < "5.3" then | |||
| 846 | if var_1 == nil then | 851 | if var_1 == nil then |
| 847 | if st.doclose then st.f:close() end | 852 | if st.doclose then st.f:close() end |
| 848 | if (...) ~= nil then | 853 | if (...) ~= nil then |
| 849 | error((...), 0) | 854 | error((...), 2) |
| 850 | end | 855 | end |
| 851 | end | 856 | end |
| 852 | return var_1, ... | 857 | return var_1, ... |
| 853 | end | 858 | end |
| 854 | 859 | ||
| 860 | local _unpack = unpack | ||
| 855 | function lines_iterator(st) | 861 | function lines_iterator(st) |
| 856 | return helper(st, st.f:read(_unpack(st, 1, st.n))) | 862 | return helper(st, st.f:read(_unpack(st, 1, st.n))) |
| 857 | end | 863 | end |
| @@ -864,14 +870,14 @@ if lua_version < "5.3" then | |||
| 864 | local doclose, file, msg | 870 | local doclose, file, msg |
| 865 | if fname ~= nil then | 871 | if fname ~= nil then |
| 866 | doclose, file, msg = true, io_open(fname, "r") | 872 | doclose, file, msg = true, io_open(fname, "r") |
| 867 | if not file then error(msg, 0) end | 873 | if not file then error(msg, 2) end |
| 868 | else | 874 | else |
| 869 | doclose, file = false, io_input() | 875 | doclose, file = false, io_input() |
| 870 | end | 876 | end |
| 871 | local st = { f=file, doclose=doclose, n=select('#', ...), ... } | 877 | local st = { f=file, doclose=doclose, n=select('#', ...), ... } |
| 872 | for i = 1, st.n do | 878 | for i = 1, st.n do |
| 873 | if type(st[i]) ~= "number" and not valid_format[st[i]] then | 879 | if type(st[i]) ~= "number" and not valid_format[st[i]] then |
| 874 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 0) | 880 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) |
| 875 | end | 881 | end |
| 876 | end | 882 | end |
| 877 | return lines_iterator, st | 883 | return lines_iterator, st |
| @@ -894,12 +900,12 @@ if lua_version < "5.3" then | |||
| 894 | 900 | ||
| 895 | file_meta.__index.lines = function(self, ...) | 901 | file_meta.__index.lines = function(self, ...) |
| 896 | if io_type(self) == "closed file" then | 902 | if io_type(self) == "closed file" then |
| 897 | error("attempt to use a closed file", 0) | 903 | error("attempt to use a closed file", 2) |
| 898 | end | 904 | end |
| 899 | local st = { f=self, doclose=false, n=select('#', ...), ... } | 905 | local st = { f=self, doclose=false, n=select('#', ...), ... } |
| 900 | for i = 1, st.n do | 906 | for i = 1, st.n do |
| 901 | if type(st[i]) ~= "number" and not valid_format[st[i]] then | 907 | if type(st[i]) ~= "number" and not valid_format[st[i]] then |
| 902 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 0) | 908 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) |
| 903 | end | 909 | end |
| 904 | end | 910 | end |
| 905 | return lines_iterator, st | 911 | return lines_iterator, st |
