9.3.6.4 Function Prologue Instructions

A function call in Guile is very cheap: the VM simply hands control to
the procedure. The procedure itself is responsible for asserting that it
has been passed an appropriate number of arguments. This strategy allows
arbitrarily complex argument parsing idioms to be developed, without
harming the common case.

For example, only calls to keyword-argument procedures “pay” for the
cost of parsing keyword arguments. (At the time of this writing, calling
procedures with keyword arguments is typically two to four times as
costly as calling procedures with a fixed set of arguments.)

Instruction: assert-nargs-ee n

Instruction: assert-nargs-ge n

Assert that the current procedure has been passed exactly n
arguments, for the -ee case, or n or more arguments, for
the -ge case. n is encoded over two bytes.

The number of arguments is determined by subtracting the frame pointer
from the stack pointer (sp - (fp -1)). See section Stack Layout, for
more details on stack frames.

Instruction: br-if-nargs-ne n offset

Instruction: br-if-nargs-gt n offset

Instruction: br-if-nargs-lt n offset

Jump to offset if the number of arguments is not equal to, greater
than, or less than n. n is encoded over two bytes, and
offset has the normal three-byte encoding.

These instructions are used to implement multiple arities, as in
case-lambda. See section Case-lambda, for more information.

Instruction: bind-optionals n

If the procedure has been called with fewer than n arguments, fill
in the remaining arguments with an unbound value (SCM_UNDEFINED).
n is encoded over two bytes.

The optionals can be later initialized conditionally via the
local-bound? instruction.

Instruction: push-rest n

Pop off excess arguments (more than n), collecting them into a
list, and push that list. Used to bind a rest argument, if the procedure
has no keyword arguments. Procedures with keyword arguments use
bind-rest instead.

Instruction: bind-rest n idx

Pop off excess arguments (more than n), collecting them into a
list. The list is then assigned to the idxth local variable.

Shuffle keyword arguments to the top of the stack, filling in the holes
with SCM_UNDEFINED. Each argument is encoded over two bytes.

This instruction is used by procedures with keyword arguments.
nreq is the number of required arguments to the procedure, and
nreq-and-opt is the total number of positional arguments (required
plus optional). bind-optionals/shuffle will scan the stack from
the nreqth argument up to the nreq-and-optth, and start
shuffling when it sees the first keyword argument or runs out of
positional arguments.

bind-optionals/shuffle-or-br does the same, except that it checks
if there are too many positional arguments before shuffling. If this is
the case, it jumps to offset, encoded using the normal three-byte
encoding.

Shuffling simply moves the keyword arguments past the total number of
arguments, ntotal, which includes keyword and rest arguments. The
free slots created by the shuffle are filled in with
SCM_UNDEFINED, so they may be conditionally initialized later in
the function’s prologue.

Instruction: bind-kwargs idx ntotal flags

Parse keyword arguments, assigning their values to the corresponding
local variables. The keyword arguments should already have been shuffled
above the ntotalth stack slot by bind-optionals/shuffle.

The parsing is driven by a keyword arguments association list, looked up
from the idxth element of the procedures object array. The alist
is a list of pairs of the form (kw . index), mapping
keyword arguments to their local variable indices.

There are two bitflags that affect the parser, allow-other-keys?
(0x1) and rest? (0x2). Unless
allow-other-keys? is set, the parser will signal an error if an
unknown key is found. If rest? is set, errors parsing the
keyword arguments will be ignored, as a later bind-rest
instruction will collect all of the tail arguments, including the
keywords, into a list. Otherwise if the keyword arguments are invalid,
an error is signalled.

idx and ntotal are encoded over two bytes each, and
flags is encoded over one byte.

Instruction: reserve-locals n

Resets the stack pointer to have space for n local variables,
including the arguments. If this operation increments the stack pointer,
as in a push, the new slots are filled with SCM_UNBOUND. If this
operation decrements the stack pointer, any excess values are dropped.

reserve-locals is typically used after argument parsing to
reserve space for local variables.

Instruction: assert-nargs-ee/locals n

Instruction: assert-nargs-ge/locals n

A combination of assert-nargs-ee and reserve-locals. The
number of arguments is encoded in the lower three bits of n, a
one-byte value. The number of additional local variables is take from
the upper 5 bits of n.