25 releases (9 breaking)
0.9.2 | Oct 6, 2020 |
---|---|
0.9.1 | Apr 10, 2020 |
0.8.0 | Apr 4, 2020 |
0.1.0 | Mar 31, 2020 |
#930 in WebAssembly
51 downloads per month
Used in wq
230KB
4K
SLoC
watson
a hyper minimalistic no_std
+ alloc
WebAssembly parser/compiler for Rust based off the official specification
- supports all section types
- helper functions for finding things
- support for compilation to wasm
- .wast parsing and assertion
- pass core WebAssembly spec tests
- interpreter
- WASI simulator
- lofi wasm mode (i.e. i32 only)
[dependencies]
watson = "0.9"
Parse a WebAssembly module
use watson::*;
let program = watons::parse(&bytes_of_wasm)?;
for s in program.sections.iter() {
match s {
CodeSection(code)=> ...,
...
}
}
...
Write an interpreter
this is in progress
async fn run(program: impl InterpretableProgram) -> Result<Vec<WasmValue>, &'static str> {
let mut interpreter = Interpreter::new(program)?;
let mut executor = interpreter.call("main", &[])?;
loop {
let execution_unit = executor.next_operation()?;
let response = match execution_unit {
// if an import is called, figure out what to do
ExecutionUnit::CallImport(x) => {
if x.name == "print" {
let start = x.params[0].to_i32() as usize;
let mem = match executor.memory() {
Some(m) => m,
None => return Err("there should be memory"),
};
let mem = mem.borrow();
let mut chars = vec![];
let mut i = 0;
loop {
if mem[start + i] == 0 {
break;
}
chars.push(mem[start + i]);
i += 1;
}
let text = from_utf8(&chars).unwrap();
println!("{}", text);
ExecutionResponse::DoNothing
} else if x.name == "sleep" {
let millis = x.params[0].to_i32();
task::sleep(Duration::from_millis(millis as u64)).await;
ExecutionResponse::DoNothing
} else {
panic!("unknown import call")
}
}
// if there's nothing left to do, break out of loop
ExecutionUnit::Complete(v) => break Ok(v),
// handle other execution units with default behavior
mut x @ _ => x.evaluate()?,
};
executor.execute(response)?;
}
}
fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
if args.len() == 2 {
let buffer = fs::read(&args[1])?;
let program = watson::parse(&buffer)?;
task::block_on(run(program))?;
} else {
eprintln!("sleepyprint <app.wasm>");
exit(1);
}
Ok(())
}
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in watson
by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
Dependencies
~0.5–1.1MB
~25K SLoC