netidx_bscript/stdfn/core/
mod.rs

1use crate::{
2    deftype, err, errf,
3    expr::{Expr, ExprId},
4    node::genn,
5    stdfn::{CachedArgs, CachedVals, EvalCached},
6    typ::FnType,
7    Apply, BindId, BuiltIn, BuiltInInitFn, Ctx, Event, ExecCtx, Node, UserEvent,
8};
9use anyhow::bail;
10use arcstr::{literal, ArcStr};
11use combine::stream::position::SourcePosition;
12use compact_str::format_compact;
13use netidx::subscriber::Value;
14use std::{collections::VecDeque, sync::Arc};
15use triomphe::Arc as TArc;
16
17pub mod array;
18
19#[derive(Debug)]
20struct IsErr;
21
22impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for IsErr {
23    const NAME: &str = "is_err";
24    deftype!("core", "fn(Any) -> bool");
25
26    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
27        Arc::new(|_, _, _, _, _| Ok(Box::new(IsErr)))
28    }
29}
30
31impl<C: Ctx, E: UserEvent> Apply<C, E> for IsErr {
32    fn update(
33        &mut self,
34        ctx: &mut ExecCtx<C, E>,
35        from: &mut [Node<C, E>],
36        event: &mut Event<E>,
37    ) -> Option<Value> {
38        from[0].update(ctx, event).map(|v| match v {
39            Value::Error(_) => Value::Bool(true),
40            _ => Value::Bool(false),
41        })
42    }
43}
44
45#[derive(Debug)]
46struct FilterErr;
47
48impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for FilterErr {
49    const NAME: &str = "filter_err";
50    deftype!("core", "fn(Any) -> error");
51
52    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
53        Arc::new(|_, _, _, _, _| Ok(Box::new(FilterErr)))
54    }
55}
56
57impl<C: Ctx, E: UserEvent> Apply<C, E> for FilterErr {
58    fn update(
59        &mut self,
60        ctx: &mut ExecCtx<C, E>,
61        from: &mut [Node<C, E>],
62        event: &mut Event<E>,
63    ) -> Option<Value> {
64        from[0].update(ctx, event).and_then(|v| match v {
65            v @ Value::Error(_) => Some(v),
66            _ => None,
67        })
68    }
69}
70
71#[derive(Debug)]
72struct ToError;
73
74impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for ToError {
75    const NAME: &str = "error";
76    deftype!("core", "fn(Any) -> error");
77
78    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
79        Arc::new(|_, _, _, _, _| Ok(Box::new(ToError)))
80    }
81}
82
83impl<C: Ctx, E: UserEvent> Apply<C, E> for ToError {
84    fn update(
85        &mut self,
86        ctx: &mut ExecCtx<C, E>,
87        from: &mut [Node<C, E>],
88        event: &mut Event<E>,
89    ) -> Option<Value> {
90        from[0].update(ctx, event).map(|v| match v.cast_to::<ArcStr>() {
91            Ok(s) => Value::Error(s),
92            Err(e) => Value::Error(format_compact!("{e}").as_str().into()),
93        })
94    }
95}
96
97#[derive(Debug)]
98struct Once {
99    val: bool,
100}
101
102impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Once {
103    const NAME: &str = "once";
104    deftype!("core", "fn('a) -> 'a");
105
106    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
107        Arc::new(|_, _, _, _, _| Ok(Box::new(Once { val: false })))
108    }
109}
110
111impl<C: Ctx, E: UserEvent> Apply<C, E> for Once {
112    fn update(
113        &mut self,
114        ctx: &mut ExecCtx<C, E>,
115        from: &mut [Node<C, E>],
116        event: &mut Event<E>,
117    ) -> Option<Value> {
118        match from {
119            [s] => s.update(ctx, event).and_then(|v| {
120                if self.val {
121                    None
122                } else {
123                    self.val = true;
124                    Some(v)
125                }
126            }),
127            _ => None,
128        }
129    }
130}
131
132#[derive(Debug, Default)]
133struct AllEv;
134
135impl EvalCached for AllEv {
136    const NAME: &str = "all";
137    deftype!("core", "fn(@args: Any) -> Any");
138
139    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
140        match &*from.0 {
141            [] => None,
142            [hd, tl @ ..] => match hd {
143                None => None,
144                v @ Some(_) => {
145                    if tl.into_iter().all(|v1| v1 == v) {
146                        v.clone()
147                    } else {
148                        None
149                    }
150                }
151            },
152        }
153    }
154}
155
156type All = CachedArgs<AllEv>;
157
158fn add_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
159    match (lhs, rhs) {
160        (None, None) | (Some(_), None) => None,
161        (None, r @ Some(_)) => r,
162        (Some(l), Some(r)) => Some(l + r),
163    }
164}
165
166#[derive(Debug, Default)]
167struct SumEv;
168
169impl EvalCached for SumEv {
170    const NAME: &str = "sum";
171    deftype!("core", "fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
172
173    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
174        from.flat_iter().fold(None, |res, v| match res {
175            res @ Some(Value::Error(_)) => res,
176            res => add_vals(res, v.clone()),
177        })
178    }
179}
180
181type Sum = CachedArgs<SumEv>;
182
183#[derive(Debug, Default)]
184struct ProductEv;
185
186fn prod_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
187    match (lhs, rhs) {
188        (None, None) | (Some(_), None) => None,
189        (None, r @ Some(_)) => r,
190        (Some(l), Some(r)) => Some(l * r),
191    }
192}
193
194impl EvalCached for ProductEv {
195    const NAME: &str = "product";
196    deftype!("core", "fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
197
198    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
199        from.flat_iter().fold(None, |res, v| match res {
200            res @ Some(Value::Error(_)) => res,
201            res => prod_vals(res, v.clone()),
202        })
203    }
204}
205
206type Product = CachedArgs<ProductEv>;
207
208#[derive(Debug, Default)]
209struct DivideEv;
210
211fn div_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
212    match (lhs, rhs) {
213        (None, None) | (Some(_), None) => None,
214        (None, r @ Some(_)) => r,
215        (Some(l), Some(r)) => Some(l / r),
216    }
217}
218
219impl EvalCached for DivideEv {
220    const NAME: &str = "divide";
221    deftype!("core", "fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
222
223    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
224        from.flat_iter().fold(None, |res, v| match res {
225            res @ Some(Value::Error(_)) => res,
226            res => div_vals(res, v.clone()),
227        })
228    }
229}
230
231type Divide = CachedArgs<DivideEv>;
232
233#[derive(Debug, Default)]
234struct MinEv;
235
236impl EvalCached for MinEv {
237    const NAME: &str = "min";
238    deftype!("core", "fn(@args: Any) -> Any");
239
240    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
241        let mut res = None;
242        for v in from.flat_iter() {
243            match (res, v) {
244                (None, None) | (Some(_), None) => return None,
245                (None, Some(v)) => {
246                    res = Some(v);
247                }
248                (Some(v0), Some(v)) => {
249                    res = if v < v0 { Some(v) } else { Some(v0) };
250                }
251            }
252        }
253        res
254    }
255}
256
257type Min = CachedArgs<MinEv>;
258
259#[derive(Debug, Default)]
260struct MaxEv;
261
262impl EvalCached for MaxEv {
263    const NAME: &str = "max";
264    deftype!("core", "fn(@args: Any) -> Any");
265
266    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
267        let mut res = None;
268        for v in from.flat_iter() {
269            match (res, v) {
270                (None, None) | (Some(_), None) => return None,
271                (None, Some(v)) => {
272                    res = Some(v);
273                }
274                (Some(v0), Some(v)) => {
275                    res = if v > v0 { Some(v) } else { Some(v0) };
276                }
277            }
278        }
279        res
280    }
281}
282
283type Max = CachedArgs<MaxEv>;
284
285#[derive(Debug, Default)]
286struct AndEv;
287
288impl EvalCached for AndEv {
289    const NAME: &str = "and";
290    deftype!("core", "fn(@args: bool) -> bool");
291
292    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
293        let mut res = Some(Value::Bool(true));
294        for v in from.flat_iter() {
295            match v {
296                None => return None,
297                Some(Value::Bool(true)) => (),
298                Some(_) => {
299                    res = Some(Value::Bool(false));
300                }
301            }
302        }
303        res
304    }
305}
306
307type And = CachedArgs<AndEv>;
308
309#[derive(Debug, Default)]
310struct OrEv;
311
312impl EvalCached for OrEv {
313    const NAME: &str = "or";
314    deftype!("core", "fn(@args: bool) -> bool");
315
316    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
317        let mut res = Some(Value::Bool(false));
318        for v in from.flat_iter() {
319            match v {
320                None => return None,
321                Some(Value::Bool(true)) => {
322                    res = Some(Value::Bool(true));
323                }
324                Some(_) => (),
325            }
326        }
327        res
328    }
329}
330
331type Or = CachedArgs<OrEv>;
332
333#[derive(Debug)]
334struct Filter<C: Ctx, E: UserEvent> {
335    ready: bool,
336    queue: VecDeque<Value>,
337    pred: Node<C, E>,
338    typ: TArc<FnType>,
339    top_id: ExprId,
340    fid: BindId,
341    x: BindId,
342    out: BindId,
343}
344
345impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Filter<C, E> {
346    const NAME: &str = "filter";
347    deftype!("core", "fn('a, fn('a) -> bool) -> 'a");
348
349    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
350        Arc::new(|ctx, typ, scope, from, top_id| match from {
351            [arg, fnode] => {
352                let (x, xn) = genn::bind(ctx, scope, "x", arg.typ().clone(), top_id);
353                let fid = BindId::new();
354                let fnode = genn::reference(ctx, fid, fnode.typ().clone(), top_id);
355                let typ = TArc::new(typ.clone());
356                let pred = genn::apply(fnode, vec![xn], typ.clone(), top_id);
357                let queue = VecDeque::new();
358                let out = BindId::new();
359                ctx.user.ref_var(out, top_id);
360                Ok(Box::new(Self { ready: true, queue, pred, typ, fid, x, out, top_id }))
361            }
362            _ => bail!("expected two arguments"),
363        })
364    }
365}
366
367impl<C: Ctx, E: UserEvent> Apply<C, E> for Filter<C, E> {
368    fn update(
369        &mut self,
370        ctx: &mut ExecCtx<C, E>,
371        from: &mut [Node<C, E>],
372        event: &mut Event<E>,
373    ) -> Option<Value> {
374        macro_rules! set {
375            ($v:expr) => {{
376                self.ready = false;
377                event.variables.insert(self.x, $v);
378            }};
379        }
380        macro_rules! maybe_cont {
381            () => {{
382                if let Some(v) = self.queue.front().cloned() {
383                    set!(v);
384                    continue;
385                }
386                break;
387            }};
388        }
389        if let Some(v) = from[0].update(ctx, event) {
390            self.queue.push_back(v);
391        }
392        if let Some(v) = from[1].update(ctx, event) {
393            ctx.cached.insert(self.fid, v.clone());
394            event.variables.insert(self.fid, v);
395        }
396        if self.ready && self.queue.len() > 0 {
397            let v = self.queue.front().unwrap().clone();
398            set!(v);
399        }
400        loop {
401            match self.pred.update(ctx, event) {
402                None => break,
403                Some(v) => {
404                    self.ready = true;
405                    match v {
406                        Value::Bool(true) => {
407                            ctx.user.set_var(self.out, self.queue.pop_front().unwrap());
408                            maybe_cont!();
409                        }
410                        _ => {
411                            let _ = self.queue.pop_front();
412                            maybe_cont!();
413                        }
414                    }
415                }
416            }
417        }
418        event.variables.get(&self.out).map(|v| v.clone())
419    }
420
421    fn typecheck(
422        &mut self,
423        ctx: &mut ExecCtx<C, E>,
424        from: &mut [Node<C, E>],
425    ) -> anyhow::Result<()> {
426        for n in from.iter_mut() {
427            n.typecheck(ctx)?;
428        }
429        self.typ.args[0].typ.check_contains(&ctx.env, &from[0].typ())?;
430        self.typ.args[1].typ.check_contains(&ctx.env, &from[1].typ())?;
431        self.pred.typecheck(ctx)
432    }
433
434    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
435        ctx.user.unref_var(self.out, self.top_id)
436    }
437}
438
439#[derive(Debug)]
440struct Queue {
441    triggered: usize,
442    queue: VecDeque<Value>,
443    id: BindId,
444    top_id: ExprId,
445}
446
447impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Queue {
448    const NAME: &str = "queue";
449    deftype!("core", "fn(#trigger:Any, 'a) -> 'a");
450
451    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
452        Arc::new(|ctx, _, _, from, top_id| match from {
453            [_, _] => {
454                let id = BindId::new();
455                ctx.user.ref_var(id, top_id);
456                Ok(Box::new(Self { triggered: 0, queue: VecDeque::new(), id, top_id }))
457            }
458            _ => bail!("expected two arguments"),
459        })
460    }
461}
462
463impl<C: Ctx, E: UserEvent> Apply<C, E> for Queue {
464    fn update(
465        &mut self,
466        ctx: &mut ExecCtx<C, E>,
467        from: &mut [Node<C, E>],
468        event: &mut Event<E>,
469    ) -> Option<Value> {
470        if from[0].update(ctx, event).is_some() {
471            self.triggered += 1;
472        }
473        if let Some(v) = from[1].update(ctx, event) {
474            self.queue.push_back(v);
475        }
476        while self.triggered > 0 && self.queue.len() > 0 {
477            self.triggered -= 1;
478            ctx.user.set_var(self.id, self.queue.pop_front().unwrap());
479        }
480        event.variables.get(&self.id).cloned()
481    }
482
483    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
484        ctx.user.unref_var(self.id, self.top_id);
485    }
486}
487
488#[derive(Debug)]
489struct Seq {
490    id: BindId,
491    top_id: ExprId,
492}
493
494impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Seq {
495    const NAME: &str = "seq";
496    deftype!("core", "fn(u64) -> u64");
497
498    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
499        Arc::new(|ctx, _, _, from, top_id| match from {
500            [_] => {
501                let id = BindId::new();
502                ctx.user.ref_var(id, top_id);
503                Ok(Box::new(Self { id, top_id }))
504            }
505            _ => bail!("expected one argument"),
506        })
507    }
508}
509
510impl<C: Ctx, E: UserEvent> Apply<C, E> for Seq {
511    fn update(
512        &mut self,
513        ctx: &mut ExecCtx<C, E>,
514        from: &mut [Node<C, E>],
515        event: &mut Event<E>,
516    ) -> Option<Value> {
517        if let Some(Value::U64(i)) = from[0].update(ctx, event) {
518            for i in 0..i {
519                ctx.user.set_var(self.id, Value::U64(i));
520            }
521        }
522        event.variables.get(&self.id).cloned()
523    }
524
525    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
526        ctx.user.unref_var(self.id, self.top_id);
527    }
528}
529
530#[derive(Debug)]
531struct Count {
532    count: u64,
533}
534
535impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Count {
536    const NAME: &str = "count";
537    deftype!("core", "fn(Any) -> u64");
538
539    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
540        Arc::new(|_, _, _, _, _| Ok(Box::new(Count { count: 0 })))
541    }
542}
543
544impl<C: Ctx, E: UserEvent> Apply<C, E> for Count {
545    fn update(
546        &mut self,
547        ctx: &mut ExecCtx<C, E>,
548        from: &mut [Node<C, E>],
549        event: &mut Event<E>,
550    ) -> Option<Value> {
551        if from.into_iter().fold(false, |u, n| u || n.update(ctx, event).is_some()) {
552            self.count += 1;
553            Some(Value::U64(self.count))
554        } else {
555            None
556        }
557    }
558}
559
560#[derive(Debug)]
561struct Sample {
562    last: Option<Value>,
563    triggered: usize,
564    id: BindId,
565    top_id: ExprId,
566}
567
568impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Sample {
569    const NAME: &str = "sample";
570    deftype!("core", "fn(#trigger:Any, 'a) -> 'a");
571
572    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
573        Arc::new(|ctx, _, _, _, top_id| {
574            let id = BindId::new();
575            ctx.user.ref_var(id, top_id);
576            Ok(Box::new(Sample { last: None, triggered: 0, id, top_id }))
577        })
578    }
579}
580
581impl<C: Ctx, E: UserEvent> Apply<C, E> for Sample {
582    fn update(
583        &mut self,
584        ctx: &mut ExecCtx<C, E>,
585        from: &mut [Node<C, E>],
586        event: &mut Event<E>,
587    ) -> Option<Value> {
588        if let Some(_) = from[0].update(ctx, event) {
589            self.triggered += 1;
590        }
591        if let Some(v) = from[1].update(ctx, event) {
592            self.last = Some(v);
593        }
594        let var = event.variables.get(&self.id).cloned();
595        let res = if self.triggered > 0 && self.last.is_some() && var.is_none() {
596            self.triggered -= 1;
597            self.last.clone()
598        } else {
599            var
600        };
601        while self.triggered > 0 && self.last.is_some() {
602            self.triggered -= 1;
603            ctx.user.set_var(self.id, self.last.clone().unwrap());
604        }
605        res
606    }
607
608    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
609        ctx.user.unref_var(self.id, self.top_id)
610    }
611}
612
613#[derive(Debug, Default)]
614struct MeanEv;
615
616impl EvalCached for MeanEv {
617    const NAME: &str = "mean";
618    deftype!(
619        "core",
620        "fn([Number, Array<Number>], @args: [Number, Array<Number>]) -> f64"
621    );
622
623    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
624        let mut total = 0.;
625        let mut samples = 0;
626        let mut error = None;
627        for v in from.flat_iter() {
628            if let Some(v) = v {
629                match v.cast_to::<f64>() {
630                    Err(e) => error = errf!("{e:?}"),
631                    Ok(v) => {
632                        total += v;
633                        samples += 1;
634                    }
635                }
636            }
637        }
638        if let Some(e) = error {
639            Some(e)
640        } else if samples == 0 {
641            err!("mean requires at least one argument")
642        } else {
643            Some(Value::F64(total / samples as f64))
644        }
645    }
646}
647
648type Mean = CachedArgs<MeanEv>;
649
650#[derive(Debug)]
651struct Uniq(Option<Value>);
652
653impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Uniq {
654    const NAME: &str = "uniq";
655    deftype!("core", "fn('a) -> 'a");
656
657    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
658        Arc::new(|_, _, _, _, _| Ok(Box::new(Uniq(None))))
659    }
660}
661
662impl<C: Ctx, E: UserEvent> Apply<C, E> for Uniq {
663    fn update(
664        &mut self,
665        ctx: &mut ExecCtx<C, E>,
666        from: &mut [Node<C, E>],
667        event: &mut Event<E>,
668    ) -> Option<Value> {
669        match from {
670            [e] => e.update(ctx, event).and_then(|v| {
671                if Some(&v) != self.0.as_ref() {
672                    self.0 = Some(v.clone());
673                    Some(v)
674                } else {
675                    None
676                }
677            }),
678            _ => unreachable!(),
679        }
680    }
681}
682
683#[derive(Debug)]
684struct Never;
685
686impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Never {
687    const NAME: &str = "never";
688    deftype!("core", "fn(@args: Any) -> _");
689
690    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
691        Arc::new(|_, _, _, _, _| Ok(Box::new(Never)))
692    }
693}
694
695impl<C: Ctx, E: UserEvent> Apply<C, E> for Never {
696    fn update(
697        &mut self,
698        ctx: &mut ExecCtx<C, E>,
699        from: &mut [Node<C, E>],
700        event: &mut Event<E>,
701    ) -> Option<Value> {
702        for n in from {
703            n.update(ctx, event);
704        }
705        None
706    }
707}
708
709#[derive(Debug)]
710struct Dbg(SourcePosition);
711
712impl<C: Ctx, E: UserEvent> BuiltIn<C, E> for Dbg {
713    const NAME: &str = "dbg";
714    deftype!("core", "fn('a) -> 'a");
715
716    fn init(_: &mut ExecCtx<C, E>) -> BuiltInInitFn<C, E> {
717        Arc::new(|_, _, _, from, _| Ok(Box::new(Dbg(from[0].spec().pos))))
718    }
719}
720
721impl<C: Ctx, E: UserEvent> Apply<C, E> for Dbg {
722    fn update(
723        &mut self,
724        ctx: &mut ExecCtx<C, E>,
725        from: &mut [Node<C, E>],
726        event: &mut Event<E>,
727    ) -> Option<Value> {
728        from[0].update(ctx, event).map(|v| {
729            eprintln!("{}: {v}", self.0);
730            v
731        })
732    }
733}
734
735const MOD: &str = r#"
736pub mod core {
737    type Sint = [ i32, z32, i64, z64 ];
738    type Uint = [ u32, v32, u64, v64 ];
739    type Int = [ Sint, Uint ];
740    type Float = [ f32, f64 ];
741    type Real = [ Float, decimal ];
742    type Number = [ Int, Real ];
743
744    type Any = [
745        Number,
746        datetime,
747        duration,
748        bool,
749        string,
750        bytes,
751        error,
752        array,
753        null
754    ];
755
756    pub mod array {
757        /// filter returns a new array containing only elements where f returned true
758        pub let filter = |a, f| 'array_filter;
759
760        /// filter_map returns a new array containing the outputs of f
761        /// that were not null
762        pub let filter_map = |a, f| 'array_filter_map;
763
764        /// return a new array where each element is the output of f applied to the
765        /// corresponding element in a
766        pub let map = |a, f| 'array_map;
767
768        /// return a new array where each element is the output of f applied to the
769        /// corresponding element in a, except that if f returns an array then it's
770        /// elements will be concatanated to the end of the output instead of nesting.
771        pub let flat_map = |a, f| 'array_flat_map;
772
773        /// return the result of f applied to the init and every element of a in
774        /// sequence. f(f(f(init, a[0]), a[1]), ...)
775        pub let fold = |a, init, f| 'array_fold;
776
777        /// each time v updates group places the value of v in an internal buffer
778        /// and calls f with the length of the internal buffer and the value of v.
779        /// If f returns true then group returns the internal buffer as an array
780        /// otherwise group returns nothing.
781        pub let group = |v, f| 'group;
782
783        /// iter produces an update for every value in the array a. updates are produced
784        /// in the order they appear in a.
785        pub let iter = |a| 'iter;
786
787        /// iterq produces updates for each value in a, but it only produces an update when
788        /// trigger updates. If trigger does not update but a does, then iterq will store each a
789        /// in an internal fifo queue. If trigger updates but a does not, iterq will record the
790        /// number of times it was triggered, and will update immediatly that many times when a
791        /// updates.
792        pub let iterq = |#trigger, a| 'iterq;
793
794        /// returns the length of a
795        pub let len = |a| 'array_len;
796
797        /// concatenates the first array with the scalar values or arrays subsuquently passed.
798        /// returns an array containing all the values of all it's arguments
799        pub let concat = |x, @args| 'array_concat;
800
801        /// flatten takes an array with two levels of nesting and produces a flat array
802        /// with all the nested elements concatenated together.
803        pub let flatten = |a| 'array_flatten;
804
805        /// applies f to every element in a and returns the first element for which f
806        /// returns true, or null if no element returns true
807        pub let find = |a, f| 'array_find;
808
809        /// applies f to every element in a and returns the first non null output of f
810        pub let find_map = |a, f| 'array_find_map;
811
812        /// return a new copy of a sorted descending
813        pub let sort = |a| 'array_sort
814    };
815
816    /// return the first argument when all arguments are equal, otherwise return nothing
817    pub let all = |@args| 'all;
818
819    /// return true if all arguments are true, otherwise return false
820    pub let and = |@args| 'and;
821
822    /// return the number of times x has updated
823    pub let count = |x| 'count;
824
825    /// return the first argument divided by all subsuquent arguments
826    pub let divide = |@args| 'divide;
827
828    /// return e only if e is an error
829    pub let filter_err = |e| 'filter_err;
830
831    /// return v if f(v) is true, otherwise return nothing
832    pub let filter = |v, f| 'filter;
833
834    /// return true if e is an error
835    pub let is_err = |e| 'is_err;
836
837    /// construct an error from the specified string
838    pub let error = |e| 'error;
839
840    /// return the maximum value of any argument
841    pub let max = |@args| 'max;
842
843    /// return the mean of the passed in arguments
844    pub let mean = |v, @args| 'mean;
845
846    /// return the minimum value of any argument
847    pub let min = |@args| 'min;
848
849    /// return v only once, subsuquent updates to v will be ignored
850    /// and once will return nothing
851    pub let once = |v| 'once;
852
853    /// seq will update i times from 0 to i - 1 in that order.
854    pub let seq = |i| 'seq;
855
856    /// return true if any argument is true
857    pub let or = |@args| 'or;
858
859    /// return the product of all arguments
860    pub let product = |@args| 'product;
861
862    /// When v updates it's value will be cached internally. When trigger updates
863    /// the cached value of v will be returned.
864    pub let sample = |#trigger, v| 'sample;
865
866    /// return the sum of all arguments
867    pub let sum = |@args| 'sum;
868
869    /// when v updates return v if the new value is different from the previous value,
870    /// otherwise return nothing.
871    pub let uniq = |v| 'uniq;
872
873    /// when v updates place it's value in an internal fifo queue. when trigger updates
874    /// return the oldest value from the fifo queue. If trigger updates and the queue is
875    /// empty, record the number of trigger updates, and produce that number of
876    /// values from the queue when they are available.
877    pub let queue = |#trigger, v| 'queue;
878
879    /// ignore updates to any argument and never return anything
880    pub let never = |@args| 'never;
881
882    /// when v updates, return it, but also print it along with the position of the expression
883    pub let dbg = |v| 'dbg;
884
885    /// This is the toplevel error sink for the ? operator. If no other lexical binding of errors
886    /// exists closer to the error site then errors handled by ? will come here.
887    pub let errors: error = never()
888}
889"#;
890
891pub fn register<C: Ctx, E: UserEvent>(ctx: &mut ExecCtx<C, E>) -> Expr {
892    ctx.register_builtin::<Queue>().unwrap();
893    ctx.register_builtin::<All>().unwrap();
894    ctx.register_builtin::<And>().unwrap();
895    ctx.register_builtin::<Count>().unwrap();
896    ctx.register_builtin::<Divide>().unwrap();
897    ctx.register_builtin::<Filter<C, E>>().unwrap();
898    ctx.register_builtin::<array::Concat>().unwrap();
899    ctx.register_builtin::<array::Len>().unwrap();
900    ctx.register_builtin::<array::Flatten>().unwrap();
901    ctx.register_builtin::<array::Filter<C, E>>().unwrap();
902    ctx.register_builtin::<array::FlatMap<C, E>>().unwrap();
903    ctx.register_builtin::<array::Find<C, E>>().unwrap();
904    ctx.register_builtin::<array::FindMap<C, E>>().unwrap();
905    ctx.register_builtin::<array::Map<C, E>>().unwrap();
906    ctx.register_builtin::<array::Fold<C, E>>().unwrap();
907    ctx.register_builtin::<array::FilterMap<C, E>>().unwrap();
908    ctx.register_builtin::<array::IterQ>().unwrap();
909    ctx.register_builtin::<array::Group<C, E>>().unwrap();
910    ctx.register_builtin::<array::Sort>().unwrap();
911    ctx.register_builtin::<FilterErr>().unwrap();
912    ctx.register_builtin::<IsErr>().unwrap();
913    ctx.register_builtin::<Max>().unwrap();
914    ctx.register_builtin::<Mean>().unwrap();
915    ctx.register_builtin::<Min>().unwrap();
916    ctx.register_builtin::<Never>().unwrap();
917    ctx.register_builtin::<Once>().unwrap();
918    ctx.register_builtin::<Seq>().unwrap();
919    ctx.register_builtin::<Or>().unwrap();
920    ctx.register_builtin::<Product>().unwrap();
921    ctx.register_builtin::<Sample>().unwrap();
922    ctx.register_builtin::<Sum>().unwrap();
923    ctx.register_builtin::<Uniq>().unwrap();
924    ctx.register_builtin::<array::Iter>().unwrap();
925    ctx.register_builtin::<ToError>().unwrap();
926    ctx.register_builtin::<Dbg>().unwrap();
927    MOD.parse().unwrap()
928}