You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

72 lines
1.5 KiB

local A, F, I = {}, {}, {}
local function unwind(stack, sp)
local x = stack[sp]
if type(x) == 'table' then
if x[1] == A then
stack[sp + 1] = x[2]
return unwind(stack, sp + 1)
elseif x[1] == I then
stack[sp] = x[2]
return unwind(stack, sp)
elseif x[1] == F then
if sp - 1 >= x[3] then
return x[2](stack, sp)
else
error("insufficient arguments for supercombinator " .. x[4])
end
end
return x
else
return x, stack, sp
end
end
local function repr(x)
if type(x) == 'table' then
if x[1] == A then
return repr(x[2]) .. '(' .. repr(x[3]) .. ')'
elseif x[1] == F then
return x[4]
elseif x[1] == I then
return '&' .. repr(x[2])
end
local r = {}
for k, v in pairs(x) do
r[k] = repr(v)
end
return '{' .. table.concat(r, ', ') .. '}'
else
return tostring(x)
end
end
local function eval(stack, sp)
local nf = (unwind({ stack[sp] }, 1))
stack[sp] = { I, nf }
return nf
end
local function getchar(stack, sp)
local k = stack[sp - 1][3]; sp = sp - 1
local knil = stack[sp - 1][3]; sp = sp - 1
local ch = io.read(1)
if ch then
stack[sp] = { A, k, ch:byte() }
else
stack[sp] = { A, knil, 0 }
end
return unwind(stack, sp)
end
local getchar_combinator = { F, getchar, 2 }
local function putchar()
local ch = stack[sp - 1][3];
local k = stack[sp - 2][3]; sp = sp - 1
io.write(string.char(ch))
stack[sp] = { A, k, ch }
return unwind(stack, sp)
end
local putchar_combinator = { F, putchar, 2 }