mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 03:45:29 +03:00
Dont expand recursive definitions
This commit is contained in:
parent
3b88a7ec9c
commit
ee4c32a68f
@ -1,24 +1,107 @@
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
|
||||
use crate::{
|
||||
fun::{Book, Term},
|
||||
fun::{Book, Name, Term},
|
||||
maybe_grow,
|
||||
};
|
||||
|
||||
/// Dereferences any generated definitions in the term.
|
||||
/// Dereferences any non recursive generated definitions in the term.
|
||||
/// Used after readback.
|
||||
impl Term {
|
||||
pub fn expand_generated(&mut self, book: &Book) {
|
||||
pub fn expand_generated(&mut self, book: &Book, recursive_defs: &RecursiveDefs) {
|
||||
maybe_grow(|| {
|
||||
if let Term::Ref { nam } = &*self {
|
||||
if nam.is_generated() {
|
||||
if nam.is_generated() && !recursive_defs.contains(nam) {
|
||||
*self = book.defs.get(nam).unwrap().rule().body.clone();
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this assumes that there will never be a loop of generated functions.
|
||||
// This is true right now, but not necessarily in the future.
|
||||
for child in self.children_mut() {
|
||||
child.expand_generated(book);
|
||||
child.expand_generated(book, recursive_defs);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type DepGraph = HashMap<Name, HashSet<Name>>;
|
||||
type Cycles = Vec<Vec<Name>>;
|
||||
type RecursiveDefs = BTreeSet<Name>;
|
||||
|
||||
pub fn find_recursive_defs(book: &Book) -> RecursiveDefs {
|
||||
let mut cycle_map = BTreeSet::new();
|
||||
let deps = book_def_deps(book);
|
||||
let cycles = cycles(&deps);
|
||||
|
||||
for cycle in cycles {
|
||||
for name in cycle {
|
||||
cycle_map.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
cycle_map
|
||||
}
|
||||
|
||||
/// Find all cycles in the dependency graph.
|
||||
fn cycles(deps: &DepGraph) -> Cycles {
|
||||
let mut cycles = vec![];
|
||||
let mut stack = vec![];
|
||||
let mut visited = HashSet::new();
|
||||
for nam in deps.keys() {
|
||||
if !visited.contains(nam) {
|
||||
find_cycles(deps, nam, &mut visited, &mut stack, &mut cycles);
|
||||
}
|
||||
}
|
||||
cycles
|
||||
}
|
||||
|
||||
fn find_cycles(
|
||||
deps: &DepGraph,
|
||||
nam: &Name,
|
||||
visited: &mut HashSet<Name>,
|
||||
stack: &mut Vec<Name>,
|
||||
cycles: &mut Cycles,
|
||||
) {
|
||||
maybe_grow(|| {
|
||||
// Check if the current ref is already in the stack, which indicates a cycle.
|
||||
if let Some(cycle_start) = stack.iter().position(|n| n == nam) {
|
||||
// If found, add the cycle to the cycles vector.
|
||||
cycles.push(stack[cycle_start..].to_vec());
|
||||
return;
|
||||
}
|
||||
// If the ref has not been visited yet, mark it as visited.
|
||||
if visited.insert(nam.clone()) {
|
||||
// Add the current ref to the stack to keep track of the path.
|
||||
stack.push(nam.clone());
|
||||
// Get the dependencies of the current ref.
|
||||
if let Some(dependencies) = deps.get(nam) {
|
||||
// Search for cycles from each dependency.
|
||||
for dep in dependencies {
|
||||
find_cycles(deps, dep, visited, stack, cycles);
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn book_def_deps(book: &Book) -> DepGraph {
|
||||
book.defs.iter().map(|(nam, def)| (nam.clone(), def_deps(def))).collect()
|
||||
}
|
||||
|
||||
fn def_deps(def: &crate::fun::Definition) -> HashSet<Name> {
|
||||
fn collect_refs(term: &Term, set: &mut HashSet<Name>) {
|
||||
if let Term::Ref { nam } = term {
|
||||
set.insert(nam.clone());
|
||||
}
|
||||
for children in term.children() {
|
||||
collect_refs(children, set);
|
||||
}
|
||||
}
|
||||
|
||||
let mut set = HashSet::new();
|
||||
let term = &def.rule().body;
|
||||
|
||||
collect_refs(term, &mut set);
|
||||
|
||||
set
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use diagnostics::{Diagnostics, DiagnosticsConfig, ERR_INDENT_SIZE};
|
||||
use fun::transform::expand_generated::find_recursive_defs;
|
||||
use net::hvm_to_net::hvm_to_net;
|
||||
|
||||
pub mod diagnostics;
|
||||
@ -191,7 +192,8 @@ pub fn readback_hvm_net(
|
||||
let mut diags = Diagnostics::default();
|
||||
let net = hvm_to_net(net);
|
||||
let mut term = net_to_term(&net, book, labels, linear, &mut diags);
|
||||
term.expand_generated(book);
|
||||
let recursive_cycles = find_recursive_defs(book);
|
||||
term.expand_generated(book, &recursive_cycles);
|
||||
term.resugar_strings(adt_encoding);
|
||||
term.resugar_lists(adt_encoding);
|
||||
(term, diags)
|
||||
|
Loading…
Reference in New Issue
Block a user