Functions¶
A function declaration defines a callable symbol, its parameter interface, an optional return type, and an executable body.
::clamp FUNCTION(@value I32, @minimum I32, @maximum I32): I32
{
IF (value < minimum) { RETURN minimum; }
IF (value > maximum) { RETURN maximum; }
RETURN value;
}
An ordinary function declaration always has a body. Signature-only functions
occur in interfaces and generic surfaces, while external declarations use
EXTERN_PROCEDURE.
Definitions¶
Function: A function is a section of code declared with the FUNCTION keyword.
Functum: A functum is a collection of 1 or more functions defined in same symbol. For example, two separate ::squareroot functions declared for F32 and F64 inputs comprise a single unified functum.
Functanoid: The concrete instantiation of a function applied to specific argument types. Functions can have formal parameters with so-called temploidic types, such as AUTO, in which case a single function can have multiple associated functanoids.
Procedure: A unit of generated machine code which is executable. It's possible for a single functanoid to have multiple associated procedures, such as with and without AVX512.
Exception contract¶
Ordinary functions may propagate exceptions. The NOEXCEPT modifier requires
exception handling to complete before control leaves the callable:
::fallback_value FUNCTION() NOEXCEPT: I32
{
TRY { THROW I32(@OTHER 17); }
CATCH error CONST& I32 { RETURN error; }
RETURN 0;
}
An escaping exception terminates execution at this boundary; an outer caller cannot catch it. See Exception Handling for local handling, cleanup, and constexpr behavior.
Named parameters¶
@api_name Type declares a named parameter. The API name is written explicitly
at multi-argument call sites and is also the default local name:
::divide FUNCTION(@numerator I32, @denominator I32): I32
{
RETURN numerator / denominator;
}
VAR result I32 := divide(@numerator 20, @denominator 4);
@api_name:local_name gives the body a different local spelling without
changing the call interface:
@ARG is the conventional name for a one-argument interface. A call with one
bare argument binds it to @ARG:
The bare form is limited to exactly one argument. Other calls write every named
argument as @name expression.
Positional parameters¶
%local_name Type declares a positional parameter:
::sum_pair FUNCTION(%left I32, %right I32): I32
{
RETURN left + right;
}
ASSERT(sum_pair(% [4, 5]) == 9);
%IGNORED Type consumes one positional argument without introducing a local
name. Positional arguments are passed in % [...] groups. A signature may mix
named and positional parameters; argument mapping uses the named API names and
the source order of positional formals independently.
Variadic positional parameters¶
%...name Type consumes the remaining positional values as a pack.
%...IGNORED Type accepts the pack without naming it.
Only one positional pack is permitted, and no ordinary positional parameter may follow it. Pack element types are checked or deduced as described in Variadic Packs.
Keyword argument capture¶
A final @KWARGS ... parameter captures unmatched named arguments in a
composite. @KWARGS:options ... names the local record options. An empty
capture is valid, and the fields preserve supplied argument types.
COMPOSITE_* operations inspect and transform the capture. APPLY forwards
the capture. The spelling @... is not accepted. See
Composites for the complete capture rules.
Parameter types and access¶
Value parameters initialize a local parameter object. Reference types express access to the caller's object:
CONST& Tpermits reads;MUT& Tpermits reads and writes;WRITE& Tis a pure output destination that the callee must initialize before reading;TEMP& Tbinds the temporary-value category;AUTO& AUTOdeduces a reference and its qualifier.
Pointer and procedure types are ordinary parameter types. AUTO, AUTO(name),
and composite patterns make the function deduced for the concrete call; see
Type Queries and Deduction and
Overload Resolution.
Default arguments¶
DEFAULT(expression) follows the parameter type:
Omitted parameters with defaults are initialized at the call. Missing required parameters make the function non-viable. Full declaration-context and overload rules are on Default Arguments.
Return type¶
The return type follows : after the parameter list and any ENABLE_IF:
Omitting : Type declares a VOID function. AUTO and other type patterns can
deduce the result from value-returning paths. Every reachable exit must satisfy
the selected result contract. See RETURN Statements.
Overloads and ENABLE_IF¶
Several declarations may share a name when their callable signatures differ:
Parameter binding, type adaptation, template deduction, candidate priorities,
and ENABLE_IF determine the selected declaration. ENABLE_IF(condition) is
written after the parameter list and before the return type:
::small_width FUNCTION(@ARG AUTO(value_type))
ENABLE_IF(BITS(value_type) < 32 AS I32): I32
{
RETURN BITS(value_type) AS I32;
}
Its condition is evaluated for the concrete candidate instantiation. See Overload Resolution for the complete ranking rules.
Member and nested functions¶
Within a structure, . declares an instance member and :: declares a nested
function that receives no object:
::counter STRUCT
{
.value VAR I32;
.read FUNCTION() CONST: I32 { RETURN .value; }
.set FUNCTION(@ARG I32) MUT { .value := ARG; }
::zero FUNCTION(): counter { RETURN counter(); }
}
The suffix MUT, CONST, WRITE, or TEMP declares the receiver qualifier
and is equivalent to an explicit @THIS <qualifier>& THISTYPE parameter.
THIS names the current object; .member is shorthand for its member.
Receiver and field rules are detailed on Structures.
Calls and function values¶
Named and positional call arguments are evaluated in source order before the selected function body begins. Calls may target a function symbol, member, procedure pointer, or callable function value. See Call Arguments and Procedure Pointers and Function Values.