1use crate::*;
2use std::collections::{HashMap, HashSet};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct Branch {
6 pub(crate) belong_to: GroupIdx,
8 pub(crate) branch_idx: usize,
10}
11
12impl Branch {
13 pub fn new(belong_to: GroupIdx, branch_idx: usize) -> Self {
14 Self {
15 belong_to,
16 branch_idx,
17 }
18 }
19}
20
21#[derive(Default, Debug, Clone)]
22pub(crate) struct BranchDepend {
23 pub(crate) depends: HashMap<GroupIdx, HashSet<usize>>,
24 pub(crate) failds: GroupError,
25}
26
27type GroupError = HashMap<GroupIdx, HashMap<usize, DeclareError>>;
28
29impl BranchDepend {
30 pub fn new_depends<E>(&mut self, group: GroupIdx, branches: HashSet<usize>, filtered: E)
31 where
32 E: Fn(Branch) -> DeclareError,
33 {
34 let new_depend = match self.depends.remove(&group) {
35 Some(previous) => {
36 let new_depend = previous
37 .into_iter()
38 .filter(|previous| {
39 if branches.contains(previous) {
40 true
41 } else {
42 let branch = Branch::new(group, *previous);
43 self.failds
44 .entry(group)
45 .or_default()
46 .insert(branch.branch_idx, filtered(branch));
47 false
48 }
49 })
50 .collect();
51
52 new_depend
53 }
54 None => branches,
55 };
56
57 self.depends.insert(group, new_depend);
58 }
59
60 pub fn merge_depends<U>(mut self, mut use_branch: U) -> Result<Vec<HashSet<Branch>>, GroupError>
61 where
62 U: FnMut(Branch) -> Branch,
63 {
64 {
65 let mut errors = GroupError::new();
66 for (group, ..) in self
67 .depends
68 .iter()
69 .filter(|(_, branches)| branches.is_empty())
70 {
71 errors.insert(*group, self.failds.remove(group).unwrap_or_default());
72 }
73 if !errors.is_empty() {
74 return Err(errors);
75 }
76 }
77
78 let mut groups: Vec<HashSet<Branch>> = vec![HashSet::default()];
79 for (group, depend) in self.depends {
80 let len = groups.len();
81 for _ in 1..depend.len() {
85 groups.extend(groups.clone());
86 }
87 for (new_depend_idx, new_depend) in depend.into_iter().enumerate() {
89 let branch = use_branch(Branch::new(group, new_depend));
90 for depends_idx in 0..len {
91 groups[new_depend_idx * len + depends_idx].insert(branch);
92 }
93 }
94 }
95
96 Ok(groups)
97 }
98}
99
100pub struct BranchesBuilder {
101 pub(crate) state: Result<Type>,
102 pub(crate) depends: BranchDepend,
103}
104
105impl From<Type> for BranchesBuilder {
106 fn from(value: Type) -> Self {
107 Self::new(value)
108 }
109}
110
111impl BranchesBuilder {
112 pub fn new(ty: Type) -> Self {
113 Self {
114 state: Ok(ty),
115 depends: Default::default(),
116 }
117 }
118
119 pub fn filter_self<T, B>(&mut self, defs: &Defs, filter: &B) -> bool
123 where
124 T: Types,
125 B: BranchFilter<T>,
126 {
127 if self.state.as_ref().is_ok_and(|ty| !filter.satisfy(ty)) {
128 let privious = std::mem::replace(&mut self.state, Err(DeclareError::Empty)).unwrap();
130 let err = DeclareError::Unexpect {
131 expect: filter.expect(defs),
132 }
133 .with_previous(privious);
134 self.state = Err(err)
135 }
136 self.state.is_ok()
137 }
138
139 pub fn new_depend<T, B>(
141 mut self,
142 map: &mut DeclareGraph,
143 defs: &Defs,
144 depend: GroupIdx,
145 filter: &B,
146 ) -> Self
147 where
148 T: Types,
149 B: BranchFilter<T>,
150 {
151 if self.state.is_err() {
152 return self;
153 }
154
155 let satisfy_branches = map[depend].alives(|alives| {
156 alives
157 .filter(|(.., ty)| filter.satisfy(ty))
158 .map(|(branch, ..)| branch.branch_idx)
159 .collect::<HashSet<_>>()
160 });
161
162 let filtered_reason = DeclareError::Unexpect {
163 expect: filter.expect(defs),
164 }
165 .with_location(filter.get_span())
166 .into_shared();
167
168 let filtered_reason =
169 |branch: Branch| filtered_reason.clone().with_previous(map[branch].clone());
170
171 self.depends
172 .new_depends(depend, satisfy_branches, filtered_reason);
173
174 self
175 }
176}
177
178#[macro_export]
179macro_rules! branches {
180 {
181 $(
182 ($($filter:expr),*) => $res:expr
183 ),*
184 } => {
185 {
186 vec![$(
187 $crate::BranchesBuilder::new(From::from($res))
188 $(.new_filter($filter))*
189 ),*]
190 }
191 };
192}