1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
--- lam.load
local m = {}
local core = require("core")
local eval = require("eval")
local port = require("port")
local read = require("read")
local type = require("type")
local function schemeprint (x)
-- possibly a candidate to put in a `write' library
if x == true then print("#t")
elseif x == false then print("#f")
elseif x == nil then return -- print("#<nil>")
else print(x)
end
end
local function handle_error (e)
local start = e:find(": ")
return e:sub(start + 2)
end
function m.load (filename, interactive)
-- interactive = { out = file/handle, prompt = string, }
local inport = port.input_port(filename)
if interactive then
io.output(interactive.out)
io.output():setvbuf("line")
else
io.output():setvbuf("no")
end
repeat
if interactive then
io.stderr:write(interactive.prompt or "")
io.stderr:flush()
end
-- read
local read_ok, form = xpcall(
function () return read.read(inport) end,
handle_error)
if form == port.eof then break end
if not read_ok then
io.stderr:write("error (read): ", form, "\n")
-- when interactive, errors should not be fatal, but
-- they should be in batch mode
inport:flush() -- avoid endless loop
if not interactive then return nil end
else
-- eval
local eval_ok, value = xpcall(
function ()
return eval.eval(form, core.environment)
end,
handle_error)
if not eval_ok then
io.stderr:write("error (eval): ", value, "\n")
if not interactive then return nil end
else
-- print
if interactive then schemeprint(value) end
end
end
until value == port.eof -- loop
end
--------
return m
|