1
0

Improved compatibility with PUC Lua 5.1 - 5.3

This commit is contained in:
Jon Michael Aanes 2017-01-05 15:50:44 +01:00
parent a333bb2b36
commit b405afeae8
4 changed files with 126 additions and 35 deletions

View File

@ -192,6 +192,8 @@ local function escape_string (str)
end end
local function get_function_info (f) local function get_function_info (f)
-- NOTE: Functions best in LuaJIT or Lua 5.2+
-- Regarding get-info: -- Regarding get-info:
-- * No need to includ 'f'. Function is already known -- * No need to includ 'f'. Function is already known
-- * No need to include 'L' (active lines) option. Ignored -- * No need to include 'L' (active lines) option. Ignored
@ -199,11 +201,19 @@ local function get_function_info (f)
local info = debug.getinfo(f, 'Su') local info = debug.getinfo(f, 'Su')
info.params = {} info.params = {}
info.ups = {} info.ups = {}
info.env = debug.getfenv(f) info.env = debug.getfenv and debug.getfenv(f)
info.builtin = info.source == '=[C]' info.builtin = info.source == '=[C]'
for i = 1, info.nparams do info.params[i] = debug.getlocal(f, i) end for i = 1, info.nparams or 0 do info.params[i] = debug.getlocal(f, i) end
if info.isvararg then info.params[#info.params+1] = '...' end if info.isvararg or not info.nparams then info.params[#info.params+1] = '...' end
for i = 1, info.nups do local k, v = debug.getupvalue(f, i); info.ups[k] = v end -- Get upvalues
for i = 1, info.nups do
local k, v = debug.getupvalue(f, i)
if k == '_ENV' and not debug.getfenv then
info.env = v
else
info.ups[k] = v
end
end
if info.source:sub(1,1) == '=' then info.defined_how = 'C' if info.source:sub(1,1) == '=' then info.defined_how = 'C'
elseif info.source:sub(1,1) == '@' then info.defined_how = 'file' elseif info.source:sub(1,1) == '@' then info.defined_how = 'file'
@ -361,7 +371,7 @@ local function format_key_and_value_string_map (l, key, value, options, depth)
l[#l+1] = key l[#l+1] = key
l[#l+1] = { #key, 'key' } l[#l+1] = { #key, 'key' }
l[#l+1] = ' = ' l[#l+1] = ' = '
format_value(value, options, depth, l) return format_value(value, options, depth, l)
end end
local function format_key_and_value_arbitr_map (l, key, value, options, depth) local function format_key_and_value_arbitr_map (l, key, value, options, depth)
@ -371,11 +381,11 @@ local function format_key_and_value_arbitr_map (l, key, value, options, depth)
l[#l+1] = ']' l[#l+1] = ']'
l[#l+1] = { width_of_strings_in_l(l, index_before_key), 'key' } l[#l+1] = { width_of_strings_in_l(l, index_before_key), 'key' }
l[#l+1] = ' = ' l[#l+1] = ' = '
format_value(value, options, depth, l) return format_value(value, options, depth, l)
end end
local function format_key_and_value_sequence (l, key, value, options, depth) local function format_key_and_value_sequence (l, key, value, options, depth)
format_value(value, options, depth, l) return format_value(value, options, depth, l)
end end
local TABLE_TYPE_TO_PAIR_FORMAT = { local TABLE_TYPE_TO_PAIR_FORMAT = {

View File

@ -57,6 +57,27 @@ local function find_cutoff_index_for_traceback_string (str)
return index return index
end end
--------------------------------------------------------------------------------
-- Lua 5.2 compat
if not setfenv then -- Lua 5.2
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
-- this assumes f is a function
local function findenv(f)
local level = 1
repeat
local name, value = debug.getupvalue(f, level)
if name == '_ENV' then return level, value end
level = level + 1
until name == nil
return nil end
getfenv = function (f) return(select(2, findenv(f)) or _G) end
setfenv = function (f, t)
local level = findenv(f)
if level then debug.setupvalue(f, level, t) end
return f end
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local TestSuite = {} local TestSuite = {}

View File

@ -12,8 +12,19 @@ Approximate strings not similar enough:
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Lua 5.1 compat:
local HAS_ADV_GETLOCAL = not not debug.getinfo(1, 'u').nparams
-- Lua 5.3 compat:
if not loadstring then
loadstring = load
end
local function format_test (t) local function format_test (t)
if t.longterm then return end if t.longterm then return end
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
SUITE:addTest(t.expect, function () SUITE:addTest(t.expect, function ()
local input_value = t.input local input_value = t.input
local input_options = t.options local input_options = t.options
@ -175,26 +186,31 @@ format_test {
-- Function printing -- Function printing
format_test { format_test {
adv_getlocal = true,
input = function () end, input = function () end,
expect = 'function () ... end', expect = 'function () ... end',
} }
format_test { format_test {
adv_getlocal = true,
input = function (a) end, input = function (a) end,
expect = 'function (a) ... end', expect = 'function (a) ... end',
} }
format_test { format_test {
adv_getlocal = true,
input = function (a, b) end, input = function (a, b) end,
expect = 'function (a, b) ... end', expect = 'function (a, b) ... end',
} }
format_test { format_test {
adv_getlocal = true,
input = function (...) end, input = function (...) end,
expect = 'function (...) ... end', expect = 'function (...) ... end',
} }
format_test { format_test {
adv_getlocal = true,
input = function (a, b, ...) end, input = function (a, b, ...) end,
expect = 'function (a, b, ...) ... end', expect = 'function (a, b, ...) ... end',
} }
@ -203,72 +219,86 @@ do
local SOME_RANDOM_UPVALUE = false local SOME_RANDOM_UPVALUE = false
format_test { format_test {
adv_getlocal = true,
input = function () l = SOME_RANDOM_UPVALUE end, input = function () l = SOME_RANDOM_UPVALUE end,
expect = 'function () ... end', expect = 'function () ... end',
} }
format_test { format_test {
adv_getlocal = true,
input = function () SOME_RANDOM_UPVALUE = true end, input = function () SOME_RANDOM_UPVALUE = true end,
expect = 'function () ... end', expect = 'function () ... end',
} }
format_test { format_test {
-- More function info is ignored if not at depth 0. -- More function info is ignored if not at depth 0.
adv_getlocal = true,
input = { a = function () SOME_RANDOM_UPVALUE = true end }, input = { a = function () SOME_RANDOM_UPVALUE = true end },
options = { more_function_info = true }, options = { more_function_info = true },
expect = '{\n\ta = function () ... end\n}', expect = '{\n\ta = function () ... end\n}',
} }
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test { format_test {
input = function () l = SOME_RANDOM_UPVALUE end, input = function () l = SOME_RANDOM_UPVALUE end,
adv_getlocal = true,
options = { more_function_info = true }, options = { more_function_info = true },
-- TODO: Make this more general, such that it won't fail when adding more tests above it. expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: 223]\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
} }
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test { format_test {
input = function () SOME_RANDOM_UPVALUE = true end, input = function () SOME_RANDOM_UPVALUE = true end,
adv_getlocal = true,
options = { more_function_info = true }, options = { more_function_info = true },
-- TODO: Make this more general, such that it won't fail when adding more tests above it. expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: 230]\n\t-- up_values: { SOME_RANDOM_UPVALUE = false }\n\n\t...\nend'
} }
end end
format_test { do
input = function () end, local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
options = { more_function_info = true }, format_test {
-- TODO: Make this more general, such that it won't fail when adding more tests above it. input = function () end,
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: 238]\n\n\t...\nend' adv_getlocal = true,
} options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend'
}
end
do do
local index = 0 local index = 0
format_test { format_test {
input = function () index = index + 1; return index end, input = function () index = index + 1; return index end,
adv_getlocal = true,
expect = 'function () ... end' expect = 'function () ... end'
} }
local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
format_test { format_test {
input = function () index = index + 1; return index end, input = function () index = index + 1; return index end,
adv_getlocal = true,
options = { more_function_info = true }, options = { more_function_info = true },
-- TODO: Make this more general, such that it won't fail when adding more tests above it. expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\t-- up_values: { index = 0 }\n\n\t...\nend'
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: 253]\n\t-- up_values: { index = 0 }\n\n\t...\nend'
} }
end end
format_test { format_test {
adv_getlocal = true,
input = loadstring('return function () end')(), input = loadstring('return function () end')(),
expect = 'function () end', expect = 'function () end',
} }
format_test { format_test {
adv_getlocal = true,
input = loadstring('return function () return function () end end')(), input = loadstring('return function () return function () end end')(),
expect = 'function () return function () end end', expect = 'function () return function () end end',
} }
format_test { format_test {
longterm = true, longterm = true,
adv_getlocal = true,
input = loadstring('return function () return function () end\nend')()(), input = loadstring('return function () return function () end\nend')()(),
expect = 'function () end', expect = 'function () end',
} }
@ -276,6 +306,7 @@ format_test {
format_test { format_test {
-- NOTE: This is HARD to fix. It's thus longerterm -- NOTE: This is HARD to fix. It's thus longerterm
longterm = true, longterm = true,
adv_getlocal = true,
input = loadstring('return function () return function () end end')()(), input = loadstring('return function () return function () end end')()(),
expect = 'function () end', expect = 'function () end',
} }
@ -294,21 +325,25 @@ format_test {
expect = 'function (a, b)\n\treturn a + b\nend', expect = 'function (a, b)\n\treturn a + b\nend',
} }
format_test { do
input = function () local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
-- NOTE: This function must cover 3 lines of code! format_test {
end, input = function ()
options = { more_function_info = true }, -- NOTE: This function must cover 3 lines of code!
-- TODO: Make this more general, such that it won't fail when adding more tests above it. end,
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Lines: 298 - 300]\n\n\t...\nend', adv_getlocal = true,
} options = { more_function_info = true },
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Lines: '..func_line..' - '..(func_line+2)..']\n\n\t...\nend',
}
format_test { local func_line = debug.getinfo(1).currentline + 2 -- Must be exactly 2 lines above function
input = function () --[[ NOTE: This function must cover a single line of code! ]] end, format_test {
options = { more_function_info = true }, input = function () --[[ NOTE: This function must cover a single line of code! ]] end,
-- TODO: Make this more general, such that it won't fail when adding more tests above it. adv_getlocal = true,
expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: 307]\n\n\t...\nend', options = { more_function_info = true },
} expect = 'function ()\n\t-- source_file: \'./test/test_pretty.lua\' [Line: '..func_line..']\n\n\t...\nend',
}
end
format_test { format_test {
input = math.abs, input = math.abs,
@ -348,12 +383,14 @@ format_test {
format_test { format_test {
-- The function part should align, if some are builtin and some are not. -- The function part should align, if some are builtin and some are not.
adv_getlocal = true,
input = { random = math.random, abs = function (x) return x < 0 and -x or x end }, input = { random = math.random, abs = function (x) return x < 0 and -x or x end },
expect = '{\n\tabs = function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}', expect = '{\n\tabs = function (x) ... end,\n\trandom = builtin function ([m [, n]) ... end\n}',
} }
format_test { format_test {
-- No special indent if no special function modifier. -- No special indent if no special function modifier.
adv_getlocal = true,
input = { max = function(a, b) return a > b and a or b end, input = { max = function(a, b) return a > b and a or b end,
abs = function (x) return x < 0 and -x or x end abs = function (x) return x < 0 and -x or x end
}, },

View File

@ -1,7 +1,30 @@
--------------------------------------------------------------------------------
-- Lua 5.2 compat
if not setfenv then -- Lua 5.2
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
-- this assumes f is a function
local function findenv(f)
local level = 1
repeat
local name, value = debug.getupvalue(f, level)
if name == '_ENV' then return level, value end
level = level + 1
until name == nil
return nil end
getfenv = function (f) return(select(2, findenv(f)) or _G) end
setfenv = function (f, t)
local level = findenv(f)
if level then debug.setupvalue(f, level, t) end
return f end
end
--------------------------------------------------------------------------------
local SUITE = require('TestSuite').new('resilience') local SUITE = require('TestSuite').new('resilience')
SUITE:setEnviroment{ SUITE:setEnviroment{
--format = require('pretty') setfenv = setfenv
} }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------