Lua.VM.Table (Lua v1.0.0-rc.0)
View SourceLua table data structure.
A single Elixir map backing both array and hash portions, plus a list of keys in insertion order and a key-set of "dead" keys whose values were cleared during iteration.
Keys and values are VM values (numbers, strings, booleans, {:tref, id},
etc.). Integer keys use 1-based indexing per Lua convention.
Dead-key tracking
Lua 5.3 §6.1 says iteration with pairs is well-defined when the body
clears existing fields (t[k] = nil). The reference implementation
preserves the iteration sequence by leaving cleared keys reachable in
the hash chain (marked TDEADKEY) so the next call to next(t, k) can
still find the entry that follows k.
We mirror that behavior with two pieces of state:
order— keys in the order they were first assigned a value. Live and dead keys both appear; assigning a fresh value to a previously dead key moves it to the end (it counts as a new insertion).dead— akey => truemap of keys that have been assignednil. Their slot inorderis preserved sonext(t, k)can locate the slot, butdatano longer contains the key, so the key is reported as absent to readers. (We use a plain map rather thanMapSethere so dialyzer can treat the empty default opaquely; the API surface is the same —Map.has_key?/2,Map.put/3,Map.delete/2.)
All mutations should flow through put/3 (or put_data/3 for code that
only has access to the underlying data map and doesn't care about the
iteration ordering).
Summary
Functions
Flushes any pending appends in order_tail into order.
Builds a table struct from a plain data map.
Reads a value from a table data map, applying Lua key normalization (integer-valued floats collapse to integers per §3.4.11).
Returns true when the table data map has an entry for the given key after normalization.
Returns true if a key is invalid for use in a table assignment.
Returns the next key/value pair in iteration order after key.
Normalizes a table key per Lua 5.3 §3.4.11.
Writes value into the table under key, honoring Lua semantics
Writes value into a raw data map under key.
Replaces the data map wholesale, rebuilding order and clearing dead.
Types
Functions
Flushes any pending appends in order_tail into order.
Idempotent: a table with an empty tail is returned unchanged. Used by
callers that want to amortize the cost of repeated next_entry calls
(e.g. lua_next in the stdlib, which iterates via repeated calls).
Builds a table struct from a plain data map.
order is derived from the data map's key list — Erlang maps surface
their keys in a deterministic order, so callers that pass us a literal
data map (e.g. stdlib initialization) get a sensible iteration order
with no extra effort.
Reads a value from a table data map, applying Lua key normalization (integer-valued floats collapse to integers per §3.4.11).
Returns true when the table data map has an entry for the given key after normalization.
Returns true if a key is invalid for use in a table assignment.
Per Lua 5.3 §3.4.11 / §6.1, table keys cannot be nil or NaN.
Callers should raise with the appropriate "table index is nil" /
"table index is NaN" error message before mutating table data.
Returns the next key/value pair in iteration order after key.
Walks the table's order list to find key, then advances through any
dead-key slots until a live entry is found. Returns {k, v} for the
next live entry, or nil when iteration is complete.
When key is nil, returns the first live entry (or nil if the
table is empty/all-dead).
When key is non-nil and is not present in order at all, returns the
sentinel :invalid_key so the caller can raise the user-facing
"invalid key to 'next'" error per Lua 5.3 §6.1.
Normalizes a table key per Lua 5.3 §3.4.11.
Float keys that hold an exact integer value are coerced to integers so
that t[1.0] and t[1] refer to the same slot. NaN keys are left as
floats; callers that disallow NaN keys (set_table, rawset) detect
the NaN and raise before reaching the data map.
Writes value into the table under key, honoring Lua semantics:
- Assigning
nilremoves the key fromdataand marks it dead inorderif it was previously live (Lua 5.3 §3.4.11 / §6.1). - Any other value is stored normally; if the key was previously
dead, it is revived and re-appended to
orderso the new assignment counts as a fresh insertion.
Used by every code path that mutates table contents (set_table,
set_field, set_list, rawset, table.insert, etc.) so the
insertion-order invariant stays consistent.
Writes value into a raw data map under key.
Lower-level than put/3: operates only on the underlying map, with no
awareness of order/dead. Use this when you have a data map but no
surrounding Table struct (e.g. while folding through set_list
intermediate state). Prefer put/3 whenever you have the full struct.
Replaces the data map wholesale, rebuilding order and clearing dead.
Used by stdlib operations that rewrite the entire table contents (e.g.
table.sort shuffles every integer key). After this call, iteration
order reflects the new map layout.