about summary refs log tree commit diff stats
path: root/repl.lua
blob: 86bc0af1efa62c175ea5805d7b91f556882f8822 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
--- lam.repl

local m = {}
local _r = require("read")
local read, inport, read_string, eof =
	_r.read, _r.inport, _r.read_string, _r.eof
local eval = require("eval").eval

local function schemeprint (x)
	-- if x == nil then return end
	if x == true then
		print("#t")
	elseif x == false then
		print("#f")
	elseif x == nil then
		print("#<nil>")
	else
		print(x)
	end
end

local lam = [[
 @,,,@
<|^ ^|>  l a m
 |   /)   0015
 |I /)))  acdw
 -------------
]]

local function handle_error (e)
	local start = e:find(": ")
	return e:sub(start + 2)
end

function m.read_eval (filename, interactive)
	-- interactive = { out = file or handle, prompt = string, }
	local inport = inport(filename)
	local prompt = interactive and interactive.prompt or "> "
	if interactive then
		io.output(interactive.out or io.stdout)
		io.write(lam)
		io.output():setvbuf("line")
	else
		io.output(io.stdout) -- hmmm
		io.output():setvbuf("no")
	end
	repeat
		if interactive then
			io.stderr:write(prompt)
			io.stderr:flush()
		end
		-- read
		local ok, x = xpcall(
			function ()
				local nxt = read(inport)
				return nxt
			end,
			handle_error
		)
		if not ok then
			io.stderr:write("(read) not ok: ", x, "\n")
			-- in interactive mode, errors should not be fatal.  in
			-- batch mode, they should be.
			if not interactive then return nil end
		end
		-- eval
		if ok then
			local ok, v = xpcall(
				function () return eval(x) end,
				handle_error
			)
			if not ok then
				io.stderr:write("(eval) not ok: ", v, "\n")
				if not interactive then return nil end
			end
			-- print
			if ok and interactive then schemeprint(v) end
		elseif interactive then
			ok = "recover"
		end
	until x == eof -- loop
	inport:close()
end

function m.repl (prompt)
	return m.read_eval(nil, { prompt = prompt, })
end

function m.load (filename)
	return m.read_eval(filename)
end

--------
return m