Trait forth3::dictionary::AsyncBuiltins

source ·
pub trait AsyncBuiltins<'forth, T: 'static> {
    type Future: Future<Output = Result<(), Error>>;

    const BUILTINS: &'static [AsyncBuiltinEntry<T>];

    // Required method
    fn dispatch_async(
        &self,
        id: &'static FaStr,
        forth: &'forth mut Forth<T>,
    ) -> Self::Future;
}
Available on crate feature async only.
Expand description

A set of asynchronous builtin words, and a method to dispatch builtin names to Futures.

This trait is used along with the AsyncForth type to allow some builtin words to be implemented by async fns (or Futures), rather than synchronous functions. See here for an overview of how asynchronous Forth VMs work.

§Implementing Async Builtins

Synchronous builtins are provided to the Forth VM as a static slice of BuiltinEntrys. These entries allow the VM to lookup builtin words by name, and also contain a function pointer to the host function that implements that builtin. Asynchronous builtins work somewhat differently: a slice of AsyncBuiltinEntrys is still used in order to define the names of the asynchronous builtin words, but because asynchronous functions return a Future whose type must be known, an AsyncBuiltinEntry does not contain a function pointer to a host function. Instead, once the name of an async builtin is looked up, it is passed to the AsyncBuiltins::dispatch_async method, which returns the Future corresponding to that builtin function.

This indirection allows the AsyncBuiltins trait to erase the various Future types which are returned by the async builtin functions, allowing the AsyncForth VM to have only a single additional generic parameter for the AsyncBuiltins implementation itself. Without the indirection of dispatch_async, the AsyncForth VM would need to be generic over every possible Future type that may be returned by an async builtin word, which would be impractical.1

In order to erase multiple Future types, one of several approaches may be used:

  • The Future returned by dispatch_async can be an enum of each builtin word’s Future type. This requires all builtin words to be implemented as named Future types, rather than async fns, but does not require heap allocation or unstable Rust features.
  • The Future type can be a Pin<Box<dyn Future<Output = Result<(), Error>> + 'forth>. This requires heap allocation, but can erase the type of any number of async builtin futures, which may be async fns or named Future types.
  • If using nightly Rust, the #![feature(impl_trait_in_assoc_type)] unstable feature can be enabled, allowing the AsyncBuiltins::Future associated type to be impl Future<Output = Result(), Error> + 'forth. This does not require heap allocation, and allows the dispatch_async method to return an async block Future which matches on the builtin’s name and calls any number of async fns or named Future types. This is the preferred approach when nightly features may be used.

Since the AsyncBuiltins trait is generic over the lifetime for which the Forth vm is borrowed mutably, the AsyncBuiltins::Future associated type may also be generic over that lifetime. This allows the returned Future to borrow the Forth VM so that its stacks can be mutated while the builtin Future executes (e.g. the result of the asynchronous operation can be pushed to the VM’s data stack, et cetera).


  1. If the AsyncForth type was generic over every possible async builtin future, it would have a large number of generic type parameters which would all need to be filled in by the user. Additionally, because Rust does not allow a type to have a variadic number of generic parameters, there would have to be an arbitrary limit on the maximum number of async builtin words. 

Required Associated Types§

source

type Future: Future<Output = Result<(), Error>>

The Future type returned by Self::dispatch_async.

Since the AsyncBuiltins trait is generic over the lifetime of the Forth VM, the Future type may mutably borrow the VM. This allows the VM’s stacks to be mutated by the async builtin function.

Required Associated Constants§

source

const BUILTINS: &'static [AsyncBuiltinEntry<T>]

A static slice of AsyncBuiltinEntrys describing the builtins provided by this implementation of AsyncBuiltins.

AsyncBuiltinEntrys may be created using the async_builtin! macro.

Required Methods§

source

fn dispatch_async( &self, id: &'static FaStr, forth: &'forth mut Forth<T>, ) -> Self::Future

Dispatch a builtin name (id) to an asynchronous builtin Future.

The returned Future may borrow the Forth VM provided as an argument to this function, allowing it to mutate the VM’s stacks as it executes.

This method should return a Future for each builtin function definition in Self::BUILTINS. Typically, this is implemented by matching the provided id, and returning the appropriate Future for each builtin name. See the AsyncBuiltin trait’s documentation for details on implementing this method.

The id parameter is 'static, as we will only resolve function names from the provided Self::BUILTINS, which must be 'static.

Object Safety§

This trait is not object safe.

Implementors§