Skip to content

Section 40: Function Calls, Argument Passing, and Return Semantics

TECHSPEC-40 — Section 40 · Version 0.1 · Status: Initial Draft

Status: draft. This section is an Initial Draft (Section 57 is a Working Register). It describes intended or proposed behavior, not a finalized, implemented language rule. Do not treat examples here as normative.

1. Function Call Philosophy

Function calls must have predictable behavior, explicit data flow, and enforceable contracts.

The language must define exactly how arguments are evaluated, passed, modified, and returned.

A function call must never silently discard a failure or conceal an unintended state change.

2. Function Invocation

A function is invoked using its declared name and arguments.

Example:

LET balance: Decimal = account.getBalance()

Rules: - The function must be accessible from the calling scope. - The number of arguments must match the function signature. - Arguments must satisfy their declared types. - Preconditions must be checked or established before execution. - Required permissions must be available. - Declared effects must be respected. - Invalid calls must be rejected by the compiler whenever detectable.

3. Argument Evaluation

Arguments are evaluated from left to right, following Section 39.

Rules: - Each argument is evaluated exactly once. - Evaluation failures must be handled explicitly. - Side effects occur in the defined evaluation order. - The compiler must not reorder arguments when doing so changes observable behavior. - Argument evaluation must not bypass contracts or permission checks.

4. Argument Passing Modes

The language supports explicit argument passing modes.

VALUE

Passes a value to the function.

FUNCTION calculateTax(amount: Decimal) -> Decimal

Rules: - The function receives a value according to the type's defined copy or value semantics. - Changes to a local value do not implicitly modify the caller's variable.

READ REF

Passes read-only access to an existing value.

FUNCTION inspectAccount(account: READ REF Account) -> Decimal

Rules: - The function may inspect the referenced value. - The function cannot mutate it through that reference. - The reference cannot outlive its permitted lifetime.

MUT REF

Passes exclusive mutable access.

FUNCTION updateAccount(account: MUT REF Account) -> Unit

Rules: - The caller must have permission to provide mutable access. - Conflicting references are prohibited. - Mutation must preserve the object's invariants. - The reference cannot outlive its permitted lifetime.

OWNERSHIP TRANSFER

Transfers ownership to the receiving function.

FUNCTION consumeResource(resource: OWNED FileHandle) -> Result<Unit, FileError>

Rules: - The caller relinquishes ownership. - The receiving function becomes responsible for the resource. - The caller cannot continue using the transferred resource. - Cleanup responsibilities must be explicit.

5. Default Argument Rules

The initial language version should require explicit arguments.

Rules: - No implicit default values. - No automatic argument insertion. - No hidden argument conversions. - If defaults are introduced later, they must be declared in the function signature and follow deterministic evaluation rules.

6. Named Arguments

Named arguments may be supported to improve readability.

Example:

createAccount(
    owner: "Adam",
    initialBalance: 100.00
)

Rules: - Argument names must match declared parameter names. - Each parameter may be supplied only once. - Unknown or missing arguments must produce compiler errors. - Evaluation order remains the written argument order. - Named arguments must not change the function's declared semantics.

7. Return Semantics

Every function must declare a return type.

Rules: - Returned values must match the declared type. - Functions returning Unit must not return an unrelated value. - Every reachable execution path must satisfy the return requirements. - Returned references must obey lifetime and ownership rules. - Return values must not bypass postconditions. - Functions must not silently convert failures into successful return values.

8. Result and Optional Returns

Functions may return explicit safety types.

Examples:

FUNCTION findUser(id: Integer) -> Optional<User>

FUNCTION saveUser(user: User) -> Result<User, DatabaseError>

Rules: - Optional<T> represents possible absence. - Result<T, E> represents success or failure. - Callers must handle these values according to the language's error-handling rules. - Absence must not be confused with operational failure. - Failure causes must remain available where required.

9. Postcondition Timing

Postconditions must be evaluated after the function body completes successfully and before the call is considered successful.

Rules: - Postconditions evaluate against the resulting state. - OLD(expression) refers to the captured pre-execution value. - Failed postconditions must not be reported as successful execution. - Side effects that occurred before a postcondition failure must be recorded. - The language must not imply that external side effects were automatically rolled back.

10. Recursive Calls

Recursive functions are permitted.

Rules: - Recursive calls must obey ordinary function contracts. - Stack and execution resource limits must be observable. - Resource exhaustion must produce an explicit failure where the runtime can report it. - Termination must not be assumed merely because a function compiles. - Recursive verification must distinguish proven termination from unverified termination.

11. Compiler and Runtime Responsibilities

The compiler and runtime must: - Validate function signatures. - Check argument counts and types. - Enforce argument passing modes. - Preserve argument evaluation order. - Track ownership transfers. - Validate return types. - Enforce postconditions. - Propagate failures explicitly. - Report invalid or unverified function behavior.

12. Verification Limitations

A valid function call does not prove that the function's implementation is correct.

Verification reports must distinguish: - Function signature checked. - Argument types checked. - Preconditions established. - Permissions established. - Function execution started. - Function execution completed. - Return type validated. - Postconditions checked or proven. - External effects confirmed or uncertain.

13. Design Goal

An AI agent must be able to determine exactly what a function receives, what it may change, what it returns, and what can go wrong.

Function calls must make data flow and responsibility explicit rather than relying on hidden language behavior.


Source file: TECHSPEC-40.md (preserved in source-original/LANG/). See the specification index, the glossary, and the cross-reference index.