cli: update run_wasm to use roc_wasm_interp

This commit is contained in:
Brian Carroll 2022-12-16 11:22:37 +00:00
parent 3ef171e620
commit eaf0211808
No known key found for this signature in database
GPG Key ID: 5C7B2EC4101703C0
2 changed files with 40 additions and 63 deletions

View File

@ -1356,73 +1356,49 @@ mod cli_run {
#[allow(dead_code)]
fn run_wasm(wasm_path: &std::path::Path, stdin: &[&str]) -> String {
use std::io::Write;
use wasmer::{Instance, Module, Store};
use bumpalo::Bump;
use roc_wasm_interp::{DefaultImportDispatcher, Instance, Value, WasiFile};
// std::process::Command::new("cp")
// .args(&[
// wasm_path.to_str().unwrap(),
// "/home/folkertdev/roc/wasm/nqueens.wasm",
// ])
// .output()
// .unwrap();
let wasm_bytes = std::fs::read(wasm_path).unwrap();
let arena = Bump::new();
let store = Store::default();
let module = Module::from_file(&store, wasm_path).unwrap();
let mut instance = {
let mut fake_stdin = vec![];
let fake_stdout = vec![];
let fake_stderr = vec![];
for s in stdin {
fake_stdin.extend_from_slice(s.as_bytes())
}
let mut fake_stdin = wasmer_wasi::Pipe::new();
let fake_stdout = wasmer_wasi::Pipe::new();
let fake_stderr = wasmer_wasi::Pipe::new();
let mut dispatcher = DefaultImportDispatcher::default();
dispatcher.wasi.files = vec![
WasiFile::ReadOnly(fake_stdin),
WasiFile::WriteOnly(fake_stdout),
WasiFile::WriteOnly(fake_stderr),
];
for line in stdin {
write!(fake_stdin, "{}", line).unwrap();
}
Instance::from_bytes(&arena, &wasm_bytes, dispatcher, false).unwrap()
};
// First, we create the `WasiEnv`
use wasmer_wasi::WasiState;
let mut wasi_env = WasiState::new("hello")
.stdin(Box::new(fake_stdin))
.stdout(Box::new(fake_stdout))
.stderr(Box::new(fake_stderr))
.finalize()
.unwrap();
let result = instance.call_export("_start", []);
// Then, we get the import object related to our WASI
// and attach it to the Wasm instance.
let import_object = wasi_env
.import_object(&module)
.unwrap_or_else(|_| wasmer::imports!());
let instance = Instance::new(&module, &import_object).unwrap();
let start = instance.exports.get_function("_start").unwrap();
match start.call(&[]) {
Ok(_) => read_wasi_stdout(wasi_env),
match result {
Ok(Some(Value::I32(0))) => match &instance.import_dispatcher.wasi.files[1] {
WasiFile::WriteOnly(fake_stdout) => String::from_utf8(fake_stdout.clone())
.unwrap_or("Wasm test printed invalid UTF-8".into()),
_ => unreachable!(),
},
Ok(Some(Value::I32(exit_code))) => {
format!("WASI app exit code {}", exit_code)
}
Ok(Some(val)) => {
format!("WASI _start returned an unexpected number type {:?}", val)
}
Ok(None) => {
format!("WASI _start returned no value")
}
Err(e) => {
use wasmer_wasi::WasiError;
match e.downcast::<WasiError>() {
Ok(WasiError::Exit(0)) => {
// we run the `_start` function, so exit(0) is expected
read_wasi_stdout(wasi_env)
}
other => format!("Something went wrong running a wasm test: {:?}", other),
}
format!("WASI error {}", e)
}
}
}
#[allow(dead_code)]
fn read_wasi_stdout(wasi_env: wasmer_wasi::WasiEnv) -> String {
let mut state = wasi_env.state.lock().unwrap();
match state.fs.stdout_mut() {
Ok(Some(stdout)) => {
let mut buf = String::new();
stdout.read_to_string(&mut buf).unwrap();
buf
}
_ => todo!(),
}
}

View File

@ -6,9 +6,10 @@ pub mod wasi;
// Main external interface
pub use instance::Instance;
pub use wasi::WasiDispatcher;
pub use wasi::{WasiDispatcher, WasiFile};
use roc_wasm_module::{Value, ValueType, WasmModule};
pub use roc_wasm_module::Value;
use roc_wasm_module::{ValueType, WasmModule};
use value_stack::ValueStack;
pub trait ImportDispatcher {
@ -31,7 +32,7 @@ impl Default for DefaultImportDispatcher<'_> {
}
pub struct DefaultImportDispatcher<'a> {
wasi: WasiDispatcher<'a>,
pub wasi: WasiDispatcher<'a>,
}
impl<'a> DefaultImportDispatcher<'a> {