Skip to content

a minimilistic web assembly parser, compiler, and interpreter for Rust

License

Apache-2.0, Apache-2.0 licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
Apache-2.0
LICENSE-MIT
Notifications You must be signed in to change notification settings

richardanaya/watson

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
  • pass core WebAssembly spec tests
  • interpreter
[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.

About

a minimilistic web assembly parser, compiler, and interpreter for Rust

Resources

License

Apache-2.0, Apache-2.0 licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
Apache-2.0
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published