From f9b7702da2193cd5c8151df1d2800ac29679a446 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Tue, 14 Jan 2020 21:11:34 -0500 Subject: [PATCH] Implement wrappers for web --- toolchain/Cargo.lock | 131 +++++++++++++++++++++++++++++++++++++++--- toolchain/Cargo.toml | 7 ++- toolchain/src/inst.rs | 8 +++ toolchain/src/js.rs | 44 ++++++++++++++ toolchain/src/lib.rs | 42 ++++++++++++-- 5 files changed, 218 insertions(+), 14 deletions(-) create mode 100644 toolchain/src/js.rs diff --git a/toolchain/Cargo.lock b/toolchain/Cargo.lock index 5f129a4..7bbc169 100644 --- a/toolchain/Cargo.lock +++ b/toolchain/Cargo.lock @@ -42,6 +42,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bumpalo" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" + [[package]] name = "byteorder" version = "1.3.2" @@ -95,6 +101,15 @@ dependencies = [ "wasi", ] +[[package]] +name = "js-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -120,6 +135,15 @@ version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.3.0" @@ -164,7 +188,16 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" +dependencies = [ + "unicode-xid 0.2.0", ] [[package]] @@ -193,9 +226,9 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d31edb17edac73aeacc947bd61462dda15220584268896a58e12f053d767f15b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", ] [[package]] @@ -210,7 +243,16 @@ version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2", + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +dependencies = [ + "proc-macro2 1.0.7", ] [[package]] @@ -444,9 +486,20 @@ version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" +dependencies = [ + "proc-macro2 1.0.7", + "quote 1.0.2", + "unicode-xid 0.2.0", ] [[package]] @@ -467,9 +520,11 @@ dependencies = [ name = "toolchain" version = "0.1.0" dependencies = [ + "js-sys", "nom", "proptest", "proptest-derive", + "wasm-bindgen", ] [[package]] @@ -478,6 +533,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + [[package]] name = "version_check" version = "0.1.5" @@ -499,6 +560,60 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasm-bindgen" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.7", + "quote 1.0.2", + "syn 1.0.13", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +dependencies = [ + "quote 1.0.2", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +dependencies = [ + "proc-macro2 1.0.7", + "quote 1.0.2", + "syn 1.0.13", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" + [[package]] name = "winapi" version = "0.3.8" diff --git a/toolchain/Cargo.toml b/toolchain/Cargo.toml index 54029fc..a4782bc 100644 --- a/toolchain/Cargo.toml +++ b/toolchain/Cargo.toml @@ -4,11 +4,16 @@ version = "0.1.0" authors = ["Cassie Jones "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib", "rlib"] [dependencies] nom = "5.1.0" +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = { version = "0.3.35" } +wasm-bindgen = { version = "0.2.58" } + [dev-dependencies] proptest = "0.9.4" proptest-derive = "0.1.0" diff --git a/toolchain/src/inst.rs b/toolchain/src/inst.rs index 9f2eaf6..4c986d2 100644 --- a/toolchain/src/inst.rs +++ b/toolchain/src/inst.rs @@ -5,6 +5,8 @@ pub mod parse; #[cfg(test)] pub mod test; +pub use self::{decode::Decode, encode::Encode}; + #[cfg(test)] use proptest_derive::Arbitrary; @@ -114,6 +116,12 @@ pub enum Inst { BEzI(i8), } +impl Inst { + pub fn parse(s: &str) -> Option { + parse::parse_inst(s) + } +} + impl Reg { pub fn new(x: u8) -> Option { U3::new(x).map(Reg) diff --git a/toolchain/src/js.rs b/toolchain/src/js.rs new file mode 100644 index 0000000..228adfd --- /dev/null +++ b/toolchain/src/js.rs @@ -0,0 +1,44 @@ +use super::{ + inst::{ Encode, Inst}, + Error, +}; +use js_sys; +use std::io::{Cursor, Write}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn assemble(code: &str) -> Result, JsValue> { + let mut result = Cursor::new(Vec::new()); + for (i, line) in code.lines().enumerate() { + let line = line.trim(); + if line.is_empty() { + continue; + } + let inst = Inst::parse(line) + .ok_or_else(|| js_sys::Error::new(&format!("Error parsing line {}", i + 1)))?; + inst.encode(&mut result) + .expect("can always write into a vector"); + } + Ok(result.into_inner()) +} + +#[wasm_bindgen] +pub fn disassemble(data: Vec) -> Result { + let mut input = Cursor::new(data); + let mut output = Cursor::new(Vec::new()); + for inst in super::disassemble(&mut input)? { + writeln!(output, "{}", inst).unwrap(); + } + // Can use _unchecked if we want because we control the display impl + Ok(String::from_utf8(output.into_inner()).unwrap()) +} + +impl From for JsValue { + fn from(e: Error) -> JsValue { + match e { + Error::Io { position, error } => { + js_sys::Error::new(&format!("Error at byte {}: {}", position, error)).into() + } + } + } +} diff --git a/toolchain/src/lib.rs b/toolchain/src/lib.rs index 67c875f..5344f0a 100644 --- a/toolchain/src/lib.rs +++ b/toolchain/src/lib.rs @@ -1,16 +1,48 @@ pub mod inst; +#[cfg(target_arch = "wasm32")] +pub mod js; -pub use inst::{decode::Decode, Inst}; -use std::io; +pub use inst::Inst; +use inst::Decode; +use std::io::{self, Read}; -pub fn disassemble(reader: &mut impl io::Read) -> io::Result> { +pub enum Error { + Io { position: usize, error: io::Error }, +} + +pub fn disassemble(reader: &mut impl io::Read) -> Result, Error> { let mut results = Vec::new(); + let mut reader = PositionedRead::new(reader); loop { - match Inst::decode(reader) { + match Inst::decode(&mut reader) { Ok(inst) => results.push(inst), Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => break, - Err(err) => return Err(err), + Err(err) => { + return Err(Error::Io { + position: reader.position, + error: err, + }) + } } } Ok(results) } + +struct PositionedRead<'a, R> { + inner: &'a mut R, + position: usize, +} + +impl<'a, R> PositionedRead<'a, R> { + pub fn new(inner: &'a mut R) -> Self { + PositionedRead { inner, position: 0 } + } +} + +impl<'a, R: Read> Read for PositionedRead<'a, R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let read = self.inner.read(buf)?; + self.position += read; + Ok(read) + } +} -- 2.47.0