From 28cb9bf36e30f0f15fee07f430a6f4dadbf78c86 Mon Sep 17 00:00:00 2001 From: Folkert Date: Fri, 22 Apr 2022 19:28:46 +0200 Subject: [PATCH] use custom type for TopologicalSort result --- compiler/can/src/def.rs | 8 +++++-- compiler/can/src/reference_matrix.rs | 32 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index e5827d40f9..4d764d337e 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -8,6 +8,7 @@ use crate::expr::{canonicalize_expr, Output, Recursive}; use crate::pattern::{bindings_from_patterns, canonicalize_def_header_pattern, Pattern}; use crate::procedure::References; use crate::reference_matrix::ReferenceMatrix; +use crate::reference_matrix::TopologicalSort; use crate::scope::create_alias; use crate::scope::Scope; use roc_collections::{default_hasher, ImEntry, ImMap, ImSet, MutMap, MutSet, SendMap}; @@ -812,7 +813,7 @@ pub fn sort_can_defs( // TODO also do the same `addDirects` check elm/compiler does, so we can // report an error if a recursive definition can't possibly terminate! match def_ids.references.topological_sort_into_groups() { - Ok(groups) => { + TopologicalSort::Groups { groups } => { let mut declarations = Vec::new(); // groups are in reversed order @@ -828,7 +829,10 @@ pub fn sort_can_defs( (Ok(declarations), output) } - Err((mut groups, nodes_in_cycle)) => { + TopologicalSort::HasCycles { + mut groups, + nodes_in_cycle, + } => { let mut declarations = Vec::new(); let mut problems = Vec::new(); diff --git a/compiler/can/src/reference_matrix.rs b/compiler/can/src/reference_matrix.rs index 0c2d67cda4..d0052993e4 100644 --- a/compiler/can/src/reference_matrix.rs +++ b/compiler/can/src/reference_matrix.rs @@ -50,13 +50,12 @@ impl ReferenceMatrix { // // Thank you, Samuel! impl ReferenceMatrix { - #[allow(clippy::type_complexity)] - pub fn topological_sort_into_groups(&self) -> Result>, (Vec>, Vec)> { + pub fn topological_sort_into_groups(&self) -> TopologicalSort { let length = self.length; let bitvec = &self.bitvec; if length == 0 { - return Ok(Vec::new()); + return TopologicalSort::Groups { groups: Vec::new() }; } let mut preds_map: Vec = vec![0; length]; @@ -85,7 +84,11 @@ impl ReferenceMatrix { if prev_group.is_empty() { let remaining: Vec = (0u32..length as u32).collect(); - return Err((Vec::new(), remaining)); + + return TopologicalSort::HasCycles { + groups: Vec::new(), + nodes_in_cycle: remaining, + }; } while preds_map.iter().any(|x| *x > 0) { @@ -114,12 +117,16 @@ impl ReferenceMatrix { let remaining: Vec = (0u32..length as u32) .filter(|i| preds_map[*i as usize] > 0) .collect(); - return Err((groups, remaining)); + + return TopologicalSort::HasCycles { + groups, + nodes_in_cycle: remaining, + }; } } groups.push(prev_group); - Ok(groups) + TopologicalSort::Groups { groups } } pub fn strongly_connected_components(&self, group: &[u32]) -> Vec> { @@ -141,6 +148,19 @@ impl ReferenceMatrix { } } +pub(crate) enum TopologicalSort { + /// There were no cycles, all nodes have been partitioned into groups + Groups { groups: Vec> }, + /// Cycles were found. All nodes that are not part of a cycle have been partitioned + /// into groups. The other elements are in the `cyclic` vector. However, there may be + /// many cycles, or just one big one. Use strongly-connected components to find out + /// exactly what the cycles are and how they fit into the groups. + HasCycles { + groups: Vec>, + nodes_in_cycle: Vec, + }, +} + #[derive(Clone, Copy)] enum Preorder { Empty,