From f42c6d409515c45ab8f85d9c68420074672e995b Mon Sep 17 00:00:00 2001 From: "J. Hinchliffe" Date: Sat, 28 Jun 2025 23:03:13 +0100 Subject: [PATCH] assembler: refactor error handling and use ModuleId::new constructor --- assembler/src/compiler_engine.rs | 41 ++++++++++++------------ assembler/src/model/module.rs | 53 +++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/assembler/src/compiler_engine.rs b/assembler/src/compiler_engine.rs index 4728136..1dcb934 100644 --- a/assembler/src/compiler_engine.rs +++ b/assembler/src/compiler_engine.rs @@ -6,6 +6,7 @@ use std::path::Path; use std::sync::mpsc; use std::thread; +use crate::error::{AssembleErrorKind, IoErrorKind}; use crate::{ context::AssemblerContext, error::AssembleError, @@ -176,8 +177,8 @@ impl CompilerEngine { // Verify file exists if !path.exists() { return Err(EngineError::Assembly(AssembleError::new_other_error( - crate::error::AssembleErrorKind::Io(crate::error::IoError::new( - crate::error::IoErrorKind::NotFound, + AssembleErrorKind::Io(crate::error::IoError::new( + IoErrorKind::NotFound, Some(format!("Source file not found: {}", path.display())), )), ))); @@ -218,12 +219,12 @@ impl Default for CompilerEngine { fn assemble(src: &Path) -> Result, AssembleError> { // Verify the file exists if !src.exists() { - return Err(AssembleError::new_other_error( - crate::error::AssembleErrorKind::Io(crate::error::IoError::new( - crate::error::IoErrorKind::NotFound, + return Err(AssembleError::new_other_error(AssembleErrorKind::Io( + crate::error::IoError::new( + IoErrorKind::NotFound, Some(format!("Source file not found: {}", src.display())), - )), - )); + ), + ))); } let mut modules = HashSet::new(); @@ -267,12 +268,10 @@ fn prepare_dependency( context: &AssemblerContext, ) -> Result<(), AssembleError> { let filename = path.file_name().and_then(|n| n.to_str()).ok_or_else(|| { - AssembleError::new_other_error(crate::error::AssembleErrorKind::Io( - crate::error::IoError::new( - crate::error::IoErrorKind::InvalidData, - Some("Failed to get file name from path".to_string()), - ), - )) + AssembleError::new_other_error(AssembleErrorKind::Io(crate::error::IoError::new( + IoErrorKind::InvalidData, + Some("Failed to get file name from path".to_string()), + ))) })?; // Calculate a simple hash for the file (similar to quick_hash) @@ -290,8 +289,8 @@ fn prepare_dependency( // Phase 1: Tokenize the file println!("Tokenising {filename}"); - let tokeniser = Tokeniser::new(path)?; - let tokens = tokeniser.tokenise(context)?; + let tokeniser = Tokeniser::new(path, context)?; + let tokens = tokeniser.tokenise()?; // Get the module ID that was registered during tokenization let module_id = get_module_id_for_file(path, context)?; @@ -328,7 +327,7 @@ fn get_module_id_for_file( { let registry = context.module_registry.read()?; - // Find module by path + // Find module by path. for module in registry.modules() { if module.path == file_path { return Ok(module.id); @@ -336,15 +335,15 @@ fn get_module_id_for_file( } } - Err(AssembleError::new_other_error( - crate::error::AssembleErrorKind::Io(crate::error::IoError::new( - crate::error::IoErrorKind::NotFound, + Err(AssembleError::new_other_error(AssembleErrorKind::Io( + crate::error::IoError::new( + IoErrorKind::NotFound, Some(format!( "Module not found for file: {}", file_path.display() )), - )), - )) + ), + ))) } /// Result of compilation. This is useless at present but compiles. diff --git a/assembler/src/model/module.rs b/assembler/src/model/module.rs index 3b45c89..44bf98c 100644 --- a/assembler/src/model/module.rs +++ b/assembler/src/model/module.rs @@ -9,15 +9,24 @@ use std::{ sync::Arc, }; +use regex::Regex; use uuid::Uuid; -use crate::model::module_registry::ModuleRegistry; +use crate::{ + error::{AssembleError, AssembleErrorKind, IoError, IoErrorKind}, + model::module_registry::ModuleRegistry, +}; /// The ID for a module. A tuple struct for type safety. #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] pub struct ModuleId(Uuid); impl ModuleId { + #[must_use] + pub fn new() -> Self { + Self(Uuid::new_v4()) + } + #[must_use] pub const fn from_module(module: &Module) -> Self { module.id @@ -36,6 +45,12 @@ impl ModuleId { } } +impl Default for ModuleId { + fn default() -> Self { + Self::new() + } +} + impl std::fmt::Display for ModuleId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) @@ -61,11 +76,35 @@ impl std::hash::Hash for Module { } impl Module { - pub fn new>(name: String, path: P) -> Self { - Self { - name, - path: path.as_ref().to_path_buf(), - id: ModuleId(Uuid::new_v4()), - } + pub fn new>(p: P) -> Result { + let path = p.as_ref().to_path_buf(); + let name = Self::extract_module_name(&path)?; + let id = ModuleId::new(); + + Ok(Self { name, path, id }) + } + + /// Gets the name for a module from the path. + fn extract_module_name>(path: P) -> Result { + let extensions_regex = Regex::new(".(dsa|S|asm)$") + .expect("For some reason the regular expression failed to compile!"); + let module_name = path + .as_ref() + .file_name() + .map(|f| f.to_string_lossy()) + .ok_or_else(|| { + AssembleError::new_other_error(AssembleErrorKind::Io(IoError::new( + IoErrorKind::InvalidData, + Some( + "the filename couldn't be extracted, is it valid UTF-8?" + .to_string(), + ), + ))) + })?; + + // Strip any file extensions given. We don't care for now. + let out = extensions_regex.replace(&module_name, ""); + + Ok(out.to_string()) } }