From f8a694267d3981b0437c05fc248406116ea9ec06 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Tue, 18 Mar 2025 11:50:19 +1300 Subject: Large restructure Files were moved to be better organised, error messages were changed to be more general, and a Compiler type was added to the library. --- src/source_unit.rs | 180 ----------------------------------------------------- 1 file changed, 180 deletions(-) delete mode 100644 src/source_unit.rs (limited to 'src/source_unit.rs') diff --git a/src/source_unit.rs b/src/source_unit.rs deleted file mode 100644 index 28cc854..0000000 --- a/src/source_unit.rs +++ /dev/null @@ -1,180 +0,0 @@ -use crate::*; - -use log::{info, warn}; -use vagabond::*; - - -type ParseFn = fn(&str, Option<&Path>) -> Option>; - - -/// Gather all source units with a given extension using a PATH-style environment variable. -pub fn gather_from_path_variable(variable: &str, extension: Option<&str>, parse: ParseFn) -> Vec { - let mut source_units = Vec::new(); - if let Ok(string) = std::env::var(variable) { - for path in string.split(":").map(PathBuf::from) { - info!("Found path {path:?} in environment variable {variable:?}"); - source_units.extend(gather_from_path(&path, extension, parse)); - } - }; - return source_units; -} - -/// Gather source units with a given extension at or descending from a path. -pub fn gather_from_path(path: &Path, extension: Option<&str>, parse: ParseFn) -> Vec { - let mut source_units = Vec::new(); - let check_optional_file = |file: &Option| -> bool { - match file { - Some(file) => match file.symbols { - Some(_) => { info!("Found source file at {:?}", file.path); true } - None => { warn!("Could not parse source file at {:?}", file.path); false } - } - None => true, - } - }; - let mut gather_source_unit = |path: &Path| { - if let Ok(unit) = SourceUnit::from_path(&path, extension, parse) { - if unit.main.symbols.is_some() { - info!("Found source file at {:?}", unit.main.path); - let head_good = check_optional_file(&unit.head); - let tail_good = check_optional_file(&unit.tail); - if head_good && tail_good { - source_units.push(unit); - } - } else { - warn!("Could not parse source file at {path:?}"); - check_optional_file(&unit.head); - check_optional_file(&unit.tail); - } - } - }; - if let Ok(entry) = Entry::from_path(path) { - if EntryType::File == entry.entry_type { - gather_source_unit(&entry.path) - } else if EntryType::Directory == entry.entry_type { - info!("Traversing directory {path:?} for source files"); - if let Ok(entries) = traverse_directory(entry.path) { - for entry in entries { - gather_source_unit(&entry.path) - } - } - } - }; - return source_units; -} - - -pub struct SourceUnit { - pub main: SourceFile, - pub head: Option, - pub tail: Option, -} - -impl SourceUnit { - /// Load source from a main file and an associated head and tail file. - pub fn from_path>(path: P, extension: Option<&str>, parse: ParseFn) -> Result { - let main_path = { path.as_ref().canonicalize().unwrap_or_else(|_| path.as_ref().to_path_buf()) }; - let main_path_str = main_path.as_os_str().to_string_lossy().to_string(); - // Attempt to extract an extension from main path if no extension was provided. - let extension = extension.or_else(|| main_path.extension().and_then(|ext| ext.to_str())); - - let head_extension = extension.map(|ext| format!("head.{ext}")); - let tail_extension = extension.map(|ext| format!("tail.{ext}")); - let is_head = head_extension.as_ref().map_or(false, |ext| main_path_str.ends_with(ext.as_str())); - let is_tail = tail_extension.as_ref().map_or(false, |ext| main_path_str.ends_with(ext.as_str())); - let is_main = extension.map_or(true, |ext| main_path_str.ends_with(ext)); - // Head and tail files will be picked up later along with the main file. - if !is_main || is_head || is_tail { return Err(FileError::InvalidExtension); } - - let parse_file = |path: PathBuf| { - if let Ok(source_code) = read_file(&path) { - let symbols = parse(&source_code, Some(&path)); - return Some(SourceFile { symbols, source_code, path: path }); - } - return None; - }; - let head = head_extension.map_or(None, |ext| parse_file(main_path.with_extension(&ext))); - let tail = tail_extension.map_or(None, |ext| parse_file(main_path.with_extension(&ext))); - let source_code = read_file(path.as_ref())?; - let symbols = parse(&source_code, Some(path.as_ref())); - let main = SourceFile { path: main_path, source_code, symbols }; - Ok(SourceUnit { main, head, tail }) - } - - /// Load from a string of source code. - pub fn from_string>(source_code: String, path: P, parse: ParseFn) -> Self { - let path = { path.as_ref().canonicalize().unwrap_or_else(|_| path.as_ref().to_path_buf()) }; - let symbols = parse(&source_code, Some(&path)); - let main = SourceFile { path, source_code, symbols }; - Self { main, head: None, tail: None } - } - - pub fn name(&self) -> Option { - self.main.path.file_name().map(|s| s.to_string_lossy().to_string()) - } - - pub fn path(&self) -> String { - self.main.path.as_os_str().to_string_lossy().to_string() - - } -} - -impl PartialEq for SourceUnit { - fn eq(&self, other: &SourceUnit) -> bool { - if let Ok(this_path) = self.main.path.canonicalize() { - if let Ok(other_path) = other.main.path.canonicalize() { - return this_path == other_path; - } - } - return false; - } -} - - -pub struct SourceFile { - pub path: PathBuf, - pub source_code: String, - pub symbols: Option>, -} - -pub struct Symbol { - pub name: String, - pub namespace: Vec, - pub source: SourceSpan, - pub role: SymbolRole, -} - -impl Symbol { - /// True if this symbol is a valid definition for a reference symbol - pub fn defines(&self, reference: &Symbol) -> bool { - self.name == reference.name && - self.namespace.len() <= reference.namespace.len() && - std::iter::zip(&self.namespace, &reference.namespace).all(|(a, b)| a == b) - } -} - -impl PartialEq for Symbol { - fn eq(&self, other: &Symbol) -> bool { - self.name == other.name && self.namespace == other.namespace - } -} - -impl std::fmt::Debug for Symbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - for name in &self.namespace { - write!(f, "{name}::")? - } - write!(f, "{}", self.name) - } -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum SymbolRole { - Definition(DefinitionType), - Reference, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum DefinitionType { - MustPrecedeReference, - CanFollowReference, -} -- cgit v1.2.3-70-g09d2