graphix_stdlib/
array.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 compact_str::format_compact;
8use graphix_compiler::{
9    expr::ExprId,
10    node::genn,
11    typ::{FnType, Type},
12    Apply, BindId, BuiltIn, BuiltInInitFn, Event, ExecCtx, LambdaId, Node, Refs, Rt,
13    UserEvent,
14};
15use netidx::{publisher::Typ, subscriber::Value, utils::Either};
16use netidx_value::ValArray;
17use smallvec::{smallvec, SmallVec};
18use std::{collections::VecDeque, fmt::Debug, iter, sync::Arc};
19
20impl MapCollection for ValArray {
21    fn iter_values(&self) -> impl Iterator<Item = Value> {
22        (**self).iter().cloned()
23    }
24
25    fn len(&self) -> usize {
26        (**self).len()
27    }
28
29    fn select(v: Value) -> Option<Self> {
30        match v {
31            Value::Array(a) => Some(a.clone()),
32            _ => None,
33        }
34    }
35
36    fn project(self) -> Value {
37        Value::Array(self)
38    }
39
40    fn etyp(ft: &FnType) -> Result<Type> {
41        match &ft.args[0].typ {
42            Type::Array(et) => Ok((**et).clone()),
43            _ => bail!("expected array"),
44        }
45    }
46}
47
48#[derive(Debug, Default)]
49pub(super) struct MapImpl;
50
51impl<R: Rt, E: UserEvent> MapFn<R, E> for MapImpl {
52    type Collection = ValArray;
53
54    const NAME: &str = "array_map";
55    deftype!(
56        "core::array",
57        "fn(Array<'a>, fn('a) -> 'b throws 'e) -> Array<'b> throws 'e"
58    );
59
60    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
61        Some(Value::Array(ValArray::from_iter_exact(
62            slots.iter().map(|s| s.cur.clone().unwrap()),
63        )))
64    }
65}
66
67pub(super) type Map<R, E> = MapQ<R, E, MapImpl>;
68
69#[derive(Debug, Default)]
70pub(super) struct FilterImpl;
71
72impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterImpl {
73    type Collection = ValArray;
74
75    const NAME: &str = "array_filter";
76    deftype!(
77        "core::array",
78        "fn(Array<'a>, fn('a) -> bool throws 'e) -> Array<'a> throws 'e"
79    );
80
81    fn finish(&mut self, slots: &[Slot<R, E>], a: &ValArray) -> Option<Value> {
82        Some(Value::Array(ValArray::from_iter(slots.iter().zip(a.iter()).filter_map(
83            |(p, v)| match p.cur {
84                Some(Value::Bool(true)) => Some(v.clone()),
85                _ => None,
86            },
87        ))))
88    }
89}
90
91pub(super) type Filter<R, E> = MapQ<R, E, FilterImpl>;
92
93#[derive(Debug, Default)]
94pub(super) struct FlatMapImpl;
95
96impl<R: Rt, E: UserEvent> MapFn<R, E> for FlatMapImpl {
97    type Collection = ValArray;
98
99    const NAME: &str = "array_flat_map";
100    deftype!(
101        "core::array",
102        "fn(Array<'a>, fn('a) -> ['b, Array<'b>] throws 'e) -> Array<'b> throws 'e"
103    );
104
105    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
106        Some(Value::Array(ValArray::from_iter(slots.iter().flat_map(|s| {
107            match s.cur.as_ref().unwrap() {
108                Value::Array(a) => Either::Left(a.clone().into_iter()),
109                v => Either::Right(iter::once(v.clone())),
110            }
111        }))))
112    }
113}
114
115pub(super) type FlatMap<R, E> = MapQ<R, E, FlatMapImpl>;
116
117#[derive(Debug, Default)]
118pub(super) struct FilterMapImpl;
119
120impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterMapImpl {
121    type Collection = ValArray;
122
123    const NAME: &str = "array_filter_map";
124    deftype!(
125        "core::array",
126        "fn(Array<'a>, fn('a) -> Option<'b> throws 'e) -> Array<'b> throws 'e"
127    );
128
129    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
130        Some(Value::Array(ValArray::from_iter(slots.iter().filter_map(|s| {
131            match s.cur.as_ref().unwrap() {
132                Value::Null => None,
133                v => Some(v.clone()),
134            }
135        }))))
136    }
137}
138
139pub(super) type FilterMap<R, E> = MapQ<R, E, FilterMapImpl>;
140
141#[derive(Debug, Default)]
142pub(super) struct FindImpl;
143
144impl<R: Rt, E: UserEvent> MapFn<R, E> for FindImpl {
145    type Collection = ValArray;
146
147    const NAME: &str = "array_find";
148    deftype!(
149        "core::array",
150        "fn(Array<'a>, fn('a) -> bool throws 'e) -> Option<'a> throws 'e"
151    );
152
153    fn finish(&mut self, slots: &[Slot<R, E>], a: &ValArray) -> Option<Value> {
154        let r = slots
155            .iter()
156            .enumerate()
157            .find(|(_, s)| match s.cur.as_ref() {
158                Some(Value::Bool(true)) => true,
159                _ => false,
160            })
161            .map(|(i, _)| a[i].clone())
162            .unwrap_or(Value::Null);
163        Some(r)
164    }
165}
166
167pub(super) type Find<R, E> = MapQ<R, E, FindImpl>;
168
169#[derive(Debug, Default)]
170pub(super) struct FindMapImpl;
171
172impl<R: Rt, E: UserEvent> MapFn<R, E> for FindMapImpl {
173    type Collection = ValArray;
174
175    const NAME: &str = "array_find_map";
176    deftype!(
177        "core::array",
178        "fn(Array<'a>, fn('a) -> Option<'b> throws 'e) -> Option<'b> throws 'e"
179    );
180
181    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
182        let r = slots
183            .iter()
184            .find_map(|s| match s.cur.as_ref().unwrap() {
185                Value::Null => None,
186                v => Some(v.clone()),
187            })
188            .unwrap_or(Value::Null);
189        Some(r)
190    }
191}
192
193pub(super) type FindMap<R, E> = MapQ<R, E, FindMapImpl>;
194
195#[derive(Debug)]
196struct FoldImpl;
197
198impl<R: Rt, E: UserEvent> FoldFn<R, E> for FoldImpl {
199    type Collection = ValArray;
200
201    const NAME: &str = "array_fold";
202    deftype!(
203        "core::array",
204        "fn(Array<'a>, 'b, fn('b, 'a) -> 'b throws 'e) -> 'b throws 'e"
205    );
206}
207
208type Fold<R, E> = FoldQ<R, E, FoldImpl>;
209
210#[derive(Debug, Default)]
211pub(super) struct ConcatEv(SmallVec<[Value; 32]>);
212
213impl EvalCached for ConcatEv {
214    const NAME: &str = "array_concat";
215    deftype!("core::array", "fn(Array<'a>, @args: Array<'a>) -> Array<'a>");
216
217    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
218        let mut present = true;
219        for v in from.0.iter() {
220            match v {
221                Some(Value::Array(a)) => {
222                    for v in a.iter() {
223                        self.0.push(v.clone())
224                    }
225                }
226                Some(v) => self.0.push(v.clone()),
227                None => present = false,
228            }
229        }
230        if present {
231            let a = ValArray::from_iter_exact(self.0.drain(..));
232            Some(Value::Array(a))
233        } else {
234            self.0.clear();
235            None
236        }
237    }
238}
239
240pub(super) type Concat = CachedArgs<ConcatEv>;
241
242#[derive(Debug, Default)]
243pub(super) struct PushBackEv(SmallVec<[Value; 32]>);
244
245impl EvalCached for PushBackEv {
246    const NAME: &str = "array_push_back";
247    deftype!("core::array", "fn(Array<'a>, @args: 'a) -> Array<'a>");
248
249    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
250        let mut present = true;
251        match &from.0[..] {
252            [Some(Value::Array(a)), tl @ ..] => {
253                self.0.extend(a.iter().map(|v| v.clone()));
254                for v in tl {
255                    match v {
256                        Some(v) => self.0.push(v.clone()),
257                        None => present = false,
258                    }
259                }
260            }
261            [] | [None, ..] | [Some(_), ..] => present = false,
262        }
263        if present {
264            let a = ValArray::from_iter_exact(self.0.drain(..));
265            Some(Value::Array(a))
266        } else {
267            self.0.clear();
268            None
269        }
270    }
271}
272
273pub(super) type PushBack = CachedArgs<PushBackEv>;
274
275#[derive(Debug, Default)]
276pub(super) struct PushFrontEv(SmallVec<[Value; 32]>);
277
278impl EvalCached for PushFrontEv {
279    const NAME: &str = "array_push_front";
280    deftype!("core::array", "fn(Array<'a>, @args: 'a) -> Array<'a>");
281
282    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
283        let mut present = true;
284        match &from.0[..] {
285            [Some(Value::Array(a)), tl @ ..] => {
286                for v in tl {
287                    match v {
288                        Some(v) => self.0.push(v.clone()),
289                        None => present = false,
290                    }
291                }
292                self.0.extend(a.iter().map(|v| v.clone()));
293            }
294            [] | [None, ..] | [Some(_), ..] => present = false,
295        }
296        if present {
297            let a = ValArray::from_iter_exact(self.0.drain(..));
298            Some(Value::Array(a))
299        } else {
300            self.0.clear();
301            None
302        }
303    }
304}
305
306pub(super) type PushFront = CachedArgs<PushFrontEv>;
307
308#[derive(Debug, Default)]
309pub(super) struct WindowEv(SmallVec<[Value; 32]>);
310
311impl EvalCached for WindowEv {
312    const NAME: &str = "array_window";
313    deftype!("core::array", "fn(#n:i64, Array<'a>, @args: 'a) -> Array<'a>");
314
315    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
316        let mut present = true;
317        match &from.0[..] {
318            [Some(Value::I64(window)), Some(Value::Array(a)), tl @ ..] => {
319                let window = *window as usize;
320                let total = a.len() + tl.len();
321                if total <= window {
322                    self.0.extend(a.iter().cloned());
323                    for v in tl {
324                        match v {
325                            Some(v) => self.0.push(v.clone()),
326                            None => present = false,
327                        }
328                    }
329                } else if a.len() >= (total - window) {
330                    self.0.extend(a[(total - window)..].iter().cloned());
331                    for v in tl {
332                        match v {
333                            Some(v) => self.0.push(v.clone()),
334                            None => present = false,
335                        }
336                    }
337                } else {
338                    for v in &tl[tl.len() - window..] {
339                        match v {
340                            Some(v) => self.0.push(v.clone()),
341                            None => present = false,
342                        }
343                    }
344                }
345            }
346            [] | [_] | [_, None, ..] | [None, _, ..] | [Some(_), Some(_), ..] => {
347                present = false
348            }
349        }
350        if present {
351            let a = ValArray::from_iter_exact(self.0.drain(..));
352            Some(Value::Array(a))
353        } else {
354            self.0.clear();
355            None
356        }
357    }
358}
359
360pub(super) type Window = CachedArgs<WindowEv>;
361
362#[derive(Debug, Default)]
363pub(super) struct LenEv;
364
365impl EvalCached for LenEv {
366    const NAME: &str = "array_len";
367    deftype!("core::array", "fn(Array<'a>) -> i64");
368
369    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
370        match &from.0[0] {
371            Some(Value::Array(a)) => Some(Value::I64(a.len() as i64)),
372            Some(_) | None => None,
373        }
374    }
375}
376
377pub(super) type Len = CachedArgs<LenEv>;
378
379#[derive(Debug, Default)]
380pub(super) struct FlattenEv(SmallVec<[Value; 32]>);
381
382impl EvalCached for FlattenEv {
383    const NAME: &str = "array_flatten";
384    deftype!("core::array", "fn(Array<Array<'a>>) -> Array<'a>");
385
386    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
387        match &from.0[0] {
388            Some(Value::Array(a)) => {
389                for v in a.iter() {
390                    match v {
391                        Value::Array(a) => self.0.extend(a.iter().map(|v| v.clone())),
392                        v => self.0.push(v.clone()),
393                    }
394                }
395                let a = ValArray::from_iter_exact(self.0.drain(..));
396                Some(Value::Array(a))
397            }
398            Some(_) | None => None,
399        }
400    }
401}
402
403pub(super) type Flatten = CachedArgs<FlattenEv>;
404
405#[derive(Debug, Default)]
406pub(super) struct SortEv(SmallVec<[Value; 32]>);
407
408impl EvalCached for SortEv {
409    const NAME: &str = "array_sort";
410    deftype!(
411        "core::array",
412        "fn(?#dir:Direction, ?#numeric:bool, Array<'a>) -> Array<'a>"
413    );
414
415    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
416        fn cn(v: &Value) -> Value {
417            v.clone().cast(Typ::F64).unwrap_or_else(|| v.clone())
418        }
419        match &from.0[..] {
420            [Some(Value::String(dir)), Some(Value::Bool(numeric)), Some(Value::Array(a))] => {
421                match &**dir {
422                    "Ascending" => {
423                        self.0.extend(a.iter().cloned());
424                        if *numeric {
425                            self.0.sort_by(|v0, v1| cn(v0).cmp(&cn(v1)))
426                        } else {
427                            self.0.sort();
428                        }
429                        Some(Value::Array(ValArray::from_iter_exact(self.0.drain(..))))
430                    }
431                    "Descending" => {
432                        self.0.extend(a.iter().cloned());
433                        if *numeric {
434                            self.0.sort_by(|a0, a1| cn(a1).cmp(&cn(a0)))
435                        } else {
436                            self.0.sort_by(|a0, a1| a1.cmp(a0));
437                        }
438                        Some(Value::Array(ValArray::from_iter_exact(self.0.drain(..))))
439                    }
440                    _ => None,
441                }
442            }
443            _ => None,
444        }
445    }
446}
447
448pub(super) type Sort = CachedArgs<SortEv>;
449
450#[derive(Debug, Default)]
451pub(super) struct EnumerateEv;
452
453impl EvalCached for EnumerateEv {
454    const NAME: &str = "array_enumerate";
455    deftype!("core::array", "fn(Array<'a>) -> Array<(i64, 'a)>");
456
457    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
458        if let Some(Value::Array(a)) = &from.0[0] {
459            let a = ValArray::from_iter_exact(
460                a.iter().enumerate().map(|(i, v)| (i, v.clone()).into()),
461            );
462            return Some(Value::Array(a));
463        }
464        None
465    }
466}
467
468pub(super) type Enumerate = CachedArgs<EnumerateEv>;
469
470#[derive(Debug, Default)]
471pub(super) struct ZipEv;
472
473impl EvalCached for ZipEv {
474    const NAME: &str = "array_zip";
475    deftype!("core::array", "fn(Array<'a>, Array<'b>) -> Array<('a, 'b)>");
476
477    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
478        match &from.0[..] {
479            [Some(Value::Array(a0)), Some(Value::Array(a1))] => {
480                Some(Value::Array(ValArray::from_iter_exact(
481                    a0.iter().cloned().zip(a1.iter().cloned()).map(|p| p.into()),
482                )))
483            }
484            _ => None,
485        }
486    }
487}
488
489pub(super) type Zip = CachedArgs<ZipEv>;
490
491#[derive(Debug, Default)]
492pub(super) struct UnzipEv {
493    t0: Vec<Value>,
494    t1: Vec<Value>,
495}
496
497impl EvalCached for UnzipEv {
498    const NAME: &str = "array_unzip";
499    deftype!("core::array", "fn(Array<('a, 'b)>) -> (Array<'a>, Array<'b>)");
500
501    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
502        match &from.0[..] {
503            [Some(Value::Array(a))] => {
504                for v in a {
505                    if let Value::Array(a) = v {
506                        match &a[..] {
507                            [v0, v1] => {
508                                self.t0.push(v0.clone());
509                                self.t1.push(v1.clone());
510                            }
511                            _ => (),
512                        }
513                    }
514                }
515                let v0 = Value::Array(ValArray::from_iter_exact(self.t0.drain(..)));
516                let v1 = Value::Array(ValArray::from_iter_exact(self.t1.drain(..)));
517                Some(Value::Array(ValArray::from_iter_exact([v0, v1].into_iter())))
518            }
519            _ => None,
520        }
521    }
522}
523
524pub(super) type Unzip = CachedArgs<UnzipEv>;
525
526#[derive(Debug)]
527pub(super) struct Group<R: Rt, E: UserEvent> {
528    queue: VecDeque<Value>,
529    buf: SmallVec<[Value; 16]>,
530    pred: Node<R, E>,
531    ready: bool,
532    pid: BindId,
533    nid: BindId,
534    xid: BindId,
535}
536
537impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Group<R, E> {
538    const NAME: &str = "array_group";
539    deftype!(
540        "core::array",
541        "fn('a, fn(i64, 'a) -> bool throws 'e) -> Array<'a> throws 'e"
542    );
543
544    fn init(_: &mut ExecCtx<R, E>) -> BuiltInInitFn<R, E> {
545        Arc::new(|ctx, typ, scope, from, top_id| match from {
546            [_, _] => {
547                let scope =
548                    scope.append(&format_compact!("fn{}", LambdaId::new().inner()));
549                let n_typ = Type::Primitive(Typ::I64.into());
550                let etyp = typ.args[0].typ.clone();
551                let mftyp = match &typ.args[1].typ {
552                    Type::Fn(ft) => ft.clone(),
553                    t => bail!("expected function not {t}"),
554                };
555                let (nid, n) =
556                    genn::bind(ctx, &scope.lexical, "n", n_typ.clone(), top_id);
557                let (xid, x) = genn::bind(ctx, &scope.lexical, "x", etyp.clone(), top_id);
558                let pid = BindId::new();
559                let fnode = genn::reference(ctx, pid, Type::Fn(mftyp.clone()), top_id);
560                let pred = genn::apply(fnode, scope, vec![n, x], &mftyp, top_id);
561                Ok(Box::new(Self {
562                    queue: VecDeque::new(),
563                    buf: smallvec![],
564                    pred,
565                    ready: true,
566                    pid,
567                    nid,
568                    xid,
569                }))
570            }
571            _ => bail!("expected two arguments"),
572        })
573    }
574}
575
576impl<R: Rt, E: UserEvent> Apply<R, E> for Group<R, E> {
577    fn update(
578        &mut self,
579        ctx: &mut ExecCtx<R, E>,
580        from: &mut [Node<R, E>],
581        event: &mut Event<E>,
582    ) -> Option<Value> {
583        macro_rules! set {
584            ($v:expr) => {{
585                self.ready = false;
586                self.buf.push($v.clone());
587                let len = Value::I64(self.buf.len() as i64);
588                ctx.cached.insert(self.nid, len.clone());
589                event.variables.insert(self.nid, len);
590                ctx.cached.insert(self.xid, $v.clone());
591                event.variables.insert(self.xid, $v);
592            }};
593        }
594        if let Some(v) = from[0].update(ctx, event) {
595            self.queue.push_back(v);
596        }
597        if let Some(v) = from[1].update(ctx, event) {
598            ctx.cached.insert(self.pid, v.clone());
599            event.variables.insert(self.pid, v);
600        }
601        if self.ready && self.queue.len() > 0 {
602            let v = self.queue.pop_front().unwrap();
603            set!(v);
604        }
605        loop {
606            match self.pred.update(ctx, event) {
607                None => break None,
608                Some(v) => {
609                    self.ready = true;
610                    match v {
611                        Value::Bool(true) => {
612                            break Some(Value::Array(ValArray::from_iter_exact(
613                                self.buf.drain(..),
614                            )))
615                        }
616                        _ => match self.queue.pop_front() {
617                            None => break None,
618                            Some(v) => set!(v),
619                        },
620                    }
621                }
622            }
623        }
624    }
625
626    fn typecheck(
627        &mut self,
628        ctx: &mut ExecCtx<R, E>,
629        _from: &mut [Node<R, E>],
630    ) -> anyhow::Result<()> {
631        self.pred.typecheck(ctx)
632    }
633
634    fn refs(&self, refs: &mut Refs) {
635        self.pred.refs(refs)
636    }
637
638    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
639        ctx.cached.remove(&self.nid);
640        ctx.cached.remove(&self.pid);
641        ctx.cached.remove(&self.xid);
642        self.pred.delete(ctx);
643    }
644
645    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
646        self.pred.sleep(ctx);
647    }
648}
649
650#[derive(Debug)]
651pub(super) struct Iter(BindId, ExprId);
652
653impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Iter {
654    const NAME: &str = "array_iter";
655    deftype!("core::array", "fn(Array<'a>) -> 'a");
656
657    fn init(_: &mut ExecCtx<R, E>) -> BuiltInInitFn<R, E> {
658        Arc::new(|ctx, _, _, _, top_id| {
659            let id = BindId::new();
660            ctx.rt.ref_var(id, top_id);
661            Ok(Box::new(Iter(id, top_id)))
662        })
663    }
664}
665
666impl<R: Rt, E: UserEvent> Apply<R, E> for Iter {
667    fn update(
668        &mut self,
669        ctx: &mut ExecCtx<R, E>,
670        from: &mut [Node<R, E>],
671        event: &mut Event<E>,
672    ) -> Option<Value> {
673        if let Some(Value::Array(a)) = from[0].update(ctx, event) {
674            for v in a.iter() {
675                ctx.rt.set_var(self.0, v.clone());
676            }
677        }
678        event.variables.get(&self.0).map(|v| v.clone())
679    }
680
681    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
682        ctx.rt.unref_var(self.0, self.1)
683    }
684
685    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
686        // there may be in flight updates which we now must ignore forever
687        ctx.rt.unref_var(self.0, self.1);
688        self.0 = BindId::new();
689        ctx.rt.ref_var(self.0, self.1);
690    }
691}
692
693#[derive(Debug)]
694pub(super) struct IterQ {
695    triggered: usize,
696    queue: VecDeque<(usize, ValArray)>,
697    id: BindId,
698    top_id: ExprId,
699}
700
701impl<R: Rt, E: UserEvent> BuiltIn<R, E> for IterQ {
702    const NAME: &str = "array_iterq";
703    deftype!("core::array", "fn(#clock:Any, Array<'a>) -> 'a");
704
705    fn init(_: &mut ExecCtx<R, E>) -> BuiltInInitFn<R, E> {
706        Arc::new(|ctx, _, _, _, top_id| {
707            let id = BindId::new();
708            ctx.rt.ref_var(id, top_id);
709            Ok(Box::new(IterQ { triggered: 0, queue: VecDeque::new(), id, top_id }))
710        })
711    }
712}
713
714impl<R: Rt, E: UserEvent> Apply<R, E> for IterQ {
715    fn update(
716        &mut self,
717        ctx: &mut ExecCtx<R, E>,
718        from: &mut [Node<R, E>],
719        event: &mut Event<E>,
720    ) -> Option<Value> {
721        if from[0].update(ctx, event).is_some() {
722            self.triggered += 1;
723        }
724        if let Some(Value::Array(a)) = from[1].update(ctx, event) {
725            if a.len() > 0 {
726                self.queue.push_back((0, a));
727            }
728        }
729        while self.triggered > 0 && self.queue.len() > 0 {
730            let (i, a) = self.queue.front_mut().unwrap();
731            while self.triggered > 0 && *i < a.len() {
732                ctx.rt.set_var(self.id, a[*i].clone());
733                *i += 1;
734                self.triggered -= 1;
735            }
736            if *i == a.len() {
737                self.queue.pop_front();
738            }
739        }
740        event.variables.get(&self.id).cloned()
741    }
742
743    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
744        ctx.rt.unref_var(self.id, self.top_id)
745    }
746
747    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
748        ctx.rt.unref_var(self.id, self.top_id);
749        self.id = BindId::new();
750        self.queue.clear();
751        self.triggered = 0;
752    }
753}
754
755pub(super) fn register<R: Rt, E: UserEvent>(ctx: &mut ExecCtx<R, E>) -> Result<ArcStr> {
756    ctx.register_builtin::<Concat>()?;
757    ctx.register_builtin::<Filter<R, E>>()?;
758    ctx.register_builtin::<FilterMap<R, E>>()?;
759    ctx.register_builtin::<Find<R, E>>()?;
760    ctx.register_builtin::<FindMap<R, E>>()?;
761    ctx.register_builtin::<FlatMap<R, E>>()?;
762    ctx.register_builtin::<Enumerate>()?;
763    ctx.register_builtin::<Zip>()?;
764    ctx.register_builtin::<Unzip>()?;
765    ctx.register_builtin::<Flatten>()?;
766    ctx.register_builtin::<Fold<R, E>>()?;
767    ctx.register_builtin::<Group<R, E>>()?;
768    ctx.register_builtin::<Iter>()?;
769    ctx.register_builtin::<IterQ>()?;
770    ctx.register_builtin::<Len>()?;
771    ctx.register_builtin::<Map<R, E>>()?;
772    ctx.register_builtin::<PushBack>()?;
773    ctx.register_builtin::<PushFront>()?;
774    ctx.register_builtin::<Sort>()?;
775    ctx.register_builtin::<Window>()?;
776    Ok(literal!(include_str!("array.gx")))
777}