Repl3.lua: an eepitch-friendly REPL for LuaEepitch is explained here.
Index:
1. IntroductionLua comes with two default repls: its "interactive mode" and debug.debug(). The interactive mode supports multi-line commands and the prefix trick, in which commands like "= exprs" are translated to "print(exprs)", and debug.debug() is as bare as possible: it doesn't support multi-line commands or the prefix trick, and it also doesn't print tracebacks on errors. Try:
You will get this: Most of the other repls for Lua suppose that the users will run them in a terminal, and so they focus on features like editing and completion. One of the most popular is Rob Hoelz's lua-repl; I used it for a while, and I even mentioned it in the slides and in the article about Dednat6, but I've never been able to understand its code, so after some time I gave up using it and started to work on repls that wouldn't have any "black boxes", in this sense... 2. Tracebacks: Prosody, PrintFunction, find-luatbOne of the first things that I wanted in my repl was a better way of printing tracebacks. In mar/2022 I sent this e-mail to lua-l asking for reimplementations in Lua of debug.traceback(), and Matthew Wild pointed to the function _traceback in Prosody (notes); I rewrote that code as the class Prosody in Prosody1.lua, and after some time I rewrote that class completely to change its output; the result was PrintFunction1.lua. The screenshot at the left below compares their outputs - its test block is here - and the screenshot at the right shows what happens when we follow one of the `find-luatb's (an elisp hyperlink): 3. PrintFunction1.luaHere are some technical details. The file PrintFunction1.lua defines only one class: PrintFunction, that implements several ways of printing a description of function - or, more precisely, several ways of printing the table returned by a debug.getinfo(o, "nSluf"), where o is either a function or an integer that represents the level of the desired stack frame. The default output format for objects of the class PrintFunction uses elisp hyperlinks when possible, like this,
but the method :v() converts a PrintFunction object into a VTable object, that is printed like this:
4. PretracebacksA call to debug.traceback() returns a traceback - i.e. "a low-resolution picture of the current stack frames" - as a string. I will use the term "pretraceback" to refer to "a low-resolution picture of the current stack frames" before it is converted to a string. When we are inside the repl defined in Repl3.lua, errors make the call stack be saved in an object of the class PreTraceback, and then that object is printed in the default way, that looks like this:
If the global variable 5. Testing code inside test blocksHere is an interesting example. I wrote this section in 2024jan28, and you can try that version of the code here. I'm not 100% happy with the current version of my class PrintFunction, and here's how I'm trying to make it better. I executed this test block - Repl-tests - in three parts delimited by dashed lines, and took a screenshot after the end of each part: In the part between the dashed lines I redefined the method
and after the redefinition of
This fixed the stack frame 5. I was still not happy with the output for the stack frames 14 and 13, so I put this after the last dashed line:
these lines print the stack frames 14 and 13 in vertical/verbose
mode, and at some point I will use them to see how to make more
changes to 6. Try it!
7. Trying an old versionHere's how to try the version mentioned in the section "Testing code inside test blocks":
8. Missing featuresMy first "serious" repl was Repl1.lua, included in emlua.
TODO: explain how to inspect the local variables and upvalues stored in each stack frame of a pretraceback! If you think that this is interesting, please send me a "hi"! |