mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 23:30:19 +00:00
doc(interface-types) Improve the documentation of the interpreter
module.
This commit is contained in:
parent
278a743e60
commit
8ba931e33f
@ -10,6 +10,8 @@ use stack::Stack;
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
use wasm::values::InterfaceValue;
|
||||
|
||||
/// Represents the `Runtime`, which is used by an adapter to execute
|
||||
/// its instructions.
|
||||
pub(crate) struct Runtime<'invocation, 'instance, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
@ -18,16 +20,104 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> + 'instance,
|
||||
{
|
||||
/// The invocation inputs are all the arguments received by an
|
||||
/// adapter.
|
||||
invocation_inputs: &'invocation [InterfaceValue],
|
||||
|
||||
/// Each runtime (so adapter) has its own stack instance.
|
||||
stack: Stack<InterfaceValue>,
|
||||
|
||||
/// The WebAssembly module instance. It is used by adapter's
|
||||
/// instructions.
|
||||
wasm_instance: &'instance mut Instance,
|
||||
|
||||
/// Phantom data.
|
||||
_phantom: PhantomData<(Export, LocalImport, Memory, MemoryView)>,
|
||||
}
|
||||
|
||||
/// Type alias for an executable instruction. It's an implementation
|
||||
/// details, but an instruction is a boxed closure instance.
|
||||
pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView> = Box<
|
||||
dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory, MemoryView>) -> Result<(), String>,
|
||||
>;
|
||||
|
||||
/// An interpreter is the central piece of this crate. It is a set of
|
||||
/// executable instructions. Each instruction takes the runtime as
|
||||
/// argument. The runtime holds the invocation inputs, the stack, and
|
||||
/// the WebAssembly instance.
|
||||
///
|
||||
/// When the interpreter executes the instructions, each of them can
|
||||
/// query the WebAssembly instance, operates on the stack, or reads
|
||||
/// the invocation inputs. At the end of the execution, the stack
|
||||
/// supposedly contains a result. Since an interpreter is used by a
|
||||
/// WIT adapter to execute its instructions, the result on the stack
|
||||
/// is the result of the adapter.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
/// use wasmer_interface_types::interpreter::{
|
||||
/// instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
|
||||
/// // ^^^^^^^^^^^^ This is private and for testing purposes only.
|
||||
/// // It is basically a fake WebAssembly runtime.
|
||||
/// stack::Stackable,
|
||||
/// wasm::values::{InterfaceType, InterfaceValue},
|
||||
/// Instruction, Interpreter,
|
||||
/// };
|
||||
///
|
||||
/// # fn main() {
|
||||
/// // 1. Creates an interpreter from a set of instructions. They will
|
||||
/// // be transformed into executable instructions.
|
||||
/// let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> = (&vec![
|
||||
/// Instruction::ArgumentGet { index: 1 },
|
||||
/// Instruction::ArgumentGet { index: 0 },
|
||||
/// Instruction::CallExport { export_name: "sum" },
|
||||
/// ])
|
||||
/// .try_into()
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // 2. Defines the arguments of the adapter.
|
||||
/// let invocation_inputs = vec![InterfaceValue::I32(3), InterfaceValue::I32(4)];
|
||||
///
|
||||
/// // 3. Creates a WebAssembly instance.
|
||||
/// let mut instance = Instance {
|
||||
/// // 3.1. Defines one exported function: `fn sum(a: i32, b: i32) -> i32 { a + b }`.
|
||||
/// exports: {
|
||||
/// let mut hashmap = HashMap::new();
|
||||
/// hashmap.insert(
|
||||
/// "sum".into(),
|
||||
/// Export {
|
||||
/// // Defines the argument types of the function.
|
||||
/// inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
///
|
||||
/// // Defines the result types.
|
||||
/// outputs: vec![InterfaceType::I32],
|
||||
///
|
||||
/// // Defines the function implementation.
|
||||
/// function: |arguments: &[InterfaceValue]| {
|
||||
/// let a: i32 = (&arguments[0]).try_into().unwrap();
|
||||
/// let b: i32 = (&arguments[1]).try_into().unwrap();
|
||||
///
|
||||
/// Ok(vec![InterfaceValue::I32(a + b)])
|
||||
/// },
|
||||
/// },
|
||||
/// );
|
||||
/// },
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
///
|
||||
/// // 4. Executes the instructions.
|
||||
/// let run = interpreter.run(&invocation_inputs, &mut instance);
|
||||
///
|
||||
/// assert!(run.is_ok());
|
||||
///
|
||||
/// let stack = run.unwrap();
|
||||
///
|
||||
/// // 5. Read the stack to get the result.
|
||||
/// assert_eq!(stack.as_slice(), &[InterfaceValue::I32(7)]);
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
@ -57,6 +147,11 @@ where
|
||||
self.executable_instructions.iter()
|
||||
}
|
||||
|
||||
/// Runs the interpreter, such as:
|
||||
/// 1. Create a fresh stack,
|
||||
/// 2. Create a fresh stack,
|
||||
/// 3. Execute the instructions one after the other, and
|
||||
/// returns the stack.
|
||||
pub fn run(
|
||||
&self,
|
||||
invocation_inputs: &[InterfaceValue],
|
||||
@ -80,6 +175,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a `Vec<Instruction>` into an `Interpreter`.
|
||||
impl<'binary_input, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
TryFrom<&Vec<Instruction<'binary_input>>>
|
||||
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
|
@ -1,2 +1,6 @@
|
||||
//! An hypothetic WebAssembly runtime, represented as a set of enums,
|
||||
//! types, and traits —basically this is the part a runtime should
|
||||
//! take a look to use the `wasmer-interface-types` crate—.
|
||||
|
||||
pub mod structures;
|
||||
pub mod values;
|
||||
|
Loading…
Reference in New Issue
Block a user