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;
}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
Futurereturned bydispatch_asynccan be anenumof each builtin word’sFuturetype. This requires all builtin words to be implemented as namedFuturetypes, rather thanasync fns, but does not require heap allocation or unstable Rust features. - The
Futuretype can be aPin<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 beasync fns or namedFuturetypes. - If using nightly Rust, the
#![feature(impl_trait_in_assoc_type)]unstable feature can be enabled, allowing theAsyncBuiltins::Futureassociated type to beimpl Future<Output = Result(), Error> + 'forth. This does not require heap allocation, and allows thedispatch_asyncmethod to return anasyncblockFuturewhichmatches on the builtin’s name and calls any number ofasync fns or namedFuturetypes. 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).
If the
AsyncForthtype 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§
Required Associated Constants§
sourceconst BUILTINS: &'static [AsyncBuiltinEntry<T>]
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§
sourcefn dispatch_async(
&self,
id: &'static FaStr,
forth: &'forth mut Forth<T>,
) -> Self::Future
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.