lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


My point is not that the table has to be implemetned necessarily as a hash with a vector indexed by hash(key) containing pointers/references to keys and collision pointers (or a randomization function like adding some prime modulo N where N is the size of the hash) plus a pointer/refernce to values, and a separate store for keys and for values. There are lot of ways to implement tables including the possibility for some kinds of keys or values to reduce it to a simple integer-indexed vector (i.e. an array).
So the alledged cost of using a table for upvalues is not true: this is here also implementation detail. As well as the way you implement the stack (not necessarily as an array, as it could be as well a double-linked list), so te implementation can also be "stackless" (i.e. the Lua VM engine could be used with a small constant maximum use of the native thread stack, all the rest only needing a head, and even all Lua objects could have a constant maximum native size, allowing efficient reuse of the native heap with low level of fragmentation, and faster use of the native heap, and low footprint on the native heap).
It's important to remember that the Lua table is a generalization of several wellknown structures: lists, arrays, vectors, associative arrays, sets, trees... it can be used in fact for all kinds of collections (including collections of collections). Lua also allows tables to be linked to another table to form a chain of tables (so it also natively allows ternary trees of collections with all orders/ranks).
If we view the language this way, there's large freedom of implementation, and much more possibilities to implement not just interpreters, but as well compilers (including JIT compilers and static compilers) than what the current Lua.org's implementation currently uses.: Even Lua.org's has changed between versions how this implementation was done. Even the opcodes where considerably changed (i.e. the VMs themselves were necessarily incompatible, but not the language itself and programs written in it). This allowed multiple implementations to appear, and allowed the language to be integrated in many more environments, including the smallest ones (e.g. on IoT devices, or even small 8-bit microcontrolers, or within other VMs for languages like Java or _javascript_, or within networked environments, or within SQL engines for example in stored procedures and triggers). Lua is extremely flexible nad much less dependant than other languages like C/C++ which require a much more complex base environement and setting up a processing model with harder to support.
The concept of "registers" in the Lua.org's implemetnation is nothing else than a conceptualization of an integer-indexed array which is used in hope to improve data locality, it is not necessarily bound to native registers. It is used only because of the way its opcodes are encoded in its VM instruction set (but the same can be said as well in C/C++ stack based implementations using [BP+offset] indexed arrays for local variables, and *caching* a few of them in native registers. The main difference being that "words" used in the Lua.org's implementation is not just n-bit integers (like in native CPUs) but can hold any Lua's datatype (i.e. it is a tagged TV value which can be represented by a fixed-size object, even if some bits are actually references to other "words").

Le ven. 16 nov. 2018 à 09:54, Dirk Laurie <dirk.laurie@gmail.com> a écrit :
Op Vr. 16 Nov. 2018 om 05:25 het Philippe Verdy <verdy_p@wanadoo.fr> geskryf:

> The upvalues are in some table (even if the LuaVM uses a faster approach using an array for the environment of function closures, which allows faster and direct indexing by it's internal opcode).

> The opcodes however are not relevant, they are internals of the VM

> When you realize that, you can see that there's a much wider way to implement a VM and its intruction set (generated by its internal compiler, which may be multistaged, with several kinds of instruction sets and opcodes).

I thnk we are all agreed that the VM and its instruction set, and
therefore binary Lua chunks, are implementation details.

Where we seem to differ, is in what other concepts are also
implementation details.

Philippe's point of view is that there exists a scripting language
called Lua, for which in principle a compiler or interpreter is
possible that does not use the Lua stack model and C API, thereby
relegating that model to an implementation detail. In such an
implementation, there would be no need for any data stucture other
than a table.

The rest of us take the point of view that whatever is in the manual
is part of the official specification ot Lua, not an implementation
detail.

I grant Philippe the validity of his point of view. There are some
practical difficulties, such as the entire run-time library that would
have to be rewritten and re-debugged if you do not have the API at
your disposal, but in theory it is fine.

But then we come to the whole question of name resolution. Lua has an
interesting mixture: local variables, including upvalues, have lexical
scope and are resolved at compile time; global variables are resolved
at runtime. This has not necessarily always been the case, but from
Lua 5.2 it has been part of the definition of Lua that a global
variable is equivalent to a field in a table named _ENV.

There would need to be a similar table _LOC for local variables (which
includes parameters), and as Philippe has said, its __index metamethod
would be another _LOC, eventually leading to _ENV.

There is a certain economy of thought here: the use of the table as
the only data structuring mechanism is carried a step further, the
distinction between "upvalue" and "global" would disappear, closures
would not be needed.

This economy is however immediately lost in performance, involving
time and memory resources. Much of the work done in the usual model at
compile time would now (repeatedly) be done at runtime. In order to
preserve lexical rather than dynamic scoping. a new _LOC table would
be necessary for every 'local' statement.

But it does seem to be _possible_ to get a working Lua interpreter that way.