libunseemly/util/
vrep.rs

1use crate::{
2    name::{n, Name},
3    runtime::reify::Reifiable,
4};
5use std::iter::FromIterator;
6
7custom_derive! {
8    #[derive(Clone, PartialEq, Eq, Debug, Reifiable)]
9    pub enum VRepElt<T> {
10        Single(T),
11        Rep(T, Vec<Name>),
12    }
13}
14
15impl<T> VRepElt<T> {
16    pub fn map<'a, U, F>(&'a self, f: &mut F) -> VRepElt<U>
17    where F: FnMut(&'a T) -> U {
18        match self {
19            Single(e) => Single(f(e)),
20            Rep(e, names) => Rep(f(e), names.clone()),
21        }
22    }
23
24    pub fn into_map<U, F>(self, f: &mut F) -> VRepElt<U>
25    where F: FnMut(T) -> U {
26        match self {
27            Single(e) => Single(f(e)),
28            Rep(e, names) => Rep(f(e), names),
29        }
30    }
31
32    pub fn zip_map<U, F>(&self, other: &VRepElt<T>, mut f: F) -> Option<VRepElt<U>>
33    where F: FnMut(&T, &T) -> U {
34        match (self, other) {
35            (Single(s), Single(r)) => Some(Single(f(s, r))),
36            (Rep(s, s_names), Rep(r, r_names)) if s_names == r_names => {
37                Some(Rep(f(s, r), s_names.clone()))
38            }
39            _ => None,
40        }
41    }
42}
43
44use VRepElt::*;
45
46#[derive(Debug, PartialEq, Eq)]
47pub enum VRepLen {
48    Exactly(usize),
49    AtLeast(usize),
50}
51
52#[derive(Clone, PartialEq, Eq)]
53pub struct VRep<T>(Vec<VRepElt<T>>);
54pub struct SRep<'a, T>(&'a [VRepElt<T>]);
55
56impl<T> VRep<T> {
57    pub fn expand_reps<F>(&self, mut f: F) -> Vec<T>
58    where
59        F: FnMut(&T, &Vec<Name>) -> Vec<T>,
60        T: Clone,
61    {
62        let mut res = vec![];
63        for elt in &self.0 {
64            match elt {
65                Single(e) => res.push(e.clone()),
66                Rep(es, names) => {
67                    let mut expanded = f(es, names);
68                    res.append(&mut expanded)
69                }
70            }
71        }
72        res
73    }
74
75    pub fn concrete(&self) -> bool {
76        for elt in &self.0 {
77            match elt {
78                Rep(_, _) => return false,
79                Single(_) => {}
80            }
81        }
82        return true;
83    }
84
85    pub fn is_empty(&self) -> bool { self.0.is_empty() }
86
87    pub fn can_be_empty(&self) -> bool {
88        for elt in &self.0 {
89            match elt {
90                Rep(_, _) => {}
91                Single(_) => return false,
92            }
93        }
94        return true;
95    }
96
97    pub fn len(&self) -> VRepLen {
98        let mut min_len: usize = 0;
99        let mut exact: bool = true;
100        for elt in &self.0 {
101            match elt {
102                Single(_) => min_len += 1,
103                Rep(_, _) => exact = false,
104            }
105        }
106        if exact {
107            VRepLen::Exactly(min_len)
108        } else {
109            VRepLen::AtLeast(min_len)
110        }
111    }
112
113    pub fn iter(&self) -> std::slice::Iter<VRepElt<T>> { self.0.iter() }
114
115    pub fn map<'a, U, F>(&'a self, mut f: F) -> VRep<U>
116    where F: FnMut(&'a T) -> U {
117        let mut res = vec![];
118        for elt in &self.0 {
119            res.push(elt.map(&mut f));
120        }
121        VRep(res)
122    }
123
124    pub fn into_map<U, F>(self, mut f: F) -> VRep<U>
125    where F: FnMut(T) -> U {
126        let mut res = vec![];
127        for elt in self.0 {
128            res.push(elt.into_map(&mut f));
129        }
130        VRep(res)
131    }
132}
133
134// Only needed because our custom_derive! doesn't support newtype-style structs:
135impl<T: Clone + Reifiable> Reifiable for VRep<T> {
136    fn ty_name() -> Name { n("VRep") }
137
138    fn concrete_arguments() -> Option<Vec<crate::ast::Ast>> { Some(vec![T::ty_invocation()]) }
139
140    fn reify(&self) -> crate::runtime::eval::Value {
141        let res: Vec<_> = self.0.iter().map(|e| std::rc::Rc::new(e.reify())).collect();
142
143        crate::runtime::eval::Value::Sequence(res)
144    }
145
146    fn reflect(v: &crate::runtime::eval::Value) -> Self {
147        let mut res = vec![];
148
149        extract!((v) crate::runtime::eval::Value::Sequence = (ref parts) => {
150            for part in parts {
151                res.push(<VRepElt<T>>::reflect(&**part));
152            }
153        });
154        VRep(res)
155    }
156}
157
158// Turns a plain Vec into a VRep without repetitions
159impl<T> From<Vec<T>> for VRep<T> {
160    fn from(flat: Vec<T>) -> Self { VRep(flat.into_iter().map(Single).collect()) }
161}
162
163impl<T: std::fmt::Debug> std::fmt::Debug for VRep<T> {
164    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
165        write!(f, "[")?;
166        let mut first = false;
167        for elt in &self.0 {
168            if !first {
169                write!(f, ", ")?;
170            }
171            first = false;
172            match elt {
173                Single(e) => write!(f, "{:?}", e)?,
174                Rep(e, names) => write!(f, "{:?} ...({:?})", e, names)?,
175            }
176        }
177        write!(f, "]")
178    }
179}
180
181impl<T> IntoIterator for VRep<T> {
182    type Item = VRepElt<T>;
183    type IntoIter = std::vec::IntoIter<Self::Item>;
184
185    fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
186}
187
188impl<'a, T: 'a> IntoIterator for &'a VRep<T> {
189    type Item = &'a VRepElt<T>;
190    type IntoIter = std::slice::Iter<'a, VRepElt<T>>;
191
192    fn into_iter(self) -> Self::IntoIter { self.0.iter() }
193}
194
195impl<T> FromIterator<VRepElt<T>> for VRep<T> {
196    fn from_iter<I: IntoIterator<Item = VRepElt<T>>>(iter: I) -> Self {
197        let mut res = vec![];
198        for i in iter {
199            res.push(i);
200        }
201        VRep(res)
202    }
203}
204
205#[test]
206fn vrep_basics() {
207    assert_eq!(vrep![1, 2, 3, 4, 5], VRep::from(vec![1, 2, 3, 4, 5]));
208
209    assert_eq!(vrep![1, 2, 3, 4, 5].len(), VRepLen::Exactly(5));
210
211    let with_rep = vrep![1, 2 => (a, b, c), 3];
212    assert_eq!(with_rep.len(), VRepLen::AtLeast(2));
213
214    assert_eq!(with_rep.expand_reps(|_, _| vec![7, 7, 7]), vec![1, 7, 7, 7, 3]);
215
216    // Reification roundtrip:
217    assert_eq!(with_rep, <VRep<i32>>::reflect(&with_rep.reify()))
218}