Expose recursive defs as a book method and rewrite find_cycles

This commit is contained in:
imaqtkatt 2024-06-04 09:08:30 -03:00
parent ee4c32a68f
commit 0ea135e3cb
2 changed files with 37 additions and 36 deletions

View File

@ -27,59 +27,61 @@ type DepGraph = HashMap<Name, HashSet<Name>>;
type Cycles = Vec<Vec<Name>>; type Cycles = Vec<Vec<Name>>;
type RecursiveDefs = BTreeSet<Name>; type RecursiveDefs = BTreeSet<Name>;
pub fn find_recursive_defs(book: &Book) -> RecursiveDefs { impl Book {
let mut cycle_map = BTreeSet::new(); pub fn recursive_defs(&self) -> RecursiveDefs {
let deps = book_def_deps(book); let mut cycle_map = BTreeSet::new();
let cycles = cycles(&deps); let deps = book_def_deps(self);
let cycles = cycles(&deps);
for cycle in cycles { for cycle in cycles {
for name in cycle { for name in cycle {
cycle_map.insert(name); cycle_map.insert(name);
}
} }
}
cycle_map cycle_map
}
} }
/// Find all cycles in the dependency graph. /// Find all cycles in the dependency graph.
fn cycles(deps: &DepGraph) -> Cycles { fn cycles(deps: &DepGraph) -> Cycles {
let mut cycles = vec![]; let mut cycles = vec![];
let mut stack = vec![];
let mut visited = HashSet::new(); let mut visited = HashSet::new();
for nam in deps.keys() { for nam in deps.keys() {
if !visited.contains(nam) { if !visited.contains(nam) {
find_cycles(deps, nam, &mut visited, &mut stack, &mut cycles); find_cycles(deps, nam, &mut visited, &mut cycles);
} }
} }
cycles cycles
} }
fn find_cycles( fn find_cycles(deps: &DepGraph, nam: &Name, visited: &mut HashSet<Name>, cycles: &mut Cycles) {
deps: &DepGraph,
nam: &Name,
visited: &mut HashSet<Name>,
stack: &mut Vec<Name>,
cycles: &mut Cycles,
) {
maybe_grow(|| { maybe_grow(|| {
// Check if the current ref is already in the stack, which indicates a cycle. let mut to_search = vec![(nam.clone(), false)];
if let Some(cycle_start) = stack.iter().position(|n| n == nam) { while let Some((current, checked)) = to_search.pop() {
// If found, add the cycle to the cycles vector. if checked {
cycles.push(stack[cycle_start..].to_vec()); to_search.pop();
return; } else {
} // Check if the current ref is already in the stack, which indicates a cycle.
// If the ref has not been visited yet, mark it as visited. if let Some(cycle_start) = to_search.iter().position(|(n, _)| n == &current) {
if visited.insert(nam.clone()) { // If found, add the cycle to the cycles vector.
// Add the current ref to the stack to keep track of the path. cycles.push(to_search[cycle_start..].iter().map(|(n, _)| n.clone()).collect::<Vec<_>>());
stack.push(nam.clone()); continue;
// Get the dependencies of the current ref. }
if let Some(dependencies) = deps.get(nam) { // If the ref has not been visited yet, mark it as visited.
// Search for cycles from each dependency. if visited.insert(current.clone()) {
for dep in dependencies { // Get the dependencies of the current ref.
find_cycles(deps, dep, visited, stack, cycles); let deps = deps.get(&current);
// Add the current ref to the stack to keep track of the path.
to_search.push((current, true));
if let Some(deps) = deps {
// Search for cycles from each dependency.
for dep in deps {
to_search.push((dep.clone(), false));
}
}
} }
} }
stack.pop();
} }
}) })
} }

View File

@ -11,7 +11,6 @@ use crate::{
}, },
}; };
use diagnostics::{Diagnostics, DiagnosticsConfig, ERR_INDENT_SIZE}; use diagnostics::{Diagnostics, DiagnosticsConfig, ERR_INDENT_SIZE};
use fun::transform::expand_generated::find_recursive_defs;
use net::hvm_to_net::hvm_to_net; use net::hvm_to_net::hvm_to_net;
pub mod diagnostics; pub mod diagnostics;
@ -192,7 +191,7 @@ pub fn readback_hvm_net(
let mut diags = Diagnostics::default(); let mut diags = Diagnostics::default();
let net = hvm_to_net(net); let net = hvm_to_net(net);
let mut term = net_to_term(&net, book, labels, linear, &mut diags); let mut term = net_to_term(&net, book, labels, linear, &mut diags);
let recursive_cycles = find_recursive_defs(book); let recursive_cycles = book.recursive_defs();
term.expand_generated(book, &recursive_cycles); term.expand_generated(book, &recursive_cycles);
term.resugar_strings(adt_encoding); term.resugar_strings(adt_encoding);
term.resugar_lists(adt_encoding); term.resugar_lists(adt_encoding);