§tiro/functions.h

Functions and type definitions for creating native functions that are callable from tiro.

§Classes

Name
structtiro_resumable_frame_desc
Represents construction parameters for a resumable function.

§Types

Name
enumtiro_resumable_state { TIRO_RESUMABLE_STATE_START = 0, TIRO_RESUMABLE_STATE_END = -1}
Lists well known state values used by resumable functions.
typedef void(*)(tiro_vm_t vm, tiro_sync_frame_t frame)tiro_sync_function_t
The prototype of a native function callback that provides a synchronous tiro function.
typedef void(*)(tiro_vm_t vm, tiro_async_frame_t frame)tiro_async_function_t
The prototype of a native function callback that provides an asynchronous tiro function.
typedef void(*)(tiro_vm_t vm, tiro_resumable_frame_t frame)tiro_resumable_function_t
The prototype of a native function that implements a resumable function.
typedef enum tiro_resumable_statetiro_resumable_state_t
Lists well known state values used by resumable functions.
typedef struct tiro_resumable_frame_desctiro_resumable_frame_desc_t
Represents construction parameters for a resumable function.

§Functions

Name
size_ttiro_sync_frame_arg_count(tiro_sync_frame_t frame)
Returns the number of function call arguments present in the given frame.
voidtiro_sync_frame_arg(tiro_sync_frame_t frame, size_t index, tiro_handle_t result, tiro_error_t * err)
Stores the function call argument with the given index into result.
voidtiro_sync_frame_closure(tiro_sync_frame_t frame, tiro_handle_t result, tiro_error_t * err)
Returns the closure value which was specified when the function was created.
voidtiro_sync_frame_return_value(tiro_sync_frame_t frame, tiro_handle_t value, tiro_error_t * err)
Sets the return value for the given function call frame to the given value.
voidtiro_sync_frame_panic_msg(tiro_sync_frame_t frame, tiro_string message, tiro_error_t * err)
Signals a panic from the given function call frame.
voidtiro_make_sync_function(tiro_vm_t vm, tiro_handle_t name, tiro_sync_function_t func, size_t argc, tiro_handle_t closure, tiro_handle_t result, tiro_error_t * err)
Constructs a new function object with the given name that will invoke the native function func when called.
size_ttiro_async_frame_arg_count(tiro_async_frame_t frame)
Returns the number of function call arguments received by this frame.
voidtiro_async_frame_arg(tiro_async_frame_t frame, size_t index, tiro_handle_t result, tiro_error_t * err)
Retrieves the function call argument at the specified index and stores it into result.
voidtiro_async_frame_closure(tiro_async_frame_t frame, tiro_handle_t result, tiro_error_t * err)
Returns the closure value which was specified when the function was created.
voidtiro_async_frame_return_value(tiro_async_frame_t frame, tiro_handle_t value, tiro_error_t * err)
Sets the return value for the given function call frame to the given value.
voidtiro_async_frame_panic_msg(tiro_async_frame_t frame, tiro_string message, tiro_error_t * err)
Signals a panic from the given function call frame.
tiro_async_token_ttiro_async_frame_token(tiro_async_frame_t frame, tiro_error_t * err)
Returns a token for resuming an async function call after yielding.
voidtiro_async_frame_yield(tiro_async_frame_t frame, tiro_error_t * err)
Yields from an async function call, pausing the current coroutine until it is resumed via an async frame token.
voidtiro_make_async_function(tiro_vm_t vm, tiro_handle_t name, tiro_async_function_t func, size_t argc, tiro_handle_t closure, tiro_handle_t result, tiro_error_t * err)
Constructs a new function object with the given name that will invoke the native function func when called.
voidtiro_async_token_free(tiro_async_token_t token)
Destroys an async token.
voidtiro_async_token_return_value(tiro_async_token_t token, tiro_handle_t value, tiro_error_t * err)
Resumes a yielding coroutine that was paused by calling yield from an async function call frame.
voidtiro_async_token_panic_msg(tiro_async_token_t token, tiro_string_t message, tiro_error_t * err)
Resumes a yielding coroutine that was paused by calling yield from an async function call frame.
size_ttiro_resumable_frame_arg_count(tiro_resumable_frame_t frame)
Returns the number of function call arguments present in the given frame.
voidtiro_resumable_frame_arg(tiro_resumable_frame_t frame, size_t index, tiro_handle_t result, tiro_error_t * err)
Stores the function call argument with the given index into result.
size_ttiro_resumable_frame_local_count(tiro_resumable_frame_t frame)
Returns the number of local values available in the given frame.
voidtiro_resumable_frame_local(tiro_resumable_frame_t frame, size_t index, tiro_handle_t result, tiro_error_t * err)
Stores the frame's local value with the given index into result.
voidtiro_resumable_frame_set_local(tiro_resumable_frame_t frame, size_t index, tiro_handle_t value, tiro_error_t * err)
Stores the given value into the local value slot with the given index.
voidtiro_resumable_frame_closure(tiro_resumable_frame_t frame, tiro_handle_t result, tiro_error_t * err)
Returns the closure value which was specified when the function was created.
inttiro_resumable_frame_state(tiro_resumable_frame_t frame)
Returns the current state of the given frame.
voidtiro_resumable_frame_set_state(tiro_resumable_frame_t frame, int next_state, tiro_error_t * err)
Sets the current state of the given frame.
voidtiro_resumable_frame_invoke(tiro_resumable_frame_t frame, int next_state, tiro_handle_t func, tiro_handle_t args, tiro_error_t * err)
Signals the vm that the function func shall be invoked with the given arguments in args.
voidtiro_resumable_frame_invoke_return(tiro_resumable_frame_t frame, tiro_handle_t result, tiro_error_t * err)
Returns the result of the last function call made via tiro_resumable_frame_invoke.
voidtiro_resumable_frame_return_value(tiro_resumable_frame_t frame, tiro_handle_t value, tiro_error_t * err)
Sets the return value for the given function call frame to the given value.
voidtiro_resumable_frame_panic_msg(tiro_resumable_frame_t frame, tiro_string message, tiro_error_t * err)
Signals a panic from the given function call frame.
voidtiro_make_resumable_function(tiro_vm_t vm, const tiro_resumable_frame_desc_t * desc, tiro_handle_t result, tiro_error_t * err)
Constructs a new function object with the given description.

§Types Documentation

§enum tiro_resumable_state

EnumeratorValueDescription
TIRO_RESUMABLE_STATE_START0The initial state value.
TIRO_RESUMABLE_STATE_END-1Signals that the function has finished executing.

Lists well known state values used by resumable functions.

All positive integers can be used freely by the application.

§typedef tiro_sync_function_t

typedef void(* tiro_sync_function_t) (tiro_vm_t vm, tiro_sync_frame_t frame);

The prototype of a native function callback that provides a synchronous tiro function.

Parameters:

  • vm The virtual machine the function is executing on.
  • frame The function call frame. Use tiro_sync_frame_arg and tiro_sync_frame_arg_count to access the function call arguments. Call tiro_sync_frame_result to set the return value (it defaults to null if not set). The closure is also available by calling tiro_sync_frame_closure. The frame value is only valid for the duration of the function call.

This type of native function is appropriate for simple, nonblocking operations. Use the more complex asynchronous API instead if the operation has the potential of blocking the process.

Note that this API does not allow for custom native userdata. Use native objects instead and pass them in the closure.

§typedef tiro_async_function_t

typedef void(* tiro_async_function_t) (tiro_vm_t vm, tiro_async_frame_t frame);

The prototype of a native function callback that provides an asynchronous tiro function.

Parameters:

  • vm The virtual machine the function is executing on.
  • frame The function call frame. Use tiro_async_frame_arg and tiro_async_frame_arg_count to access the function call arguments. Call tiro_async_frame_return_value to set the return value (it defaults to null if not set). The closure is also available by calling tiro_async_frame_closure.

Functions of this type should be used to implement long running operations that would otherwise block the calling coroutine (for example, a socket read or write).

Calling an asynchronous function can pause ("yield") the calling coroutine. It will be resumed when a result is provided to the resume token object. Attempting to resume a coroutine multiple times is an error.

Note that this API does not allow for custom native userdata. Use native objects instead and pass them in the closure.

The frame is only valid for the duration of the native function call.

§typedef tiro_resumable_function_t

typedef void(* tiro_resumable_function_t) (tiro_vm_t vm, tiro_resumable_frame_t frame);

The prototype of a native function that implements a resumable function.

Parameters:

  • vm The virtual machine the function is executing on.
  • frame The function call frame. Use associated functions to manipulate the frame's state, to access function call arguments, etc.

Resumable functions are the most versatile and most complex kind of functions in the native API. They may return or yield any number of times and may also call other tiro functions. Because of the cooperative nature of coroutines in tiro, they must be implemented as state machines.

When a resumable function is invoked by the vm, a new call frame is created on the active coroutine's stack. This frame stores the function call's state (initially TIRO_RESUMABLE_STATE_START). The vm will continue to call the native function until it reaches the TIRO_RESUMABLE_STATE_END state either by performing a final return or by panicking. Until then, the function may manipulate its own state or invoke other functions by calling the frame's associated functions.

When a resumable function has either returned or panicked, the native function will be called one last time with a special TIRO_RESUMABLE_STATE_CLEANUP state that allows it to release any acquired resources.

TODO: yield?

§typedef tiro_resumable_state_t

typedef enum tiro_resumable_state tiro_resumable_state_t;

Lists well known state values used by resumable functions.

All positive integers can be used freely by the application.

§typedef tiro_resumable_frame_desc_t

typedef struct tiro_resumable_frame_desc tiro_resumable_frame_desc_t;

Represents construction parameters for a resumable function.

§Functions Documentation

§function tiro_sync_frame_arg_count

size_t tiro_sync_frame_arg_count(
tiro_sync_frame_t frame
)

Returns the number of function call arguments present in the given frame.

Returns 0 for invalid input arguments.

§function tiro_sync_frame_arg

void tiro_sync_frame_arg(
tiro_sync_frame_t frame,
size_t index,
tiro_handle_t result,
tiro_error_t * err
)

Stores the function call argument with the given index into result.

Returns TIRO_ERROR_OUT_OF_BOUNDS if the argument index is invalid.

§function tiro_sync_frame_closure

void tiro_sync_frame_closure(
tiro_sync_frame_t frame,
tiro_handle_t result,
tiro_error_t * err
)

Returns the closure value which was specified when the function was created.

§function tiro_sync_frame_return_value

void tiro_sync_frame_return_value(
tiro_sync_frame_t frame,
tiro_handle_t value,
tiro_error_t * err
)

Sets the return value for the given function call frame to the given value.

§function tiro_sync_frame_panic_msg

void tiro_sync_frame_panic_msg(
tiro_sync_frame_t frame,
tiro_string message,
tiro_error_t * err
)

Signals a panic from the given function call frame.

TODO: Allow user defined exception objects instead of plain string?

§function tiro_make_sync_function

void tiro_make_sync_function(
tiro_vm_t vm,
tiro_handle_t name,
tiro_sync_function_t func,
size_t argc,
tiro_handle_t closure,
tiro_handle_t result,
tiro_error_t * err
)

Constructs a new function object with the given name that will invoke the native function func when called.

argc is the number of arguments required for calling func. closure may be an arbitrary value that will be passed to the function on every invocation.

On success, the new function will be stored in result. Returns TIRO_BAD_TYPE if name is not a string. Returns TIRO_BAD_ARG if the the requested number of parameters is too large. The current maximum is 1024.

§function tiro_async_frame_arg_count

size_t tiro_async_frame_arg_count(
tiro_async_frame_t frame
)

Returns the number of function call arguments received by this frame.

Returns 0 on error.

§function tiro_async_frame_arg

void tiro_async_frame_arg(
tiro_async_frame_t frame,
size_t index,
tiro_handle_t result,
tiro_error_t * err
)

Retrieves the function call argument at the specified index and stores it into result.

Returns TIRO_ERROR_OUT_OF_BOUNDS if the argument index is invalid.

§function tiro_async_frame_closure

void tiro_async_frame_closure(
tiro_async_frame_t frame,
tiro_handle_t result,
tiro_error_t * err
)

Returns the closure value which was specified when the function was created.

§function tiro_async_frame_return_value

void tiro_async_frame_return_value(
tiro_async_frame_t frame,
tiro_handle_t value,
tiro_error_t * err
)

Sets the return value for the given function call frame to the given value.

This function can be used to signal an immediate return without yielding.

§function tiro_async_frame_panic_msg

void tiro_async_frame_panic_msg(
tiro_async_frame_t frame,
tiro_string message,
tiro_error_t * err
)

Signals a panic from the given function call frame.

This function can be used to signal an immediate panic without yielding. TODO: Allow user defined exception objects instead of plain string?

§function tiro_async_frame_token

tiro_async_token_t tiro_async_frame_token(
tiro_async_frame_t frame,
tiro_error_t * err
)

Returns a token for resuming an async function call after yielding.

Return: The async token or NULL in case of an error.

Yielding from an async function call must be implemented by

  1. acquiring an async token and storing it somewhere
  2. scheduling some asynchronous operation
  3. calling tiro_async_frame_yield and returning from the native function call After the async operation has completed, the coroutine may be resumed by
  1. calling tiro_async_token_return_value or tiro_async_token_panic_msg to provide a function result
  2. calling tiro_async_token_free to destroy the token The token must be freed via tiro_async_token_free when it is no longer needed.

NOTE: When a vm instance is being destroyed, all async tokens will be freed automatically if they have not been freed already. It is not necessary to resume an async function call when the vm is shutting down.

§function tiro_async_frame_yield

void tiro_async_frame_yield(
tiro_async_frame_t frame,
tiro_error_t * err
)

Yields from an async function call, pausing the current coroutine until it is resumed via an async frame token.

The native function should return immediately after calling this function.

§function tiro_make_async_function

void tiro_make_async_function(
tiro_vm_t vm,
tiro_handle_t name,
tiro_async_function_t func,
size_t argc,
tiro_handle_t closure,
tiro_handle_t result,
tiro_error_t * err
)

Constructs a new function object with the given name that will invoke the native function func when called.

argc is the number of arguments required for calling func. closure may be an arbitrary value that will be passed to the function on every invocation.

On success, the new function will be stored in result. Returns TIRO_BAD_TYPE if name is not a string. Returns TIRO_BAD_ARG if the the requested number of parameters is too large. The current maximum is 1024.

§function tiro_async_token_free

void tiro_async_token_free(
tiro_async_token_t token
)

Destroys an async token.

Must be called for each token in order to clean up memory associated with the given token.

§function tiro_async_token_return_value

void tiro_async_token_return_value(
tiro_async_token_t token,
tiro_handle_t value,
tiro_error_t * err
)

Resumes a yielding coroutine that was paused by calling yield from an async function call frame.

The associated async function call will return with the given value.

Async token must be freed when they are no longer needed.

§function tiro_async_token_panic_msg

void tiro_async_token_panic_msg(
tiro_async_token_t token,
tiro_string_t message,
tiro_error_t * err
)

Resumes a yielding coroutine that was paused by calling yield from an async function call frame.

The associated async function call will panic with the given error message.

Async token must be freed when they are no longer needed.

§function tiro_resumable_frame_arg_count

size_t tiro_resumable_frame_arg_count(
tiro_resumable_frame_t frame
)

Returns the number of function call arguments present in the given frame.

Returns 0 for invalid input arguments.

§function tiro_resumable_frame_arg

void tiro_resumable_frame_arg(
tiro_resumable_frame_t frame,
size_t index,
tiro_handle_t result,
tiro_error_t * err
)

Stores the function call argument with the given index into result.

Returns TIRO_ERROR_OUT_OF_BOUNDS if the argument index is invalid.

NOTE: this could return a handle directly, provided that the handle is only used while the frame pointer is valid.

§function tiro_resumable_frame_local_count

size_t tiro_resumable_frame_local_count(
tiro_resumable_frame_t frame
)

Returns the number of local values available in the given frame.

Returns 0 for invalid input arguments.

§function tiro_resumable_frame_local

void tiro_resumable_frame_local(
tiro_resumable_frame_t frame,
size_t index,
tiro_handle_t result,
tiro_error_t * err
)

Stores the frame's local value with the given index into result.

Returns TIRO_ERROR_OUT_OF_BOUNDS if the local index is invalid.

Local values are private to a function frame (i.e. the current function execution) and persist between calls to the implementing native function. They can be used to transport values between yields or nested function calls.

NOTE: this could return a mutable handle directly, provided that the handle is only used while the frame pointer is valid.

§function tiro_resumable_frame_set_local

void tiro_resumable_frame_set_local(
tiro_resumable_frame_t frame,
size_t index,
tiro_handle_t value,
tiro_error_t * err
)

Stores the given value into the local value slot with the given index.

Returns TIRO_ERROR_OUT_OF_BOUNDS if the local index is invalid.

Local values are private to a function frame (i.e. the current function execution) and persist between calls to the implementing native function. They can be used to transport values between yields or nested function calls.

NOTE: this function would not be necessary if get_local returned a handle.

§function tiro_resumable_frame_closure

void tiro_resumable_frame_closure(
tiro_resumable_frame_t frame,
tiro_handle_t result,
tiro_error_t * err
)

Returns the closure value which was specified when the function was created.

§function tiro_resumable_frame_state

int tiro_resumable_frame_state(
tiro_resumable_frame_t frame
)

Returns the current state of the given frame.

Returns 0 for invalid input arguments.

§function tiro_resumable_frame_set_state

void tiro_resumable_frame_set_state(
tiro_resumable_frame_t frame,
int next_state,
tiro_error_t * err
)

Sets the current state of the given frame.

Parameters:

  • frame The resumable call frame
  • next_state The new state value

It is usually not necessary to invoke this function directly as changing the state is also implied by other functions like tiro_resumable_frame_invoke and tiro_resumable_frame_return_value.

The calling native function should return after altering the state. The new state will be active when the native function is called for the next time.

Note that a few states have special meaning (see tiro_resumable_state_t).

§function tiro_resumable_frame_invoke

void tiro_resumable_frame_invoke(
tiro_resumable_frame_t frame,
int next_state,
tiro_handle_t func,
tiro_handle_t args,
tiro_error_t * err
)

Signals the vm that the function func shall be invoked with the given arguments in args.

Parameters:

  • frame The resumable call frame
  • next_state The new state value
  • func Must refer to a valid function
  • args Must be either NULL (no arguments), refer to a null value (same) or a valid tuple (the function call arguments).

func will be invoked after the native function returned to the vm. The current native function will be called again when func has itself returned, and its return value will be accessible via tiro_resumable_frame_invoke_return(...).

Calling this function implies a state change to next_state, which will be the frame's state when the native function is called again after func's execution.

§function tiro_resumable_frame_invoke_return

void tiro_resumable_frame_invoke_return(
tiro_resumable_frame_t frame,
tiro_handle_t result,
tiro_error_t * err
)

Returns the result of the last function call made via tiro_resumable_frame_invoke.

Parameters:

  • frame The resumable call frame
  • result Will be set to the function's return value.

Only returns a useful value when the native function is called again for the first time after calling tiro_resumable_frame_invoke and returning to the vm.

§function tiro_resumable_frame_return_value

void tiro_resumable_frame_return_value(
tiro_resumable_frame_t frame,
tiro_handle_t value,
tiro_error_t * err
)

Sets the return value for the given function call frame to the given value.

The call frame's state is also set to END as a result of this call.

§function tiro_resumable_frame_panic_msg

void tiro_resumable_frame_panic_msg(
tiro_resumable_frame_t frame,
tiro_string message,
tiro_error_t * err
)

Signals a panic from the given function call frame.

The call frame's state is also set to END as a result of this call.

TODO: Allow user defined exception objects instead of plain string?

§function tiro_make_resumable_function

void tiro_make_resumable_function(
tiro_vm_t vm,
const tiro_resumable_frame_desc_t * desc,
tiro_handle_t result,
tiro_error_t * err
)

Constructs a new function object with the given description.

On success, the new function will be stored in result.


Updated on 2022-02-27 at 21:17:13 +0100