Group: calls

Calls a function when current frame is being discarded.


    defer some_function/0
    defer %some_fn local


defer instruction takes either a function name, or an operand evaluating to callable value as input. It has no output, and is used solely for its side effects.

Deferred calls are invoked when the call frame in which they were registered is being logically discarded, that is:

Deferred calls are guaranteed to finish running before the frame is dropped, and its values destroyed so all pointers to values existing in the frame being dropped that were passed to the deferred call are valid for the duration of the deferred call. This may be, for example, used to implement resource management: a deferred call may receive a pointer to a file handle, and close the handle via the pointer.

Order of invocation

Deferred calls are invoked in reverse order of registration. If deferred call to fA/0 is registered before deferred call to fB/0 then fB/0 will be invoked before fA/0.

Deferred calls may be nested, i.e. functions invoked by defer instruction may register further deferred calls. The order of invocation is preserved in such situations, meaning that if fN/0 defers fA/0 and then fB/0, and fB/0 defers fC/0 then the order of invocations is as follows:

  1. fN/0
  2. fB/0
  3. fC/0
  4. fA/0

fC/0 is invoked before fA/0 because it was deferred later.


.function: runs_nested_deferred/0
    print (text %1 local "Hello World! (nested)")

.function: runs_deferred_a/0
    print (text %1 local "Hello World! (a)")

.function: runs_deferred_b/0
    frame %0
    defer runs_nested_deferred/0

    print (text %1 local "Hello World! (b)")

.function: main/0
    frame %0
    defer runs_deferred_a/0

    frame %0
    defer runs_deferred_b/0

    izero %0 local

Expected output:

    Hello World! (b)
    Hello World! (nested)
    Hello World! (a)

Related instructions

frame, param, pamv, arg, tailcall, return, process, call.