summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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,