|
|
- 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 }
|