Skip to main content

graphix_package_map/
lib.rs

1use anyhow::Result;
2use graphix_compiler::{
3    expr::ExprId, Apply, BindId, BuiltIn, Event, ExecCtx, Node, Rt, Scope, UserEvent,
4};
5use graphix_package_core::{
6    deftype, CachedArgs, CachedVals, EvalCached, FoldFn, FoldQ, MapFn, MapQ, Slot,
7};
8use graphix_rt::GXRt;
9use immutable_chunkmap::map::Map as CMap;
10use netidx::subscriber::Value;
11use netidx_value::ValArray;
12use poolshark::local::LPooled;
13use std::collections::VecDeque;
14use std::fmt::Debug;
15
16#[derive(Debug, Default)]
17struct MapImpl;
18
19impl<R: Rt, E: UserEvent> MapFn<R, E> for MapImpl {
20    type Collection = CMap<Value, Value, 32>;
21
22    const NAME: &str = "map_map";
23    deftype!(
24        "fn(Map<'a, 'b>, fn(('a, 'b)) -> ('c, 'd) throws 'e) -> Map<'c, 'd> throws 'e"
25    );
26
27    fn finish(&mut self, slots: &[Slot<R, E>], _: &Self::Collection) -> Option<Value> {
28        Some(Value::Map(CMap::from_iter(
29            slots
30                .iter()
31                .map(|s| s.cur.clone().unwrap().cast_to::<(Value, Value)>().unwrap()),
32        )))
33    }
34}
35
36type Map<R, E> = MapQ<R, E, MapImpl>;
37
38#[derive(Debug, Default)]
39struct FilterImpl;
40
41impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterImpl {
42    type Collection = CMap<Value, Value, 32>;
43
44    const NAME: &str = "map_filter";
45    deftype!("fn(Map<'a, 'b>, fn(('a, 'b)) -> bool throws 'e) -> Map<'a, 'b> throws 'e");
46
47    fn finish(
48        &mut self,
49        slots: &[Slot<R, E>],
50        m: &CMap<Value, Value, 32>,
51    ) -> Option<Value> {
52        Some(Value::Map(CMap::from_iter(slots.iter().zip(m.into_iter()).filter_map(
53            |(p, (k, v))| match p.cur {
54                Some(Value::Bool(true)) => Some((k.clone(), v.clone())),
55                _ => None,
56            },
57        ))))
58    }
59}
60
61type Filter<R, E> = MapQ<R, E, FilterImpl>;
62
63#[derive(Debug, Default)]
64struct FilterMapImpl;
65
66impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterMapImpl {
67    type Collection = CMap<Value, Value, 32>;
68
69    const NAME: &str = "map_filter_map";
70    deftype!(
71        "fn(Map<'a, 'b>, fn(('a, 'b)) -> Option<('c, 'd)> throws 'e) -> Map<'c, 'd> throws 'e"
72    );
73
74    fn finish(
75        &mut self,
76        slots: &[Slot<R, E>],
77        _: &CMap<Value, Value, 32>,
78    ) -> Option<Value> {
79        Some(Value::Map(CMap::from_iter(slots.iter().filter_map(|s| {
80            match s.cur.as_ref().unwrap() {
81                Value::Null => None,
82                v => Some(v.clone().cast_to::<(Value, Value)>().unwrap()),
83            }
84        }))))
85    }
86}
87
88type FilterMap<R, E> = MapQ<R, E, FilterMapImpl>;
89
90#[derive(Debug)]
91struct FoldImpl;
92
93impl<R: Rt, E: UserEvent> FoldFn<R, E> for FoldImpl {
94    type Collection = CMap<Value, Value, 32>;
95
96    const NAME: &str = "map_fold";
97    deftype!("fn(Map<'a, 'b>, 'c, fn('c, ('a, 'b)) -> 'c throws 'e) -> 'c throws 'e");
98}
99
100type Fold<R, E> = FoldQ<R, E, FoldImpl>;
101
102#[derive(Debug, Default)]
103struct LenEv;
104
105impl EvalCached for LenEv {
106    const NAME: &str = "map_len";
107    deftype!("fn(Map<'a, 'b>) -> i64");
108
109    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
110        match &from.0[0] {
111            Some(Value::Map(m)) => Some(Value::I64(m.len() as i64)),
112            Some(_) | None => None,
113        }
114    }
115}
116
117type Len = CachedArgs<LenEv>;
118
119#[derive(Debug, Default)]
120struct GetEv;
121
122impl EvalCached for GetEv {
123    const NAME: &str = "map_get";
124    deftype!("fn(Map<'a, 'b>, 'a) -> Option<'b>");
125
126    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
127        match (&from.0[0], &from.0[1]) {
128            (Some(Value::Map(m)), Some(key)) => {
129                Some(m.get(key).cloned().unwrap_or(Value::Null))
130            }
131            _ => None,
132        }
133    }
134}
135
136type Get = CachedArgs<GetEv>;
137
138#[derive(Debug, Default)]
139struct InsertEv;
140
141impl EvalCached for InsertEv {
142    const NAME: &str = "map_insert";
143    deftype!("fn(Map<'a, 'b>, 'a, 'b) -> Map<'a, 'b>");
144
145    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
146        match (&from.0[0], &from.0[1], &from.0[2]) {
147            (Some(Value::Map(m)), Some(key), Some(value)) => {
148                Some(Value::Map(m.insert(key.clone(), value.clone()).0))
149            }
150            _ => None,
151        }
152    }
153}
154
155type Insert = CachedArgs<InsertEv>;
156
157#[derive(Debug, Default)]
158struct RemoveEv;
159
160impl EvalCached for RemoveEv {
161    const NAME: &str = "map_remove";
162    deftype!("fn(Map<'a, 'b>, 'a) -> Map<'a, 'b>");
163
164    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
165        match (&from.0[0], &from.0[1]) {
166            (Some(Value::Map(m)), Some(key)) => Some(Value::Map(m.remove(key).0)),
167            _ => None,
168        }
169    }
170}
171
172type Remove = CachedArgs<RemoveEv>;
173
174#[derive(Debug)]
175struct Iter {
176    id: BindId,
177    top_id: ExprId,
178}
179
180impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Iter {
181    const NAME: &str = "map_iter";
182    deftype!("fn(Map<'a, 'b>) -> ('a, 'b)");
183
184    fn init<'a, 'b, 'c>(
185        ctx: &'a mut ExecCtx<R, E>,
186        _typ: &'a graphix_compiler::typ::FnType,
187        _scope: &'b Scope,
188        _from: &'c [Node<R, E>],
189        top_id: ExprId,
190    ) -> Result<Box<dyn Apply<R, E>>> {
191        let id = BindId::new();
192        ctx.rt.ref_var(id, top_id);
193        Ok(Box::new(Self { id, top_id }))
194    }
195}
196
197impl<R: Rt, E: UserEvent> Apply<R, E> for Iter {
198    fn update(
199        &mut self,
200        ctx: &mut ExecCtx<R, E>,
201        from: &mut [Node<R, E>],
202        event: &mut Event<E>,
203    ) -> Option<Value> {
204        if let Some(Value::Map(m)) = from[0].update(ctx, event) {
205            for (k, v) in m.into_iter() {
206                let pair = Value::Array(ValArray::from_iter_exact(
207                    [k.clone(), v.clone()].into_iter(),
208                ));
209                ctx.rt.set_var(self.id, pair);
210            }
211        }
212        event.variables.get(&self.id).map(|v| v.clone())
213    }
214
215    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
216        ctx.rt.unref_var(self.id, self.top_id)
217    }
218
219    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
220        ctx.rt.unref_var(self.id, self.top_id);
221        self.id = BindId::new();
222        ctx.rt.ref_var(self.id, self.top_id);
223    }
224}
225
226#[derive(Debug)]
227struct IterQ {
228    triggered: usize,
229    queue: VecDeque<(usize, LPooled<Vec<(Value, Value)>>)>,
230    id: BindId,
231    top_id: ExprId,
232}
233
234impl<R: Rt, E: UserEvent> BuiltIn<R, E> for IterQ {
235    const NAME: &str = "map_iterq";
236    deftype!("fn(#clock:Any, Map<'a, 'b>) -> ('a, 'b)");
237
238    fn init<'a, 'b, 'c>(
239        ctx: &'a mut ExecCtx<R, E>,
240        _typ: &'a graphix_compiler::typ::FnType,
241        _scope: &'b Scope,
242        _from: &'c [Node<R, E>],
243        top_id: ExprId,
244    ) -> Result<Box<dyn Apply<R, E>>> {
245        let id = BindId::new();
246        ctx.rt.ref_var(id, top_id);
247        Ok(Box::new(IterQ { triggered: 0, queue: VecDeque::new(), id, top_id }))
248    }
249}
250
251impl<R: Rt, E: UserEvent> Apply<R, E> for IterQ {
252    fn update(
253        &mut self,
254        ctx: &mut ExecCtx<R, E>,
255        from: &mut [Node<R, E>],
256        event: &mut Event<E>,
257    ) -> Option<Value> {
258        if from[0].update(ctx, event).is_some() {
259            self.triggered += 1;
260        }
261        if let Some(Value::Map(m)) = from[1].update(ctx, event) {
262            let pairs: LPooled<Vec<(Value, Value)>> =
263                m.into_iter().map(|(k, v)| (k.clone(), v.clone())).collect();
264            if !pairs.is_empty() {
265                self.queue.push_back((0, pairs));
266            }
267        }
268        while self.triggered > 0 && !self.queue.is_empty() {
269            let (i, pairs) = self.queue.front_mut().unwrap();
270            while self.triggered > 0 && *i < pairs.len() {
271                let (k, v) = pairs[*i].clone();
272                let pair = Value::Array(ValArray::from_iter_exact([k, v].into_iter()));
273                ctx.rt.set_var(self.id, pair);
274                *i += 1;
275                self.triggered -= 1;
276            }
277            if *i == pairs.len() {
278                self.queue.pop_front();
279            }
280        }
281        event.variables.get(&self.id).cloned()
282    }
283
284    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
285        ctx.rt.unref_var(self.id, self.top_id)
286    }
287
288    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
289        ctx.rt.unref_var(self.id, self.top_id);
290        self.id = BindId::new();
291        ctx.rt.ref_var(self.id, self.top_id);
292        self.queue.clear();
293        self.triggered = 0;
294    }
295}
296
297graphix_derive::defpackage! {
298    builtins => [
299        Map as Map<GXRt<X>, X::UserEvent>,
300        Filter as Filter<GXRt<X>, X::UserEvent>,
301        FilterMap as FilterMap<GXRt<X>, X::UserEvent>,
302        Fold as Fold<GXRt<X>, X::UserEvent>,
303        Len,
304        Get,
305        Insert,
306        Remove,
307        Iter,
308        IterQ,
309    ],
310}