Skip to main content

graphix_package_map/
lib.rs

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