aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Janda <siffiejoe@gmx.net>2015-01-20 11:35:16 +0100
committerPhilipp Janda <siffiejoe@gmx.net>2015-01-20 11:35:16 +0100
commit866cb79f65c844b3fcfa99d2caa4bf19930dbc6d (patch)
tree338699b9df9b2c99cec053321790e9a5960c4b3b
parente52c3c4e7af665acd23e63fd3ae85f2c8ae87e49 (diff)
downloadlua-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
-rw-r--r--README.md5
-rw-r--r--c-api/compat-5.3.h1
-rw-r--r--compat53.lua318
-rwxr-xr-xtests/test.lua346
4 files changed, 511 insertions, 159 deletions
diff --git a/README.md b/README.md
index 26800e3..c04d2d1 100644
--- a/README.md
+++ b/README.md
@@ -116,6 +116,8 @@ For Lua 5.1 additionally:
116* `luaL_Stream` 116* `luaL_Stream`
117* `LUA_FILEHANDLE` 117* `LUA_FILEHANDLE`
118* `lua_absindex` 118* `lua_absindex`
119* `lua_arith`
120* `lua_compare`
119* `lua_len`, `lua_rawlen`, and `luaL_len` 121* `lua_len`, `lua_rawlen`, and `luaL_len`
120* `lua_copy` 122* `lua_copy`
121* `lua_pushglobaltable` 123* `lua_pushglobaltable`
@@ -141,9 +143,8 @@ For Lua 5.1 additionally:
141* the following C API functions/macros: 143* the following C API functions/macros:
142 * `lua_isyieldable` 144 * `lua_isyieldable`
143 * `lua_getextraspace` 145 * `lua_getextraspace`
144 * `lua_arith` (not at all in 5.1, operators missing in 5.2) 146 * `lua_arith` (new operators missing)
145 * `lua_pushfstring` (new formats) 147 * `lua_pushfstring` (new formats)
146 * `lua_compare` (5.1)
147 * `lua_upvalueid` (5.1) 148 * `lua_upvalueid` (5.1)
148 * `lua_upvaluejoin` (5.1) 149 * `lua_upvaluejoin` (5.1)
149 * `lua_version` (5.1) 150 * `lua_version` (5.1)
diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h
index 3905a10..8f38719 100644
--- a/c-api/compat-5.3.h
+++ b/c-api/compat-5.3.h
@@ -40,6 +40,7 @@
40#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 40#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
41 41
42/* XXX not implemented: 42/* XXX not implemented:
43 * lua_arith (new operators)
43 * lua_upvalueid 44 * lua_upvalueid
44 * lua_upvaluejoin 45 * lua_upvaluejoin
45 * lua_version 46 * lua_version
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
diff --git a/tests/test.lua b/tests/test.lua
index 423fb5b..98259fe 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -1,8 +1,9 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3local F, tproxy, ___ 3local F, tproxy, writefile, noprint, ___
4do 4do
5 local type, unpack = type, table.unpack or unpack 5 local type, unpack = type, table.unpack or unpack
6 local assert, io = assert, io
6 function F(...) 7 function F(...)
7 local args, n = { ... }, select('#', ...) 8 local args, n = { ... }, select('#', ...)
8 for i = 1, n do 9 for i = 1, n do
@@ -20,6 +21,12 @@ do
20 __len = function() return #t end, 21 __len = function() return #t end,
21 }), t 22 }), t
22 end 23 end
24 function writefile(name, contents, bin)
25 local f = assert(io.open(name, bin and "wb" or "w"))
26 f:write(contents)
27 f:close()
28 end
29 function noprint() end
23 local sep = ("="):rep(70) 30 local sep = ("="):rep(70)
24 function ___() 31 function ___()
25 print(sep) 32 print(sep)
@@ -27,6 +34,7 @@ do
27end 34end
28 35
29local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2") 36local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2")
37if jit then V = "jit" end
30 38
31print( "testing Lua API ..." ) 39print( "testing Lua API ..." )
32package.path = "../?.lua;"..package.path 40package.path = "../?.lua;"..package.path
@@ -217,6 +225,342 @@ print("math.ult", pcall(math.ult, 1, 2.1))
217___'' 225___''
218 226
219 227
228print("testing Lua API for Lua 5.1 ...")
229
230___''
231print("debug.getuservalue()", F(debug.getuservalue(false)))
232print("debug.setuservalue()", pcall(function()
233 debug.setuservalue(false, {})
234end))
235print("debug.setmetatable()", F(debug.setmetatable({}, {})))
236
237
238___''
239do
240 local t = setmetatable({}, {
241 __pairs = function() return pairs({ a = "a" }) end,
242 })
243 for k,v in pairs(t) do
244 print("pairs()", k, v)
245 end
246end
247
248
249___''
250do
251 local code = "print('hello world')\n"
252 local badcode = "print('blub\n"
253 print("load()", pcall(function() load(true) end))
254 print("load()", F(load(badcode)))
255 print("load()", F(load(code)))
256 print("load()", F(load(code, "[L]")))
257 print("load()", F(load(code, "[L]", "b")))
258 print("load()", F(load(code, "[L]", "t")))
259 print("load()", F(load(code, "[L]", "bt")))
260 local f = load(code, "[L]", "bt", {})
261 print("load()", pcall(f))
262 f = load(code, "[L]", "bt", { print = noprint })
263 print("load()", pcall(f))
264 local bytecode = string.dump(f)
265 print("load()", F(load(bytecode)))
266 print("load()", F(load(bytecode, "[L]")))
267 print("load()", F(load(bytecode, "[L]", "b")))
268 print("load()", F(load(bytecode, "[L]", "t")))
269 print("load()", F(load(bytecode, "[L]", "bt")))
270 f = load(bytecode, "[L]", "bt", {})
271 print("load()", pcall(f))
272 f = load(bytecode, "[L]", "bt", { print = noprint })
273 print("load()", pcall(f))
274 local function make_loader(code)
275 local mid = math.floor( #code/2 )
276 local array = { code:sub(1, mid), code:sub(mid+1) }
277 local i = 0
278 return function()
279 i = i + 1
280 return array[i]
281 end
282 end
283 print("load()", F(load(make_loader(badcode))))
284 print("load()", F(load(make_loader(code))))
285 print("load()", F(load(make_loader(code), "[L]")))
286 print("load()", F(load(make_loader(code), "[L]", "b")))
287 print("load()", F(load(make_loader(code), "[L]", "t")))
288 print("load()", F(load(make_loader(code), "[L]", "bt")))
289 f = load(make_loader(code), "[L]", "bt", {})
290 print("load()", pcall(f))
291 f = load(make_loader(code), "[L]", "bt", { print = noprint })
292 print("load()", pcall(f))
293 print("load()", F(load(make_loader(bytecode))))
294 print("load()", F(load(make_loader(bytecode), "[L]")))
295 print("load()", F(load(make_loader(bytecode), "[L]", "b")))
296 print("load()", F(load(make_loader(bytecode), "[L]", "t")))
297 print("load()", F(load(make_loader(bytecode), "[L]", "bt")))
298 f = load(make_loader(bytecode), "[L]", "bt", {})
299 print("load()", pcall(f))
300 f = load(make_loader(bytecode), "[L]", "bt", { print = noprint })
301 print("load()", pcall(f))
302 writefile("good.lua", code)
303 writefile("bad.lua", badcode)
304 writefile("good.luac", bytecode, true)
305 print("loadfile()", F(loadfile("bad.lua")))
306 print("loadfile()", F(loadfile("good.lua")))
307 print("loadfile()", F(loadfile("good.lua", "b")))
308 print("loadfile()", F(loadfile("good.lua", "t")))
309 print("loadfile()", F(loadfile("good.lua", "bt")))
310 f = loadfile("good.lua", "bt", {})
311 print("loadfile()", pcall(f))
312 f = loadfile("good.lua", "bt", { print = noprint })
313 print("loadfile()", pcall(f))
314 print("loadfile()", F(loadfile("good.luac")))
315 print("loadfile()", F(loadfile("good.luac", "b")))
316 print("loadfile()", F(loadfile("good.luac", "t")))
317 print("loadfile()", F(loadfile("good.luac", "bt")))
318 f = loadfile("good.luac", "bt", {})
319 print("loadfile()", pcall(f))
320 f = loadfile("good.luac", "bt", { print = noprint })
321 print("loadfile()", pcall(f))
322 os.remove("good.lua")
323 os.remove("bad.lua")
324 os.remove("good.luac")
325end
326
327
328___''
329do
330 local function func(throw)
331 if throw then
332 error("argh")
333 else
334 return 1, 2, 3
335 end
336 end
337 local function tb(err) return "|"..err.."|" end
338 print("xpcall()", xpcall(func, debug.traceback, false))
339 print("xpcall()", xpcall(func, debug.traceback, true))
340 print("xpcall()", xpcall(func, tb, true))
341 local function func2(cb)
342 print("xpcall()", xpcall(cb, debug.traceback, "str"))
343 end
344 local function func3(cb)
345 print("pcall()", pcall(cb, "str"))
346 end
347 local function cb(arg)
348 coroutine.yield(2)
349 return arg
350 end
351 local c = coroutine.wrap(func2)
352 print("xpcall()", c(cb))
353 print("xpcall()", c())
354 local c = coroutine.wrap(func3)
355 print("pcall()", c(cb))
356 print("pcall()", c())
357end
358
359
360___''
361do
362 local t = setmetatable({ 1 }, { __len = function() return 5 end })
363 print("rawlen()", rawlen(t), rawlen("123"))
364end
365
366
367___''
368print("os.execute()", os.execute("exit 1"))
369io.flush()
370print("os.execute()", os.execute("echo 'hello world!'"))
371io.flush()
372print("os.execute()", os.execute("no_such_file"))
373
374
375___''
376do
377 local t = table.pack("a", nil, "b", nil)
378 print("table.(un)pack()", t.n, table.unpack(t, 1, t.n))
379end
380
381
382___''
383do
384 print("coroutine.running()", F(coroutine.wrap(function()
385 return coroutine.running()
386 end)()))
387 print("coroutine.running()", F(coroutine.running()))
388 local main_co, co1, co2 = coroutine.running()
389 -- coroutine.yield
390 print("coroutine.yield()", pcall(function()
391 coroutine.yield(1, 2, 3)
392 end))
393 print("coroutine.yield()", coroutine.wrap(function()
394 coroutine.yield(1, 2, 3)
395 end)())
396 print("coroutine.resume()", coroutine.resume(main_co, 1, 2, 3))
397 co1 = coroutine.create(function(a, b, c)
398 print("coroutine.resume()", a, b, c)
399 return a, b, c
400 end)
401 print("coroutine.resume()", coroutine.resume(co1, 1, 2, 3))
402 co1 = coroutine.create(function()
403 print("coroutine.status()", "[co1] main is", coroutine.status(main_co))
404 print("coroutine.status()", "[co1] co2 is", coroutine.status(co2))
405 end)
406 co2 = coroutine.create(function()
407 print("coroutine.status()", "[co2] main is", coroutine.status(main_co))
408 print("coroutine.status()", "[co2] co2 is", coroutine.status(co2))
409 coroutine.yield()
410 coroutine.resume(co1)
411 end)
412 print("coroutine.status()", coroutine.status(main_co))
413 print("coroutine.status()", coroutine.status(co2))
414 coroutine.resume(co2)
415 print("coroutine.status()", F(coroutine.status(co2)))
416 coroutine.resume(co2)
417 print("coroutine.status()", F(coroutine.status(co2)))
418end
419
420
421___''
422print("math.log()", math.log(1000))
423print("math.log()", math.log(1000, 10))
424
425
426___''
427do
428 local path, prefix = "./?.lua;?/init.lua;../?.lua", "package.searchpath()"
429 print(prefix, package.searchpath("no.such.module", path))
430 print(prefix, package.searchpath("no.such.module", ""))
431 print(prefix, package.searchpath("compat52", path))
432 print(prefix, package.searchpath("no:such:module", path, ":", "|"))
433end
434
435
436___''
437do
438 local function mod_func() return {} end
439 local function my_searcher(name)
440 if name == "my.module" then
441 print("package.searchers", "my.module found")
442 return mod_func
443 end
444 end
445 local function my_searcher2(name)
446 if name == "my.module" then
447 print("package.searchers", "my.module found 2")
448 return mod_func
449 end
450 end
451 table.insert(package.searchers, my_searcher)
452 require("my.module")
453 package.loaded["my.module"] = nil
454 local new_s = { my_searcher2 }
455 for i,f in ipairs(package.searchers) do
456 new_s[i+1] = f
457 end
458 package.searchers = new_s
459 require("my.module")
460end
461
462
463___''
464do
465 print("string.find()", ("abc\0abc\0abc"):find("[^a\0]+"))
466 print("string.find()", ("abc\0abc\0abc"):find("%w+\0", 5))
467 for x in ("abc\0def\0ghi"):gmatch("[^\0]+") do
468 print("string.gmatch()", x)
469 end
470 for x in ("abc\0def\0ghi"):gmatch("%w*\0") do
471 print("string.gmatch()", #x)
472 end
473 print("string.gsub()", ("abc\0def\0ghi"):gsub("[\0]", "X"))
474 print("string.gsub()", ("abc\0def\0ghi"):gsub("%w*\0", "X"))
475 print("string.gsub()", ("abc\0def\0ghi"):gsub("%A", "X"))
476 print("string.match()", ("abc\0abc\0abc"):match("([^\0a]+)"))
477 print("string.match()", #("abc\0abc\0abc"):match(".*\0"))
478 print("string.rep()", string.rep("a", 0))
479 print("string.rep()", string.rep("b", 1))
480 print("string.rep()", string.rep("c", 4))
481 print("string.rep()", string.rep("a", 0, "|"))
482 print("string.rep()", string.rep("b", 1, "|"))
483 print("string.rep()", string.rep("c", 4, "|"))
484 local _tostring = tostring
485 function tostring(v)
486 if type(v) == "number" then
487 return "(".._tostring(v)..")"
488 else
489 return _tostring(v)
490 end
491 end
492 print("string.format()", string.format("%q", "\"\\\0000\0010\r0\n0\t0\""))
493 print("string.format()", string.format("%12.3fx%%sxx%.6s", 3.1, {}))
494 print("string.format()", string.format("%-3f %%%s %%s", 3.1, true))
495 print("string.format()", string.format("% 3.2g %%d %%%s", 3.1, nil))
496 print("string.format()", string.format("%+3d %%d %%%%%10.6s", 3, io.stdout))
497 print("string.format()", pcall(function()
498 print("string.format()", string.format("%d %%s", {}))
499 end))
500 tostring = _tostring
501end
502
503
504___''
505do
506 print("io.write()", io.type(io.write("hello world\n")))
507 local f = assert(io.tmpfile())
508 print("file:write()", io.type(f:write("hello world\n")))
509 f:close()
510end
511
512
513___''
514do
515 writefile("data.txt", "123 18.8 hello world\ni'm here\n")
516 for a,b in io.lines("test.lua", 2, "*l") do
517 print("io.lines()", a, b)
518 break
519 end
520 for l in io.lines("test.lua") do
521 print("io.lines()", l)
522 break
523 end
524 for n1,n2,rest in io.lines("data.txt", "*n", "*n", "*a") do
525 print("io.lines()", n1, n2, rest)
526 end
527 for l in io.lines("data.txt") do
528 print("io.lines()", l)
529 end
530 print("io.lines()", pcall(function()
531 for l in io.lines("data.txt", "*x") do print(l) end
532 end))
533 print("io.lines()", pcall(function()
534 for l in io.lines("no_such_file.txt") do print(l) end
535 end))
536 local f = assert(io.open("test.lua", "r"))
537 for a,b in f:lines(2, "*l") do
538 print("file:lines()", a, b)
539 break
540 end
541 f:close()
542 f = assert(io.open("data.txt", "r"))
543 for n1,n2,rest in f:lines("*n", "*n", "*a") do
544 print("file:lines()", n1, n2, rest)
545 end
546 f:close()
547 f = assert(io.open("data.txt", "r"))
548 for l in f:lines() do
549 print("file:lines()", l)
550 end
551 f:close()
552 print("file:lines()", pcall(function()
553 for l in f:lines() do print(l) end
554 end))
555 print("file:lines()", pcall(function()
556 local f = assert(io.open("data.txt", "r"))
557 for l in f:lines("*l", "*x") do print(l) end
558 f:close()
559 end))
560 os.remove("data.txt")
561end
562___''
563
220 564
221print("testing C API ...") 565print("testing C API ...")
222local mod = require("testmod") 566local mod = require("testmod")