--- lam.load local m = {} local core = require("core") local eval = require("eval") 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("#") else print(x) end end function core.environment.read (r) type.assert_arity(r,1,1) error("unimplemented") end function core.environment.eval (r) type.assert_arity(r,1,2) local form = r[1] local env = r[2][1] or core.environment return eval.eval(form, env) end function core.environment.load (r) type.assert_arity(r,1,1) return m.load(tostring(r[1])) end function m.load (filename, interactive) -- interactive = { out = file/handle, prompt = string, } local inport = type.input_port(filename) if interactive then io.output(interactive.out) io.output():setvbuf("line") else io.output():setvbuf("no") end local function handle_error (e) local start = e:find(": ") return e:sub(start + 2) 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 == type.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 == type.eof -- loop end -------- return m