diff --git a/Cargo.lock b/Cargo.lock index e77351e..63862e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,6 +104,7 @@ dependencies = [ "hashbrown 0.14.0", "hbbytecode", "lasso", + "literify", "logos", "paste", ] @@ -135,6 +136,26 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "literify" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e4d365df794ed78b4ce1061886f82eae7afa8e3a98ce4c4b0bfd0c777b1175" +dependencies = [ + "litrs", + "proc-macro2", + "quote", +] + +[[package]] +name = "litrs" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f17c3668f3cc1132437cdadc93dab05e52d592f06948d3f64828430c36e4a70" +dependencies = [ + "proc-macro2", +] + [[package]] name = "log" version = "0.4.17" diff --git a/hbasm/Cargo.toml b/hbasm/Cargo.toml index 1f98378..4659ae5 100644 --- a/hbasm/Cargo.toml +++ b/hbasm/Cargo.toml @@ -4,10 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +ariadne = "0.3.0" hbbytecode = { path = "../hbbytecode" } +literify = "0.1" paste = "1.0" hashbrown = "0.14.0" -ariadne = "0.3.0" [dependencies.lasso] version = "0.7" diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index b3e12e3..aba245e 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -3,7 +3,7 @@ extern crate alloc; -pub mod text; +pub mod text_r; mod macros; @@ -15,25 +15,24 @@ pub struct Assembler { sub: HashSet, } -impl Assembler { - macros::impl_asm!( - bbbb(p0: u8, p1: u8, p2: u8, p3: u8) - => [DIR, DIRF, FMAF], - bbb(p0: u8, p1: u8, p2: u8) - => [ADD, SUB, MUL, AND, OR, XOR, SL, SR, SRS, CMP, CMPU, BRC, ADDF, SUBF, MULF], - bbdh(p0: u8, p1: u8, p2: impl Imm, p3: u16) - => [LD, ST], - bbd(p0: u8, p1: u8, p2: impl Imm) - => [ADDI, MULI, ANDI, ORI, XORI, SLI, SRI, SRSI, CMPI, CMPUI, - BMC, JEQ, JNE, JLT, JGT, JLTU, JGTU, ADDFI, MULFI], - bb(p0: u8, p1: u8) - => [NEG, NOT, CP, SWA, NEGF, ITF, FTI], - bd(p0: u8, p1: impl Imm) - => [LI, JMP], - n() - => [NOP, ECALL], - ); -} +macros::impl_both!( + bbbb(p0: R, p1: R, p2: R, p3: R) + => [DIR, DIRF, FMAF], + bbb(p0: R, p1: R, p2: R) + => [ADD, SUB, MUL, AND, OR, XOR, SL, SR, SRS, CMP, CMPU, BRC, ADDF, SUBF, MULF], + bbdh(p0: R, p1: R, p2: I, p3: u16) + => [LD, ST], + bbd(p0: R, p1: R, p2: I) + => [ADDI, MULI, ANDI, ORI, XORI, SLI, SRI, SRSI, CMPI, CMPUI, + BMC, JEQ, JNE, JLT, JGT, JLTU, JGTU, ADDFI, MULFI], + bb(p0: R, p1: R) + => [NEG, NOT, CP, SWA, NEGF, ITF, FTI], + bd(p0: R, p1: I) + => [LI, JMP], + n() + => [NOP, ECALL], +); + pub trait Imm { fn insert(&self, asm: &mut Assembler); diff --git a/hbasm/src/macros.rs b/hbasm/src/macros/asm.rs similarity index 58% rename from hbasm/src/macros.rs rename to hbasm/src/macros/asm.rs index 0a3c93b..2e1c904 100644 --- a/hbasm/src/macros.rs +++ b/hbasm/src/macros/asm.rs @@ -18,47 +18,41 @@ macro_rules! impl_asm_opcodes { } } - macros::impl_asm_opcodes!( + macros::asm::impl_asm_opcodes!( $generic($($param_i: $param_ty),*) => [$($rest)*] ); }; } -macro_rules! gen_impl_asm_insert { - ($($ty:ident),* $(,)?) => { - macro_rules! impl_asm_insert { - $(($self:expr, $id:ident, $ty) => { - $self.buf.extend($id.to_le_bytes()) - };)* +macro_rules! impl_asm_insert { + ($self:expr, $id:ident, I) => { + Imm::insert(&$id, $self) + }; - ($self:expr, $id:ident, $_:ty) => { - Imm::insert(&$id, $self) - }; - } + ($self:expr, $id:ident, $_:ident) => { + $self.buf.extend($id.to_le_bytes()) }; } -gen_impl_asm_insert!(u8, u16, u64); - macro_rules! impl_asm { ( $( $ityn:ident - ($($param_i:ident: $param_ty:ty),* $(,)?) + ($($param_i:ident: $param_ty:ident),* $(,)?) => [$($opcode:ident),* $(,)?], )* ) => { paste::paste! { $( #[allow(dead_code)] - fn [](&mut self, opcode: u8, $($param_i: $param_ty),*) { + fn [](&mut self, opcode: u8, $($param_i: macros::asm::ident_map_ty!($param_ty)),*) { self.buf.push(opcode); - $(macros::impl_asm_insert!(self, $param_i, $param_ty);)* + $(macros::asm::impl_asm_insert!(self, $param_i, $param_ty);)* } - macros::impl_asm_opcodes!( - []($($param_i: $param_ty),*) + macros::asm::impl_asm_opcodes!( + []($($param_i: macros::asm::ident_map_ty!($param_ty)),*) => [$($opcode,)*] ); )* @@ -66,7 +60,14 @@ macro_rules! impl_asm { }; } -pub(super) use {impl_asm, impl_asm_opcodes}; +#[rustfmt::skip] +macro_rules! ident_map_ty { + (R) => { u8 }; + (I) => { impl Imm }; + ($id:ident) => { $id }; +} + +pub(crate) use {ident_map_ty, impl_asm, impl_asm_opcodes}; #[allow(clippy::single_component_path_imports)] -pub(super) use impl_asm_insert; +pub(crate) use impl_asm_insert; diff --git a/hbasm/src/macros/mod.rs b/hbasm/src/macros/mod.rs new file mode 100644 index 0000000..6fd1e58 --- /dev/null +++ b/hbasm/src/macros/mod.rs @@ -0,0 +1,14 @@ +pub mod asm; +pub mod text; + +macro_rules! impl_both { + ($($tt:tt)*) => { + impl Assembler { + $crate::macros::asm::impl_asm!($($tt)*); + } + + $crate::macros::text::gen_text!($($tt)*); + }; +} + +pub(crate) use impl_both; diff --git a/hbasm/src/macros/text.rs b/hbasm/src/macros/text.rs new file mode 100644 index 0000000..ffa2df0 --- /dev/null +++ b/hbasm/src/macros/text.rs @@ -0,0 +1,59 @@ +macro_rules! gen_text { + ( + $( + $ityn:ident + ($($param_i:ident: $param_ty:ident),* $(,)?) + => [$($opcode:ident),* $(,)?], + )* + ) => { + pub mod text { + use { + lasso::{Rodeo, Spur}, + logos::Logos, + }; + + paste::paste!(literify::literify! { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Logos)] + #[logos(extras = Rodeo)] + #[logos(skip r"[ \t\t]+")] + #[logos(skip r"-- .*")] + pub enum Token { + $($(#[token(~([<$opcode:lower>]), |_| hbbytecode::opcode::[<$opcode:upper>])])*)* + Opcode(u8), + + #[regex("[0-9]+", |l| l.slice().parse().ok())] + #[regex( + "-[0-9]+", + |lexer| { + Some(u64::from_ne_bytes(lexer.slice().parse::().ok()?.to_ne_bytes())) + }, + )] Integer(u64), + + #[regex( + "r[0-9]+", + |lexer| match lexer.slice()[1..].parse() { + Ok(n) => Some(n), + _ => None + }, + )] Register(u8), + + #[regex( + r"\p{XID_Start}\p{XID_Continue}*:", + |lexer| lexer.extras.get_or_intern(&lexer.slice()[..lexer.slice().len() - 1]), + )] Label(Spur), + + #[regex( + r"\p{XID_Start}\p{XID_Continue}*", + |lexer| lexer.extras.get_or_intern(lexer.slice()), + )] Symbol(Spur), + + #[token("\n")] + #[token(";")] ISep, + #[token(",")] PSep, + } + }); + } + }; +} + +pub(crate) use gen_text; diff --git a/hbasm/src/main.rs b/hbasm/src/main.rs index d59a873..29cf888 100644 --- a/hbasm/src/main.rs +++ b/hbasm/src/main.rs @@ -12,20 +12,20 @@ fn main() -> Result<(), Box> { let mut buf = vec![]; - if let Err(e) = hbasm::text::assembly(&code, &mut buf) { + if let Err(e) = hbasm::text_r::assembly(&code, &mut buf) { let mut colors = ColorGenerator::new(); let e_code = match e.kind { - hbasm::text::ErrorKind::UnexpectedToken => 1, - hbasm::text::ErrorKind::InvalidToken => 2, - hbasm::text::ErrorKind::UnexpectedEnd => 3, - hbasm::text::ErrorKind::InvalidSymbol => 4, + hbasm::text_r::ErrorKind::UnexpectedToken => 1, + hbasm::text_r::ErrorKind::InvalidToken => 2, + hbasm::text_r::ErrorKind::UnexpectedEnd => 3, + hbasm::text_r::ErrorKind::InvalidSymbol => 4, }; let message = match e.kind { - hbasm::text::ErrorKind::UnexpectedToken => "This token is not expected!", - hbasm::text::ErrorKind::InvalidToken => "The token is not valid!", - hbasm::text::ErrorKind::UnexpectedEnd => "The assembler reached the end of input unexpectedly!", - hbasm::text::ErrorKind::InvalidSymbol => "This referenced symbol doesn't have a corresponding label!", + hbasm::text_r::ErrorKind::UnexpectedToken => "This token is not expected!", + hbasm::text_r::ErrorKind::InvalidToken => "The token is not valid!", + hbasm::text_r::ErrorKind::UnexpectedEnd => "The assembler reached the end of input unexpectedly!", + hbasm::text_r::ErrorKind::InvalidSymbol => "This referenced symbol doesn't have a corresponding label!", }; let a = colors.next(); diff --git a/hbasm/src/text.rs b/hbasm/src/text_r.rs similarity index 100% rename from hbasm/src/text.rs rename to hbasm/src/text_r.rs