Expand description
The Lua backend of the shared codec walk.
DDS-XTypes 1.3 §7.4 from the clause, the same as runtime/c,
runtime/python and the rest do, and none of them calls another.
Where two columns disagree on an octet, one has misread the
specification — which is the only reason to have another.
§The shapes this column holds a value in
adapter/lua.rs is the authority and this file spells nothing it
does not declare:
- a struct, a union, a bitset, a sequence, an array and a map are
all tables — a sequence 1-based, a map an array of
{ key = …, value = … }pairs; - a
charand awcharare integers holding the code point, which is whyLua::code_pointis the identity and a character case label stays the number it arrived as; - an
unsigned long longis the 64-bit two’s-complement bit pattern in a Lua integer, which is whyLua::unsigned_lessanswersmath.ultat eight octets — Lua’s<on two patterns is signed and sorted16045690984833335998after7; - a
long doubleand afixedare decimal strings, converted at the octet byruntime/lua; - an absent
@optionalmember is an absent key:v.m ~= nilis the presence test andv.m = nilthe removal, because in Lua the absence of a value is the absence of the key.
§The four decisions this column turns on
Codecs live in one table. Every generated routine is
function ZD.zd_enc_T(w, v) … end and every call is ZD.zd_enc_T,
because a chunk holds at most 200 locals and a corpus case’s codecs,
defaulters and dumpers together would cross that as local functions.
A table lookup also resolves at the call and not at the definition,
so a recursive or mutually recursive type needs no forward
declaration — Lua::routine answers None for one, exactly as
the Python backend does. The caller binds local ZD = {} before the
declarations, the same contract adapter::lua::lua_items has for M.
An assignment is a statement. a = b is not a Lua expression.
The shared walk builds one through T::perform(T::binary("=", …))
at every assignment site, so Lua::perform recognises that shape
and answers lua::Stat::Assign; everything else it receives is a
call, which is the one expression Lua’s grammar takes as a statement.
A counted loop stays zero-based and the subscript adds one. The
walk counts 0 .. bound exclusive and compares counters against
ranks; a backend that moved the loop to 1 .. bound would have to
move the rank arithmetic with it. So Lua::count_up writes
for i = 0, bound - 1 and Lua::index writes t[(i) + 1], and
the 1-based convention is decided in exactly one method.
The boolean spellings are Lua’s. &&, ||, ! and != become
and, or, not and ~=; false before true — the raw token the
walk escapes through Literal::Int — is rewritten to the literal,
as the Python backend does for False.
§What Lua cannot check, said plainly
Nothing in a generated chunk declares a type, so a wrong shape here
is not a compile error anywhere — it is a wrong octet in the
measurement or an error at run time. That is why this backend leans
on the two loud failure modes Lua does have: a call through a name
ZD does not hold reports the name at the line, and runtime/lua
range-checks every value at the octet.
Structs§
- Lua
- The Lua backend.
- LuaType
- The nominal type a local is annotated with — which in Lua is
nothing at all, so the type is a tag this backend keeps for its own
two decisions: whether a cast target is
boolean(a union label becomestrue/false), and whether a storage request is the map entry marker. Everything else is carried through untouched.