libunseemly/util/
sky.rs

1use crate::{
2    name::Name,
3    util::{
4        assoc::Assoc,
5        asterism::{AsterMarchable, Asterism, AsterismSlice},
6    },
7};
8use std::iter::Iterator;
9
10type Sky<T> = Assoc<Name, Asterism<T>>;
11/// `SkySlice` isn't a slice itself,
12///  so we can't pull the same trick we pulled with `AsterismSlice`.
13/// (Maybe rename it, then?)
14type SkySlice<'a, T> = Assoc<Name, AsterismSlice<'a, T>>;
15
16impl<'a, T> SkySlice<'a, T>
17where T: Clone
18{
19    fn get(&self, n: Name) -> AsterismSlice<'a, T> { self.find_or_panic(&n).clone() }
20
21    fn combine_overriding(&self, rhs: &Self) -> Assoc<Name, AsterismSlice<'a, T>> {
22        self.set_assoc(rhs)
23    }
24
25    #[deprecated]
26    // In `EnvMBE`, this respected named repeats.
27    fn merge(&self, rhs: &Self) -> Assoc<Name, AsterismSlice<'a, T>> { self.set_assoc(rhs) }
28
29    /// Each of `driving_names` must be a repetition of the same length.
30    /// Produces an iterator with the same length,
31    ///  yielding `SkySlice`s in which the driven names have that repetition removed.
32    fn march(&self, driving_names: &[Name]) -> Box<dyn Iterator<Item = SkySlice<'a, T>> + 'a> {
33        let marchers: Vec<(Name, std::vec::IntoIter<AsterismSlice<'a, T>>)> =
34            driving_names.iter().map(|n| (*n, self.get(*n).march())).collect();
35
36        // Require the lengths to be the same
37        for (n, marcher) in &marchers[1..] {
38            if marcher.len() != marchers[0].1.len() {
39                icp!(
40                    "Lengths don't match in march names: {} ({}) != {} ({})",
41                    marcher.len(),
42                    n,
43                    marchers[0].1.len(),
44                    marchers[0].0
45                );
46            }
47        }
48
49        // By default, names refer to the same Asterims (just sliced)
50        let mut res: Box<dyn Iterator<Item = SkySlice<'a, T>> + 'a> =
51            Box::new(std::iter::repeat(self.clone()));
52
53        // For the driving names, override with the current step of the march
54        for (name, marched) in marchers {
55            res = Box::new(res.zip(marched.into_iter()).map(
56                move |(base, marched): (SkySlice<T>, AsterismSlice<T>)| base.set(name, marched),
57            ));
58        }
59
60        res
61    }
62
63    #[deprecated(note = "use `march` instead")]
64    // The `_all` is no longer meaningful. This does a bunch of unnecessary cloning.
65    fn march_all(&self, driving_names: &[Name]) -> Vec<Sky<T>> {
66        self.march(driving_names).map(|s| s.to_sky()).collect()
67    }
68
69    #[deprecated(note = "do we need this?")]
70    fn get_leaf<'b>(&'b self, n: Name) -> Option<&'a T> {
71        match self.find(&n) {
72            None => None,
73            Some(aster) => Some(aster.as_leaf()),
74        }
75    }
76
77    fn leaf<'b>(&'b self, n: Name) -> &'a T
78    where 'a: 'b {
79        self.get(n).as_leaf()
80    }
81
82    #[deprecated(note = "use `leaf` instead")]
83    fn get_leaf_or_panic(&self, n: Name) -> &T { self.get(n).as_leaf() }
84
85    #[deprecated(note = "use `depth_1` instead")]
86    fn get_rep_leaf(&self, n: Name) -> Option<Vec<&T>> {
87        self.find(&n).map(|asterism| asterism.as_depth_1().collect::<Vec<&T>>())
88    }
89
90    #[deprecated(note = "use `depth_1` instead")]
91    fn get_rep_leaf_or_panic(&'a self, n: Name) -> Vec<&'a T> {
92        self.get(n).as_depth_1().collect::<Vec<&T>>()
93    }
94
95    fn depth_1<'b>(&'b self, n: Name) -> Box<dyn std::iter::Iterator<Item = &'a T> + 'a> {
96        self.get(n).as_depth_1()
97    }
98
99    // fn map_flatten_rep_leaf_or_panic<S>(&self, n: Name, depth: u8, m: &dyn Fn(&T) -> S, f: &dyn Fn(Vec<S>) -> S) -> S {
100    //    unimplemented!()
101    // }
102}
103
104impl<T: Clone> SkySlice<'_, T> {
105    pub fn to_sky(&self) -> Sky<T> {
106        self.map_borrow_f(&mut |a: &AsterismSlice<T>| a.to_asterism())
107    }
108}
109
110impl<T: Clone> Sky<T> {
111    // `l` could be a reference, but do we ever want that?
112    pub fn new_from_leaves(l: Assoc<Name, T>) -> Self { l.map(|l| Asterism::from_leaf(l.clone())) }
113
114    #[deprecated]
115    pub fn new_from_named_repeat(_n: Name, r: Vec<Self>) -> Self { Self::new_from_anon_repeat(r) }
116
117    pub fn new_from_anon_repeat(mut r: Vec<Self>) -> Self {
118        if r.len() == 0 {
119            return Sky::new();
120        }
121        let mut res = Assoc::<Name, Asterism<T>>::new();
122        if r.len() > 0 {
123            let keys: Vec<Name> = r[0].iter_keys().map(|k| *k).collect();
124            for k in keys {
125                let per_name_asterisms: Vec<Asterism<T>> =
126                    r.iter_mut().map(|sky| sky.remove_or_panic(&k)).collect();
127                res = res.set(k, Asterism::join(per_name_asterisms));
128            }
129        }
130        res
131    }
132
133    pub fn leaf(&self, n: Name) -> &T { self.find_or_panic(&n).as_leaf() }
134
135    pub fn depth_1<'b>(&'b self, n: Name) -> Box<dyn std::iter::Iterator<Item = &'b T> + 'b> {
136        self.find_or_panic(&n).as_depth_1()
137    }
138
139    pub fn to_sky_slices<'b>(&'b self) -> SkySlice<'b, T> {
140        self.map_borrow_f(&mut |a: &Asterism<T>| a.as_slice())
141    }
142
143    pub fn march<'b>(
144        &'b self,
145        driving_names: &'b [Name],
146    ) -> Box<dyn Iterator<Item = SkySlice<'b, T>> + 'b> {
147        self.to_sky_slices().march(driving_names)
148    }
149
150    pub fn add_leaf(&mut self, n: Name, v: T) { self.mut_set(n, Asterism::from_leaf(v)); }
151
152    #[deprecated(note = "inefficent, and named repeats are gone")]
153    pub fn add_named_repeat(&mut self, _: Name, sub: Vec<Sky<T>>) { self.add_anon_repeat(sub) }
154
155    // TODO: how DO we construct in a general case?
156    #[deprecated(note = "inefficent")]
157    pub fn add_anon_repeat(&mut self, sub: Vec<Sky<T>>) {
158        if (sub.len() == 0) || sub[0].empty() {
159            return;
160        }
161        for n in sub[0].iter_keys() {
162            let asters: Vec<Asterism<T>> =
163                sub.iter().map(|sky| sky.find_or_panic(n).clone()).collect();
164            self.mut_set(*n, Asterism::join(asters));
165        }
166    }
167
168    #[deprecated(note = "named repeats are gone")]
169    pub fn anonimize_repeat(&mut self, _: Name) {}
170}
171
172// TODO: move these to macros.rs (and fully-qualify their names)
173macro_rules! asterism {
174    ([$( $sub:tt ),*]) => {
175        Asterism::join(vec![
176            $( asterism!($sub) ),*
177        ])
178    };
179    ($leaf:expr) => { Asterism::from_leaf($leaf) };
180}
181
182macro_rules! sky {
183    ( $($n:tt => $rhs:tt),* ) => {
184        assoc_n!( $( (stringify!($n)) => asterism!($rhs) ),* )
185    };
186}
187
188#[test]
189fn sky_basics() {
190    use crate::name::n;
191
192    let abc: Sky<usize> = sky!(
193        a => [[1, 2], [3], []],
194        b => 9,
195        c => [4, 5, 6],
196        d => [7, 8]
197    );
198
199    assert_eq!(abc.leaf(n("b")), &9);
200    assert_eq!(abc.depth_1(n("c")).collect::<Vec<_>>(), vec![&4, &5, &6]);
201
202    let mut cur_c = 4;
203    for abccc in abc.march(&[n("c")]) {
204        assert_eq!(abccc.leaf(n("b")), &9);
205        assert_eq!(abccc.leaf(n("c")), &cur_c);
206        cur_c += 1;
207        assert_eq!(abccc.depth_1(n("d")).collect::<Vec<_>>(), vec![&7, &8]);
208    }
209}