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 }