[HN Gopher] Interesting things about the Lua interpreter (2020)
___________________________________________________________________
Interesting things about the Lua interpreter (2020)
Author : memorable
Score : 56 points
Date : 2023-01-02 02:57 UTC (1 days ago)
(HTM) web link (thesephist.com)
(TXT) w3m dump (thesephist.com)
| jhatemyjob wrote:
| thanks for sharing this. been casually thinking about how you
| would implement the Lua interpreter in a FPGA and this is a good
| starting point
| babelfishstudio wrote:
| I love that they went from a single-pass interpreter to a byte-
| code virtual machine, and now like PHP, also has direct access to
| C & system libraries! Lua has come a long way since it's advent.
| giraffe_lady wrote:
| The paper and article are about lua 5.0 which came out in 2003.
| I don't believe it had any prominence at all before that so
| this stuff has "always" been there in lua unless you were in
| the CS dept at puc-rio in the 90s.
| ivoras wrote:
| Lua's simplicity is sometimes it's real selling point. I was just
| today searching for a small scripting language to implement in a
| mobile app in .net, where app size is a premium, and it turns out
| that the smallest useful JavaScript interpreter is at least 3x
| the size of a Lua interpreter.
|
| I do believe that an un-bloated JavaScript language from when it
| was just invented would be simpler than Lua (as both were
| designed as "scripting" languages, not as main ones), but history
| didn't go that route :)
|
| But... Lua is WEIRD! Weird nomenclature, weird string
| concatenation operand, 1-based arrays, too clever "tables" and
| "metatables" stuff.
| giraffe_lady wrote:
| Timing on this is confusing. Article was written in 2020 about a
| paper published in 2003 or so about the design of lua 5.0.
|
| It's still a really insightful and approachable paper that's
| worth reading, and it does still help understand the constraints
| and approach of lua. But the current "old" version of the
| language is 5.2 released in 2011, and there have been a couple
| major versions after that as well.
|
| So some of it may not actually be applicable to using lua now,
| depending on what your "now" looks like.
| ufo wrote:
| For the most part, the info is still valid today. The main
| thing that changed since then is that Lua 5.3 introduced
| integers and several new bytecode instructions for the common
| case where one of the operands is a small integer constant.
| mftb wrote:
| The Lua interpreters, "upvalues" sound suspiciously like the
| results of Tcl's, "upvar", can anybody comment on how similar
| they actually are?
| munificent wrote:
| I don't think there's any deep connection. "upvar" in Tcl is a
| language feature. Upvalues in Lua are purely an implementation
| detail of the interpreter.
|
| If you want all the gritty details, a chapter of Crafting
| Interpreters walks through a complete implementation of Lua's
| approach to closures:
|
| http://craftinginterpreters.com/closures.html
| giraffe_lady wrote:
| I'm not sure about that though I haven't used tcl in a while
| and was never an expert. I think tcl upvar _allows_ you to
| explicitly do what lua 's closure implementation
| automatically does.
|
| They aren't the same thing but they are closely related
| concepts and similar solutions to the same potential problem.
| ufo wrote:
| A big difference is that Tcl's upvar is dynamically scoped.
| A more appropriate Lua analog would be Lua's debug API
| (e.g. debug.setlocal)
| ufo wrote:
| Nowadays the upvalues in Lua are bona-fide lexical scoping a-la
| Scheme or Javascript. However, the name comes from Lua 4.0
| where the upvalues worked in a more unusual way. Not in the
| same way as Tcl though, but just as surprising for the
| uninitiated.
|
| https://www.lua.org/manual/4.0/manual.html#4.6
| deathanatos wrote:
| I'd love to see upvalues diagrammed as they are represented in
| memory.
|
| It sounds like the stack is perhaps a Stack<Frame pointer1>,
| where each Frame contains the locals for that stack frame; then a
| coroutine just needs to keep a pointer to the stack frame it is
| closing over. (And then, Frame does too, recursively, incase
| there is more than one scope being closed over.)
|
| This would be extremely similar to ... most any other language
| ... and makes me wonder why Lua gives them such a unique name. It
| has been hard to really comprehend the Lua spec, when I've tried
| to understand that facet of it.
|
| (I'd also argue that Lua isn't as simple as it is made out to be:
| primitives behave wildly different from objects, there's the
| 1-based indexing, multiple-return is pretty much unique to Lua
| (vs. returning a tuple, which other languages such as Python,
| Rust, and sort-of JS, go for; I think that's conceptually
| simpler).)
|
| 1and note "pointer" here might really be "GC ref", to permit
| these to be GC'd as necessary, as closures can keep stuff alive
| far longer than normal.
| hcs wrote:
| It's not a Lua VM but the bytecode interpreter in Crafting
| Interpreters uses upvalues similarly and has some diagrams:
| https://craftinginterpreters.com/closures.html#upvalues
|
| Edit: And yeah I don't think it's anything unique to Lua, it's
| an implementation detail of closures and lexical scope
| generally. It's a non-stack wrapper for closed-over variables,
| the end of the introduction to chapter 25 explains:
|
| > For locals that aren't used in closures, we'll keep them just
| as they are on the stack. When a local is captured by a
| closure, we'll adopt another solution that lifts them onto the
| heap where they can live as long as needed.
| ufo wrote:
| > The 5.0 VM is a register machine, which operates on a set of
| virtual registers that can store and act on the local variables
| of a function, in addition to the traditional runtime stack.
|
| This is a common source of confusion, because the name "register
| machine" makes people think about CPU registers. However, the
| registers in a register VM are merely slots in the traditional
| runtime stack. The difference between a stack and register
| machine has to do with how the bytecode instructions are encoded.
| In a stack machine, most instructions implicitly pop arguments
| from and push their results to the top of the stack. The
| instructions are byte-sized, encoding just the operation name.
| For example, to add 10+10 LOADK 10 DUP
| ADD
|
| Meanwhile, in a register machine the instructions can read and
| write to any slot in the stack. Instructions are larger, because
| in addition to the operation name they also encode the indexes of
| the input slots and the index of the output slot. But it's worth
| it because you need less instructions in total and do less stack
| shuffling. LOADK 1 10 ADD 1 1 2
| ithkuil wrote:
| This. Some CPU architecture even blur the line between hardware
| registers and stack slots: register windows! Indeed what
| matters is whether each instruction addresses operands
| explicitly (registers) or implicitly (top of the stack)
___________________________________________________________________
(page generated 2023-01-03 23:00 UTC)