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}