watson

Crates.iowatson
lib.rswatson
version0.9.2
sourcesrc
created_at2020-03-25 18:53:30.576279
updated_at2020-10-06 03:44:01.164259
descriptiona no_std web assembly loader
homepage
repositoryhttps://www.github.com/richardanaya/watson
max_upload_size
id222742
size2,888,995
RICHΛRD ΛNΛYΛ (richardanaya)

documentation

README

watson

docs.rs docs

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

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.

Commit count: 0

cargo fmt