assembler: refactor error handling and use ModuleId::new constructor

This commit is contained in:
2025-06-28 23:03:13 +01:00
parent eebea82c4a
commit f42c6d4095
2 changed files with 66 additions and 28 deletions
+19 -20
View File
@@ -6,6 +6,7 @@ use std::path::Path;
use std::sync::mpsc; use std::sync::mpsc;
use std::thread; use std::thread;
use crate::error::{AssembleErrorKind, IoErrorKind};
use crate::{ use crate::{
context::AssemblerContext, context::AssemblerContext,
error::AssembleError, error::AssembleError,
@@ -176,8 +177,8 @@ impl CompilerEngine {
// Verify file exists // Verify file exists
if !path.exists() { if !path.exists() {
return Err(EngineError::Assembly(AssembleError::new_other_error( return Err(EngineError::Assembly(AssembleError::new_other_error(
crate::error::AssembleErrorKind::Io(crate::error::IoError::new( AssembleErrorKind::Io(crate::error::IoError::new(
crate::error::IoErrorKind::NotFound, IoErrorKind::NotFound,
Some(format!("Source file not found: {}", path.display())), Some(format!("Source file not found: {}", path.display())),
)), )),
))); )));
@@ -218,12 +219,12 @@ impl Default for CompilerEngine {
fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> { fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
// Verify the file exists // Verify the file exists
if !src.exists() { if !src.exists() {
return Err(AssembleError::new_other_error( return Err(AssembleError::new_other_error(AssembleErrorKind::Io(
crate::error::AssembleErrorKind::Io(crate::error::IoError::new( crate::error::IoError::new(
crate::error::IoErrorKind::NotFound, IoErrorKind::NotFound,
Some(format!("Source file not found: {}", src.display())), Some(format!("Source file not found: {}", src.display())),
)), ),
)); )));
} }
let mut modules = HashSet::new(); let mut modules = HashSet::new();
@@ -267,12 +268,10 @@ fn prepare_dependency(
context: &AssemblerContext, context: &AssemblerContext,
) -> Result<(), AssembleError> { ) -> Result<(), AssembleError> {
let filename = path.file_name().and_then(|n| n.to_str()).ok_or_else(|| { let filename = path.file_name().and_then(|n| n.to_str()).ok_or_else(|| {
AssembleError::new_other_error(crate::error::AssembleErrorKind::Io( AssembleError::new_other_error(AssembleErrorKind::Io(crate::error::IoError::new(
crate::error::IoError::new( IoErrorKind::InvalidData,
crate::error::IoErrorKind::InvalidData,
Some("Failed to get file name from path".to_string()), Some("Failed to get file name from path".to_string()),
), )))
))
})?; })?;
// Calculate a simple hash for the file (similar to quick_hash) // Calculate a simple hash for the file (similar to quick_hash)
@@ -290,8 +289,8 @@ fn prepare_dependency(
// Phase 1: Tokenize the file // Phase 1: Tokenize the file
println!("Tokenising {filename}"); println!("Tokenising {filename}");
let tokeniser = Tokeniser::new(path)?; let tokeniser = Tokeniser::new(path, context)?;
let tokens = tokeniser.tokenise(context)?; let tokens = tokeniser.tokenise()?;
// Get the module ID that was registered during tokenization // Get the module ID that was registered during tokenization
let module_id = get_module_id_for_file(path, context)?; 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()?; let registry = context.module_registry.read()?;
// Find module by path // Find module by path.
for module in registry.modules() { for module in registry.modules() {
if module.path == file_path { if module.path == file_path {
return Ok(module.id); return Ok(module.id);
@@ -336,15 +335,15 @@ fn get_module_id_for_file(
} }
} }
Err(AssembleError::new_other_error( Err(AssembleError::new_other_error(AssembleErrorKind::Io(
crate::error::AssembleErrorKind::Io(crate::error::IoError::new( crate::error::IoError::new(
crate::error::IoErrorKind::NotFound, IoErrorKind::NotFound,
Some(format!( Some(format!(
"Module not found for file: {}", "Module not found for file: {}",
file_path.display() file_path.display()
)), )),
)), ),
)) )))
} }
/// Result of compilation. This is useless at present but compiles. /// Result of compilation. This is useless at present but compiles.
+46 -7
View File
@@ -9,15 +9,24 @@ use std::{
sync::Arc, sync::Arc,
}; };
use regex::Regex;
use uuid::Uuid; 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. /// The ID for a module. A tuple struct for type safety.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub struct ModuleId(Uuid); pub struct ModuleId(Uuid);
impl ModuleId { impl ModuleId {
#[must_use]
pub fn new() -> Self {
Self(Uuid::new_v4())
}
#[must_use] #[must_use]
pub const fn from_module(module: &Module) -> Self { pub const fn from_module(module: &Module) -> Self {
module.id module.id
@@ -36,6 +45,12 @@ impl ModuleId {
} }
} }
impl Default for ModuleId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for ModuleId { impl std::fmt::Display for ModuleId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)
@@ -61,11 +76,35 @@ impl std::hash::Hash for Module {
} }
impl Module { impl Module {
pub fn new<P: AsRef<Path>>(name: String, path: P) -> Self { pub fn new<P: AsRef<Path>>(p: P) -> Result<Self, AssembleError> {
Self { let path = p.as_ref().to_path_buf();
name, let name = Self::extract_module_name(&path)?;
path: path.as_ref().to_path_buf(), let id = ModuleId::new();
id: ModuleId(Uuid::new_v4()),
} Ok(Self { name, path, id })
}
/// Gets the name for a module from the path.
fn extract_module_name<P: AsRef<Path>>(path: P) -> Result<String, AssembleError> {
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())
} }
} }