graphix_stdlib/
map.rs

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