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}