Skip to content

§ 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:

GlobalTypeValue
inputstableA 1-indexed sequence of the unit’s input paths, in the order recorded.
outputstableA 1-indexed sequence of the unit’s output paths, in the order recorded.
inputstringinputs[1], or the empty string if inputs is empty.
outputstringoutputs[1], or the empty string if outputs is empty.
input_NtableFor 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):

BindingModeTypeMeaning
inputone-to-onestringThe current iteration item — one of the source items
inputsmany-to-onetable (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).