diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index 36cc276a..d36a7c08 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -67,6 +67,7 @@ pub enum ErrorKind { UnexpectedToken, InvalidToken, UnexpectedEnd, + InvalidSymbol, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -94,8 +95,8 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { struct Assembler<'a> { lexer: Lexer<'a, Token>, buf: &'a mut Vec, - lblmap: HashMap, - subset: HashSet, + label_map: HashMap, + to_sub_label: HashMap, } impl<'a> Assembler<'a> { @@ -129,7 +130,7 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { } } Some(Ok(Token::Label(lbl))) => { - self.lblmap.insert(lbl, self.buf.len() as u64 + 1); + self.label_map.insert(lbl, self.buf.len() as u64 + 1); } Some(Ok(Token::ISep)) => (), Some(Ok(_)) => return Err(ErrorKind::UnexpectedToken), @@ -139,6 +140,22 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { } } + fn link_local_syms(&mut self) -> Result<(), ErrorKind> { + for (ix, sym) in &self.to_sub_label { + self.label_map + .get(sym) + .ok_or(ErrorKind::InvalidSymbol)? + .to_le_bytes() + .iter() + .enumerate() + .for_each(|(i, b)| { + self.buf[ix + i] = *b; + }); + } + + Ok(()) + } + fn rrr(&mut self) -> Result<(), ErrorKind> { expect_matches!( self, @@ -159,19 +176,9 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { } fn ri(&mut self) -> Result<(), ErrorKind> { - expect_matches!(self, Token::Register(r0), Token::PSep, imm @ (Token::Integer(_) | Token::Symbol(_))); - + expect_matches!(self, Token::Register(r0), Token::PSep); self.buf.push(r0); - let imm = match imm { - Token::Integer(n) => n.to_le_bytes(), - Token::Symbol(s) => { - self.subset.insert(self.buf.len()); - s.into_usize().to_le_bytes() - } - _ => unreachable!(), - }; - - self.buf.extend(imm); + self.insert_imm()?; Ok(()) } @@ -182,18 +189,21 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { Token::PSep, Token::Register(r1), Token::PSep, - imm @ (Token::Integer(_) | Token::Symbol(_)), ); self.buf.extend([r0, r1]); - let imm = match imm { - Token::Integer(n) => n.to_le_bytes(), - Token::Symbol(s) => { - self.subset.insert(self.buf.len()); - s.into_usize().to_le_bytes() - } - _ => unreachable!(), - }; + self.insert_imm()?; + Ok(()) + } + fn insert_imm(&mut self) -> Result<(), ErrorKind> { + let imm = match self.next()? { + Token::Integer(i) => i.to_le_bytes(), + Token::Symbol(s) => { + self.to_sub_label.insert(self.buf.len(), s); + [0; 8] + } + _ => return Err(ErrorKind::UnexpectedToken), + }; self.buf.extend(imm); Ok(()) } @@ -201,8 +211,8 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { let mut asm = Assembler { lexer: Token::lexer(code), - lblmap: Default::default(), - subset: Default::default(), + label_map: Default::default(), + to_sub_label: Default::default(), buf, }; @@ -211,20 +221,6 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { span: asm.lexer.span(), })?; - for sub in asm.subset { - asm.lblmap[&Spur::try_from_usize(usize::from_le_bytes( - asm.buf[sub..sub + core::mem::size_of::()] - .try_into() - .expect("Expected location"), - )) - .expect("Expected valid intern key")] - .to_le_bytes() - .iter() - .enumerate() - .for_each(|(i, b)| { - asm.buf[sub + i] = *b; - }); - } - - Ok(()) + asm.link_local_syms() + .map_err(|kind| Error { kind, span: 0..0 }) }