My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Crate to represent wasm in Rust?

Mark's photo
Mark
·May 2, 2018

Is there any package to represent the parts of WebAssembly in Rust?

Ideally I'd build up an abstract syntax structure in memory, then parse is to either text (wat) of binary (wasm). The representation can either map 1-to-1 to wasm, or something fairly close.

The closest I've found is Binaryens format, but I prefer native Rust. It doesn't seem very hard to make, but even easier if it's already done.

EDIT Sorry for the slow response, I made a MWE to show what I mean.

I'd like to write something like this in Rust:

let param_n = Parameter::new(Name::new("n".to_owned()).unwrap(), Type::Int32);
let var_n = param_n.local();
let loop_condition_decl =
    DeclareLocal::new(Name::new("loop_condition".to_owned()).unwrap(), Type::Bool);
let loop_condition = loop_condition_decl.local();
let fac_result_decl =
    DeclareLocal::new(Name::new("fac_result".to_owned()).unwrap(), Type::Int32);
let fac_result = fac_result_decl.local();
let loop_name = Name::new("fac_loop".to_owned()).unwrap();
let mut the_loop = Loop::new_named(
    loop_name.clone(),
    vec![
        Statement::Assign(Assign::new(
            fac_result.clone(),
            Expression::Mul(Mul::new(
                Expression::Local(fac_result.get()),
                Expression::Local(var_n.get()),
            )),
        )),
        Statement::Assign(Assign::new(
            loop_condition.clone(),
            Expression::Gt(Gt::new(
                Expression::Local(var_n.get()),
                Expression::Const(Const::new(Type::Int32, Value::Int(2))),
            )),
        )),
        Statement::Assign(Assign::new(
            var_n.clone(),
            Expression::Add(Add::new(
                Expression::Local(var_n.get()),
                Expression::Const(Const::new(Type::Int32, Value::Int(-1))),
            )),
        )),
    ],
);
let loop_label = the_loop.label();
the_loop.add(Statement::BranchIf(BranchIf::new(
    Expression::Local(loop_condition.get()),
    loop_label,
)));
let wasm = Module::new(vec![Function::new(
    Name::new("fac".to_owned()).unwrap(),
    vec![param_n],
    vec![Output::new(Type::Int32)],
    Group::new(vec![
        // Function body
        Statement::Local(fac_result_decl),
        Statement::Local(loop_condition_decl),
        Statement::Assign(Assign::new(
            fac_result.clone(),
            Expression::Const(Const::new(Type::Int32, Value::Int(1))),
        )),
        //            Statement::Block(Block::new_named("".to_owned(), vec![])),
        Statement::Loop(the_loop),
        Statement::Return(Return::new(Expression::Local(fac_result.get()))),
    ]),
)]);

println!("{}", wasm.as_wat());

Which'd then produce this:

(module
(func $fac (export "fac") (param $n i32) (result i32)
    (local $fac_result i32)
    (local $loop_condition i32)
    i32.const 1
    set_local $fac_result
    loop $fac_loop
        get_local $fac_result
        get_local $n
        i32.mul
        set_local $fac_result
        get_local $n
        i32.const 2
        i32.gt_s
        set_local $loop_condition
        get_local $n
        i32.const -1
        i32.add
        set_local $n
        get_local $loop_condition
        br_if $fac_loop
    end ;; loop $fac_loop
    get_local $fac_result
) ;; func $fac
) ;; module

So the Rust type system makes sure the syntax and some of the semantics are correct. It's much easier to manipulate this structure than it is for text.

Does a library like that already exist? It's not very hard to make, but it's a lot of typing, and I'm sure someone smarter will do it somewhat better.