From 55ff07fdddffb794bb86b18dfd403f78ead6f0ec Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Wed, 28 Oct 2009 12:40:18 +0100 Subject: A lot more functional, now, though still deficient. --- crawl-ref/source/luaterp.cc | 119 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 12 deletions(-) (limited to 'crawl-ref/source/luaterp.cc') diff --git a/crawl-ref/source/luaterp.cc b/crawl-ref/source/luaterp.cc index a2c4ec8b42..39252d1fa3 100644 --- a/crawl-ref/source/luaterp.cc +++ b/crawl-ref/source/luaterp.cc @@ -1,3 +1,10 @@ +/* + * File: luaterp.cc + * Summary: An interactive lua interpreter. + * + * Based heavily on lua.c from the Lua distribution. + */ + #include "AppHdr.h" #include "luaterp.h" @@ -6,28 +13,116 @@ #include "clua.h" #include "dlua.h" -void _debug_call_lua(lua_State *ls) +static int _incomplete(lua_State *ls, int status) { - char specs[80]; - while (true) + if (status == LUA_ERRSYNTAX) + { + size_t lmsg; + const char *msg = lua_tolstring(ls, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("")) - 1); + if (strstr(msg, LUA_QL("")) == tp) + { + lua_pop(ls, 1); + return 1; + } + } + return 0; +} + +static int _pushline(lua_State *ls, int firstline) +{ + char buffer[80]; + char *b = buffer; + size_t l; + mpr(firstline ? "> " : ". ", MSGCH_PROMPT); + get_input_line(buffer, sizeof(buffer)); + l = strlen(b); + if (l == 0) + return (0); + + if (l > 0 && b[l-1] == '\n') // line ends with newline? + b[l-1] = '\0'; // remove it + if (firstline && b[0] == '=') // first line starts with `=' ? + lua_pushfstring(ls, "return %s", b+1); // change it to `return' + else + lua_pushstring(ls, b); + return 1; +} + +static int _loadline(lua_State *ls) +{ + int status; + lua_settop(ls, 0); + + if (!_pushline(ls, 1)) + return -1; /* no input */ + + // repeat until gets a complete line + for (;;) { - mpr("> ", MSGCH_PROMPT); - get_input_line(specs, sizeof(specs)); - std::string s = specs; + status = luaL_loadbuffer(ls, lua_tostring(ls, 1), + lua_strlen(ls, 1), "=terp"); - if (s.empty()) - return; + if (!_incomplete(ls, status)) + break; + if (!_pushline(ls, 0)) + return -1; + lua_pushliteral(ls, "\n"); // add a new line... + lua_insert(ls, -2); // ...between the two lines + lua_concat(ls, 3); // join them + } + lua_remove(ls, 1); // remove line + return status; +} - int err = 0; - if (err = luaL_dostring(ls, s.c_str())) +static int _docall(lua_State *ls) +{ + int status; + int base = lua_gettop(ls); + status = lua_pcall(ls, 0, LUA_MULTRET, base); + if (status != 0) + lua_gc(ls, LUA_GCCOLLECT, 0); + return (status); +} + +static int _report(lua_State *ls, int status) +{ + if (status && !lua_isnil(ls, -1)) + { + const char *msg = lua_tostring(ls, -1); + if (msg == NULL) + msg = "(error object is not a string)"; + mprf(MSGCH_ERROR, msg); + lua_pop(ls, 1); + } + return status; +} + +void run_clua_interpreter(lua_State *ls) +{ + int status; + while ((status = _loadline(ls)) != -1) + { + if (status == 0) + status = _docall(ls); + _report(ls, status); + if (status == 0 && lua_gettop(ls) > 0) { - mprf(MSGCH_ERROR, "lua error: %d", err); + lua_getglobal(ls, "__echo"); + lua_insert(ls, 1); + if (lua_pcall(ls, lua_gettop(ls) - 1, 0, 0) != 0) + { + mprf(MSGCH_ERROR, "error calling crawl.mpr (%s)", + lua_tostring(ls, -1)); + } +// mpr("got return values"); } } + lua_settop(ls, 0); // clear stack } void debug_call_dlua() { - _debug_call_lua(dlua); + run_clua_interpreter(dlua); } -- cgit v1.2.3-54-g00ecf