Skip to content

Commit

Permalink
fix(pretty): update integer check for Lua5.4 (#456)
Browse files Browse the repository at this point in the history
  • Loading branch information
sadSader authored Sep 21, 2023
1 parent 3bf0326 commit dc6d19c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
40 changes: 38 additions & 2 deletions lua/pl/pretty.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,42 @@ local assert_arg = utils.assert_arg

local original_tostring = tostring

-- Calculate min and max integer supported by lua_Number
-- Assumptions:
-- 1. max_int = 2 ^ n - 1
-- 2. min_int = -max_int
-- 3. if n > max_int versions with integer support will have
-- integer overflow and versions without integers will lose least significant bit
-- Note: if lua_Integer is smaller than lua_Number mantissa string.format('%d')
-- can throw runtime error
local max_int, min_int
local next_cand = 1
while next_cand > 0 and next_cand % 2 == 1 do
max_int = next_cand
min_int = -next_cand
next_cand = next_cand * 2 + 1
end

local function is_integer(value)
if _VERSION == "Lua 5.3" or _VERSION == "Lua 5.4" then
return mtype(value) == "integer"
end
if value < min_int or value > max_int then
return false
end
return math.floor(value) == value
end

local function is_float(value)
if _VERSION == "Lua 5.3" or _VERSION == "Lua 5.4" then
return mtype(value) == "float"
end
if value < min_int or value > max_int then
return true
end
return mfloor(value) == value
end

-- Patch tostring to format numbers with better precision
-- and to produce cross-platform results for
-- infinite values and NaN.
Expand All @@ -29,11 +65,11 @@ local function tostring(value)
return "Inf"
elseif value == -mhuge then
return "-Inf"
elseif (_VERSION ~= "Lua 5.3" or mtype(value) == "integer") and mfloor(value) == value then
elseif is_integer(value) then
return ("%d"):format(value)
else
local res = ("%.14g"):format(value)
if _VERSION == "Lua 5.3" and mtype(value) == "float" and not res:find("%.") then
if is_float(value) and not res:find("%.") then
-- Number is internally a float but looks like an integer.
-- Insert ".0" after first run of digits.
res = res:gsub("%d+", "%0.0", 1)
Expand Down
17 changes: 16 additions & 1 deletion tests/test-pretty.lua
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ asserteq( pretty.write(t1,""), [[{1,["false"]="untrue",["true"]="boolean",a="a",
-- Check number formatting
asserteq(pretty.write({1/0, -1/0, 0/0, 1, 1/2}, ""), "{Inf,-Inf,NaN,1,0.5}")

if _VERSION == "Lua 5.3" then
if _VERSION == "Lua 5.3" or _VERSION == "Lua 5.4" then
asserteq(pretty.write({1.0}, ""), "{1.0}")
else
asserteq(pretty.write({1.0}, ""), "{1}")
Expand All @@ -105,6 +105,21 @@ do -- issue #203, item 3
end


do
local float = 1e100
local max_int = 9007199254740991 -- 1 << 53 - 1
local min_int = -9007199254740991

asserteq(pretty.write(float), "1.0e+100")
if _VERSION == "Lua 5.3" or _VERSION == "Lua 5.4" then
--There is no way to portably format with %d before 5.3
asserteq(pretty.write(min_int - 3), "-9007199254740994")
asserteq(pretty.write(max_int + 3), "9007199254740994")
asserteq(pretty.write(min_int), "-9007199254740991")
asserteq(pretty.write(max_int), "9007199254740991")
end
end

-- pretty.write fails if an __index metatable raises an error #257
-- only applies to 5.3+ where iterators respect metamethods
do
Expand Down

0 comments on commit dc6d19c

Please sign in to comment.