summaryrefslogtreecommitdiff
path: root/src/source_hierarchy.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-02-05 12:58:02 +1300
committerBen Bridle <ben@derelict.engineering>2025-02-05 13:03:36 +1300
commit80da2af821385b2fc89091e9ac37a047349da4bd (patch)
tree2ba50368301e041f8d1b99145ab0a1fe28f91571 /src/source_hierarchy.rs
parent8d11be64f6c1747e7c4049105a6dd4ea9ab0d27f (diff)
downloadassembler-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.rs58
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>");
+ }
+ }
+}