diff --git a/assembler/src/lexer.rs b/assembler/src/lexer.rs index fc08910..0202a2c 100644 --- a/assembler/src/lexer.rs +++ b/assembler/src/lexer.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use crate::{AssembleError, parser::Opcode}; use common::prelude::Register; @@ -26,9 +28,9 @@ pub fn lexer(mut program: String) -> Result, AssembleError> { break; } - if token.starts_with('"') { - literal.push_str(&token[1..]); - println!("literal: {}", literal); + if let Some(stripped) = token.strip_prefix('"') { + literal.push_str(stripped); + println!("literal: {literal}"); } if !literal.is_empty() { @@ -72,7 +74,7 @@ pub fn lexer(mut program: String) -> Result, AssembleError> { Ok(tokens) } pub fn parse_register(token: &str) -> Result, AssembleError> { - Ok(Register::try_from(token).map(|r| Token::Register(r)).ok()) + Ok(Register::try_from(token).map(Token::Register).ok()) } pub fn parse_opcode(token: &str) -> Result, AssembleError> { @@ -117,23 +119,23 @@ pub fn parse_binary(token: &str) -> Result, AssembleError> { } pub fn parse_decimal(token: &str) -> Result, AssembleError> { - if !token.parse::().is_ok() { - return Ok(None); + if token.parse::().is_err() { + Ok(None) } else { - return Ok(Some(Token::Immediate(token.parse().unwrap()))); + Ok(Some(Token::Immediate(token.parse().unwrap()))) } } pub fn parse_label(token: &str) -> Result, AssembleError> { if !token.ends_with(":") { - return Ok(None); + Ok(None) } else { - return Ok(Some(Token::Symbol(token[0..token.len() - 1].to_string()))); + Ok(Some(Token::Symbol(token[0..token.len() - 1].to_string()))) } } pub fn parse_symbol(token: &str) -> Result, AssembleError> { - if token.chars().nth(0).unwrap().is_numeric() { + if token.chars().next().unwrap().is_numeric() { return Ok(None); } diff --git a/assembler/src/lib.rs b/assembler/src/lib.rs index d233a24..477f968 100644 --- a/assembler/src/lib.rs +++ b/assembler/src/lib.rs @@ -7,7 +7,7 @@ use crate::{lexer::Token, parser::TokenType}; pub mod lexer; pub mod parser; -pub fn assemble(src: &str) -> Vec { +pub fn assemble(_src: &str) -> Vec { todo!() } @@ -31,7 +31,7 @@ impl fmt::Display for AssembleError { match self { AssembleError::Generic => write!(f, "Generic error"), AssembleError::UnexpectedToken(tok, expected) => { - write!(f, "Unexpected token {:?}, expected {:?}", tok, expected) + write!(f, "Unexpected token {tok:?}, expected {expected:?}") } } } diff --git a/assembler/src/main.rs b/assembler/src/main.rs index 78bf551..469040c 100644 --- a/assembler/src/main.rs +++ b/assembler/src/main.rs @@ -7,11 +7,11 @@ fn main() { let program = fs::read_to_string("../resources/dsa/print.dsa").unwrap(); let tokens = lexer::lexer(program).unwrap(); - println!("{:?}", tokens); + println!("{tokens:?}"); let parser = Parser::new(tokens); for node in parser { - println!("{:?}", node); + println!("{node:?}"); } } diff --git a/assembler/src/parser.rs b/assembler/src/parser.rs index ad4d21f..6cd39d6 100644 --- a/assembler/src/parser.rs +++ b/assembler/src/parser.rs @@ -1,6 +1,4 @@ -use std::path::Iter; - -use common::prelude::Register; +use std::str::FromStr; use crate::AssembleError; use crate::lexer::{Symbol, Token}; @@ -58,6 +56,7 @@ impl TokenType { // TODO: MAKE SURE I DO THE BIT SHIFT FOR LUI CODEGEN #[derive(Debug)] +#[expect(dead_code)] pub struct Node(Option, Opcode, Vec); impl Iterator for Parser { @@ -116,7 +115,8 @@ impl Parser { Opcode::Ldb | Opcode::Ldbs | Opcode::Ldh | Opcode::Ldhs | Opcode::Ldw => { let base = self.expect_any(&[TokenType::Register, TokenType::Symbol])?; let dest = self.expect_any(&[TokenType::Register, TokenType::Symbol])?; - let offset = self.maybe_expect(&[TokenType::Register, TokenType::Immediate]); + let offset = + self.maybe_expect(&[TokenType::Register, TokenType::Immediate]); if offset.is_some() { self.tokens.pop(); args = vec![base, offset.unwrap(), dest]; @@ -129,7 +129,8 @@ impl Parser { let base = self.expect_any(&[TokenType::Register, TokenType::Symbol])?; let dest = self.expect_any(&[TokenType::Register, TokenType::Symbol])?; - let offset = self.maybe_expect(&[TokenType::Register, TokenType::Immediate]); + let offset = + self.maybe_expect(&[TokenType::Register, TokenType::Immediate]); if offset.is_some() { self.tokens.pop(); args = vec![base, offset.unwrap(), dest]; @@ -224,10 +225,13 @@ impl Parser { Ok(Node(label, opcode, args)) } - fn parse_data_definition(&mut self, opcode: Opcode) -> Result, AssembleError> { + fn parse_data_definition( + &mut self, + opcode: Opcode, + ) -> Result, AssembleError> { let mut values = Vec::new(); - let name = self.expect(TokenType::Symbol)?; + let _name = self.expect(TokenType::Symbol)?; values.push(self.tokens.pop().unwrap()); match opcode { @@ -301,7 +305,7 @@ impl Parser { fn maybe_expect(&mut self, types: &[TokenType]) -> Option { let tok = self.tokens.last().unwrap(); - if types.contains(&TokenType::from_token(&tok)) { + if types.contains(&TokenType::from_token(tok)) { Some(tok.clone()) } else { None @@ -363,70 +367,89 @@ pub enum Opcode { Lwi, } +#[derive(Debug)] +pub enum OpcodeFromStrError { + InvalidRegister(&'static str), +} + +impl std::fmt::Display for OpcodeFromStrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::InvalidRegister(reg) => write!(f, "register does not exist: {reg}"), + } + } +} + +impl std::error::Error for OpcodeFromStrError {} + +impl FromStr for Opcode { + type Err = OpcodeFromStrError; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "nop" => Ok(Self::Nop), + "mov" => Ok(Self::Mov), + "movs" => Ok(Self::Movs), + "ldb" => Ok(Self::Ldb), + "ldbs" => Ok(Self::Ldbs), + "ldh" => Ok(Self::Ldh), + "ldhs" => Ok(Self::Ldhs), + "ldw" => Ok(Self::Ldw), + "stb" => Ok(Self::Stb), + "sth" => Ok(Self::Sth), + "stw" => Ok(Self::Stw), + "lli" => Ok(Self::Lli), + "lui" => Ok(Self::Lui), + "jmp" => Ok(Self::Jmp), + "jeq" => Ok(Self::Jeq), + "jne" => Ok(Self::Jne), + "jgt" => Ok(Self::Jgt), + "jge" => Ok(Self::Jge), + "jlt" => Ok(Self::Jlt), + "jle" => Ok(Self::Jle), + "cmp" => Ok(Self::Cmp), + "inc" => Ok(Self::Inc), + "dec" => Ok(Self::Dec), + "shl" => Ok(Self::Shl), + "shr" => Ok(Self::Shr), + "add" => Ok(Self::Add), + "sub" => Ok(Self::Sub), + "and" => Ok(Self::And), + "or" => Ok(Self::Or), + "not" => Ok(Self::Not), + "xor" => Ok(Self::Xor), + "nand" => Ok(Self::Nand), + "nor" => Ok(Self::Nor), + "xnor" => Ok(Self::Xnor), + "int" => Ok(Self::Int), + "irt" => Ok(Self::Irt), + "hlt" => Ok(Self::Hlt), + "iadd" => Ok(Self::Iadd), + "isub" => Ok(Self::Isub), + "db" => Ok(Self::Db), + "dh" => Ok(Self::Dh), + "dw" => Ok(Self::Dw), + "resb" => Ok(Self::Resb), + "resh" => Ok(Self::Resh), + "resw" => Ok(Self::Resw), + "push" => Ok(Self::Push), + "pop" => Ok(Self::Pop), + "lwi" => Ok(Self::Lwi), + _ => Err(OpcodeFromStrError::InvalidRegister("unknown opcode")), + } + } +} + impl Opcode { pub const OPCODES: &[&str] = &[ // Real instructions (0x00-0x26) - "nop", "mov", "movs", "ldb", "ldbs", "ldh", "ldhs", "ldw", "stb", "sth", "stw", "lli", - "lui", "jmp", "jeq", "jne", "jgt", "jge", "jlt", "jle", "cmp", "inc", "dec", "shl", "shr", - "add", "sub", "and", "or", "not", "xor", "nand", "nor", "xnor", "int", "irt", "hlt", - "iadd", "isub", // Pseudo-instructions + "nop", "mov", "movs", "ldb", "ldbs", "ldh", "ldhs", "ldw", "stb", "sth", "stw", + "lli", "lui", "jmp", "jeq", "jne", "jgt", "jge", "jlt", "jle", "cmp", "inc", + "dec", "shl", "shr", "add", "sub", "and", "or", "not", "xor", "nand", "nor", + "xnor", "int", "irt", "hlt", "iadd", "isub", // Pseudo-instructions "db", "dh", "dw", "resb", "resh", "resw", "push", "pop", "lwi", ]; - pub fn from_str(s: &str) -> Option { - match s.to_lowercase().as_str() { - "nop" => Some(Self::Nop), - "mov" => Some(Self::Mov), - "movs" => Some(Self::Movs), - "ldb" => Some(Self::Ldb), - "ldbs" => Some(Self::Ldbs), - "ldh" => Some(Self::Ldh), - "ldhs" => Some(Self::Ldhs), - "ldw" => Some(Self::Ldw), - "stb" => Some(Self::Stb), - "sth" => Some(Self::Sth), - "stw" => Some(Self::Stw), - "lli" => Some(Self::Lli), - "lui" => Some(Self::Lui), - "jmp" => Some(Self::Jmp), - "jeq" => Some(Self::Jeq), - "jne" => Some(Self::Jne), - "jgt" => Some(Self::Jgt), - "jge" => Some(Self::Jge), - "jlt" => Some(Self::Jlt), - "jle" => Some(Self::Jle), - "cmp" => Some(Self::Cmp), - "inc" => Some(Self::Inc), - "dec" => Some(Self::Dec), - "shl" => Some(Self::Shl), - "shr" => Some(Self::Shr), - "add" => Some(Self::Add), - "sub" => Some(Self::Sub), - "and" => Some(Self::And), - "or" => Some(Self::Or), - "not" => Some(Self::Not), - "xor" => Some(Self::Xor), - "nand" => Some(Self::Nand), - "nor" => Some(Self::Nor), - "xnor" => Some(Self::Xnor), - "int" => Some(Self::Int), - "irt" => Some(Self::Irt), - "hlt" => Some(Self::Hlt), - "iadd" => Some(Self::Iadd), - "isub" => Some(Self::Isub), - "db" => Some(Self::Db), - "dh" => Some(Self::Dh), - "dw" => Some(Self::Dw), - "resb" => Some(Self::Resb), - "resh" => Some(Self::Resh), - "resw" => Some(Self::Resw), - "push" => Some(Self::Push), - "pop" => Some(Self::Pop), - "lwi" => Some(Self::Lwi), - _ => None, - } - } - pub fn to_opcode_value(&self) -> Option { match self { Self::Nop => Some(0x00), diff --git a/emulator/src/emulator/ui/control_unit.rs b/emulator/src/emulator/ui/control_unit.rs index 33e982c..1dbaf81 100644 --- a/emulator/src/emulator/ui/control_unit.rs +++ b/emulator/src/emulator/ui/control_unit.rs @@ -59,9 +59,9 @@ impl Component for ControlPanel { // Step if ui.button("Step").clicked() { - self.sender - .send(Command::Step) - .unwrap_or_else(|_| state.error = Some("Failed to send command".to_string())); + self.sender.send(Command::Step).unwrap_or_else(|_| { + state.error = Some("Failed to send command".to_string()); + }); } ui.separator(); @@ -78,12 +78,13 @@ impl Component for ControlPanel { ui.label(format!("Instructions: {}", state.instructions)); ui.label(format!("PC: 0x{:08X}", state.reg_file.get(Register::Pcx))); - let instruction = match Instruction::decode(state.reg_file.get(Register::Cir)) { - Ok(instruction) => instruction.to_string(), - Err(_) => "Invalid Instruction".to_string(), - }; + let instruction = Instruction::decode(state.reg_file.get(Register::Cir)) + .map_or_else( + |_| "Invalid Instruction".to_string(), + |instruction| instruction.to_string(), + ); - ui.label(format!("Instruction: {}", instruction)); + ui.label(format!("Instruction: {instruction}")); }); render_register_table(state, ui, ctx); diff --git a/emulator/src/emulator/ui/editor.rs b/emulator/src/emulator/ui/editor.rs index a9efea1..e608718 100644 --- a/emulator/src/emulator/ui/editor.rs +++ b/emulator/src/emulator/ui/editor.rs @@ -306,7 +306,7 @@ impl Editor { self.sender .send(Command::Write(self.load_offset, self.output.clone())) .unwrap_or_else(|_| { - self.error = Some("Failed to send command".to_string()) + self.error = Some("Failed to send command".to_string()); }); } @@ -323,7 +323,7 @@ impl Editor { // Resets the emulator and all attached devices if ui.button("Reset Emulator").clicked() { self.sender.send(Command::Reset).unwrap_or_else(|_| { - self.error = Some("Failed to send command".to_string()) + self.error = Some("Failed to send command".to_string()); }); } });