§ 23 — Execute-phase API
23. Execute-phase API
Normative. This chapter defines the Cook Lua API surfaces that are only bound during the execute phase: the cook-body globals on Lua-code work units, and the test Lua-block bindings.
23.1. Cook-body Lua globals
Phase. Execute-phase only.
When the execute phase runs a Lua-code unit recorded by cook.add_unit (§ 22.1) with a lua_code payload — for example, one recorded from >{ ... } on a cook step (§ 8.4, § 8.5) — a conforming implementation MUST, immediately before evaluating lua_code, bind the following globals on the worker’s Lua VM:
| Global | Type | Value |
|---|---|---|
inputs | table | A 1-indexed sequence of the unit’s input paths, in the order recorded. |
outputs | table | A 1-indexed sequence of the unit’s output paths, in the order recorded. |
input | string | inputs[1], or the empty string if inputs is empty. |
output | string | outputs[1], or the empty string if outputs is empty. |
input_N | table | For each input group g at 1-based index N in the unit’s gather_groups, input_N is a 1-indexed sequence of the paths in g. |
A conforming implementation MUST bind input_N for every input group recorded, in increasing N. Groups not recorded MUST NOT be implicitly bound — a reference to input_3 when only two groups exist MUST read as nil rather than as an empty table.
Example 23.1.1
For the multi-output Lua-block cook step
recipe build_lua
gather "src/*.rs"
cook "staging-lua/out.js" "staging-lua/out.wasm" >{
os.execute("mkdir -p staging-lua")
local sources = table.concat(inputs, " ")
local js = io.open(outputs[1], "w")
js:write("// generated from " .. sources .. "\n")
js:close()
local wasm = io.open(outputs[2], "w")
wasm:write("BINARY\n")
wasm:close()
}
the execute-phase worker binds inputs to the resolved input paths, outputs to { "staging-lua/out.js", "staging-lua/out.wasm" }, input to inputs[1], output to "staging-lua/out.js", and input_1 to the first (and only) input group.
Note 23.1.1
These globals are bindings on the worker VM, not on the register-phase VM. A register-phase Lua step (> expr or >{ ... } outside a cook-step body) MUST NOT observe them.
23.2. Test Lua-block bindings
A Lua block in a test_step body (§ 8.6) is bound according to the step’s mode (§ 8.4.1):
| Binding | Mode | Type | Meaning |
|---|---|---|---|
input | one-to-one | string | The current iteration item — one of the source items |
inputs | many-to-one | table (1-indexed) | The full source list |
A conforming implementation MUST bind exactly one of input / inputs per unit when the step is in one-to-one or many-to-one mode, per the mode the body’s content selected. The other is unbound (Lua nil on reference). In one-shot mode (§ 8.4.1), neither input nor inputs is bound — both are nil on reference.
A conforming implementation MUST NOT bind output / outputs for test units; these have no meaning in a step that declares no outputs. A conforming implementation MUST NOT bind input_N (indexed input access) for test units; the source list is exposed wholesale via inputs in many-to-one mode.
Cross-recipe references inside a test Lua body use cook.dep_output() / cook.dep_output_list(), identical to a >{ … } Lua body (§ 23.1).