Features
pre
values
pre x = math.sqrt(32474278874217828742598412787427624675241676742)
rather than calculating math.sqrt(3247427887…) on runtime it will calculate than on preprocess time and render:
local x = tonumber("1.802062120855378e+23")
(the tonumber is automatically added for numbers that are too big)
#if
, #endif
, #elif
, #else
#if 1+1 == 2
print("According to the preprocessor 1+1 is 2")
#elif 1+1==3
print("According to the preprocessor 1+1 is 3 (wrong)")
#else
print("According to the preprocessor 1+1 is not 2 or 3 (wrong)")
#endif
will generate
print("According to the preprocessor 1+1 is 2")
#define
, #ifdef
, #ifndef
#define DEBUGMODE false
print(`debug mode is: {DEBUGMODE}`) -- the code can access defined variables normally
-- code..
#ifdef DEBUGMODE -- #ifndef does the means if not defined
print("On debug mode")
#endif
-- code..
#error
, #warn
errors or warns from the preprocessor
#if 1+1 ~= 2
#warn uh oh
#error 1+1 is not 2!!!!!
#endif
#include
includes the source code of another file (script
does not work)
#include game.Workspace.file
Source
locktostring = function(val)
if typeof(val) == "string" then
return val
elseif typeof(val) == "number" then
if val == math.huge then
return "math.huge"
elseif val == -math.huge then
return "-math.huge"
end
if not tonumber(typeof(val)) then
return "tonumber(\"" .. tostring(val) .. "\")"
end
return tostring(val)
elseif typeof(val) == "boolean" then
return tostring(val)
elseif typeof(val) == "table" then
local str = "{"
for i, v in pairs(val) do
str = str .. locktostring(i) .. "=" .. locktostring(v) .. ","
end
str = str .. "}"
return str
elseif typeof(val) == "Instance" then
error("Instances are not supported yet for pre-values")
elseif typeof(val) == "function" then
error("Functions are not supported yet for pre-values")
elseif typeof(val) == "userdata" then
error("Userdata is not supported yet for pre-values")
elseif typeof(val) == "nil" then
return "nil"
else
error("Unhandled type: " .. typeof(val))
end
end
loadenvstring = function(env, str)
local fn = loadstring(str)
if not fn then
print(fn, str)
error("Failed to load stringenv")
end
setfenv(fn, env)
return fn
end
fn = function(code)
lines = code:split("\n")
on = true
env = {}
for i, line in ipairs(lines) do
if not on then
lines[i] = ""
continue
end
if line:sub(1, 1) == "#" then
if line:sub(1, 3) == "#if" and (line:sub(4, 4) == " ") then
local var = line:sub(5)
if not loadenvstring(env, "return " .. var)() then
on = false
end
line = ""
elseif line:sub(1, 6) == "#endif" then
on = true
line = ""
elseif line:sub(1, 5) == "#else" then
on = not on
line = ""
elseif line:sub(1, 7) == "#elif" then
local var = line:sub(9)
if loadenvstring(env, "return " .. var)() then
on = true
end
line = ""
elseif line:sub(1, 7) == "#define" then
local var = line:sub(9)
local name, val = var:match("(.*) (.*)")
name = name or var
val = val or "true"
env[name] = val
line = "local " .. name .. " = " .. val
elseif line:sub(1, 6) == "#ifdef" then
local var = line:sub(8)
if not _G[var] then
on = false
end
line = ""
elseif line:sub(1, 7) == "#ifndef" then
local var = line:sub(9)
if _G[var] then
on = false
end
line = ""
elseif line:sub(1, 6) == "#error" then
error(line:sub(8))
elseif line:sub(1, 6) == "#warn " then
warn(line:sub(7))
line = ""
elseif line:sub(1, 8) == "#include" then
local var = line:sub(10)
line = loadstring("return " .. var)().Source
else
error("Unknown preprocessor directive: " .. line)
end
end
--// look for a match like this: pre x = 5
--// if found, replace with local x = 5 (but x will be calculated)
lines[i] = line:gsub("pre (.*) = (.*)", function(var,val)
--// replace line with new line
return ("local "..var .. " = " .. locktostring(loadstring("return "..val)()))
end)
end
return table.concat(lines, "\n")
end
return fn
Todo
- Allow
#
commands to be run with whitespace before it
-- code..
#directive
doesn’t work,
-- code..
#directive
works.
Credits/License
All of the code is written by me, No credits is needed for products/games that use it but if the source code of another project includes this that requires credits.