diff options
-rw-r--r-- | src/reports/resolver_error.rs | 6 | ||||
-rw-r--r-- | src/resolver.rs | 63 |
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, |