Lua.VM.State (Lua v1.0.0-rc.3)
View SourceRuntime state for the Lua VM.
Summary
Functions
Allocates a fresh table in the state, returning {{:tref, id}, new_state}.
Allocates userdata and returns a reference.
Guards against unbounded recursion.
Deletes a private value.
Returns the _G table reference.
Reads a global variable from the VM state. Returns nil if unset.
Retrieves a private value. Raises KeyError if the key doesn't exist.
Fetches a table by reference.
Gets userdata by reference.
Returns the underlying globals data map (read-only convenience).
Creates a new VM state.
Stores a private value not exposed to Lua.
Registers a native Elixir function as a global in the VM state.
Sets a global variable in the VM state.
Charges one instruction against the budget and returns the new tally.
Recovers the state a protected call should continue with after trapping an error.
Updates a table in-place via a function.
Types
@type t() :: %Lua.VM.State{ call_depth: non_neg_integer(), call_stack: list(), g_ref: nil | {:tref, non_neg_integer()}, instruction_count: non_neg_integer(), max_call_depth: pos_integer() | :infinity, max_instructions: pos_integer() | :infinity, max_string_bytes: pos_integer(), metatables: map(), multi_return_count: non_neg_integer(), open_upvalues: term(), private: map(), table_next_id: non_neg_integer(), tables: %{optional(non_neg_integer()) => Lua.VM.Table.t()}, upvalue_cells: map(), userdata: %{optional(non_neg_integer()) => term()}, userdata_next_id: non_neg_integer() }
Functions
@spec alloc_table(t(), map()) :: {{:tref, non_neg_integer()}, t()}
Allocates a fresh table in the state, returning {{:tref, id}, new_state}.
@spec alloc_userdata(t(), term()) :: {{:udref, non_neg_integer()}, t()}
Allocates userdata and returns a reference.
Userdata stores arbitrary Elixir terms that can be passed through Lua but not directly manipulated by Lua code.
@spec check_call_depth!(t()) :: :ok
Guards against unbounded recursion.
Raises a Lua "stack overflow" runtime error when the call depth has
reached max_call_depth. Call it immediately before pushing a frame
onto call_stack.
No-op when depth is under the limit or when max_call_depth is
:infinity (the default). The clauses are ordered so both common cases
resolve in a single function-head match with no struct rebuild.
Deletes a private value.
@spec g_ref(t()) :: {:tref, non_neg_integer()}
Returns the _G table reference.
Reads a global variable from the VM state. Returns nil if unset.
Retrieves a private value. Raises KeyError if the key doesn't exist.
@spec get_table( t(), {:tref, non_neg_integer()} ) :: Lua.VM.Table.t()
Fetches a table by reference.
@spec get_userdata( t(), {:udref, non_neg_integer()} ) :: term()
Gets userdata by reference.
Returns the underlying globals data map (read-only convenience).
Equivalent to state._G.data. Avoid using this for state mutation —
use set_global/3 instead so that future invariants stay consistent.
@spec new() :: t()
Creates a new VM state.
Allocates an empty _G table to hold globals.
Stores a private value not exposed to Lua.
Registers a native Elixir function as a global in the VM state.
The function should accept (args, state) and return {results, state},
where args is a list of Lua values and results is a list of return values.
Sets a global variable in the VM state.
Writes into the _G table's data map. Globals storage lives entirely
inside the _G table since Plan A16 (Lua 5.3 _ENV semantics).
@spec tick!(t(), non_neg_integer()) :: non_neg_integer()
Charges one instruction against the budget and returns the new tally.
Guards against unbounded CPU work within a single evaluation by folding
the running-tally increment and the budget check into one call. Call it
at loop back-edges and call boundaries — never per opcode — so the
default :infinity path stays free of per-instruction cost.
The tally is threaded as a parameter, not stored in %State{}. When
max_instructions is :infinity (the default) this is a true no-op: it returns
the tally unchanged in a single function-head match, doing no arithmetic
and rebuilding no struct, so the default path's only per-boundary cost is
this one call. When a finite budget is set it increments the tally and,
once the new tally reaches max_instructions, raises a catchable Lua
"instruction budget exceeded" runtime error. The clauses are ordered so
both the :infinity and under-budget cases resolve in a single
function-head match.
The raise reuses the same Lua.VM.RuntimeError used by "stack overflow", carrying the raise-time state: so pcall/xpcall recover
heap effects for free. The live tally is stamped into that state: (the
threaded instruction_count is not otherwise in %State{}), so unwind_to/2 can
carry it forward and a caught budget error stays spent — a protected call
cannot refund the work it burned.
Recovers the state a protected call should continue with after trapping an error.
Lua 5.3 §2.3: an error aborts the protected call, but heap effects made
before it — global writes, table mutations, upvalue-cell assignments,
metatable changes — are kept. Only control state unwinds. Accordingly,
heap fields come from raised (the state captured at the raise site,
ferried out on the exception's :state field) while control fields are
restored from entry (the state at protected-call entry):
kept from raised (heap) | restored from entry (control) |
|---|---|
tables, table_next_id | call_stack, call_depth |
userdata, userdata_next_id | open_upvalues |
metatables, upvalue_cells, private | multi_return_count |
The instruction tally instruction_count is also carried forward (monotonic max), not
reset to the entry value: the work a protected call burned must still count
against the one per-evaluation :max_instructions budget, so wrapping heavy work in
pcall (or looping over pcall) cannot escape the cap.
Keeping upvalue_cells while restoring open_upvalues matches reference
upvalue semantics: cells captured before the protected call keep their
mutated values, while cells opened by the unwound frames become
unreachable garbage.
When no raise-time state was captured (raised is nil, e.g. the error
came from outside Lua execution), falls back to entry unchanged.
@spec update_table( t(), {:tref, non_neg_integer()}, (Lua.VM.Table.t() -> Lua.VM.Table.t()) ) :: t()
Updates a table in-place via a function.