mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
87496f3376
This example add a module thats starts an interactive READ-EVAL- PRINT-LOOP written in Lua.
95 lines
2.6 KiB
Lua
95 lines
2.6 KiB
Lua
--[[
|
|
@file repl.lua
|
|
@brief Read-eval-print loop for LUA
|
|
@author Juan Carrano <j.carrano@fu-berlin.de>
|
|
Copyright (C) 2018 Freie Universität Berlin. Distributed under the GNU Lesser General Public License v2.1.
|
|
]]
|
|
|
|
local _R_EVAL = 0
|
|
local _R_CONT = 1
|
|
local _R_EXIT = 2
|
|
local _R_ERROR = 3
|
|
|
|
--[[ Read code from standard input (whatever stdin means for lua)
|
|
@return action_code what the eval loop should do
|
|
@return code_or_msg either code (_R_EVAL) or a message (_R_ERROR) or nil
|
|
(_R_CONT, _R_EXIT).
|
|
]]
|
|
|
|
local function re()
|
|
io.write("L> ")
|
|
io.flush()
|
|
local ln = io.read()
|
|
|
|
if not ln then
|
|
return _R_EXIT
|
|
elseif ln == "\n" then
|
|
return _R_CONT
|
|
end
|
|
-- Try to see if we have an expression
|
|
local maybe_code, compile_err = load("return "..ln)
|
|
-- Try to see if we have a single-line statement
|
|
if not maybe_code then
|
|
maybe_code, compile_err = load(ln)
|
|
end
|
|
-- Try a multiline statement
|
|
if not maybe_code then
|
|
-- It's not really necessary to use a coroutine, but it shows that they
|
|
-- work.
|
|
local _get_multiline = coroutine.create(
|
|
function ()
|
|
coroutine.yield(ln.."\n") -- We already have the first line of input
|
|
while 1 do
|
|
io.write("L.. ")
|
|
io.flush()
|
|
local l = io.read()
|
|
if #l ~= 0 then
|
|
l = l.."\n"
|
|
end
|
|
coroutine.yield(l)
|
|
end
|
|
end
|
|
)
|
|
local get_multiline = function()
|
|
local a, b = coroutine.resume(_get_multiline)
|
|
if a then
|
|
return b
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
maybe_code, compile_err = load(get_multiline)
|
|
end
|
|
|
|
if not maybe_code then
|
|
return _R_ERROR, compile_err
|
|
else
|
|
return _R_EVAL, maybe_code
|
|
end
|
|
end
|
|
|
|
local function repl()
|
|
io.write("Welcome to the interactive interpreter\n");
|
|
|
|
while 1 do
|
|
local action, fn_or_message = re()
|
|
|
|
if action == _R_EVAL then
|
|
local success, msg_or_ret = pcall(fn_or_message)
|
|
if not success then
|
|
print("Runtime error", msg_or_ret)
|
|
elseif msg_or_ret ~= nil then
|
|
print(msg_or_ret)
|
|
end
|
|
elseif action == _R_EXIT then
|
|
print()
|
|
return
|
|
elseif action == _R_ERROR then
|
|
print("Compile error:", fn_or_message)
|
|
end -- (action == _R_CONT) : do nothing
|
|
end
|
|
end
|
|
|
|
repl()
|