Skip to content

Instantly share code, notes, and snippets.

@FRex
Created November 13, 2017 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FRex/65506c5dd14d36fa9555437e0053f73c to your computer and use it in GitHub Desktop.
Save FRex/65506c5dd14d36fa9555437e0053f73c to your computer and use it in GitHub Desktop.
local io = require'io'
local math = require'math'
local function push(s, v) s[#s + 1] = v; return v end
local function top(s) return s[#s] end
local function pop(s) local r = top(s); s[#s] = nil; return r end
local function empty(s) return #s == 0 end
local function fixtoplist(stack)
local oldtop = top(stack)
if oldtop and #oldtop == 1 then
newtop = push(stack, {})
oldtop[2] = newtop
oldtop = newtop
end
return oldtop
end
local function parse(code)
local stack = {}
for token in code:gmatch('%S+') do
if tonumber(token) ~= nil then token = tonumber(token) end
if token == '(' then
local oldtop = fixtoplist(stack)
local newtop = push(stack, {opening = true})
if oldtop then oldtop[1] = newtop end
elseif token == ')' then
while not empty(stack) and not top(stack).opening do
pop(stack)
end
local r = pop(stack)
if empty(stack) then return r end
else
fixtoplist(stack)[1] = token
end
end --for token
end --function parse
local function progtostr(x, types)
if x == nil then return '@NIL' end
if type(x) ~= 'table' then
if types then
return ('%s[%s]'):format(type(x), tostring(x))
else
return tostring(x)
end
end
return ('(%s %s)'):format(progtostr(x[1], types), progtostr(x[2], types))
end
local function listhead(t)
return t[1], t[2]
end
local function listend(t)
return #t ~= 2
end
local funcs = {}
funcs['+'] = function(t) return 'PLUS' end
local function printf(fmt, ...) io.stdout:write(fmt:format(...)) end
local eval
local function iterlist(l)
local f = function(s)
ll = s[1]
if ll == nil then return nil end
s[1] = ll[2]
return ll[1]
end
return f, {l}
end
local funcs = {}
funcs['+'] = function(l)
local sum = 0
for x in iterlist(l) do sum = sum + eval(x) end
return sum
end
funcs['*'] = function(l)
local prod = 1
for x in iterlist(l) do prod = prod * eval(x) end
return prod
end
local function openlist(l) return l[1], l[2] end
funcs['/'] = function(l)
local a, l = openlist(l)
local b = openlist(l)
return eval(a) / eval(b)
end
funcs['//'] = function(l)
local a, l = openlist(l)
local b = openlist(l)
return math.floor(eval(a) / eval(b))
end
funcs['..'] = function(l)
local parts = {}
for x in iterlist(l) do table.insert(parts, eval(x)) end
return table.concat(parts)
end
funcs['sin'] = function(l) return math.sin(eval(l[1])) end
funcs['cos'] = function(l) return math.sin(eval(l[1])) end
funcs['pi'] = math.pi
eval = function(l)
--print('aa', l, l[1], l[2])
if type(l) == 'number' then return l end
if type(l) == 'string' then
local q = string.byte"'"
if l:byte(1) == q and l:byte(-1) == q then return l:sub(2, -2) end
return funcs[l] or l
end
local first = eval(l[1])
first = funcs[first] or first
if type(first) == 'function' then return first(l[2]) end
return first
end
local function interpret(code)
code = code:gsub('%(', ' ( '):gsub('%)', ' ) ')
program = parse(code)
return eval(program)
end
if arg then
for i=1,#arg do
result = interpret(arg[i])
printf('Result: %s\n', tostring(result))
end
end
local function simplify(code, types)
code = code:gsub('%(', ' ( '):gsub('%)', ' ) ')
program = parse(code)
return progtostr(program, types)
end
return {interpret = interpret, simplify = simplify}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment