diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-02-05 12:58:02 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-02-05 13:03:36 +1300 |
commit | 80da2af821385b2fc89091e9ac37a047349da4bd (patch) | |
tree | 2ba50368301e041f8d1b99145ab0a1fe28f91571 /src/source_hierarchy.rs | |
parent | 8d11be64f6c1747e7c4049105a6dd4ea9ab0d27f (diff) | |
download | assembler-80da2af821385b2fc89091e9ac37a047349da4bd.zip |
Implement source unit compilation, symbol resolution, error reporting
This library can now carry out all stages of assembly from collecting
source fragments to resolving symbols to pruning unused libraries to
generating a single compiled source file.
Pretty-printing of state has also been implemented in this library.
The source tree hierarchy, symbol resolution errors, and file read
errors can all be printed in a tidy format.
Diffstat (limited to 'src/source_hierarchy.rs')
-rw-r--r-- | src/source_hierarchy.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/source_hierarchy.rs b/src/source_hierarchy.rs new file mode 100644 index 0000000..9478c56 --- /dev/null +++ b/src/source_hierarchy.rs @@ -0,0 +1,58 @@ +use crate::*; + +use ansi::*; + + +pub struct SourceHierarchy<'a> { + pub resolver: &'a Resolver, +} + +impl<'a> SourceHierarchy<'a> { + pub fn report(&self) { + eprintln!("."); + let len = self.resolver.root_unit_ids.len(); + for (i, id) in self.resolver.root_unit_ids.iter().enumerate() { + let end = i + 1 == len; + self.report_leaf(*id, Vec::new(), end); + } + } + + fn report_leaf(&self, id: usize, mut levels: Vec<bool>, end: bool) { + // A level entry is true if all entries in that level have been printed. + for level in &levels { + match level { + false => eprint!("│ "), + true => eprint!(" "), + } + } + // The end value is true if all siblings of this entry have been printed. + match end { + false => eprint!("├── "), + true => eprint!("└── "), + } + if let Some(unit) = self.resolver.source_units.get(id) { + let path_str = &unit.source_unit.main.path.as_os_str().to_string_lossy(); + if let Some(name_str) = unit.source_unit.name() { + eprint!("{name_str}{BLUE}"); + if unit.source_unit.head.is_some() { eprint!(" +head") } + if unit.source_unit.tail.is_some() { eprint!(" +tail") } + let mut unresolved = 0; + for symbol in &self.resolver.unresolved { + if symbol.source_id == id { unresolved += 1; } + } + if unresolved > 0 { eprint!("{RED} ({unresolved})"); } + eprintln!("{NORMAL} {DIM}({path_str}){NORMAL}"); + } else { + eprintln!("{path_str}"); + } + levels.push(end); + let len = unit.child_ids.len(); + for (i, id) in unit.child_ids.iter().enumerate() { + let end = i + 1 == len; + self.report_leaf(*id, levels.clone(), end); + } + } else { + eprintln!("<error loading source unit details>"); + } + } +} |