diff options
Diffstat (limited to 'repl.lua')
-rw-r--r-- | repl.lua | 95 |
1 files changed, 53 insertions, 42 deletions
diff --git a/repl.lua b/repl.lua index be739c7..86bc0af 100644 --- a/repl.lua +++ b/repl.lua | |||
@@ -1,9 +1,10 @@ | |||
1 | --- lam.repl | 1 | --- lam.repl |
2 | 2 | ||
3 | local m = {} | 3 | local m = {} |
4 | local read = require("read") | 4 | local _r = require("read") |
5 | local eval = require("eval") | 5 | local read, inport, read_string, eof = |
6 | local pp = require("dump").pp | 6 | _r.read, _r.inport, _r.read_string, _r.eof |
7 | local eval = require("eval").eval | ||
7 | 8 | ||
8 | local function schemeprint (x) | 9 | local function schemeprint (x) |
9 | -- if x == nil then return end | 10 | -- if x == nil then return end |
@@ -12,7 +13,7 @@ local function schemeprint (x) | |||
12 | elseif x == false then | 13 | elseif x == false then |
13 | print("#f") | 14 | print("#f") |
14 | elseif x == nil then | 15 | elseif x == nil then |
15 | print("#n") | 16 | print("#<nil>") |
16 | else | 17 | else |
17 | print(x) | 18 | print(x) |
18 | end | 19 | end |
@@ -26,57 +27,67 @@ local lam = [[ | |||
26 | ------------- | 27 | ------------- |
27 | ]] | 28 | ]] |
28 | 29 | ||
29 | function m.repl (prompt, infile, out) | 30 | local function handle_error (e) |
30 | -- PROMPT should be a string, INFILE is a filename, and OUT is either a | 31 | local start = e:find(": ") |
31 | -- filename, nil (in which case it will be stdout), or false (which | 32 | return e:sub(start + 2) |
32 | -- suppresses output) | 33 | end |
33 | local inport = read.inport(infile) | 34 | |
34 | if out ~= false then | 35 | function m.read_eval (filename, interactive) |
35 | io.output(out) | 36 | -- interactive = { out = file or handle, prompt = string, } |
37 | local inport = inport(filename) | ||
38 | local prompt = interactive and interactive.prompt or "> " | ||
39 | if interactive then | ||
40 | io.output(interactive.out or io.stdout) | ||
36 | io.write(lam) | 41 | io.write(lam) |
42 | io.output():setvbuf("line") | ||
43 | else | ||
44 | io.output(io.stdout) -- hmmm | ||
45 | io.output():setvbuf("no") | ||
37 | end | 46 | end |
38 | io.output():setvbuf("line") | 47 | repeat |
39 | if prompt then | 48 | if interactive then |
40 | stderr = io.open("/dev/stderr", "w") -- Linux-only ! | 49 | io.stderr:write(prompt) |
41 | end | 50 | io.stderr:flush() |
42 | while true do -- loop | ||
43 | if prompt then | ||
44 | stderr:write(prompt) | ||
45 | stderr:flush() | ||
46 | end | 51 | end |
47 | -- read | 52 | -- read |
48 | local ok, x = xpcall( | 53 | local ok, x = xpcall( |
49 | function () return read.read(inport) end, | 54 | function () |
50 | function (e) | 55 | local nxt = read(inport) |
51 | local start = e:find(": ") | 56 | return nxt |
52 | return e:sub(start+2) | 57 | end, |
53 | end | 58 | handle_error |
54 | ) | 59 | ) |
55 | if not ok then | 60 | if not ok then |
56 | print("(read) not ok: " .. x) | 61 | io.stderr:write("(read) not ok: ", x, "\n") |
57 | x = nil | 62 | -- in interactive mode, errors should not be fatal. in |
63 | -- batch mode, they should be. | ||
64 | if not interactive then return nil end | ||
58 | end | 65 | end |
59 | -- eval | 66 | -- eval |
60 | if x then | 67 | if ok then |
61 | local ok, val = | 68 | local ok, v = xpcall( |
62 | xpcall( | 69 | function () return eval(x) end, |
63 | function () return eval.eval(x) end, | 70 | handle_error |
64 | function (e) | 71 | ) |
65 | local start = e:find(": ") | ||
66 | return e:sub(start+2) | ||
67 | end | ||
68 | ) | ||
69 | if not ok then | 72 | if not ok then |
70 | print("(eval) not ok: " .. val) | 73 | io.stderr:write("(eval) not ok: ", v, "\n") |
71 | elseif out ~= false then | 74 | if not interactive then return nil end |
72 | |||
73 | schemeprint(val) | ||
74 | end | 75 | end |
76 | |||
77 | if ok and interactive then schemeprint(v) end | ||
78 | elseif interactive then | ||
79 | ok = "recover" | ||
75 | end | 80 | end |
76 | end | 81 | until x == eof -- loop |
77 | inport:close() | 82 | inport:close() |
78 | stderr:close() | 83 | end |
79 | io.output():close() | 84 | |
85 | function m.repl (prompt) | ||
86 | return m.read_eval(nil, { prompt = prompt, }) | ||
87 | end | ||
88 | |||
89 | function m.load (filename) | ||
90 | return m.read_eval(filename) | ||
80 | end | 91 | end |
81 | 92 | ||
82 | -------- | 93 | -------- |