Crate to represent wasm in Rust?

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.

Comments (4)

j's photo

wasm-bindgen - you means something like this? I am not sure why you need the AST transformation from rust to JS. maybe I missunderstand the inquire.

Mark's photo

I've added an example that I hope clarifies somewhat what I want to do.

It's not related to Javascript, I just want to represent the WebAssembly language in Rust objects.

j's photo

Mark hmm I don't know if this exists the only thing that come to mind is from the rust nursery

the stdweb crate.