misc: apply clippy lints

This commit is contained in:
2025-06-19 15:51:23 +01:00
parent c1d72e8d4c
commit 81433dcbcd
17 changed files with 134 additions and 127 deletions
+20 -23
View File
@@ -1,11 +1,8 @@
use common::{ use common::{args, prelude::*};
args, instructions,
prelude::{ITypeArgs, Instruction, Interrupt, RTypeArgs, Register},
};
use crate::{ use crate::{
AssembleError, expect_token, expect_type, AssembleError, expect_token,
model::{Node, Opcode, Token, TokenType}, model::{Node, Opcode},
}; };
pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> { pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> {
@@ -25,12 +22,12 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
match opcode { match opcode {
Opcode::Nop => Ok(Instruction::Nop), Opcode::Nop => Ok(Instruction::Nop),
Opcode::Mov => { Opcode::Mov => {
let src = expect_token!(args.get(0).unwrap(), Register)?; let src = expect_token!(args.first().unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Mov(args!(R, sr1: src, dr: dest))) Ok(Instruction::Mov(args!(R, sr1: src, dr: dest)))
} }
Opcode::Movs => { Opcode::Movs => {
let src = expect_token!(args.get(0).unwrap(), Register)?; let src = expect_token!(args.first().unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::MovSigned(args!(R, sr1: src, dr: dest))) Ok(Instruction::MovSigned(args!(R, sr1: src, dr: dest)))
} }
@@ -42,7 +39,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
| Opcode::Stb | Opcode::Stb
| Opcode::Stw | Opcode::Stw
| Opcode::Sth => { | Opcode::Sth => {
let base = expect_token!(args.get(0).unwrap(), Register)?; let base = expect_token!(args.first().unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
let offset = expect_token!(args.get(2).unwrap(), Immediate)?; let offset = expect_token!(args.get(2).unwrap(), Immediate)?;
let args = args!(I, immediate: offset as u16, r1: base, r2: dest); let args = args!(I, immediate: offset as u16, r1: base, r2: dest);
@@ -60,14 +57,14 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
} }
} }
Opcode::Lli => { Opcode::Lli => {
let value = expect_token!(args.get(0).unwrap(), Immediate)?; let value = expect_token!(args.first().unwrap(), Immediate)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: value as u16, r1: dest); let args = args!(I, immediate: value as u16, r1: dest);
Ok(Instruction::LoadLowerImmediate(args)) Ok(Instruction::LoadLowerImmediate(args))
} }
Opcode::Lui => { Opcode::Lui => {
let value = expect_token!(args.get(0).unwrap(), Immediate)? >> 16; let value = expect_token!(args.first().unwrap(), Immediate)? >> 16;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: value as u16, r1: dest); let args = args!(I, immediate: value as u16, r1: dest);
@@ -80,7 +77,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
| Opcode::Jge | Opcode::Jge
| Opcode::Jlt | Opcode::Jlt
| Opcode::Jle => { | Opcode::Jle => {
let address = expect_token!(args.get(0).unwrap(), Immediate)?; let address = expect_token!(args.first().unwrap(), Immediate)?;
let offset = expect_token!(args.get(1).unwrap(), Register)?; let offset = expect_token!(args.get(1).unwrap(), Register)?;
let args = args!(I, immediate: address as u16, r1: offset); let args = args!(I, immediate: address as u16, r1: offset);
@@ -96,25 +93,25 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
} }
} }
Opcode::Cmp => { Opcode::Cmp => {
let left = expect_token!(args.get(0).unwrap(), Register)?; let left = expect_token!(args.first().unwrap(), Register)?;
let right = expect_token!(args.get(1).unwrap(), Register)?; let right = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Compare(args!(R, sr1: left, sr2: right))) Ok(Instruction::Compare(args!(R, sr1: left, sr2: right)))
} }
Opcode::Inc => { Opcode::Inc => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
Ok(Instruction::Increment(args!(R, sr1: reg))) Ok(Instruction::Increment(args!(R, sr1: reg)))
} }
Opcode::Dec => { Opcode::Dec => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
Ok(Instruction::Decrement(args!(R, sr1: reg))) Ok(Instruction::Decrement(args!(R, sr1: reg)))
} }
Opcode::Shl => { Opcode::Shl => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8; let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount))) Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount)))
} }
Opcode::Shr => { Opcode::Shr => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8; let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount))) Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount)))
} }
@@ -126,7 +123,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
| Opcode::Nand | Opcode::Nand
| Opcode::Nor | Opcode::Nor
| Opcode::Xnor => { | Opcode::Xnor => {
let left = expect_token!(args.get(0).unwrap(), Register)?; let left = expect_token!(args.first().unwrap(), Register)?;
let right = expect_token!(args.get(1).unwrap(), Register)?; let right = expect_token!(args.get(1).unwrap(), Register)?;
let dest = expect_token!(args.get(2).unwrap(), Register)?; let dest = expect_token!(args.get(2).unwrap(), Register)?;
let args = args!(R, sr1: left, sr2: right, dr: dest); let args = args!(R, sr1: left, sr2: right, dr: dest);
@@ -144,7 +141,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
} }
} }
Opcode::Iadd | Opcode::Isub => { Opcode::Iadd | Opcode::Isub => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
let immediate = expect_token!(args.get(1).unwrap(), Immediate)? as u16; let immediate = expect_token!(args.get(1).unwrap(), Immediate)? as u16;
let dest = expect_token!(args.get(2).unwrap(), Register)?; let dest = expect_token!(args.get(2).unwrap(), Register)?;
let args = args!(I, immediate: immediate, r1: reg, r2: dest); let args = args!(I, immediate: immediate, r1: reg, r2: dest);
@@ -156,22 +153,22 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
} }
} }
Opcode::Not => { Opcode::Not => {
let reg = expect_token!(args.get(0).unwrap(), Register)?; let reg = expect_token!(args.first().unwrap(), Register)?;
let dest = expect_token!(args.get(1).unwrap(), Register)?; let dest = expect_token!(args.get(1).unwrap(), Register)?;
Ok(Instruction::Not(args!(R, sr1: reg, dr: dest))) Ok(Instruction::Not(args!(R, sr1: reg, dr: dest)))
} }
Opcode::Int => { Opcode::Int => {
let code = expect_token!(args.get(0).unwrap(), Immediate)? as u8; let code = expect_token!(args.first().unwrap(), Immediate)? as u8;
Ok(Instruction::Interrupt(Interrupt::Software(code))) Ok(Instruction::Interrupt(Interrupt::Software(code)))
} }
Opcode::Irt => Ok(Instruction::IntReturn), Opcode::Irt => Ok(Instruction::IntReturn),
Opcode::Hlt => Ok(Instruction::Halt), Opcode::Hlt => Ok(Instruction::Halt),
Opcode::Data => { Opcode::Data => {
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?; let immediate = expect_token!(args.first().unwrap(), Immediate)?;
Ok(Instruction::Data(immediate)) Ok(Instruction::Data(immediate))
} }
Opcode::Segment => { Opcode::Segment => {
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?; let immediate = expect_token!(args.first().unwrap(), Immediate)?;
Ok(Instruction::Segment(immediate)) Ok(Instruction::Segment(immediate))
} }
Opcode::Db Opcode::Db
+6 -6
View File
@@ -1,8 +1,8 @@
use common::prelude::Register; use common::prelude::Register;
use crate::{ use crate::{
AssembleError, dsa, expect_token, expect_type, AssembleError, expect_token, expect_type,
model::{Node, Opcode, Token, TokenType}, model::{Node, Opcode, Token},
node, node,
}; };
@@ -13,7 +13,7 @@ pub fn expand_pseudo_ops(
let mut result = Vec::<Node>::with_capacity(nodes.len()); let mut result = Vec::<Node>::with_capacity(nodes.len());
for node in nodes.iter_mut() { for node in nodes.iter_mut() {
if let Err(_) = try_expand(node.clone(), &mut result, module) { if try_expand(node.clone(), &mut result, module).is_err() {
result.push(node.clone()); result.push(node.clone());
} }
} }
@@ -22,9 +22,9 @@ pub fn expand_pseudo_ops(
} }
fn try_expand( fn try_expand(
mut node: Node, node: Node,
result: &mut Vec<Node>, result: &mut Vec<Node>,
module: u64, _module: u64,
) -> Result<(), AssembleError> { ) -> Result<(), AssembleError> {
match node.opcode() { match node.opcode() {
Opcode::Push => expand_push(node.clone(), result)?, Opcode::Push => expand_push(node.clone(), result)?,
@@ -176,7 +176,7 @@ fn expand_dx(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError>
let mut buffer = vec![]; let mut buffer = vec![];
let mut args = current.args(); let mut args = current.args();
let label = args.remove(0); let _label = args.remove(0);
for word in process_dx_data(args, size)? { for word in process_dx_data(args, size)? {
buffer.push(node!(None, Opcode::Data, Token::Immediate(word))); buffer.push(node!(None, Opcode::Data, Token::Immediate(word)));
+29 -32
View File
@@ -6,7 +6,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use common::prelude::Instruction; use common::prelude::*;
use crate::{ use crate::{
codegen::codegen, codegen::codegen,
@@ -38,7 +38,7 @@ pub fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
let instructions = codegen(nodes)?; let instructions = codegen(nodes)?;
for inst in instructions.iter() { for inst in instructions.iter() {
println!("{}", inst); println!("{inst}");
} }
Ok(instructions) Ok(instructions)
@@ -87,7 +87,7 @@ fn prepare_dependency(
); );
for n in nodes.iter() { for n in nodes.iter() {
println!("{}", n); println!("{n}");
} }
program.add_module(nodes); program.add_module(nodes);
@@ -161,86 +161,83 @@ fn log(message: &str) {
// create a macro that lexes and parses the input string into Nodes // create a macro that lexes and parses the input string into Nodes
#[macro_export] #[macro_export]
#[macro_use]
macro_rules! dsa { macro_rules! dsa {
// Version with formatting arguments // Version with formatting arguments
($hash:expr, $input:expr, $($args:expr),+) => {{ ($hash:expr, $input:expr, $($args:expr),+) => {{
let input = format!($input, $($args),+); let input = format!($input, $($args),+);
let tokens = crate::lexer::lexer(input, $hash)?; let tokens = $crate::lexer::lexer(input, $hash)?;
let parsed = crate::parser::Parser::parse_nodes(tokens)?; let parsed = $crate::parser::Parser::parse_nodes(tokens)?;
parsed parsed
}}; }};
// Version without formatting // Version without formatting
($hash:expr, $input:expr) => {{ ($hash:expr, $input:expr) => {{
let input = String::from($input); let input = String::from($input);
let tokens = crate::lexer::lexer(input, $hash)?; let tokens = $crate::lexer::lexer(input, $hash)?;
let parsed = crate::parser::Parser::parse_nodes(tokens)?; let parsed = $crate::parser::Parser::parse_nodes(tokens)?;
parsed parsed
}}; }};
} }
#[macro_export] #[macro_export]
#[macro_use]
macro_rules! expect_token { macro_rules! expect_token {
($token:expr, Symbol) => { ($token:expr, Symbol) => {
match $token { match $token {
Token::Symbol(value) => Ok(value.clone()), $crate::model::Token::Symbol(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken( other => Err($crate::AssembleError::UnexpectedToken(
other.clone(), other.clone(),
TokenType::Symbol, $crate::model::TokenType::Symbol,
)), )),
} }
}; };
($token:expr, Register) => { ($token:expr, Register) => {
match $token { match $token {
Token::Register(value) => Ok(value.clone()), $crate::model::Token::Register(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken( other => Err($crate::AssembleError::UnexpectedToken(
other.clone(), other.clone(),
TokenType::Register, $crate::model::TokenType::Register,
)), )),
} }
}; };
($token:expr, Immediate) => { ($token:expr, Immediate) => {
match $token { match $token {
Token::Immediate(value) => Ok(value.clone()), $crate::model::Token::Immediate(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken( other => Err($crate::AssembleError::UnexpectedToken(
other.clone(), other.clone(),
TokenType::Immediate, $crate::model::TokenType::Immediate,
)), )),
} }
}; };
($token:expr, StringLit) => { ($token:expr, StringLit) => {
match $token { match $token {
Token::StringLit(value) => Ok(value.clone()), $crate::model::Token::StringLit(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken( other => Err($crate::AssembleError::UnexpectedToken(
other.clone(), other.clone(),
TokenType::StringLit, $crate::model::TokenType::StringLit,
)), )),
} }
}; };
($token:expr, Opcode) => { ($token:expr, Opcode) => {
match $token { match $token {
Token::Opcode(value) => Ok(value.clone()), $crate::model::Token::Opcode(value) => Ok(value.clone()),
other => Err(AssembleError::UnexpectedToken( other => Err($crate::AssembleError::UnexpectedToken(
other.clone(), other.clone(),
TokenType::Opcode, $crate::model::TokenType::Opcode,
)), )),
} }
}; };
} }
#[macro_export] #[macro_export]
#[macro_use]
macro_rules! expect_type { macro_rules! expect_type {
($token:expr, $($variant:ident),+) => {{ ($token:expr, $($variant:ident),+) => {{
let token = $token; let token = $token;
match &token { match &token {
$( $(
Token::$variant(_) => Ok(token.clone()), $crate::model::Token::$variant(_) => Ok(token.clone()),
)+ )+
other => { other => {
let expected_type = expect_type!(@get_first_type $($variant),+); let expected_type = expect_type!(@get_first_type $($variant),+);
Err(AssembleError::UnexpectedToken( Err($crate::AssembleError::UnexpectedToken(
other.clone().clone(), other.clone().clone(),
expected_type, expected_type,
)) ))
@@ -248,9 +245,9 @@ macro_rules! expect_type {
} }
}}; }};
(@get_first_type Symbol $(, $rest:ident)*) => { TokenType::Symbol }; (@get_first_type Symbol $(, $rest:ident)*) => { $crate::model::TokenType::Symbol };
(@get_first_type Register $(, $rest:ident)*) => { TokenType::Register }; (@get_first_type Register $(, $rest:ident)*) => { $crate::model::TokenType::Register };
(@get_first_type Immediate $(, $rest:ident)*) => { TokenType::Immediate }; (@get_first_type Immediate $(, $rest:ident)*) => { $crate::model::TokenType::Immediate };
(@get_first_type StringLit $(, $rest:ident)*) => { TokenType::StringLit }; (@get_first_type StringLit $(, $rest:ident)*) => { $crate::model::TokenType::StringLit };
(@get_first_type Opcode $(, $rest:ident)*) => { TokenType::Opcode }; (@get_first_type Opcode $(, $rest:ident)*) => { $crate::model::TokenType::Opcode };
} }
+1 -1
View File
@@ -20,7 +20,7 @@ fn main() {
}); });
} }
Err(e) => { Err(e) => {
eprintln!("{}", e); eprintln!("{e}");
std::process::exit(1); std::process::exit(1);
} }
} }
+9 -3
View File
@@ -12,7 +12,6 @@ pub struct Node {
} }
#[macro_export] #[macro_export]
#[macro_use]
macro_rules! node { macro_rules! node {
($symbol: expr, $opcode: expr, args: $tokens: expr) => { ($symbol: expr, $opcode: expr, args: $tokens: expr) => {
Node::new($symbol.clone(), $opcode.clone(), $tokens.clone()) Node::new($symbol.clone(), $opcode.clone(), $tokens.clone())
@@ -55,7 +54,7 @@ impl Node {
impl fmt::Display for Node { impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let symbol = match &self.label() { let symbol = match &self.label() {
Some(symbol) => format!("{}:\n", symbol), Some(symbol) => format!("{symbol}:\n"),
None => "".to_string(), None => "".to_string(),
}; };
@@ -146,12 +145,19 @@ impl fmt::Display for Opcode {
} }
} }
#[derive(Debug, Clone, Eq, Hash)] #[derive(Debug, Clone, Eq)]
pub struct Symbol { pub struct Symbol {
pub name: String, pub name: String,
pub module: Module, pub module: Module,
} }
impl std::hash::Hash for Symbol {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.module.hash(state);
}
}
impl PartialEq for Symbol { impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.module == other.module self.name == other.name && self.module == other.module
+9 -6
View File
@@ -1,9 +1,12 @@
use std::path::PathBuf; use std::path::PathBuf;
use common::prelude::{Instruction, Register}; use crate::{
AssembleError, expect_token, expect_type,
model::{Node, Opcode, Token, TokenType},
node,
};
use crate::model::{Module, Node, Opcode, Symbol, Token, TokenType}; use common::prelude::*;
use crate::{AssembleError, dsa, expect_token, expect_type, node, quick_hash};
pub struct Parser { pub struct Parser {
tokens: Vec<Token>, tokens: Vec<Token>,
@@ -93,7 +96,7 @@ impl Parser {
let mut offset = Token::Immediate(0); let mut offset = Token::Immediate(0);
if let Ok(next) = self.peek_next() { if let Ok(next) = self.peek_next() {
if let Ok(_) = expect_type!(next, Immediate) { if expect_type!(next, Immediate).is_ok() {
offset = self.next()?; offset = self.next()?;
} }
} }
@@ -105,7 +108,7 @@ impl Parser {
let dest = expect_type!(self.next()?, Register, Symbol)?; let dest = expect_type!(self.next()?, Register, Symbol)?;
let mut offset = Token::Immediate(0); let mut offset = Token::Immediate(0);
if let Ok(next) = self.peek_next() { if let Ok(next) = self.peek_next() {
if let Ok(_) = expect_type!(next, Immediate) { if expect_type!(next, Immediate).is_ok() {
offset = self.next()?; offset = self.next()?;
} }
} }
@@ -273,7 +276,7 @@ impl Parser {
Token::StringLit(_) => { Token::StringLit(_) => {
values.push(self.tokens.pop().unwrap()); values.push(self.tokens.pop().unwrap());
} }
Token::Immediate(val) if *val <= u32::MAX as u32 => { Token::Immediate(_) => {
values.push(self.tokens.pop().unwrap()); values.push(self.tokens.pop().unwrap());
} }
_ => break, _ => break,
+3 -5
View File
@@ -8,8 +8,8 @@ use crate::{
node, quick_hash, node, quick_hash,
}; };
pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> { pub fn resolve_symbols(nodes: &mut [Node]) -> Result<(), AssembleError> {
let symbol_table = generate_symbol_table(&nodes)?; let symbol_table = generate_symbol_table(nodes)?;
for node in nodes.iter_mut() { for node in nodes.iter_mut() {
match node.opcode() { match node.opcode() {
@@ -53,9 +53,7 @@ pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
Ok(()) Ok(())
} }
fn generate_symbol_table( fn generate_symbol_table(nodes: &[Node]) -> Result<HashMap<Symbol, u32>, AssembleError> {
nodes: &Vec<Node>,
) -> Result<HashMap<Symbol, u32>, AssembleError> {
let mut table = HashMap::new(); let mut table = HashMap::new();
for (i, node) in nodes.iter().enumerate() { for (i, node) in nodes.iter().enumerate() {
+5 -4
View File
@@ -86,7 +86,8 @@ impl TryFrom<u8> for Register {
} }
Ok(match idx { Ok(match idx {
// System registers are not indexable in the reg file so they cannot be modified by instructions. // System registers are not indexable in the reg file so they cannot be
// modified by instructions.
0x0 => Self::Rg0, 0x0 => Self::Rg0,
0x1 => Self::Rg1, 0x1 => Self::Rg1,
0x2 => Self::Rg2, 0x2 => Self::Rg2,
@@ -414,8 +415,8 @@ impl std::fmt::Display for Instruction {
Self::Increment(a) | Self::Decrement(a) => write!(f, " {}", a.sr1), Self::Increment(a) | Self::Decrement(a) => write!(f, " {}", a.sr1),
Self::Interrupt(a) => write!(f, " {}", a.as_u8()), Self::Interrupt(a) => write!(f, " {}", a.as_u8()),
Self::Data(a) => write!(f, " {}", a), Self::Data(a) => write!(f, " {a}"),
Self::Segment(x) => write!(f, " [SEGMENT {}]", x), Self::Segment(x) => write!(f, " [SEGMENT {x}]"),
_ => Ok(()), _ => Ok(()),
} }
} }
@@ -469,7 +470,7 @@ impl TryFrom<u32> for Instruction {
0x24 => Ok(Self::Halt), 0x24 => Ok(Self::Halt),
0x25 => Ok(Self::AddImmediate(ITypeArgs::try_from(data)?)), 0x25 => Ok(Self::AddImmediate(ITypeArgs::try_from(data)?)),
0x26 => Ok(Self::SubImmediate(ITypeArgs::try_from(data)?)), 0x26 => Ok(Self::SubImmediate(ITypeArgs::try_from(data)?)),
0x3F => Ok(Self::Segment(data as u8 as u32)), 0x3F => Ok(Self::Segment(u32::from(data as u8))),
_ => Err(InstructionDecodeError::InvalidOpcode(opcode)), _ => Err(InstructionDecodeError::InvalidOpcode(opcode)),
} }
} }
+3 -2
View File
@@ -16,7 +16,8 @@ fn encode_no_args(opcode: u8) -> u32 {
(opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6) (opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6)
} }
/// Expands to a match statement that calls encode on instructions that implement [`Encode`]: /// Expands to a match statement that calls encode on instructions that implement
/// [`Encode`]:
/// ///
/// # Usage /// # Usage
/// ///
@@ -58,7 +59,7 @@ impl Encode for Instruction {
Self::Segment(segment) => { Self::Segment(segment) => {
let opcode = u32::from(self.opcode()); let opcode = u32::from(self.opcode());
let segment = segment as u8; let segment = segment as u8;
(opcode << 26) | (segment as u32) (opcode << 26) | u32::from(segment)
} }
] ]
) )
+1 -1
View File
@@ -246,7 +246,7 @@ impl CodeEditor {
text: &mut dyn egui::TextBuffer, text: &mut dyn egui::TextBuffer,
) -> TextEditOutput { ) -> TextEditOutput {
let mut text_edit_output: Option<TextEditOutput> = None; let mut text_edit_output: Option<TextEditOutput> = None;
let mut code_editor = |ui: &mut egui::Ui| { let code_editor = |ui: &mut egui::Ui| {
ui.horizontal_top(|h| { ui.horizontal_top(|h| {
self.theme.modify_style(h, self.fontsize); self.theme.modify_style(h, self.fontsize);
if self.numlines { if self.numlines {
+2 -2
View File
@@ -97,7 +97,7 @@ pub fn run_emulator(
// Execute one cycle. // Execute one cycle.
match processor.cycle() { match processor.cycle() {
Ok((addr, instruction)) => { Ok((addr, instruction)) => {
history.push((addr, instruction.clone())); history.push((addr, instruction));
} }
Err(why) => { Err(why) => {
let pcx = processor.get(Register::Pcx); let pcx = processor.get(Register::Pcx);
@@ -148,7 +148,7 @@ pub fn run_emulator(
} }
}; };
history.push(instruction.clone()); history.push(instruction);
// let instruction = match Instruction::decode(cpu_lock.get(Register::Cir)) // let instruction = match Instruction::decode(cpu_lock.get(Register::Cir))
// {}; // {};
+2 -8
View File
@@ -225,19 +225,13 @@ impl Default for State {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, Default)]
pub struct PersistentState { pub struct PersistentState {
pub history: Vec<(u32, Instruction)>, pub history: Vec<(u32, Instruction)>,
} }
impl Default for PersistentState {
fn default() -> Self {
Self { history: vec![] }
}
}
impl PersistentState { impl PersistentState {
pub fn update(&mut self, new_state: &PersistentState) { pub fn update(&mut self, new_state: &Self) {
self.history.extend(new_state.history.clone()); self.history.extend(new_state.history.clone());
if self.history.len() > 32768 { if self.history.len() > 32768 {
let len = self.history.len() - 32768; let len = self.history.len() - 32768;
@@ -31,7 +31,7 @@ impl Processor {
} }
} }
pub fn reset(&mut self) { pub const fn reset(&mut self) {
// set all registers to zero // set all registers to zero
// run memory.reset() // run memory.reset()
self.registers.reset(); self.registers.reset();
@@ -166,8 +166,6 @@ impl Executable for Instruction {
fn execute(self, cpu: &mut Processor) { fn execute(self, cpu: &mut Processor) {
match self { match self {
// No operation - a blank line. // No operation - a blank line.
Self::Nop => {}
// Copies from SrcReg to a.drReg. // Copies from SrcReg to a.drReg.
Self::Mov(a) => { Self::Mov(a) => {
*cpu.reg(a.dr) = cpu.get(a.sr1); *cpu.reg(a.dr) = cpu.get(a.sr1);
@@ -395,11 +393,9 @@ impl Executable for Instruction {
cpu.halted = true; cpu.halted = true;
} }
Self::Segment(_) => {} Self::Segment(_) | Self::Nop | Self::Data(_) => {}
Self::Data(_) => {}
_ => { _ => {
println!("unimplemented instruction: {}", self); eprintln!("WARN: unimplemented instruction: {self}");
todo!() todo!()
} }
} }
+14 -4
View File
@@ -4,7 +4,7 @@ use crate::emulator::{
}; };
use eframe::egui; use eframe::egui;
use egui::{Color32, FontId, Margin, RichText, Vec2}; use egui::{Color32, FontId, Vec2};
const VGA_WIDTH: usize = 80; const VGA_WIDTH: usize = 80;
const VGA_HEIGHT: usize = 25; const VGA_HEIGHT: usize = 25;
@@ -14,11 +14,18 @@ pub struct Display {
} }
impl Display { impl Display {
pub fn new() -> Self { #[must_use]
pub const fn new() -> Self {
Self { visible: false } Self { visible: false }
} }
} }
impl Default for Display {
fn default() -> Self {
Self::new()
}
}
impl Component for Display { impl Component for Display {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"Display" "Display"
@@ -32,13 +39,14 @@ impl Component for Display {
&mut self.visible &mut self.visible
} }
fn render(&mut self, state: &mut State, ui: &mut egui::Ui, ctx: &egui::Context) { fn render(&mut self, state: &mut State, ui: &mut egui::Ui, _ctx: &egui::Context) {
let display: Vec<u8> = state.display_view.clone(); let display: Vec<u8> = state.display_view.clone();
let font_id = FontId::monospace(12.0); let font_id = FontId::monospace(12.0);
let char_width = ui.fonts(|f| f.glyph_width(&font_id, 'W')); let char_width = ui.fonts(|f| f.glyph_width(&font_id, 'W'));
let line_height = ui.fonts(|f| f.row_height(&font_id)); let line_height = ui.fonts(|f| f.row_height(&font_id));
#[expect(clippy::cast_precision_loss)]
let display_size = Vec2::new( let display_size = Vec2::new(
char_width * VGA_WIDTH as f32, char_width * VGA_WIDTH as f32,
line_height * VGA_HEIGHT as f32, line_height * VGA_HEIGHT as f32,
@@ -56,7 +64,7 @@ impl Component for Display {
let index = y * VGA_WIDTH + x; let index = y * VGA_WIDTH + x;
if index < display.len() { if index < display.len() {
let byte = display[index]; let byte = display[index];
let ch = if byte >= 32 && byte <= 126 { let ch = if (32..=126).contains(&byte) {
byte as char byte as char
} else { } else {
' ' ' '
@@ -67,7 +75,9 @@ impl Component for Display {
} }
} }
#[expect(clippy::cast_precision_loss)]
let text_pos = rect.min + Vec2::new(0.0, y as f32 * line_height); let text_pos = rect.min + Vec2::new(0.0, y as f32 * line_height);
ui.painter().text( ui.painter().text(
text_pos, text_pos,
egui::Align2::LEFT_TOP, egui::Align2::LEFT_TOP,
+16 -18
View File
@@ -82,7 +82,7 @@ impl Component for Editor {
impl Editor { impl Editor {
#[must_use] #[must_use]
pub fn new(sender: Sender<Command>) -> Self { pub const fn new(sender: Sender<Command>) -> Self {
Self { Self {
path: None, path: None,
text: String::new(), text: String::new(),
@@ -176,7 +176,7 @@ impl Editor {
{ {
if let Ok(contents) = std::fs::read_to_string(&path) { if let Ok(contents) = std::fs::read_to_string(&path) {
self.path = Some(path); self.path = Some(path);
self.text = contents.clone(); self.text.clone_from(&contents);
self.buffer = contents; self.buffer = contents;
self.unsaved = false; self.unsaved = false;
} }
@@ -294,7 +294,7 @@ impl Editor {
editor.show(ui, &mut self.text); editor.show(ui, &mut self.text);
} }
fn render_bottom_bar(&mut self, _state: &mut State, ui: &mut Ui, _ctx: &Context) { fn render_bottom_bar(&self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
ui.horizontal(|ui| { ui.horizontal(|ui| {
// error display // error display
ui.label( ui.label(
@@ -337,22 +337,20 @@ impl Editor {
} }
// builds the current file // builds the current file
if ui.button("Build").clicked() { if ui.button("Build").clicked() && !self.unsaved {
if !self.unsaved { if let Some(path) = &self.path {
if let Some(path) = &self.path { let instructions = match assembler::assemble(path) {
let instructions = match assembler::assemble(path) { Ok(instructions) => instructions,
Ok(instructions) => instructions, Err(error) => {
Err(error) => { self.error = Some(error.to_string());
self.error = Some(error.to_string()); return;
return; }
} };
};
self.output = instructions self.output = instructions
.iter() .iter()
.flat_map(|i| i.encode().to_be_bytes().to_vec()) .flat_map(|i| i.encode().to_be_bytes().to_vec())
.collect(); .collect();
}
} }
} }
+8 -2
View File
@@ -42,7 +42,7 @@ impl Component for History {
for (idx, instruction) in for (idx, instruction) in
state.persistent.history.iter().enumerate() state.persistent.history.iter().enumerate()
{ {
ui.label(format!("{}: ", idx)); ui.label(format!("{idx}: "));
// Hex column // Hex column
let addr = instruction.0; let addr = instruction.0;
@@ -65,9 +65,15 @@ impl Component for History {
} }
} }
impl Default for History {
fn default() -> Self {
Self::new()
}
}
impl History { impl History {
#[must_use] #[must_use]
pub fn new() -> Self { pub const fn new() -> Self {
Self { visible: false } Self { visible: false }
} }
} }
+3 -3
View File
@@ -1,5 +1,3 @@
use std::io::Read;
use crate::emulator::{system::model::State, ui::interface::Component}; use crate::emulator::{system::model::State, ui::interface::Component};
use common::instructions::Register; use common::instructions::Register;
@@ -52,7 +50,9 @@ impl Component for StackInspector {
for (i, value) in for (i, value) in
state.stack_view.chunks(4).take(32).enumerate() state.stack_view.chunks(4).take(32).enumerate()
{ {
let value = u32::from_be_bytes(value.try_into().unwrap()); let value = u32::from_be_bytes(value.try_into().expect(
"Could not read 4 byte instruction or data! Something is wrong.",
));
ui.label(format!( ui.label(format!(
"{} [{}]", "{} [{}]",
i, i,