Attempt to index a number value (local 'p')
I've been using LuaX, and I seem to have encountered an issue with the standard library. I don't anything wrong with my function. Using normal Lua, as you can see here on TIO, executes the function perfectly fine. This is LuaX via ypp, if that helps things.
Error trace:
$luax:libluax/fs/fs.lua:48: error: attempt to index a number value (local 'p')
/home/stag/ghq/github.com/stag-enterprises/assets/mod.lua:24:
19 | end
20 |
21 | function format_mode(mode)
22 | local str = ""
23 | for i = 8, 0, -1 do
24 => local bit = math.floor(mode / 2 ^ i) % 2 == 1
25 | if i % 3 == 2 then
26 | str = str .. (bit and "r" or "-")
27 | elseif i % 3 == 1 then
28 | str = str .. (bit and "w" or "-")
29 | else
/home/stag/ghq/github.com/stag-enterprises/assets/mod.lua:43:
38 | data.context = "/" .. data.context .. "/"
39 |
40 | for i = 1, #data.dirs do
41 | data.dirs[i].modified = os.date("%Y-%m-%d %H:%M:%S", data.dirs[i].modified)
42 | data.dirs[i].accessed = os.date("%Y-%m-%d %H:%M:%S", data.dirs[i].accessed)
43 => data.dirs[i].mode = format_mode(data.dirs[i].mode)
44 | end
45 |
46 | for i = 1, #data.files do
47 | data.files[i].modified = os.date("%Y-%m-%d %H:%M:%S", data.files[i].modified)
48 | data.files[i].accessed = os.date("%Y-%m-%d %H:%M:%S", data.files[i].accessed)
[string "..."]:2:
1 |
2 => mod = require "mod"
3 | each, data = mod.each, mod.data
The offending function:
function format_mode(mode)
local str = ""
for i = 8, 0, -1 do
local bit = math.floor(mode / 2 ^ i) % 2 == 1
if i % 3 == 2 then
str = str .. (bit and "r" or "-")
elseif i % 3 == 1 then
str = str .. (bit and "w" or "-")
else
str = str .. (bit and "x" or "-")
end
end
return str
end
LuaX redefines the / operator to build path, using the right path separator according to the OS (/ or \\).
I guess your function receives a string (containing a number) instead of a number and fs.join can not make a path with mode and 2^i since the second argument is not a string.
In this case, an explicit conversion should help (mode = tonumber(mode)).
When I wrote this operator (which is clearly not a division) I made the assumption that arithmetic operators are not used on strings (which is obviously not the case).
I would suggest not to use arithmetic operations on string since not all of them will convert string to numbers (+, / will, <, <= won't, e.g. "1" > "010" is true and "1"+0 > "010"+0 is false !)
Your code assumes mode is in base 8, so the fix is mode = tonumber(mode, 8).
If you can use bit operations, you ca also simplify your function. E.g.:
function format_mode(mode)
mode = tonumber(mode, 8)
local m = {[2]="r", [1]="w", [0]="x"}
local str = ""
for i = 0, 8 do
str = (mode&(1<<i) ~= 0 and m[i%3] or "-") .. str
end
return str
end
print(format_mode("755")) -- prints "rwxr-xr-x"