assembler: refactor error handling and use ModuleId::new constructor
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user