diff options
| -rw-r--r-- | crates/cli/src/args.rs | 48 | ||||
| -rw-r--r-- | crates/cli/src/bin.rs | 42 | ||||
| -rw-r--r-- | examples/wasm/loop.wat | 20 |
3 files changed, 97 insertions, 13 deletions
diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs new file mode 100644 index 0000000..4023be6 --- /dev/null +++ b/crates/cli/src/args.rs @@ -0,0 +1,48 @@ +use std::str::FromStr; +use tinywasm::WasmValue; + +#[derive(Debug)] +pub struct WasmArg(WasmValue); + +pub fn to_wasm_args(args: Vec<WasmArg>) -> Vec<WasmValue> { + args.into_iter().map(|a| a.into()).collect() +} + +impl From<WasmArg> for WasmValue { + fn from(value: WasmArg) -> Self { + value.0 + } +} + +impl FromStr for WasmArg { + type Err = String; + fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> { + let [ty, val]: [&str; 2] = s + .split(':') + .collect::<Vec<_>>() + .try_into() + .map_err(|e| format!("invalid arguments: {:?}", e))?; + + let arg: WasmValue = match ty { + "i32" => val + .parse::<i32>() + .map_err(|e| format!("invalid argument value for i32: {e:?}"))? + .into(), + "i64" => val + .parse::<i64>() + .map_err(|e| format!("invalid argument value for i64: {e:?}"))? + .into(), + "f32" => val + .parse::<f32>() + .map_err(|e| format!("invalid argument value for f32: {e:?}"))? + .into(), + "f64" => val + .parse::<f64>() + .map_err(|e| format!("invalid argument value for f64: {e:?}"))? + .into(), + t => return Err(format!("Invalid arg type: {}", t)), + }; + + Ok(WasmArg(arg)) + } +} diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs index f9c9f63..07513fb 100644 --- a/crates/cli/src/bin.rs +++ b/crates/cli/src/bin.rs @@ -1,9 +1,13 @@ use std::str::FromStr; use argh::FromArgs; +use args::WasmArg; use color_eyre::eyre::Result; -use log::info; -use tinywasm::{self, Module}; +use log::{debug, info}; +use tinywasm::{self, Module, WasmValue}; + +use crate::args::to_wasm_args; +mod args; mod util; #[cfg(feature = "wat")] @@ -49,6 +53,14 @@ struct Run { #[argh(positional)] wasm_file: String, + /// function to run + #[argh(option, short = 'f')] + func: Option<String>, + + /// arguments to pass to the wasm file + #[argh(option, short = 'a')] + args: Vec<WasmArg>, + /// engine to use #[argh(option, short = 'e', default = "Engine::Main")] engine: Engine, @@ -72,7 +84,14 @@ fn main() -> Result<()> { let cwd = std::env::current_dir()?; match args.nested { - TinyWasmSubcommand::Run(Run { wasm_file, engine }) => { + TinyWasmSubcommand::Run(Run { + wasm_file, + engine, + args, + func, + }) => { + debug!("args: {:?}", args); + let path = cwd.join(wasm_file.clone()); let module = match wasm_file.ends_with(".wat") { #[cfg(feature = "wat")] @@ -87,24 +106,21 @@ fn main() -> Result<()> { }; match engine { - Engine::Main => run(module), + Engine::Main => run(module, func, to_wasm_args(args)), } } } } -fn run(module: Module) -> Result<()> { +fn run(module: Module, func: Option<String>, args: Vec<WasmValue>) -> Result<()> { let mut store = tinywasm::Store::default(); let instance = module.instantiate(&mut store)?; - let func = instance.get_typed_func::<(i32, i32), (i32,)>(&store, "add")?; - let (res,) = func.call(&mut store, (2, 2))?; - info!("{res:?}"); - - // let func = instance.get_func(&store, "add")?; - // let params = vec![WasmValue::I32(2), WasmValue::I32(2)]; - // let res = func.call(&mut store, ¶ms)?; - // info!("{res:?}"); + if let Some(func) = func { + let func = instance.get_func(&store, &func)?; + let res = func.call(&mut store, &args)?; + info!("{res:?}"); + } Ok(()) } diff --git a/examples/wasm/loop.wat b/examples/wasm/loop.wat new file mode 100644 index 0000000..27c6d2e --- /dev/null +++ b/examples/wasm/loop.wat @@ -0,0 +1,20 @@ +(module + (func $loopExample (export "loopExample") + (local i32) ;; Declare a local i32 variable, let's call it 'i' + (i32.const 0) ;; Initialize 'i' to 0 + (local.set 0) + + (loop $loopStart ;; Start of the loop + (local.get 0) ;; Get the current value of 'i' + (i32.const 1) ;; Push 1 onto the stack + (i32.add) ;; Add 'i' and 1 + (local.set 0) ;; Update 'i' with the new value + + (local.get 0) ;; Push the current value of 'i' to check the condition + (i32.const 10) ;; Push 10 onto the stack + (i32.lt_s) ;; Check if 'i' is less than 10 + (br_if $loopStart) ;; If 'i' < 10, continue the loop + ) + ) +) + |
