@@ -14,6 +14,8 @@ local visitast = require("prometheus.visitast")
1414local util = require (" prometheus.util" )
1515local logger = require (" logger" )
1616local AstKind = Ast .AstKind
17+ local SAFE_INT_LIMIT = jit and math.huge or 2 ^ 53
18+ local MAX_VAL = jit and math.huge or 2 ^ 54
1719
1820local NumbersToExpressions = Step :extend ()
1921NumbersToExpressions .Description = " This Step Converts number Literals to Expressions"
@@ -37,6 +39,9 @@ NumbersToExpressions.SettingsDescriptor = {
3739 NumberRepresentationMutation = {
3840 type = " boolean" ,
3941 default = false ,
42+
43+ -- NOTE: This alias is a legacy misspelling preservation.
44+ -- Please don't remove it.
4045 aliases = { " NumberRepresentationMutaton" },
4146 },
4247
@@ -92,7 +97,9 @@ function NumbersToExpressions:init(_)
9297 end ,
9398
9499 function (val , depth ) -- Modulo
100+ if val > MAX_VAL then return false end
95101 local lhs , rhs = generateModuloExpression (val )
102+ if lhs > SAFE_INT_LIMIT or rhs > SAFE_INT_LIMIT then return false end
96103 if tonumber (tostring (lhs )) % tonumber (tostring (rhs )) ~= val then
97104 return false
98105 end
@@ -153,7 +160,30 @@ function NumbersToExpressions:CreateNumberExpression(val, depth)
153160
154161 local exp = math.floor (math.log10 (math.abs (val )))
155162 local mantissa = val / (10 ^ exp )
156- return Ast .NumberExpression (string.format (" %.15ge%d" , mantissa , exp ))
163+
164+ -- LuaJIT has full double precision support. Meaning we don't need aggressive safety harnesses for LuaJIT.
165+ if jit then
166+ return Ast .NumberExpression (string.format (" %.15ge%d" , mantissa , exp ))
167+ end
168+
169+ local formatStr = string.format (" %ge%+d" , mantissa , exp )
170+ local concatStr = mantissa .. " e" .. (exp >= 0 and " +" or " " ) .. exp
171+
172+ local formatVal = loadstring (" return " .. formatStr )
173+ local concatVal = loadstring (" return " .. concatStr )
174+
175+ local formatResult = formatVal and formatVal ()
176+ local concatResult = concatVal and concatVal ()
177+
178+ local formatErr = formatResult and math.abs (formatResult - val ) or math.huge
179+ local concatErr = concatResult and math.abs (concatResult - val ) or math.huge
180+
181+ if formatErr > 0 and concatErr > 0 then
182+ return Ast .NumberExpression (val )
183+ end
184+
185+ local useFormat = formatErr <= concatErr
186+ return Ast .NumberExpression (useFormat and formatStr or concatStr )
157187 end
158188
159189 if format == " normal" then
@@ -185,4 +215,4 @@ function NumbersToExpressions:apply(ast)
185215 end )
186216end
187217
188- return NumbersToExpressions
218+ return NumbersToExpressions
0 commit comments