#![deny(missing_docs)]
use std::io::Write;
mod wasm_macro;
use wasm_macro::wasm;
pub(crate) mod compiler;
pub use compiler::{Error, ErrorKind};
#[cfg(test)]
mod run_wasm;
#[cfg(test)]
mod test;
fn write_section(w: &mut Vec<u8>, section_type: u8, f: impl Fn(&mut Vec<u8>)) {
w.write_all(&[section_type]).unwrap();
let section_start = w.len();
f(w);
let section_len = w.len() - section_start;
let len = leb128::write::unsigned(w, section_len as u64).unwrap();
w[section_start..].rotate_right(len);
}
pub fn compile<'s>(source: &'s str) -> Result<Vec<u8>, Error<'s>> {
let functions = compiler::Parser::parse(source)?;
let mut binary = wasm!( new
(magic version)
);
write_section(&mut binary, wasm!(section_type type), |mut w| {
leb128::write::unsigned(&mut w, 1 + functions.len() as u64).unwrap();
wasm!(&mut w, (functype (vec f32) (vec)));
for f in &functions {
wasm!(&mut w, functype);
leb128::write::unsigned(&mut w, f.num_param as u64).unwrap();
for _ in 0..f.num_param {
wasm!(&mut w, f32);
}
wasm!(&mut w, (vec));
}
});
wasm!(&mut binary,
(section import (vec
(import "env" "print" (function 0x0))
(import "env" "memory" (memory 1))))
);
write_section(&mut binary, wasm!(section_type function), |mut w| {
leb128::write::unsigned(&mut w, functions.len() as u64).unwrap();
for f in &functions {
leb128::write::unsigned(&mut w, f.idx as u64).unwrap();
}
});
wasm!(&mut binary, (section export (vec (export "main" function 0x1))));
write_section(&mut binary, wasm!(section_type code), |mut w| {
leb128::write::unsigned(&mut w, functions.len() as u64).unwrap();
for f in &functions {
leb128::write::unsigned(&mut w, f.code.len() as u64).unwrap();
w.write_all(&f.code).unwrap();
}
});
Ok(binary)
}