py_declare/
group.rs

1use super::*;
2use std::{cell::LazyCell, collections::HashMap};
3use terl::{Span, WithSpan};
4
5#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct GroupIdx {
7    pub(crate) idx: usize,
8}
9
10impl GroupIdx {
11    pub fn new(idx: usize) -> Self {
12        Self { idx }
13    }
14}
15
16#[derive(Debug, Clone)]
17pub enum DeclareState {
18    Empty,
19    Declared(usize, Type),
20    Declaring(HashMap<usize, Type>),
21}
22
23impl DeclareState {
24    pub fn alives<'t, A, T: 't>(&'t self, gidx: GroupIdx, active: A) -> T
25    where
26        A: FnOnce(&mut dyn Iterator<Item = (Branch, &'t Type)>) -> T,
27    {
28        let alives: &mut dyn Iterator<Item = (Branch, &Type)> = match self {
29            DeclareState::Empty => &mut std::iter::empty(),
30            DeclareState::Declared(branch, ty) => {
31                &mut std::iter::once((Branch::new(gidx, *branch), ty))
32            }
33            DeclareState::Declaring(alives) => &mut alives
34                .iter()
35                .map(|(branch, ty)| (Branch::new(gidx, *branch), ty)),
36        };
37        active(alives)
38    }
39}
40
41impl From<(usize, Type)> for DeclareState {
42    fn from((v1, v2): (usize, Type)) -> Self {
43        Self::Declared(v1, v2)
44    }
45}
46
47impl From<HashMap<usize, Type>> for DeclareState {
48    fn from(v: HashMap<usize, Type>) -> Self {
49        match v.len() {
50            0 => Self::Empty,
51            1 => {
52                let Some((branch, unique)) = v.into_iter().next() else {
53                    unreachable!()
54                };
55                Self::Declared(branch, unique)
56            }
57            _ => Self::Declaring(v),
58        }
59    }
60}
61
62impl FromIterator<Type> for DeclareState {
63    fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
64        Self::from_iter(iter.into_iter().enumerate())
65    }
66}
67
68impl FromIterator<(usize, Type)> for DeclareState {
69    fn from_iter<T: IntoIterator<Item = (usize, Type)>>(iter: T) -> Self {
70        let mut iter = iter.into_iter().peekable();
71        let Some(next) = iter.next() else {
72            return Self::Empty;
73        };
74        if iter.peek().is_some() {
75            Self::Declaring(std::iter::once(next).chain(iter).collect())
76        } else {
77            Self::Declared(next.0, next.1)
78        }
79    }
80}
81
82#[derive(Debug, Clone)]
83pub struct DeclareGroup {
84    span: Span,
85    group: GroupIdx,
86    failds: HashMap<usize, DeclareError>,
87    status: DeclareState,
88}
89
90impl DeclareGroup {
91    pub fn new(
92        span: Span,
93        group: GroupIdx,
94        fails: HashMap<usize, DeclareError>,
95        status: DeclareState,
96    ) -> Self {
97        Self {
98            span,
99            group,
100            failds: fails,
101            status,
102        }
103    }
104
105    pub fn push_error(&mut self, at: usize, error: DeclareError) {
106        self.failds.insert(at, error);
107    }
108
109    fn update_state<U>(&mut self, updater: U)
110    where
111        U: FnOnce(DeclareState) -> DeclareState,
112    {
113        let previous = std::mem::replace(&mut self.status, DeclareState::Empty);
114        self.status = updater(previous);
115    }
116
117    pub fn filter_alive<F, C>(&mut self, mut filter: F) -> C
118    where
119        F: FnMut(Branch, Type) -> Result<(Branch, Type), DeclareError>,
120        C: Default + Extend<(Branch, DeclareError)>,
121    {
122        let mut remove = C::default();
123        let belong_to = self.group;
124        let filter_map = |(branch, ty)| {
125            let branch = Branch::new(belong_to, branch);
126            filter(branch, ty)
127                .map_err(|e| remove.extend(Some((branch, e))))
128                .map(|(branch, ty)| (branch.branch_idx, ty))
129                .ok()
130        };
131
132        self.update_state(|state| match state {
133            DeclareState::Empty => DeclareState::Empty,
134            DeclareState::Declared(branch, ty) => {
135                let iter = std::iter::once((branch, ty)).filter_map(filter_map);
136                DeclareState::from_iter(iter)
137            }
138            DeclareState::Declaring(branches) => {
139                let iter = branches.into_iter().filter_map(filter_map);
140                DeclareState::from_iter(iter)
141            }
142        });
143        remove
144    }
145
146    /// remove only one branch
147    ///
148    /// note: this method will do nothing if the branch is not exist(including have been remvoed)
149    pub fn remove_branch(&mut self, branch: usize, reason: DeclareError) -> DeclareError {
150        let mut new_reason = DeclareError::Empty;
151        self.update_state(|state| match state {
152            DeclareState::Declared(unique, previous) => {
153                if unique == branch {
154                    new_reason = reason.with_previous(previous);
155                    DeclareState::Empty
156                } else {
157                    DeclareState::Declared(unique, previous)
158                }
159            }
160            DeclareState::Declaring(mut items) => {
161                let previous = items.remove(&branch);
162                new_reason = reason.with_previous(previous.unwrap_or_else(|| unreachable!()));
163                items.into()
164            }
165            _ => unreachable!(),
166        });
167        new_reason
168    }
169
170    /// # Note
171    ///
172    /// the [`DeclareError`] generated by `reason` will be clone many times, so, you should
173    /// call [`DeclareError::into_shared`] to wrapped it in [`Rc`]
174    ///
175    /// and, [`DeclareError::with_previous`] will be called on [`DeclareError`]
176    ///
177    /// [`Rc`]: std::rc
178    pub fn remove_branches<F, R>(&mut self, remove_if: F, reason: R) -> Vec<(Branch, DeclareError)>
179    where
180        F: Fn(Branch, &Type) -> bool,
181        R: FnOnce() -> DeclareError,
182    {
183        let reason = LazyCell::new(reason);
184
185        self.filter_alive(move |branch, ty| {
186            if remove_if(branch, &ty) {
187                Err((*reason).clone().with_previous(ty))
188            } else {
189                Ok((branch, ty))
190            }
191        })
192    }
193
194    pub fn alives<'t, A, T: 't>(&'t self, active: A) -> T
195    where
196        A: FnOnce(&mut dyn Iterator<Item = (Branch, &'t Type)>) -> T,
197    {
198        self.status.alives(self.group, active)
199    }
200
201    pub fn is_declared(&self) -> bool {
202        matches!(self.status, DeclareState::Declared(..))
203    }
204
205    /// return declare result
206    ///
207    /// # Panic
208    ///
209    /// panic if the group it not declared
210    pub fn result(&self) -> &Type {
211        match &self.status {
212            DeclareState::Declared(_, ty) => ty,
213            _ => panic!("group is not declared yet"),
214        }
215    }
216
217    pub fn make_error(&self) -> terl::Error {
218        let mut err = <Self as terl::WithSpan>::make_error(self, "cant infer type");
219        match &self.status {
220            DeclareState::Empty => err += "this cant be declared as any type!",
221            DeclareState::Declaring(alives) => {
222                err += "this cant be declared as:";
223                for alives in alives.values() {
224                    err += format!("\t{alives}")
225                }
226            }
227            DeclareState::Declared(_, _) => unreachable!(),
228        }
229
230        err.extend(self.failds.values().flat_map(|faild| faild.generate()));
231        err
232    }
233
234    /// # Panic
235    ///
236    /// panic if the branch is not exist, faild, or isnot belong to this group
237    pub fn get_branch(&self, branch: Branch) -> &Type {
238        debug_assert_eq!(
239            branch.belong_to, self.group,
240            "the branch is not belong to this group"
241        );
242
243        let branch = branch.branch_idx;
244        match &self.status {
245            DeclareState::Declared(idx, ty) if *idx == branch => ty,
246            DeclareState::Declaring(alives) if alives.contains_key(&branch) => &alives[&branch],
247            _ => panic!("the branch isnot exist, or faild"),
248        }
249    }
250}
251
252impl WithSpan for DeclareGroup {
253    fn get_span(&self) -> Span {
254        self.span
255    }
256}
257
258pub struct GroupBuilder {
259    pub(crate) span: Span,
260    pub(crate) branches: Vec<BranchesBuilder>,
261}
262
263impl GroupBuilder {
264    pub fn new(span: Span, branches: Vec<BranchesBuilder>) -> GroupBuilder {
265        GroupBuilder { span, branches }
266    }
267}
268
269impl WithSpan for GroupBuilder {
270    fn get_span(&self) -> Span {
271        self.span
272    }
273}