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 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}