mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
simplify earlier topological sort of abilities/aliases
This commit is contained in:
parent
0f4a5bdd74
commit
a7e781ece2
2 changed files with 27 additions and 53 deletions
|
@ -170,66 +170,35 @@ impl Declaration {
|
||||||
|
|
||||||
/// Returns a topologically sorted sequence of alias/opaque names
|
/// Returns a topologically sorted sequence of alias/opaque names
|
||||||
fn sort_type_defs_before_introduction(
|
fn sort_type_defs_before_introduction(
|
||||||
mut referenced_symbols: MutMap<Symbol, Vec<Symbol>>,
|
referenced_symbols: VecMap<Symbol, Vec<Symbol>>,
|
||||||
) -> Vec<Symbol> {
|
) -> Vec<Symbol> {
|
||||||
let defined_symbols: Vec<Symbol> = referenced_symbols.keys().copied().collect();
|
let capacity = referenced_symbols.len();
|
||||||
|
let mut matrix = ReferenceMatrix::new(capacity);
|
||||||
|
|
||||||
// find the strongly connected components and their relations
|
let (symbols, referenced) = referenced_symbols.unzip();
|
||||||
let sccs = {
|
|
||||||
// only retain symbols from the current set of defined symbols; the rest come from other modules
|
|
||||||
for v in referenced_symbols.iter_mut() {
|
|
||||||
v.1.retain(|x| defined_symbols.iter().any(|s| s == x));
|
|
||||||
}
|
|
||||||
|
|
||||||
let all_successors_with_self = |symbol: &Symbol| referenced_symbols[symbol].iter().copied();
|
for (index, references) in referenced.iter().enumerate() {
|
||||||
|
for referenced in references {
|
||||||
ven_graph::strongly_connected_components(&defined_symbols, all_successors_with_self)
|
match symbols.iter().position(|k| k == referenced) {
|
||||||
};
|
None => { /* not defined in this scope */ }
|
||||||
|
Some(ref_index) => matrix.set_row_col(index, ref_index, true),
|
||||||
// then sort the strongly connected components
|
|
||||||
let groups: Vec<_> = (0..sccs.len()).collect();
|
|
||||||
let mut group_symbols: Vec<Vec<Symbol>> = vec![Vec::new(); groups.len()];
|
|
||||||
|
|
||||||
let mut symbol_to_group_index = MutMap::default();
|
|
||||||
let mut group_to_groups = vec![Vec::new(); groups.len()];
|
|
||||||
|
|
||||||
for (index, group) in sccs.iter().enumerate() {
|
|
||||||
for s in group {
|
|
||||||
symbol_to_group_index.insert(*s, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index, group) in sccs.iter().enumerate() {
|
|
||||||
for s in group {
|
|
||||||
let reachable = &referenced_symbols[s];
|
|
||||||
for r in reachable {
|
|
||||||
let new_index = symbol_to_group_index[r];
|
|
||||||
|
|
||||||
if new_index != index {
|
|
||||||
group_to_groups[index].push(new_index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in group_symbols.iter_mut() {
|
// find the strongly connected components and their relations
|
||||||
v.sort();
|
let nodes: Vec<_> = (0..capacity as u32).collect();
|
||||||
v.dedup();
|
let sccs = matrix.strongly_connected_components(&nodes);
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(capacity);
|
||||||
|
|
||||||
|
for group in sccs {
|
||||||
|
for index in group {
|
||||||
|
output.push(symbols[index as usize])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let all_successors_with_self = |group: &usize| group_to_groups[*group].iter().copied();
|
output
|
||||||
|
|
||||||
// split into self-recursive and mutually recursive
|
|
||||||
match topological_sort(&groups, all_successors_with_self) {
|
|
||||||
Ok(result) => result
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.flat_map(|group_index| sccs[*group_index].iter())
|
|
||||||
.copied()
|
|
||||||
.collect(),
|
|
||||||
|
|
||||||
Err(_loop_detected) => unreachable!("the groups cannot recurse"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -299,7 +268,7 @@ pub(crate) fn canonicalize_defs<'a>(
|
||||||
let mut type_defs = MutMap::default();
|
let mut type_defs = MutMap::default();
|
||||||
let mut abilities_in_scope = Vec::new();
|
let mut abilities_in_scope = Vec::new();
|
||||||
|
|
||||||
let mut referenced_type_symbols = MutMap::default();
|
let mut referenced_type_symbols = VecMap::default();
|
||||||
|
|
||||||
// Determine which idents we introduced in the course of this process.
|
// Determine which idents we introduced in the course of this process.
|
||||||
let mut symbols_introduced = MutMap::default();
|
let mut symbols_introduced = MutMap::default();
|
||||||
|
@ -454,7 +423,8 @@ pub(crate) fn canonicalize_defs<'a>(
|
||||||
can_ann.typ.clone(),
|
can_ann.typ.clone(),
|
||||||
kind,
|
kind,
|
||||||
);
|
);
|
||||||
aliases.insert(symbol, alias.clone());
|
|
||||||
|
aliases.insert(symbol, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDef::Ability(name, members) => {
|
TypeDef::Ability(name, members) => {
|
||||||
|
|
|
@ -77,6 +77,10 @@ impl<K: PartialEq, V> VecMap<K, V> {
|
||||||
self.values.iter()
|
self.values.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn keys(&self) -> impl Iterator<Item = &K> {
|
||||||
|
self.keys.iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unzip(self) -> (Vec<K>, Vec<V>) {
|
pub fn unzip(self) -> (Vec<K>, Vec<V>) {
|
||||||
(self.keys, self.values)
|
(self.keys, self.values)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue