wasmer_interface_types/
macros.rs

1//! Collection of helpful macros.
2
3/// This macro creates a `Vec1` by checking at compile-time that its
4/// invariant holds.
5#[macro_export]
6macro_rules! vec1 {
7    ($item:expr; 0) => {
8        compile_error!("Cannot create an empty `Vec1`, it violates its invariant.")
9    };
10
11    () => {
12        compile_error!("Cannot create an empty `Vec1`, it violates its invariant.")
13    };
14
15    ($item:expr; $length:expr) => {
16        {
17            crate::vec1::Vec1::new(vec![$item; $length]).unwrap()
18        }
19    };
20
21    ($($item:expr),+ $(,)?) => {
22        {
23            crate::vec1::Vec1::new(vec![$($item),*]).unwrap()
24        }
25    };
26}
27
28/// This macro runs a parser, extracts the next input and the parser
29/// output, and positions the next input on `$input`.
30macro_rules! consume {
31    (($input:ident, $parser_output:ident) = $parser_expression:expr) => {
32        let (next_input, $parser_output) = $parser_expression;
33        $input = next_input;
34    };
35
36    (($input:ident, mut $parser_output:ident) = $parser_expression:expr) => {
37        let (next_input, mut $parser_output) = $parser_expression;
38        $input = next_input;
39    };
40}
41
42/// This macro creates an executable instruction for the interpreter.
43///
44/// # Example
45///
46/// The following example creates a `foo` executable instruction,
47/// which takes 2 arguments (`x` and `y`), and does something
48/// mysterious by using the `interpreter::Runtime` API.
49///
50/// ```rust,ignore
51/// executable_instruction!(
52///     foo(x: u64, y: u64, instruction_name: String) -> _ {
53/// //                                                   ^ output type is purposely blank
54/// //                      ^^^^^^^^^^^^^^^^ the instruction name, for debugging purposes
55/// //              ^ the `y` argument
56/// //      ^ the `x` argument
57///
58///     // an executable instruction is a closure that takes a `Runtime` instance
59///     move |runtime| -> _ {
60///         // Do something.
61///
62///         Ok(())
63///     }
64/// );
65/// ```
66///
67/// Check the existing executable instruction to get more examples.
68macro_rules! executable_instruction {
69    ($name:ident ( $($argument_name:ident: $argument_type:ty),* ) -> _ $implementation:block ) => {
70        pub(crate) fn $name<Instance, Export, LocalImport, Memory, MemoryView>(
71            $($argument_name: $argument_type),*
72        ) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
73        where
74            Export: crate::interpreter::wasm::structures::Export,
75            LocalImport: crate::interpreter::wasm::structures::LocalImport,
76            Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
77            MemoryView: crate::interpreter::wasm::structures::MemoryView,
78            Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
79        {
80            #[allow(unused_imports)]
81            use crate::interpreter::{stack::Stackable};
82
83            Box::new($implementation)
84        }
85    };
86}
87
88#[cfg(test)]
89macro_rules! test_executable_instruction {
90    (
91        $test_name:ident =
92            instructions: [ $($instructions:expr),* $(,)* ],
93            invocation_inputs: [ $($invocation_inputs:expr),* $(,)* ],
94            instance: $instance:expr,
95            stack: [ $($stack:expr),* $(,)* ]
96            $(,)*
97    ) => {
98        #[test]
99        #[allow(non_snake_case, unused)]
100        fn $test_name() {
101            use crate::{
102                interpreter::{
103                    instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
104                    stack::Stackable,
105                    Instruction, Interpreter,
106                },
107                types::InterfaceType,
108                values::InterfaceValue,
109            };
110            use std::{cell::Cell, collections::HashMap, convert::TryInto};
111
112            let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
113                (&vec![$($instructions),*]).try_into().unwrap();
114
115            let invocation_inputs = vec![$($invocation_inputs),*];
116            let mut instance = $instance;
117            let run = interpreter.run(&invocation_inputs, &mut instance);
118
119            let err = match &run {
120                Ok(_) => "".to_string(),
121                Err(e) => e.to_string(),
122            };
123
124            assert!(run.is_ok(), err);
125
126            let stack = run.unwrap();
127
128            assert_eq!(stack.as_slice(), &[$($stack),*]);
129        }
130    };
131
132    (
133        $test_name:ident =
134            instructions: [ $($instructions:expr),* $(,)* ],
135            invocation_inputs: [ $($invocation_inputs:expr),* $(,)* ],
136            instance: $instance:expr,
137            error: $error:expr
138            $(,)*
139    ) => {
140        #[test]
141        #[allow(non_snake_case, unused)]
142        fn $test_name() {
143            use crate::{
144                interpreter::{
145                    instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
146                    stack::Stackable,
147                    Instruction, Interpreter,
148                },
149                types::InterfaceType,
150                values::InterfaceValue,
151            };
152            use std::{cell::Cell, collections::HashMap, convert::TryInto};
153
154            let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
155                (&vec![$($instructions),*]).try_into().unwrap();
156
157            let invocation_inputs = vec![$($invocation_inputs),*];
158            let mut instance = $instance;
159            let run = interpreter.run(&invocation_inputs, &mut instance);
160
161            assert!(run.is_err());
162
163            let error = run.unwrap_err().to_string();
164
165            assert_eq!(error, String::from($error));
166        }
167    };
168}