minetest-i4/src/preprocessor.lua

91 lines
1.9 KiB
Lua
Raw Normal View History

2021-11-29 13:41:33 -06:00
--[[ All source files have to be preprocessed before loading.
This allows implementing custom operators like bitwise ones. ]]
2021-11-30 11:39:35 -06:00
local fmt, split = string.format, string.split
2021-11-28 19:47:36 -06:00
local var = "[%w%.%[%]\"\'_]"
2022-06-22 18:14:45 -05:00
local modpath = core.get_modpath"i3"
local _,_, fs_elements = dofile(modpath .. "/src/styles.lua")
2021-11-28 16:55:11 -06:00
local operators = {
["([%+%-%*%^/&|])="] = function(a, b, c)
return fmt("%s = %s %s %s", a, a, b, c)
end,
["+%+"] = function(a, b)
return fmt("%s = %s + 1\n%s", a, a, b)
end,
["&"] = function(a, b)
return fmt("bit.band(%s, %s)", a, b)
end,
["|"] = function(a, b)
return fmt("bit.bor(%s, %s)", a, b)
end,
["<<"] = function(a, b)
return fmt("bit.lshift(%s, %s)", a, b)
end,
[">>"] = function(a, b)
return fmt("bit.rshift(%s, %s)", a, b)
end,
2021-11-28 19:47:36 -06:00
["<<="] = function(a, b)
return fmt("%s = bit.lshift(%s, %s)", a, a, b)
end,
[">>="] = function(a, b)
return fmt("%s = bit.rshift(%s, %s)", a, a, b)
end,
2021-11-28 16:55:11 -06:00
}
local function compile(data)
2021-11-29 12:15:14 -06:00
data = data:gsub("IMPORT%((.-)%)", function(a)
return "local " .. a:gsub("\"", "") .. " = i3.get(" .. a .. ")"
end)
2022-06-22 18:14:45 -05:00
data = data:gsub("([%w_]+)%(", function(a)
if fs_elements[a] then
return fmt("fs('%s',", a)
end
end)
2021-11-28 16:55:11 -06:00
for op, func in pairs(operators) do
data = data:gsub("(" .. var .. "+)%s?" .. op .. "%s?(" .. var .. "*)", func)
end
return data
end
2021-11-29 08:51:12 -06:00
local function _load(path, line, data, t)
2021-11-28 16:55:11 -06:00
if line then
2021-11-29 08:51:12 -06:00
if not t then
2021-11-30 11:39:35 -06:00
t = split(data, "\n")
2021-11-29 08:51:12 -06:00
end
t[line] = t[line]:gsub("(" .. var .. "+)%s?=%s?(" .. var .. "*)", "%2")
data = table.concat(t, "\n")
2021-11-28 16:55:11 -06:00
else
local file = assert(io.open(path, "r"))
data = file:read"*a"
file:close()
data = compile(data)
end
local l, err = loadstring(data)
if not l then
local err_line = tonumber(err:match(":(%d+):"))
if line ~= err_line then
2021-11-29 08:51:12 -06:00
return _load(path, err_line, data, t)
2021-11-28 16:55:11 -06:00
end
end
return l, err
end
2021-11-28 19:47:36 -06:00
return function(path)
return _load(path) or loadfile(path)
2021-11-28 16:55:11 -06:00
end