From b5d62d3991cb2940462bfcc06670edfe7d4e2dde Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 21 Oct 2021 14:22:06 -0400 Subject: [PATCH] Reimplemented 'print', channeled it through PrintBuffer --- luprex/core/cpp/luastack.hpp | 2 +- luprex/core/cpp/pprint.cpp | 74 ++++++++++++++++++++++-------- luprex/core/cpp/pprint.hpp | 42 ++++++++--------- luprex/core/cpp/world-accessor.cpp | 12 +++++ 4 files changed, 86 insertions(+), 44 deletions(-) diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index e34e99eb..89718f84 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -329,7 +329,7 @@ public: L_ = L; count_slots<0, 0, 0>(stackslots...); if (lua_gettop(L) < narg_) { - luaL_error(L, "not enough arguments on stack"); + luaL_error(L, "not enough arguments to function"); } assign_slots(argpos_, varpos_, retpos_, stackslots...); clear_frame(); diff --git a/luprex/core/cpp/pprint.cpp b/luprex/core/cpp/pprint.cpp index fdfea46e..9d2f5654 100644 --- a/luprex/core/cpp/pprint.cpp +++ b/luprex/core/cpp/pprint.cpp @@ -5,20 +5,31 @@ #include -LuaDefine(string_isidentifier, "c") { - LuaArg str; - LuaRet result; - LuaStack LS(L, str, result); - if (LS.isstring(str)) { - std::string s = LS.ckstring(str); - LS.set(result, util::is_identifier(s)); - } else { - LS.set(result, false); +void atomic_print(LuaStack &LS, LuaSlot val, std::ostream *os) { + switch (LS.type(val)) { + case LUA_TNIL: + (*os) << "nil"; + return; + case LUA_TSTRING: + // TODO: this could be more efficient. + (*os) << LS.ckstring(val); + return; + case LUA_TNUMBER: + (*os) << LS.ckinteger(val); + return; + case LUA_TBOOLEAN: + (*os) << (LS.ckboolean(val) ? "true" : "false"); + return; + case LUA_TTABLE: + (*os) << "table"; + return; + default: + (*os) << "unknown"; + return; } - return LS.result(); } -bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os) { +static bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os) { switch (LS.type(val)) { case LUA_TNIL: (*os) << "nil"; @@ -37,15 +48,6 @@ bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os) { } } -LuaDefine(string_quote, "c") { - LuaArg val; - LuaRet result; - LuaStack LS(L, val, result); - std::ostringstream oss; - string_quote(LS, val, &oss); - LS.set(result, oss.str()); - return LS.result(); -} // Find tables recursively. // @@ -242,6 +244,28 @@ void pprint(LuaStack &LS0, LuaSlot root, bool indent, std::ostream *os) { LS.result(); } +LuaDefine(string_isidentifier, "c") { + LuaArg str; + LuaRet result; + LuaStack LS(L, str, result); + if (LS.isstring(str)) { + std::string s = LS.ckstring(str); + LS.set(result, util::is_identifier(s)); + } else { + LS.set(result, false); + } + return LS.result(); +} + +LuaDefine(string_print, "c") { + LuaArg val; + LuaRet result; + LuaStack LS(L, val, result); + std::ostringstream oss; + atomic_print(LS, val, &oss); + LS.set(result, oss.str()); + return LS.result(); +} LuaDefine(string_pprint, "c") { LuaArg root, indent; @@ -253,3 +277,13 @@ LuaDefine(string_pprint, "c") { LS.set(result, oss.str()); return LS.result(); } + +LuaDefine(string_tostring, "f") { + LuaArg val; + LuaRet result; + LuaStack LS(L, val, result); + std::ostringstream oss; + atomic_print(LS, val, &oss); + LS.set(result, oss.str()); + return LS.result(); +} diff --git a/luprex/core/cpp/pprint.hpp b/luprex/core/cpp/pprint.hpp index 03465aa3..f78750a2 100644 --- a/luprex/core/cpp/pprint.hpp +++ b/luprex/core/cpp/pprint.hpp @@ -1,24 +1,33 @@ -///////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// // -// Pretty-print routine. +// print, pprint, and tostring // -// The pretty-printer can be called from C++ or Lua. +// This module implements the heart of the lua 'print', lua 'pprint', and lua +// 'tostring' functions. Note that we have to override the lua builtins 'print' +// and 'tostring' for two reasons: // -///////////////////////////////////////////////////////// +// * We need to suppress the printing of table addresses, for determinism. +// * We need to channel the output to a PrintBuffer in the world model. +// +// Note that the actual lua 'print' and 'pprint' routines aren't defined in this +// module, they're in the World module, because they send their output into the +// PrintBuffer of the world model. But all the tricky code to implement 'print' +// and 'pprint' are in this module. +// +////////////////////////////////////////////////////////////////////////////////// #ifndef PPRINT_HPP #define PPRINT_HPP #include "luastack.hpp" -// Output a simple value to a stream. +// Atomic print to a stream. // -// If the value is a string, number, boolean, or nil, it is -// quoted and output to the stream, and this function returns -// true. Otherwise, this function returns false and nothing -// is sent to the stream. +// This prints an atomic value to a stream. If you give it a table, +// it just prints "table". This routine is the heart of the lua +// primitives 'print' and 'tostring'. // -bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os); +void atomic_print(LuaStack &LS, LuaSlot val, std::ostream *os); // Pretty print to a stream. // @@ -30,17 +39,4 @@ bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os); // void pprint(LuaStack &LS, LuaSlot val, bool indent, std::ostream *os); -// The following lua interfaces to this code are included: -// -// pprint(expr, expr, expr...) -// -// - pretty print the specified expression to stdout. -// -// string.pprint(expr, indent) -// -// - pretty print the specified expression, return the result as a string. -// -int lfn_pprint_pprint(lua_State *L); -int lfn_string_pprint(lua_State *L); - #endif // PPRINT_HPP \ No newline at end of file diff --git a/luprex/core/cpp/world-accessor.cpp b/luprex/core/cpp/world-accessor.cpp index 75fc493e..d7f75601 100644 --- a/luprex/core/cpp/world-accessor.cpp +++ b/luprex/core/cpp/world-accessor.cpp @@ -220,4 +220,16 @@ LuaDefine(world_pprint, "f") { (*ostream) << std::endl; } return LS.result(); +} + +LuaDefine(world_print, "f") { + World *w = World::fetch_global_pointer(L); + std::ostream *ostream = w->lthread_print_stream(); + LuaStack LS(L); + for (int i = 1; i <= lua_gettop(L); i++) { + LuaSpecial root(i); + atomic_print(LS, root, ostream); + (*ostream) << std::endl; + } + return LS.result(); } \ No newline at end of file