py_declare/
branch.rs

1use crate::*;
2use std::collections::{HashMap, HashSet};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct Branch {
6    /// index of [ReflectDeclare] in [DeclareMap]
7    pub(crate) belong_to: GroupIdx,
8    /// index of possiable of [Declare]
9    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            // resize depends
82            //
83            // depend.len() >= 1 because depend.len() == 0 is an error and solved above
84            for _ in 1..depend.len() {
85                groups.extend(groups.clone());
86            }
87            // insert
88            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    /// # Return
120    ///
121    /// is self.state ok
122    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            // update state to error
129            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    /// let the bench depend on benches which satisfy the filter in group
140    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}