summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2025-02-10 12:42:33 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2025-02-10 12:44:42 +1300
commit8ddf72ad0252f17913540a2e767966899a29d1b6 (patch)
treec97e01c761727b3fbdcf4006f6c0b70a41f59f23
parent1c9e795245c5da0ea896a4824fb41c9542857ecc (diff)
downloadassembler-8ddf72ad0252f17913540a2e767966899a29d1b6.zip
Track related symbols in resolver
As well as the already-implemented tracking of the existing definition of redefinitions, the resolver will now also track the definition that resolves each reference, and the references resolved by each definition. Instead of using tuples to hold this information, named wrapper structs have been created for each category.
-rw-r--r--src/reports/resolver_error.rs6
-rw-r--r--src/resolver.rs63
2 files changed, 45 insertions, 24 deletions
diff --git a/src/reports/resolver_error.rs b/src/reports/resolver_error.rs
index a1a5598..1aa3e37 100644
--- a/src/reports/resolver_error.rs
+++ b/src/reports/resolver_error.rs
@@ -16,12 +16,12 @@ impl<'a> ResolverError<'a> {
report_source_issue(LogLevel::Error, &context, &message);
}
for redefinition in &self.resolver.redefinitions {
- let definition = self.resolver.definitions.get(redefinition.1).unwrap();
+ let definition = &self.resolver.definitions[redefinition.definition];
let message = format!(
"Redefined symbol, first defined at {}",
- &definition.symbol.source.in_merged,
+ &definition.tracked.symbol.source.in_merged,
);
- let context = redefinition.0.context(&self.resolver);
+ let context = redefinition.tracked.context(&self.resolver);
report_source_issue(LogLevel::Error, &context, &message);
}
}
diff --git a/src/resolver.rs b/src/resolver.rs
index eb55a82..5fc4690 100644
--- a/src/resolver.rs
+++ b/src/resolver.rs
@@ -8,14 +8,13 @@ type PushFn = fn(&mut String, &SourceFile);
/// Resolve undeclared symbols in a source unit with definitions from other units.
pub struct Resolver {
/// Definitions from all included source units.
- pub definitions: Vec<TrackedSymbol>,
+ pub definitions: Vec<TrackedDefinition>,
/// All resolved references in all included source units.
- pub resolved: Vec<TrackedSymbol>,
+ pub resolved: Vec<TrackedReference>,
/// All unresolved references in all included source units.
pub unresolved: Vec<TrackedSymbol>,
/// All redefined (duplicate) definitions in all included source units.
- /// Points to the 'definitions' index of the existing definition.
- pub redefinitions: Vec<(TrackedSymbol, usize)>,
+ pub redefinitions: Vec<TrackedRedefinition>,
/// All included source units.
pub source_units: Vec<HeirarchicalSourceUnit>,
/// The 'source_units' indices of the root source units.
@@ -72,26 +71,30 @@ impl Resolver {
match symbol.role {
SymbolRole::Definition(_) => {
// Check if the symbol has already been defined.
- let equal = |d: &TrackedSymbol| { &d.symbol == &symbol };
+ let equal = |d: &TrackedDefinition| { &d.tracked.symbol == &symbol };
if let Some(original) = self.definitions.iter().position(equal) {
- let definition = TrackedSymbol { symbol, source_id, source_role };
- let redefinition = (definition, original);
- self.redefinitions.push(redefinition);
+ let tracked = TrackedSymbol { symbol, source_id, source_role };
+ let definition = original;
+ self.redefinitions.push(TrackedRedefinition { tracked, definition });
} else {
// Resolve all unresolved references that match this symbol.
let defines = |r: &mut TrackedSymbol| symbol.defines(&r.symbol);
- for symbol in self.unresolved.extract_if(defines) {
- self.resolved.push(symbol);
+ let definition = self.definitions.len();
+ let mut references = Vec::new();
+ for tracked in self.unresolved.extract_if(defines) {
+ references.push(self.resolved.len());
+ self.resolved.push(TrackedReference { tracked, definition });
}
- let definition = TrackedSymbol { symbol, source_id, source_role };
- self.definitions.push(definition);
+ let tracked = TrackedSymbol { symbol, source_id, source_role };
+ self.definitions.push(TrackedDefinition { tracked, references });
}
}
SymbolRole::Reference => {
- let reference = TrackedSymbol { symbol, source_id, source_role };
- match self.definitions.iter().any(|d| d.symbol.defines(&reference.symbol)) {
- true => self.resolved.push(reference),
- false => self.unresolved.push(reference),
+ let tracked = TrackedSymbol { symbol, source_id, source_role };
+ let defines = |d: &TrackedDefinition| d.tracked.symbol.defines(&tracked.symbol);
+ match self.definitions.iter().position(defines) {
+ Some(definition) => self.resolved.push(TrackedReference { tracked, definition }),
+ None => self.unresolved.push(tracked),
}
}
}
@@ -177,14 +180,14 @@ impl Resolver {
}
// Populate the .parent_ids field of every source unit.
for reference in &self.resolved {
- let predicate = |d: &&TrackedSymbol| d.symbol.name == reference.symbol.name;
+ let predicate = |d: &&TrackedDefinition| d.tracked.symbol.name == reference.tracked.symbol.name;
if let Some(definition) = self.definitions.iter().find(predicate) {
// A unit cannot be its own parent.
- let is_self = reference.source_id == definition.source_id;
+ let is_self = reference.tracked.source_id == definition.tracked.source_id;
let must_precede = SymbolRole::Definition(DefinitionType::MustPrecedeReference);
- if is_self || definition.symbol.role != must_precede { continue; }
- let referencing_unit = &mut self.source_units[reference.source_id];
- referencing_unit.parent_ids.push(definition.source_id);
+ if is_self || definition.tracked.symbol.role != must_precede { continue; }
+ let referencing_unit = &mut self.source_units[reference.tracked.source_id];
+ referencing_unit.parent_ids.push(definition.tracked.source_id);
};
}
}
@@ -259,6 +262,24 @@ pub struct HeirarchicalSourceUnit {
pub parent_ids: Vec<usize>,
}
+pub struct TrackedDefinition {
+ pub tracked: TrackedSymbol,
+ /// Points to resolved references in `resolved`.
+ pub references: Vec<usize>,
+}
+
+pub struct TrackedRedefinition {
+ pub tracked: TrackedSymbol,
+ /// Points to existing definition in `definitions`.
+ pub definition: usize,
+}
+
+pub struct TrackedReference {
+ pub tracked: TrackedSymbol,
+ /// Points to resolving definition in `definitions`.
+ pub definition: usize,
+}
+
pub struct TrackedSymbol {
pub symbol: Symbol,
pub source_id: usize,