diff options
author | Philipp Janda <siffiejoe@gmx.net> | 2015-04-11 17:09:37 +0200 |
---|---|---|
committer | Philipp Janda <siffiejoe@gmx.net> | 2015-04-11 17:09:37 +0200 |
commit | ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4 (patch) | |
tree | a02b62ce9ad9135dd8dc6aab13940e96ea87dcfe | |
parent | ba8686d6af119fc7ecf734a2d2b6e319c8d74df5 (diff) | |
download | lua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.tar.gz lua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.tar.bz2 lua-compat-5.3-ddeb3f7a1e25667694eaf3c8bf639b66d6809cb4.zip |
split compat53 Lua module into separate modules that do/don't modify the global env
-rw-r--r-- | compat53/base.lua (renamed from compat53.lua) | 305 | ||||
-rw-r--r-- | compat53/init.lua | 103 | ||||
-rw-r--r-- | compat53/module.lua | 37 | ||||
-rwxr-xr-x | tests/test.lua | 2 |
4 files changed, 282 insertions, 165 deletions
diff --git a/compat53.lua b/compat53/base.lua index 84ef101..370909a 100644 --- a/compat53.lua +++ b/compat53/base.lua | |||
@@ -1,8 +1,28 @@ | |||
1 | local _G, _VERSION, setmetatable = _G, _VERSION, setmetatable | ||
1 | local lua_version = _VERSION:sub(-3) | 2 | local lua_version = _VERSION:sub(-3) |
2 | 3 | ||
4 | |||
5 | local M = {} | ||
6 | local M_meta = { | ||
7 | __index = _G | ||
8 | } | ||
9 | setmetatable(M, M_meta) | ||
10 | |||
11 | |||
3 | if lua_version < "5.3" then | 12 | if lua_version < "5.3" then |
4 | -- local aliases for commonly used functions | 13 | |
5 | local type, select, error = type, select, error | 14 | -- cache globals in upvalues |
15 | local error, getmetatable, ipairs, pairs, pcall, require, select, type = | ||
16 | error, getmetatable, ipairs, pairs, pcall, require, select, type | ||
17 | local debug, math, package, string, table = | ||
18 | debug, math, package, string, table | ||
19 | |||
20 | -- create subtables | ||
21 | M.math = setmetatable({}, { __index = math }) | ||
22 | M.string = setmetatable({}, { __index = string }) | ||
23 | M.table = setmetatable({}, { __index = table }) | ||
24 | M.utf8 = {} | ||
25 | |||
6 | 26 | ||
7 | -- select the most powerful getmetatable function available | 27 | -- select the most powerful getmetatable function available |
8 | local gmt = type(debug) == "table" and debug.getmetatable or | 28 | local gmt = type(debug) == "table" and debug.getmetatable or |
@@ -29,11 +49,13 @@ if lua_version < "5.3" then | |||
29 | -- load utf8 library | 49 | -- load utf8 library |
30 | local utf8_ok, utf8lib = pcall(require, "compat53.utf8") | 50 | local utf8_ok, utf8lib = pcall(require, "compat53.utf8") |
31 | if utf8_ok then | 51 | if utf8_ok then |
32 | utf8 = utf8lib | ||
33 | package.loaded["utf8"] = utf8lib | ||
34 | if lua_version == "5.1" then | 52 | if lua_version == "5.1" then |
35 | utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" | 53 | utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" |
36 | end | 54 | end |
55 | for k,v in pairs(utf8lib) do | ||
56 | M.utf8[k] = v | ||
57 | end | ||
58 | package.loaded["utf8"] = M.utf8 | ||
37 | end | 59 | end |
38 | 60 | ||
39 | 61 | ||
@@ -41,7 +63,7 @@ if lua_version < "5.3" then | |||
41 | local table_ok, tablib = pcall(require, "compat53.table") | 63 | local table_ok, tablib = pcall(require, "compat53.table") |
42 | if table_ok then | 64 | if table_ok then |
43 | for k,v in pairs(tablib) do | 65 | for k,v in pairs(tablib) do |
44 | table[k] = v | 66 | M.table[k] = v |
45 | end | 67 | end |
46 | end | 68 | end |
47 | 69 | ||
@@ -50,7 +72,7 @@ if lua_version < "5.3" then | |||
50 | local str_ok, strlib = pcall(require, "compat53.string") | 72 | local str_ok, strlib = pcall(require, "compat53.string") |
51 | if str_ok then | 73 | if str_ok then |
52 | for k,v in pairs(strlib) do | 74 | for k,v in pairs(strlib) do |
53 | string[k] = v | 75 | M.string[k] = v |
54 | end | 76 | end |
55 | end | 77 | end |
56 | 78 | ||
@@ -60,9 +82,9 @@ if lua_version < "5.3" then | |||
60 | if not str_ok then | 82 | if not str_ok then |
61 | local struct_ok, struct = pcall(require, "struct") | 83 | local struct_ok, struct = pcall(require, "struct") |
62 | if struct_ok then | 84 | if struct_ok then |
63 | string.pack = struct.pack | 85 | M.string.pack = struct.pack |
64 | string.packsize = struct.size | 86 | M.string.packsize = struct.size |
65 | string.unpack = struct.unpack | 87 | M.string.unpack = struct.unpack |
66 | end | 88 | end |
67 | end | 89 | end |
68 | 90 | ||
@@ -81,17 +103,17 @@ if lua_version < "5.3" then | |||
81 | maxint = maxint | 103 | maxint = maxint |
82 | minint = -maxint | 104 | minint = -maxint |
83 | end | 105 | end |
84 | math.maxinteger = maxint | 106 | M.math.maxinteger = maxint |
85 | math.mininteger = minint | 107 | M.math.mininteger = minint |
86 | 108 | ||
87 | function math.tointeger(n) | 109 | function M.math.tointeger(n) |
88 | if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then | 110 | if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then |
89 | return n | 111 | return n |
90 | end | 112 | end |
91 | return nil | 113 | return nil |
92 | end | 114 | end |
93 | 115 | ||
94 | function math.type(n) | 116 | function M.math.type(n) |
95 | if type(n) == "number" then | 117 | if type(n) == "number" then |
96 | if n <= maxint and n >= minint and n % 1 == 0 then | 118 | if n <= maxint and n >= minint and n % 1 == 0 then |
97 | return "integer" | 119 | return "integer" |
@@ -116,7 +138,7 @@ if lua_version < "5.3" then | |||
116 | end | 138 | end |
117 | end | 139 | end |
118 | 140 | ||
119 | function math.ult(m, n) | 141 | function M.math.ult(m, n) |
120 | m = checkinteger(m, "1", "math.ult") | 142 | m = checkinteger(m, "1", "math.ult") |
121 | n = checkinteger(n, "2", "math.ult") | 143 | n = checkinteger(n, "2", "math.ult") |
122 | if m >= 0 and n < 0 then | 144 | if m >= 0 and n < 0 then |
@@ -132,7 +154,6 @@ if lua_version < "5.3" then | |||
132 | 154 | ||
133 | -- ipairs should respect __index metamethod | 155 | -- ipairs should respect __index metamethod |
134 | do | 156 | do |
135 | local _ipairs = ipairs | ||
136 | local function ipairs_iterator(st, var) | 157 | local function ipairs_iterator(st, var) |
137 | var = var + 1 | 158 | var = var + 1 |
138 | local val = st[var] | 159 | local val = st[var] |
@@ -140,11 +161,11 @@ if lua_version < "5.3" then | |||
140 | return var, st[var] | 161 | return var, st[var] |
141 | end | 162 | end |
142 | end | 163 | end |
143 | function ipairs(t) | 164 | function M.ipairs(t) |
144 | if gmt(t) ~= nil then -- t has metatable | 165 | if gmt(t) ~= nil then -- t has metatable |
145 | return ipairs_iterator, t, 0 | 166 | return ipairs_iterator, t, 0 |
146 | else | 167 | else |
147 | return _ipairs(t) | 168 | return ipairs(t) |
148 | end | 169 | end |
149 | end | 170 | end |
150 | end | 171 | end |
@@ -153,7 +174,12 @@ if lua_version < "5.3" then | |||
153 | -- update table library (if C module not available) | 174 | -- update table library (if C module not available) |
154 | if not table_ok then | 175 | if not table_ok then |
155 | local table_concat = table.concat | 176 | local table_concat = table.concat |
156 | function table.concat(list, sep, i, j) | 177 | local table_insert = table.insert |
178 | local table_remove = table.remove | ||
179 | local table_sort = table.sort | ||
180 | local table_unpack = lua_version == "5.1" and unpack or table.unpack | ||
181 | |||
182 | function M.table.concat(list, sep, i, j) | ||
157 | local mt = gmt(list) | 183 | local mt = gmt(list) |
158 | if type(mt) == "table" and type(mt.__len) == "function" then | 184 | if type(mt) == "table" and type(mt.__len) == "function" then |
159 | local src = list | 185 | local src = list |
@@ -165,8 +191,7 @@ if lua_version < "5.3" then | |||
165 | return table_concat(list, sep, i, j) | 191 | return table_concat(list, sep, i, j) |
166 | end | 192 | end |
167 | 193 | ||
168 | local table_insert = table.insert | 194 | function M.table.insert(list, ...) |
169 | function table.insert(list, ...) | ||
170 | local mt = gmt(list) | 195 | local mt = gmt(list) |
171 | local has_mt = type(mt) == "table" | 196 | local has_mt = type(mt) == "table" |
172 | local has_len = has_mt and type(mt.__len) == "function" | 197 | local has_len = has_mt and type(mt.__len) == "function" |
@@ -191,7 +216,7 @@ if lua_version < "5.3" then | |||
191 | end | 216 | end |
192 | end | 217 | end |
193 | 218 | ||
194 | function table.move(a1, f, e, t, a2) | 219 | function M.table.move(a1, f, e, t, a2) |
195 | a2 = a2 or a1 | 220 | a2 = a2 or a1 |
196 | f = checkinteger(f, "2", "table.move") | 221 | f = checkinteger(f, "2", "table.move") |
197 | argcheck(f > 0, "2", "table.move", | 222 | argcheck(f > 0, "2", "table.move", |
@@ -208,8 +233,7 @@ if lua_version < "5.3" then | |||
208 | return a2 | 233 | return a2 |
209 | end | 234 | end |
210 | 235 | ||
211 | local table_remove = table.remove | 236 | function M.table.remove(list, pos) |
212 | function table.remove(list, pos) | ||
213 | local mt = gmt(list) | 237 | local mt = gmt(list) |
214 | local has_mt = type(mt) == "table" | 238 | local has_mt = type(mt) == "table" |
215 | local has_len = has_mt and type(mt.__len) == "function" | 239 | local has_len = has_mt and type(mt.__len) == "function" |
@@ -282,8 +306,7 @@ if lua_version < "5.3" then | |||
282 | end | 306 | end |
283 | end | 307 | end |
284 | 308 | ||
285 | local table_sort = table.sort | 309 | function M.table.sort(list, cmp) |
286 | function table.sort(list, cmp) | ||
287 | local mt = gmt(list) | 310 | local mt = gmt(list) |
288 | local has_mt = type(mt) == "table" | 311 | local has_mt = type(mt) == "table" |
289 | local has_len = has_mt and type(mt.__len) == "function" | 312 | local has_len = has_mt and type(mt.__len) == "function" |
@@ -297,7 +320,6 @@ if lua_version < "5.3" then | |||
297 | end | 320 | end |
298 | end | 321 | end |
299 | 322 | ||
300 | local table_unpack = lua_version == "5.1" and unpack or table.unpack | ||
301 | local function unpack_helper(list, i, j, ...) | 323 | local function unpack_helper(list, i, j, ...) |
302 | if j < i then | 324 | if j < i then |
303 | return ... | 325 | return ... |
@@ -305,7 +327,7 @@ if lua_version < "5.3" then | |||
305 | return unpack_helper(list, i, j-1, list[j], ...) | 327 | return unpack_helper(list, i, j-1, list[j], ...) |
306 | end | 328 | end |
307 | end | 329 | end |
308 | function table.unpack(list, i, j) | 330 | function M.table.unpack(list, i, j) |
309 | local mt = gmt(list) | 331 | local mt = gmt(list) |
310 | local has_mt = type(mt) == "table" | 332 | local has_mt = type(mt) == "table" |
311 | local has_len = has_mt and type(mt.__len) == "function" | 333 | local has_len = has_mt and type(mt.__len) == "function" |
@@ -319,7 +341,6 @@ if lua_version < "5.3" then | |||
319 | end -- update table library | 341 | end -- update table library |
320 | 342 | ||
321 | 343 | ||
322 | |||
323 | -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 | 344 | -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 |
324 | if lua_version == "5.1" then | 345 | if lua_version == "5.1" then |
325 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) | 346 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) |
@@ -327,6 +348,35 @@ if lua_version < "5.3" then | |||
327 | local is_luajit52 = is_luajit and | 348 | local is_luajit52 = is_luajit and |
328 | #setmetatable({}, { __len = function() return 1 end }) == 1 | 349 | #setmetatable({}, { __len = function() return 1 end }) == 1 |
329 | 350 | ||
351 | -- cache globals in upvalues | ||
352 | local load, loadfile, loadstring, setfenv, tostring, unpack, xpcall = | ||
353 | load, loadfile, loadstring, setfenv, tostring, unpack, xpcall | ||
354 | local coroutine, io, os = coroutine, io, os | ||
355 | local coroutine_create = coroutine.create | ||
356 | local coroutine_resume = coroutine.resume | ||
357 | local coroutine_running = coroutine.running | ||
358 | local coroutine_status = coroutine.status | ||
359 | local coroutine_yield = coroutine.yield | ||
360 | local io_input = io.input | ||
361 | local io_open = io.open | ||
362 | local io_output = io.output | ||
363 | local io_write = io.write | ||
364 | local math_log = math.log | ||
365 | local os_execute = os.execute | ||
366 | local string_find = string.find | ||
367 | local string_format = string.format | ||
368 | local string_gmatch = string.gmatch | ||
369 | local string_gsub = string.gsub | ||
370 | local string_match = string.match | ||
371 | local string_rep = string.rep | ||
372 | local table_concat = table.concat | ||
373 | |||
374 | -- create subtables | ||
375 | M.coroutine = setmetatable({}, { __index = coroutine }) | ||
376 | M.io = setmetatable({}, { __index = io }) | ||
377 | M.os = setmetatable({}, { __index = os }) | ||
378 | M.package = setmetatable({}, { __index = package }) | ||
379 | |||
330 | 380 | ||
331 | -- table that maps each running coroutine to the coroutine that resumed it | 381 | -- table that maps each running coroutine to the coroutine that resumed it |
332 | -- this is used to build complete tracebacks when "coroutine-friendly" pcall | 382 | -- this is used to build complete tracebacks when "coroutine-friendly" pcall |
@@ -334,15 +384,19 @@ if lua_version < "5.3" then | |||
334 | local pcall_previous = {} | 384 | local pcall_previous = {} |
335 | local pcall_callOf = {} | 385 | local pcall_callOf = {} |
336 | local xpcall_running = {} | 386 | local xpcall_running = {} |
337 | local coroutine_running = coroutine.running | ||
338 | 387 | ||
339 | -- handle debug functions | 388 | -- handle debug functions |
340 | if type(debug) == "table" then | 389 | if type(debug) == "table" then |
390 | local debug_setfenv = debug.setfenv | ||
391 | local debug_getfenv = debug.getfenv | ||
392 | local debug_setmetatable = debug.setmetatable | ||
393 | local debug_getinfo = debug.getinfo | ||
394 | local debug_traceback = debug.traceback | ||
395 | |||
396 | M.debug = setmetatable({}, { __index = debug }) | ||
341 | 397 | ||
342 | if not is_luajit52 then | 398 | if not is_luajit52 then |
343 | local _G, package = _G, package | 399 | function M.debug.setuservalue(obj, value) |
344 | local debug_setfenv = debug.setfenv | ||
345 | function debug.setuservalue(obj, value) | ||
346 | if type(obj) ~= "userdata" then | 400 | if type(obj) ~= "userdata" then |
347 | error("bad argument #1 to 'setuservalue' (userdata expected, got ".. | 401 | error("bad argument #1 to 'setuservalue' (userdata expected, got ".. |
348 | type(obj)..")", 2) | 402 | type(obj)..")", 2) |
@@ -355,8 +409,7 @@ if lua_version < "5.3" then | |||
355 | return debug_setfenv(obj, value) | 409 | return debug_setfenv(obj, value) |
356 | end | 410 | end |
357 | 411 | ||
358 | local debug_getfenv = debug.getfenv | 412 | function M.debug.getuservalue(obj) |
359 | function debug.getuservalue(obj) | ||
360 | if type(obj) ~= "userdata" then | 413 | if type(obj) ~= "userdata" then |
361 | return nil | 414 | return nil |
362 | else | 415 | else |
@@ -368,15 +421,13 @@ if lua_version < "5.3" then | |||
368 | end | 421 | end |
369 | end | 422 | end |
370 | 423 | ||
371 | local debug_setmetatable = debug.setmetatable | 424 | function M.debug.setmetatable(value, tab) |
372 | function debug.setmetatable(value, tab) | ||
373 | debug_setmetatable(value, tab) | 425 | debug_setmetatable(value, tab) |
374 | return value | 426 | return value |
375 | end | 427 | end |
376 | end -- not luajit with compat52 enabled | 428 | end -- not luajit with compat52 enabled |
377 | 429 | ||
378 | if not is_luajit then | 430 | if not is_luajit then |
379 | local debug_getinfo = debug.getinfo | ||
380 | local function calculate_trace_level(co, level) | 431 | local function calculate_trace_level(co, level) |
381 | if level ~= nil then | 432 | if level ~= nil then |
382 | for out = 1, 1/0 do | 433 | for out = 1, 1/0 do |
@@ -395,8 +446,7 @@ if lua_version < "5.3" then | |||
395 | 446 | ||
396 | local stack_pattern = "\nstack traceback:" | 447 | local stack_pattern = "\nstack traceback:" |
397 | local stack_replace = "" | 448 | local stack_replace = "" |
398 | local debug_traceback = debug.traceback | 449 | function M.debug.traceback(co, msg, level) |
399 | function debug.traceback(co, msg, level) | ||
400 | local lvl | 450 | local lvl |
401 | local nilmsg | 451 | local nilmsg |
402 | if type(co) ~= "thread" then | 452 | if type(co) ~= "thread" then |
@@ -471,13 +521,12 @@ if lua_version < "5.3" then | |||
471 | 521 | ||
472 | 522 | ||
473 | if not is_luajit52 then | 523 | if not is_luajit52 then |
474 | local _pairs = pairs | 524 | function M.pairs(t) |
475 | function pairs(t) | ||
476 | local mt = gmt(t) | 525 | local mt = gmt(t) |
477 | if type(mt) == "table" and type(mt.__pairs) == "function" then | 526 | if type(mt) == "table" and type(mt.__pairs) == "function" then |
478 | return mt.__pairs(t) | 527 | return mt.__pairs(t) |
479 | else | 528 | else |
480 | return _pairs(t) | 529 | return pairs(t) |
481 | end | 530 | end |
482 | end | 531 | end |
483 | end | 532 | end |
@@ -497,9 +546,7 @@ if lua_version < "5.3" then | |||
497 | end | 546 | end |
498 | end | 547 | end |
499 | 548 | ||
500 | local setfenv = setfenv | 549 | function M.load(ld, source, mode, env) |
501 | local _load, _loadstring = load, loadstring | ||
502 | function load(ld, source, mode, env) | ||
503 | mode = mode or "bt" | 550 | mode = mode or "bt" |
504 | local chunk, msg | 551 | local chunk, msg |
505 | if type( ld ) == "string" then | 552 | if type( ld ) == "string" then |
@@ -507,7 +554,7 @@ if lua_version < "5.3" then | |||
507 | local merr = check_mode(mode, ld) | 554 | local merr = check_mode(mode, ld) |
508 | if merr then return nil, merr end | 555 | if merr then return nil, merr end |
509 | end | 556 | end |
510 | chunk, msg = _loadstring(ld, source) | 557 | chunk, msg = loadstring(ld, source) |
511 | else | 558 | else |
512 | local ld_type = type(ld) | 559 | local ld_type = type(ld) |
513 | if ld_type ~= "function" then | 560 | if ld_type ~= "function" then |
@@ -527,10 +574,10 @@ if lua_version < "5.3" then | |||
527 | return v | 574 | return v |
528 | end | 575 | end |
529 | end | 576 | end |
530 | chunk, msg = _load(checked_ld, source) | 577 | chunk, msg = load(checked_ld, source) |
531 | if merr then return nil, merr end | 578 | if merr then return nil, merr end |
532 | else | 579 | else |
533 | chunk, msg = _load(ld, source) | 580 | chunk, msg = load(ld, source) |
534 | end | 581 | end |
535 | end | 582 | end |
536 | if not chunk then | 583 | if not chunk then |
@@ -542,11 +589,9 @@ if lua_version < "5.3" then | |||
542 | return chunk | 589 | return chunk |
543 | end | 590 | end |
544 | 591 | ||
545 | loadstring = load | 592 | M.loadstring = load |
546 | 593 | ||
547 | local _loadfile = loadfile | 594 | function M.loadfile(file, mode, env) |
548 | local io_open = io.open | ||
549 | function loadfile(file, mode, env) | ||
550 | mode = mode or "bt" | 595 | mode = mode or "bt" |
551 | if mode ~= "bt" then | 596 | if mode ~= "bt" then |
552 | local f = io_open(file, "rb") | 597 | local f = io_open(file, "rb") |
@@ -559,7 +604,7 @@ if lua_version < "5.3" then | |||
559 | end | 604 | end |
560 | end | 605 | end |
561 | end | 606 | end |
562 | local chunk, msg = _loadfile(file) | 607 | local chunk, msg = loadfile(file) |
563 | if not chunk then | 608 | if not chunk then |
564 | return chunk, msg | 609 | return chunk, msg |
565 | end | 610 | end |
@@ -572,7 +617,7 @@ if lua_version < "5.3" then | |||
572 | 617 | ||
573 | 618 | ||
574 | if not is_luajit52 then | 619 | if not is_luajit52 then |
575 | function rawlen(v) | 620 | function M.rawlen(v) |
576 | local t = type(v) | 621 | local t = type(v) |
577 | if t ~= "string" and t ~= "table" then | 622 | if t ~= "string" and t ~= "table" then |
578 | error("bad argument #1 to 'rawlen' (table or string expected)", 2) | 623 | error("bad argument #1 to 'rawlen' (table or string expected)", 2) |
@@ -583,32 +628,29 @@ if lua_version < "5.3" then | |||
583 | 628 | ||
584 | 629 | ||
585 | if not is_luajit52 then | 630 | if not is_luajit52 then |
586 | local os_execute = os.execute | 631 | function M.os.execute(cmd) |
587 | function os.execute(cmd) | ||
588 | local code = os_execute(cmd) | 632 | local code = os_execute(cmd) |
589 | -- Lua 5.1 does not report exit by signal. | 633 | -- Lua 5.1 does not report exit by signal. |
590 | if code == 0 then | 634 | if code == 0 then |
591 | return true, "exit", code | 635 | return true, "exit", code |
592 | else | 636 | else |
593 | return nil, "exit", code/256 -- only correct on POSIX! | 637 | return nil, "exit", code/256 -- only correct on Linux! |
594 | end | 638 | end |
595 | end | 639 | end |
596 | end | 640 | end |
597 | 641 | ||
598 | 642 | ||
599 | if not table_ok and not is_luajit52 then | 643 | if not table_ok and not is_luajit52 then |
600 | table.pack = function(...) | 644 | M.table.pack = function(...) |
601 | return { n = select('#', ...), ... } | 645 | return { n = select('#', ...), ... } |
602 | end | 646 | end |
603 | end | 647 | end |
604 | 648 | ||
605 | 649 | ||
606 | local main_coroutine = coroutine.create(function() end) | 650 | local main_coroutine = coroutine_create(function() end) |
607 | 651 | ||
608 | local _pcall = pcall | 652 | function M.coroutine.create(func) |
609 | local coroutine_create = coroutine.create | 653 | local success, result = pcall(coroutine_create, func) |
610 | function coroutine.create(func) | ||
611 | local success, result = _pcall(coroutine_create, func) | ||
612 | if not success then | 654 | if not success then |
613 | if type(func) ~= "function" then | 655 | if type(func) ~= "function" then |
614 | error("bad argument #1 (function expected)", 0) | 656 | error("bad argument #1 (function expected)", 0) |
@@ -621,7 +663,7 @@ if lua_version < "5.3" then | |||
621 | local pcall_mainOf = {} | 663 | local pcall_mainOf = {} |
622 | 664 | ||
623 | if not is_luajit52 then | 665 | if not is_luajit52 then |
624 | function coroutine.running() | 666 | function M.coroutine.running() |
625 | local co = coroutine_running() | 667 | local co = coroutine_running() |
626 | if co then | 668 | if co then |
627 | return pcall_mainOf[co] or co, false | 669 | return pcall_mainOf[co] or co, false |
@@ -631,8 +673,7 @@ if lua_version < "5.3" then | |||
631 | end | 673 | end |
632 | end | 674 | end |
633 | 675 | ||
634 | local coroutine_yield = coroutine.yield | 676 | function M.coroutine.yield(...) |
635 | function coroutine.yield(...) | ||
636 | local co, flag = coroutine_running() | 677 | local co, flag = coroutine_running() |
637 | if co and not flag then | 678 | if co and not flag then |
638 | return coroutine_yield(...) | 679 | return coroutine_yield(...) |
@@ -642,8 +683,7 @@ if lua_version < "5.3" then | |||
642 | end | 683 | end |
643 | 684 | ||
644 | if not is_luajit then | 685 | if not is_luajit then |
645 | local coroutine_resume = coroutine.resume | 686 | function M.coroutine.resume(co, ...) |
646 | function coroutine.resume(co, ...) | ||
647 | if co == main_coroutine then | 687 | if co == main_coroutine then |
648 | return false, "cannot resume non-suspended coroutine" | 688 | return false, "cannot resume non-suspended coroutine" |
649 | else | 689 | else |
@@ -651,8 +691,7 @@ if lua_version < "5.3" then | |||
651 | end | 691 | end |
652 | end | 692 | end |
653 | 693 | ||
654 | local coroutine_status = coroutine.status | 694 | function M.coroutine.status(co) |
655 | function coroutine.status(co) | ||
656 | local notmain = coroutine_running() | 695 | local notmain = coroutine_running() |
657 | if co == main_coroutine then | 696 | if co == main_coroutine then |
658 | return notmain and "normal" or "running" | 697 | return notmain and "normal" or "running" |
@@ -683,7 +722,7 @@ if lua_version < "5.3" then | |||
683 | end | 722 | end |
684 | return pcall_results(current, call, coroutine_resume(call, ...)) | 723 | return pcall_results(current, call, coroutine_resume(call, ...)) |
685 | end | 724 | end |
686 | local coroutine_create52 = coroutine.create | 725 | local coroutine_create52 = M.coroutine.create |
687 | local function pcall_coroutine(func) | 726 | local function pcall_coroutine(func) |
688 | if type(func) ~= "function" then | 727 | if type(func) ~= "function" then |
689 | local callable = func | 728 | local callable = func |
@@ -691,32 +730,29 @@ if lua_version < "5.3" then | |||
691 | end | 730 | end |
692 | return coroutine_create52(func) | 731 | return coroutine_create52(func) |
693 | end | 732 | end |
694 | function pcall(func, ...) | 733 | function M.pcall(func, ...) |
695 | local current = coroutine_running() | 734 | local current = coroutine_running() |
696 | if not current then return _pcall(func, ...) end | 735 | if not current then return pcall(func, ...) end |
697 | return pcall_exec(current, pcall_coroutine(func), ...) | 736 | return pcall_exec(current, pcall_coroutine(func), ...) |
698 | end | 737 | end |
699 | 738 | ||
700 | local _tostring = tostring | ||
701 | local function xpcall_catch(current, call, msgh, success, ...) | 739 | local function xpcall_catch(current, call, msgh, success, ...) |
702 | if not success then | 740 | if not success then |
703 | xpcall_running[current] = call | 741 | xpcall_running[current] = call |
704 | local ok, result = _pcall(msgh, ...) | 742 | local ok, result = pcall(msgh, ...) |
705 | xpcall_running[current] = nil | 743 | xpcall_running[current] = nil |
706 | if not ok then | 744 | if not ok then |
707 | return false, "error in error handling (".._tostring(result)..")" | 745 | return false, "error in error handling ("..tostring(result)..")" |
708 | end | 746 | end |
709 | return false, result | 747 | return false, result |
710 | end | 748 | end |
711 | return true, ... | 749 | return true, ... |
712 | end | 750 | end |
713 | local _xpcall = xpcall | 751 | function M.xpcall(f, msgh, ...) |
714 | local _unpack = unpack | ||
715 | function xpcall(f, msgh, ...) | ||
716 | local current = coroutine_running() | 752 | local current = coroutine_running() |
717 | if not current then | 753 | if not current then |
718 | local args, n = { ... }, select('#', ...) | 754 | local args, n = { ... }, select('#', ...) |
719 | return _xpcall(function() return f(_unpack(args, 1, n)) end, msgh) | 755 | return xpcall(function() return f(unpack(args, 1, n)) end, msgh) |
720 | end | 756 | end |
721 | local call = pcall_coroutine(f) | 757 | local call = pcall_coroutine(f) |
722 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) | 758 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) |
@@ -725,8 +761,7 @@ if lua_version < "5.3" then | |||
725 | 761 | ||
726 | 762 | ||
727 | if not is_luajit then | 763 | if not is_luajit then |
728 | local math_log = math.log | 764 | M.math.log = function(x, base) |
729 | math.log = function(x, base) | ||
730 | if base ~= nil then | 765 | if base ~= nil then |
731 | return math_log(x)/math_log(base) | 766 | return math_log(x)/math_log(base) |
732 | else | 767 | else |
@@ -736,11 +771,8 @@ if lua_version < "5.3" then | |||
736 | end | 771 | end |
737 | 772 | ||
738 | 773 | ||
739 | local package = package | ||
740 | if not is_luajit then | 774 | if not is_luajit then |
741 | local io_open = io.open | 775 | function M.package.searchpath(name, path, sep, rep) |
742 | local table_concat = table.concat | ||
743 | function package.searchpath(name, path, sep, rep) | ||
744 | sep = (sep or "."):gsub("(%p)", "%%%1") | 776 | sep = (sep or "."):gsub("(%p)", "%%%1") |
745 | rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") | 777 | rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") |
746 | local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") | 778 | local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") |
@@ -758,48 +790,29 @@ if lua_version < "5.3" then | |||
758 | end | 790 | end |
759 | end | 791 | end |
760 | 792 | ||
761 | local p_index = { searchers = package.loaders } | ||
762 | local rawset = rawset | ||
763 | setmetatable(package, { | ||
764 | __index = p_index, | ||
765 | __newindex = function(p, k, v) | ||
766 | if k == "searchers" then | ||
767 | rawset(p, "loaders", v) | ||
768 | p_index.searchers = v | ||
769 | else | ||
770 | rawset(p, k, v) | ||
771 | end | ||
772 | end | ||
773 | }) | ||
774 | |||
775 | 793 | ||
776 | local string_gsub = string.gsub | ||
777 | local function fix_pattern(pattern) | 794 | local function fix_pattern(pattern) |
778 | return (string_gsub(pattern, "%z", "%%z")) | 795 | return (string_gsub(pattern, "%z", "%%z")) |
779 | end | 796 | end |
780 | 797 | ||
781 | local string_find = string.find | 798 | function M.string.find(s, pattern, ...) |
782 | function string.find(s, pattern, ...) | ||
783 | return string_find(s, fix_pattern(pattern), ...) | 799 | return string_find(s, fix_pattern(pattern), ...) |
784 | end | 800 | end |
785 | 801 | ||
786 | local string_gmatch = string.gmatch | 802 | function M.string.gmatch(s, pattern) |
787 | function string.gmatch(s, pattern) | ||
788 | return string_gmatch(s, fix_pattern(pattern)) | 803 | return string_gmatch(s, fix_pattern(pattern)) |
789 | end | 804 | end |
790 | 805 | ||
791 | function string.gsub(s, pattern, ...) | 806 | function M.string.gsub(s, pattern, ...) |
792 | return string_gsub(s, fix_pattern(pattern), ...) | 807 | return string_gsub(s, fix_pattern(pattern), ...) |
793 | end | 808 | end |
794 | 809 | ||
795 | local string_match = string.match | 810 | function M.string.match(s, pattern, ...) |
796 | function string.match(s, pattern, ...) | ||
797 | return string_match(s, fix_pattern(pattern), ...) | 811 | return string_match(s, fix_pattern(pattern), ...) |
798 | end | 812 | end |
799 | 813 | ||
800 | if not is_luajit then | 814 | if not is_luajit then |
801 | local string_rep = string.rep | 815 | function M.string.rep(s, n, sep) |
802 | function string.rep(s, n, sep) | ||
803 | if sep ~= nil and sep ~= "" and n >= 2 then | 816 | if sep ~= nil and sep ~= "" and n >= 2 then |
804 | return s .. string_rep(sep..s, n-1) | 817 | return s .. string_rep(sep..s, n-1) |
805 | else | 818 | else |
@@ -809,7 +822,6 @@ if lua_version < "5.3" then | |||
809 | end | 822 | end |
810 | 823 | ||
811 | if not is_luajit then | 824 | if not is_luajit then |
812 | local string_format = string.format | ||
813 | do | 825 | do |
814 | local addqt = { | 826 | local addqt = { |
815 | ["\n"] = "\\\n", | 827 | ["\n"] = "\\\n", |
@@ -821,15 +833,14 @@ if lua_version < "5.3" then | |||
821 | return addqt[c] or string_format("\\%03d", c:byte()) | 833 | return addqt[c] or string_format("\\%03d", c:byte()) |
822 | end | 834 | end |
823 | 835 | ||
824 | local _unpack = unpack | 836 | function M.string.format(fmt, ...) |
825 | function string.format(fmt, ...) | ||
826 | local args, n = { ... }, select('#', ...) | 837 | local args, n = { ... }, select('#', ...) |
827 | local i = 0 | 838 | local i = 0 |
828 | local function adjust_fmt(lead, mods, kind) | 839 | local function adjust_fmt(lead, mods, kind) |
829 | if #lead % 2 == 0 then | 840 | if #lead % 2 == 0 then |
830 | i = i + 1 | 841 | i = i + 1 |
831 | if kind == "s" then | 842 | if kind == "s" then |
832 | args[i] = tostring(args[i]) | 843 | args[i] = _G.tostring(args[i]) |
833 | elseif kind == "q" then | 844 | elseif kind == "q" then |
834 | args[i] = '"'..string_gsub(args[i], "[%z%c\\\"\n]", addquoted)..'"' | 845 | args[i] = '"'..string_gsub(args[i], "[%z%c\\\"\n]", addquoted)..'"' |
835 | return lead.."%"..mods.."s" | 846 | return lead.."%"..mods.."s" |
@@ -837,16 +848,13 @@ if lua_version < "5.3" then | |||
837 | end | 848 | end |
838 | end | 849 | end |
839 | fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) | 850 | fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) |
840 | return string_format(fmt, _unpack(args, 1, n)) | 851 | return string_format(fmt, unpack(args, 1, n)) |
841 | end | 852 | end |
842 | end | 853 | end |
843 | end | 854 | end |
844 | 855 | ||
845 | 856 | ||
846 | local io_open = io.open | 857 | function M.io.write(...) |
847 | local io_write = io.write | ||
848 | local io_output = io.output | ||
849 | function io.write(...) | ||
850 | local res, msg, errno = io_write(...) | 858 | local res, msg, errno = io_write(...) |
851 | if res then | 859 | if res then |
852 | return io_output() | 860 | return io_output() |
@@ -856,28 +864,23 @@ if lua_version < "5.3" then | |||
856 | end | 864 | end |
857 | 865 | ||
858 | if not is_luajit then | 866 | if not is_luajit then |
859 | local lines_iterator | 867 | local function helper(st, var_1, ...) |
860 | do | 868 | if var_1 == nil then |
861 | local function helper( st, var_1, ... ) | 869 | if st.doclose then st.f:close() end |
862 | if var_1 == nil then | 870 | if (...) ~= nil then |
863 | if st.doclose then st.f:close() end | 871 | error((...), 2) |
864 | if (...) ~= nil then | ||
865 | error((...), 2) | ||
866 | end | ||
867 | end | 872 | end |
868 | return var_1, ... | ||
869 | end | 873 | end |
874 | return var_1, ... | ||
875 | end | ||
870 | 876 | ||
871 | local _unpack = unpack | 877 | local function lines_iterator(st) |
872 | function lines_iterator(st) | 878 | return helper(st, st.f:read(unpack(st, 1, st.n))) |
873 | return helper(st, st.f:read(_unpack(st, 1, st.n))) | ||
874 | end | ||
875 | end | 879 | end |
876 | 880 | ||
877 | local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true } | 881 | local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true } |
878 | 882 | ||
879 | local io_input = io.input | 883 | function M.io.lines(fname, ...) |
880 | function io.lines(fname, ...) | ||
881 | local doclose, file, msg | 884 | local doclose, file, msg |
882 | if fname ~= nil then | 885 | if fname ~= nil then |
883 | doclose, file, msg = true, io_open(fname, "r") | 886 | doclose, file, msg = true, io_open(fname, "r") |
@@ -893,36 +896,6 @@ if lua_version < "5.3" then | |||
893 | end | 896 | end |
894 | return lines_iterator, st | 897 | return lines_iterator, st |
895 | end | 898 | end |
896 | |||
897 | do | ||
898 | local io_stdout = io.stdout | ||
899 | local io_type = io.type | ||
900 | local file_meta = gmt(io_stdout) | ||
901 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then | ||
902 | local file_write = file_meta.__index.write | ||
903 | file_meta.__index.write = function(self, ...) | ||
904 | local res, msg, errno = file_write(self, ...) | ||
905 | if res then | ||
906 | return self | ||
907 | else | ||
908 | return nil, msg, errno | ||
909 | end | ||
910 | end | ||
911 | |||
912 | file_meta.__index.lines = function(self, ...) | ||
913 | if io_type(self) == "closed file" then | ||
914 | error("attempt to use a closed file", 2) | ||
915 | end | ||
916 | local st = { f=self, doclose=false, n=select('#', ...), ... } | ||
917 | for i = 1, st.n do | ||
918 | if type(st[i]) ~= "number" and not valid_format[st[i]] then | ||
919 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) | ||
920 | end | ||
921 | end | ||
922 | return lines_iterator, st | ||
923 | end | ||
924 | end | ||
925 | end | ||
926 | end -- not luajit | 899 | end -- not luajit |
927 | 900 | ||
928 | 901 | ||
@@ -930,4 +903,8 @@ if lua_version < "5.3" then | |||
930 | 903 | ||
931 | end -- lua < 5.3 | 904 | end -- lua < 5.3 |
932 | 905 | ||
906 | |||
907 | -- return module table | ||
908 | return M | ||
909 | |||
933 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : | 910 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : |
diff --git a/compat53/init.lua b/compat53/init.lua new file mode 100644 index 0000000..cdd5f34 --- /dev/null +++ b/compat53/init.lua | |||
@@ -0,0 +1,103 @@ | |||
1 | local _G, _VERSION, type, pairs, require = | ||
2 | _G, _VERSION, type, pairs, require | ||
3 | |||
4 | local M = require("compat53.base") | ||
5 | local lua_version = _VERSION:sub(-3) | ||
6 | |||
7 | |||
8 | -- apply other global effects | ||
9 | if lua_version == "5.1" then | ||
10 | |||
11 | -- cache globals | ||
12 | local error, rawset, select, setmetatable, type, unpack = | ||
13 | error, rawset, select, setmetatable, type, unpack | ||
14 | local debug, io, package, string = debug, io, package, string | ||
15 | local io_type, io_stdout = io.type, io.stdout | ||
16 | |||
17 | -- select the most powerful getmetatable function available | ||
18 | local gmt = type(debug) == "table" and debug.getmetatable or | ||
19 | getmetatable or function() return false end | ||
20 | |||
21 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) | ||
22 | local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" | ||
23 | |||
24 | |||
25 | -- make package.searchers available as an alias for package.loaders | ||
26 | local p_index = { searchers = package.loaders } | ||
27 | setmetatable(package, { | ||
28 | __index = p_index, | ||
29 | __newindex = function(p, k, v) | ||
30 | if k == "searchers" then | ||
31 | rawset(p, "loaders", v) | ||
32 | p_index.searchers = v | ||
33 | else | ||
34 | rawset(p, k, v) | ||
35 | end | ||
36 | end | ||
37 | }) | ||
38 | |||
39 | |||
40 | if not is_luajit then | ||
41 | local function helper(st, var_1, ...) | ||
42 | if var_1 == nil then | ||
43 | if (...) ~= nil then | ||
44 | error((...), 2) | ||
45 | end | ||
46 | end | ||
47 | return var_1, ... | ||
48 | end | ||
49 | |||
50 | local function lines_iterator(st) | ||
51 | return helper(st, st.f:read(unpack(st, 1, st.n))) | ||
52 | end | ||
53 | |||
54 | local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true } | ||
55 | |||
56 | local file_meta = gmt(io_stdout) | ||
57 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then | ||
58 | local file_write = file_meta.__index.write | ||
59 | file_meta.__index.write = function(self, ...) | ||
60 | local res, msg, errno = file_write(self, ...) | ||
61 | if res then | ||
62 | return self | ||
63 | else | ||
64 | return nil, msg, errno | ||
65 | end | ||
66 | end | ||
67 | |||
68 | file_meta.__index.lines = function(self, ...) | ||
69 | if io_type(self) == "closed file" then | ||
70 | error("attempt to use a closed file", 2) | ||
71 | end | ||
72 | local st = { f=self, n=select('#', ...), ... } | ||
73 | for i = 1, st.n do | ||
74 | if type(st[i]) ~= "number" and not valid_format[st[i]] then | ||
75 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) | ||
76 | end | ||
77 | end | ||
78 | return lines_iterator, st | ||
79 | end | ||
80 | end | ||
81 | end -- not luajit | ||
82 | |||
83 | end -- lua == 5.1 | ||
84 | |||
85 | |||
86 | -- handle exporting to global scope | ||
87 | local function extend_table(from, to) | ||
88 | for k,v in pairs(from) do | ||
89 | if type(v) == "table" and | ||
90 | type(to[k]) == "table" and | ||
91 | v ~= to[k] then | ||
92 | extend_table(v, to[k]) | ||
93 | else | ||
94 | to[k] = v | ||
95 | end | ||
96 | end | ||
97 | end | ||
98 | |||
99 | extend_table(M, _G) | ||
100 | |||
101 | return _G | ||
102 | |||
103 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : | ||
diff --git a/compat53/module.lua b/compat53/module.lua new file mode 100644 index 0000000..f6fd1f7 --- /dev/null +++ b/compat53/module.lua | |||
@@ -0,0 +1,37 @@ | |||
1 | local _G, _VERSION, debug, error, require, setfenv, setmetatable = | ||
2 | _G, _VERSION, debug, error, require, setfenv, setmetatable | ||
3 | local lua_version = _VERSION:sub(-3) | ||
4 | local M = require("compat53.base") | ||
5 | |||
6 | local function findmain() | ||
7 | local i = 3 | ||
8 | local info = debug.getinfo(i, "fS") | ||
9 | while info do | ||
10 | if info.what == "main" then | ||
11 | return info.func | ||
12 | end | ||
13 | i = i + 1 | ||
14 | info = debug.getinfo(i, "fS") | ||
15 | end | ||
16 | end | ||
17 | |||
18 | local main = findmain() | ||
19 | if not main then | ||
20 | error("must require 'compat53.module' from Lua") | ||
21 | end | ||
22 | local env = setmetatable({}, { | ||
23 | __index = M, | ||
24 | __newindex = _G, | ||
25 | }) | ||
26 | if lua_version == "5.1" then | ||
27 | setfenv(main, env) | ||
28 | elseif lua_version == "5.2" or lua_version == "5.3" then | ||
29 | debug.setupvalue(main, 1, env) | ||
30 | else | ||
31 | error("unsupported Lua version") | ||
32 | end | ||
33 | |||
34 | -- return false to force reevaluation on next require | ||
35 | return false | ||
36 | |||
37 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : | ||
diff --git a/tests/test.lua b/tests/test.lua index 83e174e..664cfa6 100755 --- a/tests/test.lua +++ b/tests/test.lua | |||
@@ -37,7 +37,7 @@ local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2") | |||
37 | if jit then V = "jit" end | 37 | if jit then V = "jit" end |
38 | 38 | ||
39 | print( "testing Lua API ..." ) | 39 | print( "testing Lua API ..." ) |
40 | package.path = "../?.lua;"..package.path | 40 | package.path = "../?.lua;../?/init.lua;"..package.path |
41 | package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll" | 41 | package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll" |
42 | require("compat53") | 42 | require("compat53") |
43 | 43 | ||