math.calcfuncs = {
time = CurTime or function() return os.time() end,
}
for k,v in pairs(math) do
math.calcfuncs[k] = type(v) == "function" and v or function() return v end
end
local TB = 0
function math.varsnum(n, vars)
--print(string.rep("-", TB).."VAR:", n, tonumber(n) or vars[n])
return tonumber(n) or vars[n] or error("Invalid number "..string.format("%q", n)..".", 3)
end
function math.calc(v, vars)
TB = TB+1
v = string.match(tostring(v), "^%s*(.-)%s*$")
--print(string.rep("-", TB).."CALC:", v)
if v:sub(1,1) == "\"" or v:sub(1,1) == "'" then
return {v:gsub("[%'%\"](.-)[%'%\"]", "%1")}
end
vars = vars or {}
vars.now = CurTime and CurTime() or os.time()
local output, count = {}
repeat
v, count = string.gsub(v, "([^%;]+)%;", function(a)
table.insert(output, math.calc(a, vars)[1])
return ""
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "([%w_#]*)%s*(%b())", function(a, b)
--print(a, b)
if a == "" then
--print(string.rep("\t", TB).."thing", string.match(b, "^%(%s*(.-)%s*%)$") or "0")
return math.calc(string.match(b, "^%(%s*(.-)%s*%)$") or "0")[1]
elseif a == "#" then
table.insert(output, math.calc(string.match(b, "^%(%s*(.-)%s*%)$") or "0", vars)[1])
return ""
elseif math.calcfuncs[a:lower()] then
local worked, result = pcall(math.calcfuncs[a:lower()],
unpack(math.calc(string.match(b, "^%(%s*(.-)%s*%)$") or "", vars)))
return worked and (result or "")
or error("Error in function "..string.format("%q", a:lower())..": "..tostring(result), 2)
end
error("No such function "..string.format("%q", a)..".", 2)
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "([%w_%d]+)%s*=%s*([^=;]+)", function(a,c)
--print(a, "=", c)
vars[a] = math.calc(c, vars)[1]
return ""
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "(%-?[%w_%d%.e]+)%s*^%s*(%-?[%w_%d%.e]+)", function(a,c)
--print(a, "^", c)
return math.varsnum(a, vars)^math.varsnum(c, vars)
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "(%-?[%w_%d%.e]+)%s*([%*%/%%])%s*(%-?[%w%_%d%.e]+)", function(a,b,c)
--print(a, b, c)
return b == "*"
and math.varsnum(a, vars)*math.varsnum(c, vars)
or b == "/"
and math.varsnum(a, vars)/math.varsnum(c, vars)
or b == "%"
and math.varsnum(a, vars)%math.varsnum(c, vars)
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "(%-?[%w%_%d%.e]+)%s*([%+%-])%s*(%-?[%w%_%d%.e]+)", function(a,b,c)
--print(a, b, c)
return b == "+"
and math.varsnum(a, vars)+math.varsnum(c, vars)
or b == "-"
and math.varsnum(a, vars)-math.varsnum(c, vars)
end, 1)
until count == 0
repeat
v, count = string.gsub(v, "(%-?[%w%_%d%.e]+)%s*([!~<>=]+)%s*(%-?[%w%_%d%.e]+)", function(a,b,c)
--print(a, b, c)
return( b == "=="
and math.varsnum(a, vars) == math.varsnum(c, vars)
or b == "~=" or b == "!="
and math.varsnum(a, vars) ~= math.varsnum(c, vars)
or b == ">"
and math.varsnum(a, vars) > math.varsnum(c, vars)
or b == "<"
and math.varsnum(a, vars) < math.varsnum(c, vars)
or b == "<="
and math.varsnum(a, vars) <= math.varsnum(c, vars)
or b == ">="
and math.varsnum(a, vars) >= math.varsnum(c, vars)
) and 1 or 0
end, 1)
until count == 0
if string.match(v, "%S") then
table.insert(output, math.varsnum(v, vars))
end
--print(string.rep("-", TB).."RES:", unpack(output))
TB = TB-1
return output
end
print(table.concat(math.calc[[
(3+6) * 5^( 15 % 2 ) / 3;
time();
sin(deg(180))*random();
x = 32+9;
y = x/random();
#(y);
randomseed(32);
a = random();
randomseed(32);
b = random();
#("This should be 1:");
a == b;
5*-7;
]], "\n"))