1#![doc(
2 html_logo_url = "https://graphix-lang.github.io/graphix/graphix-icon.svg",
3 html_favicon_url = "https://graphix-lang.github.io/graphix/graphix-icon.svg"
4)]
5use anyhow::{bail, Result};
6use arcstr::{literal, ArcStr};
7use compact_str::format_compact;
8use graphix_compiler::{
9 err, errf,
10 expr::{Expr, ExprId},
11 node::genn,
12 typ::{FnType, TVal, Type},
13 Apply, BindId, BuiltIn, Event, ExecCtx, LambdaId, Node, Refs, Rt, Scope, UserEvent,
14};
15use graphix_rt::GXRt;
16use immutable_chunkmap::map::Map as CMap;
17use netidx::subscriber::Value;
18use netidx_core::utils::Either;
19use netidx_value::{FromValue, ValArray};
20use poolshark::local::LPooled;
21use std::{
22 any::Any,
23 collections::{hash_map::Entry, VecDeque},
24 fmt::Debug,
25 iter,
26 marker::PhantomData,
27 sync::LazyLock,
28 time::Duration,
29};
30use tokio::time::Instant;
31use triomphe::Arc as TArc;
32
33#[macro_export]
36macro_rules! deftype {
37 ($s:literal) => {
38 const TYP: ::std::sync::LazyLock<graphix_compiler::typ::FnType> =
39 ::std::sync::LazyLock::new(|| {
40 graphix_compiler::expr::parser::parse_fn_type($s)
41 .expect("failed to parse fn type {s}")
42 });
43 };
44}
45
46#[macro_export]
47macro_rules! arity1 {
48 ($from:expr, $updates:expr) => {
49 match (&*$from, &*$updates) {
50 ([arg], [arg_up]) => (arg, arg_up),
51 (_, _) => unreachable!(),
52 }
53 };
54}
55
56#[macro_export]
57macro_rules! arity2 {
58 ($from:expr, $updates:expr) => {
59 match (&*$from, &*$updates) {
60 ([arg0, arg1], [arg0_up, arg1_up]) => ((arg0, arg1), (arg0_up, arg1_up)),
61 (_, _) => unreachable!(),
62 }
63 };
64}
65
66pub mod testing;
69
70#[derive(Debug)]
73pub struct CachedVals(pub Box<[Option<Value>]>);
74
75impl CachedVals {
76 pub fn new<R: Rt, E: UserEvent>(from: &[Node<R, E>]) -> CachedVals {
77 CachedVals(from.into_iter().map(|_| None).collect())
78 }
79
80 pub fn clear(&mut self) {
81 for v in &mut self.0 {
82 *v = None
83 }
84 }
85
86 pub fn update<R: Rt, E: UserEvent>(
87 &mut self,
88 ctx: &mut ExecCtx<R, E>,
89 from: &mut [Node<R, E>],
90 event: &mut Event<E>,
91 ) -> bool {
92 from.into_iter().enumerate().fold(false, |res, (i, src)| {
93 match src.update(ctx, event) {
94 None => res,
95 v @ Some(_) => {
96 self.0[i] = v;
97 true
98 }
99 }
100 })
101 }
102
103 pub fn update_diff<R: Rt, E: UserEvent>(
106 &mut self,
107 up: &mut [bool],
108 ctx: &mut ExecCtx<R, E>,
109 from: &mut [Node<R, E>],
110 event: &mut Event<E>,
111 ) {
112 for (i, n) in from.iter_mut().enumerate() {
113 match n.update(ctx, event) {
114 None => (),
115 v => {
116 self.0[i] = v;
117 up[i] = true
118 }
119 }
120 }
121 }
122
123 pub fn flat_iter<'a>(&'a self) -> impl Iterator<Item = Option<Value>> + 'a {
124 self.0.iter().flat_map(|v| match v {
125 None => Either::Left(iter::once(None)),
126 Some(v) => Either::Right(v.clone().flatten().map(Some)),
127 })
128 }
129
130 pub fn get<T: FromValue>(&self, i: usize) -> Option<T> {
131 self.0.get(i).and_then(|v| v.as_ref()).and_then(|v| v.clone().cast_to::<T>().ok())
132 }
133}
134
135pub trait EvalCached: Debug + Default + Send + Sync + 'static {
136 const NAME: &str;
137 const TYP: LazyLock<FnType>;
138
139 fn eval(&mut self, from: &CachedVals) -> Option<Value>;
140}
141
142#[derive(Debug)]
143pub struct CachedArgs<T: EvalCached> {
144 cached: CachedVals,
145 t: T,
146}
147
148impl<R: Rt, E: UserEvent, T: EvalCached> BuiltIn<R, E> for CachedArgs<T> {
149 const NAME: &str = T::NAME;
150 const TYP: LazyLock<FnType> = T::TYP;
151
152 fn init<'a, 'b, 'c>(
153 _ctx: &'a mut ExecCtx<R, E>,
154 _typ: &'a graphix_compiler::typ::FnType,
155 _scope: &'b Scope,
156 from: &'c [Node<R, E>],
157 _top_id: ExprId,
158 ) -> Result<Box<dyn Apply<R, E>>> {
159 let t = CachedArgs::<T> { cached: CachedVals::new(from), t: T::default() };
160 Ok(Box::new(t))
161 }
162}
163
164impl<R: Rt, E: UserEvent, T: EvalCached> Apply<R, E> for CachedArgs<T> {
165 fn update(
166 &mut self,
167 ctx: &mut ExecCtx<R, E>,
168 from: &mut [Node<R, E>],
169 event: &mut Event<E>,
170 ) -> Option<Value> {
171 if self.cached.update(ctx, from, event) {
172 self.t.eval(&self.cached)
173 } else {
174 None
175 }
176 }
177
178 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
179 self.cached.clear()
180 }
181}
182
183pub trait EvalCachedAsync: Debug + Default + Send + Sync + 'static {
184 const NAME: &str;
185 const TYP: LazyLock<FnType>;
186 type Args: Debug + Any + Send + Sync;
187
188 fn prepare_args(&mut self, cached: &CachedVals) -> Option<Self::Args>;
189 fn eval(args: Self::Args) -> impl Future<Output = Value> + Send;
190}
191
192#[derive(Debug)]
193pub struct CachedArgsAsync<T: EvalCachedAsync> {
194 cached: CachedVals,
195 id: BindId,
196 top_id: ExprId,
197 queued: VecDeque<T::Args>,
198 running: bool,
199 t: T,
200}
201
202impl<R: Rt, E: UserEvent, T: EvalCachedAsync> BuiltIn<R, E> for CachedArgsAsync<T> {
203 const NAME: &str = T::NAME;
204 const TYP: LazyLock<FnType> = T::TYP;
205
206 fn init<'a, 'b, 'c>(
207 ctx: &'a mut ExecCtx<R, E>,
208 _typ: &'a graphix_compiler::typ::FnType,
209 _scope: &'b Scope,
210 from: &'c [Node<R, E>],
211 top_id: ExprId,
212 ) -> Result<Box<dyn Apply<R, E>>> {
213 let id = BindId::new();
214 ctx.rt.ref_var(id, top_id);
215 let t = CachedArgsAsync::<T> {
216 id,
217 top_id,
218 cached: CachedVals::new(from),
219 queued: VecDeque::new(),
220 running: false,
221 t: T::default(),
222 };
223 Ok(Box::new(t))
224 }
225}
226
227impl<R: Rt, E: UserEvent, T: EvalCachedAsync> Apply<R, E> for CachedArgsAsync<T> {
228 fn update(
229 &mut self,
230 ctx: &mut ExecCtx<R, E>,
231 from: &mut [Node<R, E>],
232 event: &mut Event<E>,
233 ) -> Option<Value> {
234 if self.cached.update(ctx, from, event)
235 && let Some(args) = self.t.prepare_args(&self.cached)
236 {
237 self.queued.push_back(args);
238 }
239 let res = event.variables.remove(&self.id).map(|v| {
240 self.running = false;
241 v
242 });
243 if !self.running
244 && let Some(args) = self.queued.pop_front()
245 {
246 self.running = true;
247 let id = self.id;
248 ctx.rt.spawn_var(async move { (id, T::eval(args).await) });
249 }
250 res
251 }
252
253 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
254 ctx.rt.unref_var(self.id, self.top_id);
255 self.queued.clear();
256 self.cached.clear();
257 }
258
259 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
260 self.delete(ctx);
261 let id = BindId::new();
262 ctx.rt.ref_var(id, self.top_id);
263 }
264}
265
266pub trait MapCollection: Debug + Clone + Default + Send + Sync + 'static {
267 fn len(&self) -> usize;
269
270 fn iter_values(&self) -> impl Iterator<Item = Value>;
272
273 fn select(v: Value) -> Option<Self>;
276
277 fn project(self) -> Value;
279
280 fn etyp(ft: &FnType) -> Result<Type>;
282}
283
284impl MapCollection for ValArray {
285 fn iter_values(&self) -> impl Iterator<Item = Value> {
286 (**self).iter().cloned()
287 }
288
289 fn len(&self) -> usize {
290 (**self).len()
291 }
292
293 fn select(v: Value) -> Option<Self> {
294 match v {
295 Value::Array(a) => Some(a.clone()),
296 _ => None,
297 }
298 }
299
300 fn project(self) -> Value {
301 Value::Array(self)
302 }
303
304 fn etyp(ft: &FnType) -> Result<Type> {
305 match &ft.args[0].typ {
306 Type::Array(et) => Ok((**et).clone()),
307 _ => bail!("expected array"),
308 }
309 }
310}
311
312impl MapCollection for CMap<Value, Value, 32> {
313 fn iter_values(&self) -> impl Iterator<Item = Value> {
314 self.into_iter().map(|(k, v)| {
315 Value::Array(ValArray::from_iter_exact([k.clone(), v.clone()].into_iter()))
316 })
317 }
318
319 fn len(&self) -> usize {
320 CMap::len(self)
321 }
322
323 fn select(v: Value) -> Option<Self> {
324 match v {
325 Value::Map(m) => Some(m.clone()),
326 _ => None,
327 }
328 }
329
330 fn project(self) -> Value {
331 Value::Map(self)
332 }
333
334 fn etyp(ft: &FnType) -> Result<Type> {
335 match &ft.args[0].typ {
336 Type::Map { key, value } => {
337 Ok(Type::Tuple(TArc::from_iter([(**key).clone(), (**value).clone()])))
338 }
339 _ => bail!("expected Map, got {:?}", ft.args[0].typ),
340 }
341 }
342}
343
344pub trait MapFn<R: Rt, E: UserEvent>: Debug + Default + Send + Sync + 'static {
345 type Collection: MapCollection;
346
347 const NAME: &str;
348 const TYP: LazyLock<FnType>;
349
350 fn finish(&mut self, slots: &[Slot<R, E>], a: &Self::Collection) -> Option<Value>;
356}
357
358#[derive(Debug)]
359pub struct Slot<R: Rt, E: UserEvent> {
360 pub id: BindId,
361 pub pred: Node<R, E>,
362 pub cur: Option<Value>,
363}
364
365impl<R: Rt, E: UserEvent> Slot<R, E> {
366 pub fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
367 self.pred.delete(ctx);
368 ctx.cached.remove(&self.id);
369 ctx.env.unbind_variable(self.id);
370 }
371}
372
373#[derive(Debug)]
374pub struct MapQ<R: Rt, E: UserEvent, T: MapFn<R, E>> {
375 scope: Scope,
376 predid: BindId,
377 top_id: ExprId,
378 mftyp: TArc<FnType>,
379 etyp: Type,
380 slots: Vec<Slot<R, E>>,
381 cur: T::Collection,
382 t: T,
383}
384
385impl<R: Rt, E: UserEvent, T: MapFn<R, E>> BuiltIn<R, E> for MapQ<R, E, T> {
386 const NAME: &str = T::NAME;
387 const TYP: LazyLock<FnType> = T::TYP;
388
389 fn init<'a, 'b, 'c>(
390 _ctx: &'a mut ExecCtx<R, E>,
391 typ: &'a graphix_compiler::typ::FnType,
392 scope: &'b Scope,
393 from: &'c [Node<R, E>],
394 top_id: ExprId,
395 ) -> Result<Box<dyn Apply<R, E>>> {
396 match from {
397 [_, _] => Ok(Box::new(Self {
398 scope: scope.append(&format_compact!("fn{}", LambdaId::new().inner())),
399 predid: BindId::new(),
400 top_id,
401 etyp: T::Collection::etyp(typ)?,
402 mftyp: match &typ.args[1].typ {
403 Type::Fn(ft) => ft.clone(),
404 t => bail!("expected a function not {t}"),
405 },
406 slots: vec![],
407 cur: Default::default(),
408 t: T::default(),
409 })),
410 _ => bail!("expected two arguments"),
411 }
412 }
413}
414
415impl<R: Rt, E: UserEvent, T: MapFn<R, E>> Apply<R, E> for MapQ<R, E, T> {
416 fn update(
417 &mut self,
418 ctx: &mut ExecCtx<R, E>,
419 from: &mut [Node<R, E>],
420 event: &mut Event<E>,
421 ) -> Option<Value> {
422 let slen = self.slots.len();
423 if let Some(v) = from[1].update(ctx, event) {
424 ctx.cached.insert(self.predid, v.clone());
425 event.variables.insert(self.predid, v);
426 }
427 let (up, resized) =
428 match from[0].update(ctx, event).and_then(|v| T::Collection::select(v)) {
429 Some(a) if a.len() == slen => (Some(a), false),
430 Some(a) if a.len() < slen => {
431 while self.slots.len() > a.len() {
432 if let Some(mut s) = self.slots.pop() {
433 s.delete(ctx)
434 }
435 }
436 (Some(a), true)
437 }
438 Some(a) => {
439 while self.slots.len() < a.len() {
440 let (id, node) = genn::bind(
441 ctx,
442 &self.scope.lexical,
443 "x",
444 self.etyp.clone(),
445 self.top_id,
446 );
447 let fargs = vec![node];
448 let fnode = genn::reference(
449 ctx,
450 self.predid,
451 Type::Fn(self.mftyp.clone()),
452 self.top_id,
453 );
454 let pred = genn::apply(
455 fnode,
456 self.scope.clone(),
457 fargs,
458 &self.mftyp,
459 self.top_id,
460 );
461 self.slots.push(Slot { id, pred, cur: None });
462 }
463 (Some(a), true)
464 }
465 None => (None, false),
466 };
467 if let Some(a) = up {
468 for (s, v) in self.slots.iter().zip(a.iter_values()) {
469 ctx.cached.insert(s.id, v.clone());
470 event.variables.insert(s.id, v);
471 }
472 self.cur = a.clone();
473 if a.len() == 0 {
474 return Some(T::Collection::project(a));
475 }
476 }
477 let init = event.init;
478 let mut up = resized;
479 for (i, s) in self.slots.iter_mut().enumerate() {
480 if i == slen {
481 event.init = true;
483 if let Entry::Vacant(e) = event.variables.entry(self.predid)
484 && let Some(v) = ctx.cached.get(&self.predid)
485 {
486 e.insert(v.clone());
487 }
488 }
489 if let Some(v) = s.pred.update(ctx, event) {
490 s.cur = Some(v);
491 up = true;
492 }
493 }
494 event.init = init;
495 if up && self.slots.iter().all(|s| s.cur.is_some()) {
496 self.t.finish(&mut &self.slots, &self.cur)
497 } else {
498 None
499 }
500 }
501
502 fn typecheck(
503 &mut self,
504 ctx: &mut ExecCtx<R, E>,
505 _from: &mut [Node<R, E>],
506 ) -> anyhow::Result<()> {
507 let (_, node) =
508 genn::bind(ctx, &self.scope.lexical, "x", self.etyp.clone(), self.top_id);
509 let fargs = vec![node];
510 let ft = self.mftyp.clone();
511 let fnode = genn::reference(ctx, self.predid, Type::Fn(ft.clone()), self.top_id);
512 let mut node = genn::apply(fnode, self.scope.clone(), fargs, &ft, self.top_id);
513 let r = node.typecheck(ctx);
514 node.delete(ctx);
515 r
516 }
517
518 fn refs(&self, refs: &mut Refs) {
519 for s in &self.slots {
520 s.pred.refs(refs)
521 }
522 }
523
524 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
525 ctx.cached.remove(&self.predid);
526 for sl in &mut self.slots {
527 sl.delete(ctx)
528 }
529 }
530
531 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
532 self.cur = Default::default();
533 for sl in &mut self.slots {
534 sl.cur = None;
535 sl.pred.sleep(ctx);
536 }
537 }
538}
539
540pub trait FoldFn<R: Rt, E: UserEvent>: Debug + Send + Sync + 'static {
541 type Collection: MapCollection;
542
543 const NAME: &str;
544 const TYP: LazyLock<FnType>;
545}
546
547#[derive(Debug)]
548pub struct FoldQ<R: Rt, E: UserEvent, T: FoldFn<R, E>> {
549 top_id: ExprId,
550 fid: BindId,
551 scope: Scope,
552 binds: Vec<BindId>,
553 nodes: Vec<Node<R, E>>,
554 inits: Vec<Option<Value>>,
555 initids: Vec<BindId>,
556 initid: BindId,
557 mftype: TArc<FnType>,
558 etyp: Type,
559 ityp: Type,
560 init: Option<Value>,
561 t: PhantomData<T>,
562}
563
564impl<R: Rt, E: UserEvent, T: FoldFn<R, E>> BuiltIn<R, E> for FoldQ<R, E, T> {
565 const NAME: &str = T::NAME;
566 const TYP: LazyLock<FnType> = T::TYP;
567
568 fn init<'a, 'b, 'c>(
569 _ctx: &'a mut ExecCtx<R, E>,
570 typ: &'a graphix_compiler::typ::FnType,
571 scope: &'b Scope,
572 from: &'c [Node<R, E>],
573 top_id: ExprId,
574 ) -> Result<Box<dyn Apply<R, E>>> {
575 match from {
576 [_, _, _] => Ok(Box::new(Self {
577 top_id,
578 scope: scope.clone(),
579 binds: vec![],
580 nodes: vec![],
581 inits: vec![],
582 initids: vec![],
583 initid: BindId::new(),
584 fid: BindId::new(),
585 etyp: T::Collection::etyp(typ)?,
586 ityp: typ.args[1].typ.clone(),
587 mftype: match &typ.args[2].typ {
588 Type::Fn(ft) => ft.clone(),
589 t => bail!("expected a function not {t}"),
590 },
591 init: None,
592 t: PhantomData,
593 })),
594 _ => bail!("expected three arguments"),
595 }
596 }
597}
598
599impl<R: Rt, E: UserEvent, T: FoldFn<R, E>> Apply<R, E> for FoldQ<R, E, T> {
600 fn update(
601 &mut self,
602 ctx: &mut ExecCtx<R, E>,
603 from: &mut [Node<R, E>],
604 event: &mut Event<E>,
605 ) -> Option<Value> {
606 let init = match from[0].update(ctx, event).and_then(|v| T::Collection::select(v))
607 {
608 None => self.nodes.len(),
609 Some(a) if a.len() == self.binds.len() => {
610 for (id, v) in self.binds.iter().zip(a.iter_values()) {
611 ctx.cached.insert(*id, v.clone());
612 event.variables.insert(*id, v.clone());
613 }
614 self.nodes.len()
615 }
616 Some(a) => {
617 let vals = a.iter_values().collect::<LPooled<Vec<Value>>>();
618 while self.binds.len() < a.len() {
619 self.binds.push(BindId::new());
620 self.inits.push(None);
621 self.initids.push(BindId::new());
622 }
623 while a.len() < self.binds.len() {
624 if let Some(id) = self.binds.pop() {
625 ctx.cached.remove(&id);
626 }
627 if let Some(id) = self.initids.pop() {
628 ctx.cached.remove(&id);
629 }
630 self.inits.pop();
631 if let Some(mut n) = self.nodes.pop() {
632 n.delete(ctx);
633 }
634 }
635 let init = self.nodes.len();
636 for i in 0..self.binds.len() {
637 ctx.cached.insert(self.binds[i], vals[i].clone());
638 event.variables.insert(self.binds[i], vals[i].clone());
639 if i >= self.nodes.len() {
640 let n = genn::reference(
641 ctx,
642 if i == 0 { self.initid } else { self.initids[i - 1] },
643 self.ityp.clone(),
644 self.top_id,
645 );
646 let x = genn::reference(
647 ctx,
648 self.binds[i],
649 self.etyp.clone(),
650 self.top_id,
651 );
652 let fnode = genn::reference(
653 ctx,
654 self.fid,
655 Type::Fn(self.mftype.clone()),
656 self.top_id,
657 );
658 let node = genn::apply(
659 fnode,
660 self.scope.clone(),
661 vec![n, x],
662 &self.mftype,
663 self.top_id,
664 );
665 self.nodes.push(node);
666 }
667 }
668 init
669 }
670 };
671 if let Some(v) = from[1].update(ctx, event) {
672 ctx.cached.insert(self.initid, v.clone());
673 event.variables.insert(self.initid, v.clone());
674 self.init = Some(v);
675 }
676 if let Some(v) = from[2].update(ctx, event) {
677 ctx.cached.insert(self.fid, v.clone());
678 event.variables.insert(self.fid, v);
679 }
680 let old_init = event.init;
681 for i in 0..self.nodes.len() {
682 if i == init {
683 event.init = true;
684 if let Some(v) = ctx.cached.get(&self.fid)
685 && let Entry::Vacant(e) = event.variables.entry(self.fid)
686 {
687 e.insert(v.clone());
688 }
689 if i == 0 {
690 if let Some(v) = self.init.as_ref()
691 && let Entry::Vacant(e) = event.variables.entry(self.initid)
692 {
693 e.insert(v.clone());
694 }
695 } else {
696 if let Some(v) = self.inits[i - 1].clone() {
697 event.variables.insert(self.initids[i - 1], v);
698 }
699 }
700 }
701 match self.nodes[i].update(ctx, event) {
702 Some(v) => {
703 ctx.cached.insert(self.initids[i], v.clone());
704 event.variables.insert(self.initids[i], v.clone());
705 self.inits[i] = Some(v);
706 }
707 None => {
708 ctx.cached.remove(&self.initids[i]);
709 event.variables.remove(&self.initids[i]);
710 self.inits[i] = None;
711 }
712 }
713 }
714 event.init = old_init;
715 self.inits.last().and_then(|v| v.clone())
716 }
717
718 fn typecheck(
719 &mut self,
720 ctx: &mut ExecCtx<R, E>,
721 _from: &mut [Node<R, E>],
722 ) -> anyhow::Result<()> {
723 let mut n = genn::reference(ctx, self.initid, self.ityp.clone(), self.top_id);
724 let x = genn::reference(ctx, BindId::new(), self.etyp.clone(), self.top_id);
725 let fnode =
726 genn::reference(ctx, self.fid, Type::Fn(self.mftype.clone()), self.top_id);
727 n = genn::apply(fnode, self.scope.clone(), vec![n, x], &self.mftype, self.top_id);
728 let r = n.typecheck(ctx);
729 n.delete(ctx);
730 r
731 }
732
733 fn refs(&self, refs: &mut Refs) {
734 for n in &self.nodes {
735 n.refs(refs)
736 }
737 }
738
739 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
740 let i =
741 iter::once(&self.initid).chain(self.binds.iter()).chain(self.initids.iter());
742 for id in i {
743 ctx.cached.remove(id);
744 }
745 for n in &mut self.nodes {
746 n.delete(ctx);
747 }
748 }
749
750 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
751 self.init = None;
752 for v in &mut self.inits {
753 *v = None
754 }
755 for n in &mut self.nodes {
756 n.sleep(ctx)
757 }
758 }
759}
760
761#[derive(Debug)]
764struct IsErr;
765
766impl<R: Rt, E: UserEvent> BuiltIn<R, E> for IsErr {
767 const NAME: &str = "core_is_err";
768 deftype!("fn(Any) -> bool");
769
770 fn init<'a, 'b, 'c>(
771 _ctx: &'a mut ExecCtx<R, E>,
772 _typ: &'a graphix_compiler::typ::FnType,
773 _scope: &'b Scope,
774 _from: &'c [Node<R, E>],
775 _top_id: ExprId,
776 ) -> Result<Box<dyn Apply<R, E>>> {
777 Ok(Box::new(IsErr))
778 }
779}
780
781impl<R: Rt, E: UserEvent> Apply<R, E> for IsErr {
782 fn update(
783 &mut self,
784 ctx: &mut ExecCtx<R, E>,
785 from: &mut [Node<R, E>],
786 event: &mut Event<E>,
787 ) -> Option<Value> {
788 from[0].update(ctx, event).map(|v| match v {
789 Value::Error(_) => Value::Bool(true),
790 _ => Value::Bool(false),
791 })
792 }
793
794 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
795}
796
797#[derive(Debug)]
798struct FilterErr;
799
800impl<R: Rt, E: UserEvent> BuiltIn<R, E> for FilterErr {
801 const NAME: &str = "core_filter_err";
802 deftype!("fn(Result<'a, 'b>) -> Error<'b>");
803
804 fn init<'a, 'b, 'c>(
805 _ctx: &'a mut ExecCtx<R, E>,
806 _typ: &'a graphix_compiler::typ::FnType,
807 _scope: &'b Scope,
808 _from: &'c [Node<R, E>],
809 _top_id: ExprId,
810 ) -> Result<Box<dyn Apply<R, E>>> {
811 Ok(Box::new(FilterErr))
812 }
813}
814
815impl<R: Rt, E: UserEvent> Apply<R, E> for FilterErr {
816 fn update(
817 &mut self,
818 ctx: &mut ExecCtx<R, E>,
819 from: &mut [Node<R, E>],
820 event: &mut Event<E>,
821 ) -> Option<Value> {
822 from[0].update(ctx, event).and_then(|v| match v {
823 v @ Value::Error(_) => Some(v),
824 _ => None,
825 })
826 }
827
828 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
829}
830
831#[derive(Debug)]
832struct ToError;
833
834impl<R: Rt, E: UserEvent> BuiltIn<R, E> for ToError {
835 const NAME: &str = "core_error";
836 deftype!("fn('a) -> Error<'a>");
837
838 fn init<'a, 'b, 'c>(
839 _ctx: &'a mut ExecCtx<R, E>,
840 _typ: &'a graphix_compiler::typ::FnType,
841 _scope: &'b Scope,
842 _from: &'c [Node<R, E>],
843 _top_id: ExprId,
844 ) -> Result<Box<dyn Apply<R, E>>> {
845 Ok(Box::new(ToError))
846 }
847}
848
849impl<R: Rt, E: UserEvent> Apply<R, E> for ToError {
850 fn update(
851 &mut self,
852 ctx: &mut ExecCtx<R, E>,
853 from: &mut [Node<R, E>],
854 event: &mut Event<E>,
855 ) -> Option<Value> {
856 from[0].update(ctx, event).map(|e| Value::Error(triomphe::Arc::new(e)))
857 }
858
859 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
860}
861
862#[derive(Debug)]
863struct Once {
864 val: bool,
865}
866
867impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Once {
868 const NAME: &str = "core_once";
869 deftype!("fn('a) -> 'a");
870
871 fn init<'a, 'b, 'c>(
872 _ctx: &'a mut ExecCtx<R, E>,
873 _typ: &'a graphix_compiler::typ::FnType,
874 _scope: &'b Scope,
875 _from: &'c [Node<R, E>],
876 _top_id: ExprId,
877 ) -> Result<Box<dyn Apply<R, E>>> {
878 Ok(Box::new(Once { val: false }))
879 }
880}
881
882impl<R: Rt, E: UserEvent> Apply<R, E> for Once {
883 fn update(
884 &mut self,
885 ctx: &mut ExecCtx<R, E>,
886 from: &mut [Node<R, E>],
887 event: &mut Event<E>,
888 ) -> Option<Value> {
889 match from {
890 [s] => s.update(ctx, event).and_then(|v| {
891 if self.val {
892 None
893 } else {
894 self.val = true;
895 Some(v)
896 }
897 }),
898 _ => None,
899 }
900 }
901
902 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
903 self.val = false
904 }
905}
906
907#[derive(Debug)]
908struct Take {
909 n: Option<usize>,
910}
911
912impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Take {
913 const NAME: &str = "core_take";
914 deftype!("fn(#n:Any, 'a) -> 'a");
915
916 fn init<'a, 'b, 'c>(
917 _ctx: &'a mut ExecCtx<R, E>,
918 _typ: &'a graphix_compiler::typ::FnType,
919 _scope: &'b Scope,
920 _from: &'c [Node<R, E>],
921 _top_id: ExprId,
922 ) -> Result<Box<dyn Apply<R, E>>> {
923 Ok(Box::new(Take { n: None }))
924 }
925}
926
927impl<R: Rt, E: UserEvent> Apply<R, E> for Take {
928 fn update(
929 &mut self,
930 ctx: &mut ExecCtx<R, E>,
931 from: &mut [Node<R, E>],
932 event: &mut Event<E>,
933 ) -> Option<Value> {
934 if let Some(n) =
935 from[0].update(ctx, event).and_then(|v| v.cast_to::<usize>().ok())
936 {
937 self.n = Some(n)
938 }
939 match from[1].update(ctx, event) {
940 None => None,
941 Some(v) => match &mut self.n {
942 None => None,
943 Some(n) if *n > 0 => {
944 *n -= 1;
945 return Some(v);
946 }
947 Some(_) => None,
948 },
949 }
950 }
951
952 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
953 self.n = None
954 }
955}
956
957#[derive(Debug)]
958struct Skip {
959 n: Option<usize>,
960}
961
962impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Skip {
963 const NAME: &str = "core_skip";
964 deftype!("fn(#n:Any, 'a) -> 'a");
965
966 fn init<'a, 'b, 'c>(
967 _ctx: &'a mut ExecCtx<R, E>,
968 _typ: &'a graphix_compiler::typ::FnType,
969 _scope: &'b Scope,
970 _from: &'c [Node<R, E>],
971 _top_id: ExprId,
972 ) -> Result<Box<dyn Apply<R, E>>> {
973 Ok(Box::new(Skip { n: None }))
974 }
975}
976
977impl<R: Rt, E: UserEvent> Apply<R, E> for Skip {
978 fn update(
979 &mut self,
980 ctx: &mut ExecCtx<R, E>,
981 from: &mut [Node<R, E>],
982 event: &mut Event<E>,
983 ) -> Option<Value> {
984 if let Some(n) =
985 from[0].update(ctx, event).and_then(|v| v.cast_to::<usize>().ok())
986 {
987 self.n = Some(n)
988 }
989 match from[1].update(ctx, event) {
990 None => None,
991 Some(v) => match &mut self.n {
992 None => Some(v),
993 Some(n) if *n > 0 => {
994 *n -= 1;
995 None
996 }
997 Some(_) => Some(v),
998 },
999 }
1000 }
1001
1002 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1003 self.n = None
1004 }
1005}
1006
1007#[derive(Debug, Default)]
1008struct AllEv;
1009
1010impl EvalCached for AllEv {
1011 const NAME: &str = "core_all";
1012 deftype!("fn(@args: Any) -> Any");
1013
1014 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1015 match &*from.0 {
1016 [] => None,
1017 [hd, tl @ ..] => match hd {
1018 None => None,
1019 v @ Some(_) => {
1020 if tl.into_iter().all(|v1| v1 == v) {
1021 v.clone()
1022 } else {
1023 None
1024 }
1025 }
1026 },
1027 }
1028 }
1029}
1030
1031type All = CachedArgs<AllEv>;
1032
1033fn add_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1034 match (lhs, rhs) {
1035 (None, None) | (Some(_), None) => None,
1036 (None, r @ Some(_)) => r,
1037 (Some(l), Some(r)) => Some(l + r),
1038 }
1039}
1040
1041#[derive(Debug, Default)]
1042struct SumEv;
1043
1044impl EvalCached for SumEv {
1045 const NAME: &str = "core_sum";
1046 deftype!("fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
1047
1048 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1049 from.flat_iter().fold(None, |res, v| match res {
1050 res @ Some(Value::Error(_)) => res,
1051 res => add_vals(res, v.clone()),
1052 })
1053 }
1054}
1055
1056type Sum = CachedArgs<SumEv>;
1057
1058#[derive(Debug, Default)]
1059struct ProductEv;
1060
1061fn prod_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1062 match (lhs, rhs) {
1063 (None, None) | (Some(_), None) => None,
1064 (None, r @ Some(_)) => r,
1065 (Some(l), Some(r)) => Some(l * r),
1066 }
1067}
1068
1069impl EvalCached for ProductEv {
1070 const NAME: &str = "core_product";
1071 deftype!("fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
1072
1073 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1074 from.flat_iter().fold(None, |res, v| match res {
1075 res @ Some(Value::Error(_)) => res,
1076 res => prod_vals(res, v.clone()),
1077 })
1078 }
1079}
1080
1081type Product = CachedArgs<ProductEv>;
1082
1083#[derive(Debug, Default)]
1084struct DivideEv;
1085
1086fn div_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1087 match (lhs, rhs) {
1088 (None, None) | (Some(_), None) => None,
1089 (None, r @ Some(_)) => r,
1090 (Some(l), Some(r)) => Some(l / r),
1091 }
1092}
1093
1094impl EvalCached for DivideEv {
1095 const NAME: &str = "core_divide";
1096 deftype!("fn(@args: [Number, Array<[Number, Array<Number>]>]) -> Number");
1097
1098 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1099 from.flat_iter().fold(None, |res, v| match res {
1100 res @ Some(Value::Error(_)) => res,
1101 res => div_vals(res, v.clone()),
1102 })
1103 }
1104}
1105
1106type Divide = CachedArgs<DivideEv>;
1107
1108#[derive(Debug, Default)]
1109struct MinEv;
1110
1111impl EvalCached for MinEv {
1112 const NAME: &str = "core_min";
1113 deftype!("fn('a, @args:'a) -> 'a");
1114
1115 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1116 let mut res = None;
1117 for v in from.flat_iter() {
1118 match (res, v) {
1119 (None, None) | (Some(_), None) => return None,
1120 (None, Some(v)) => {
1121 res = Some(v);
1122 }
1123 (Some(v0), Some(v)) => {
1124 res = if v < v0 { Some(v) } else { Some(v0) };
1125 }
1126 }
1127 }
1128 res
1129 }
1130}
1131
1132type Min = CachedArgs<MinEv>;
1133
1134#[derive(Debug, Default)]
1135struct MaxEv;
1136
1137impl EvalCached for MaxEv {
1138 const NAME: &str = "core_max";
1139 deftype!("fn('a, @args: 'a) -> 'a");
1140
1141 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1142 let mut res = None;
1143 for v in from.flat_iter() {
1144 match (res, v) {
1145 (None, None) | (Some(_), None) => return None,
1146 (None, Some(v)) => {
1147 res = Some(v);
1148 }
1149 (Some(v0), Some(v)) => {
1150 res = if v > v0 { Some(v) } else { Some(v0) };
1151 }
1152 }
1153 }
1154 res
1155 }
1156}
1157
1158type Max = CachedArgs<MaxEv>;
1159
1160#[derive(Debug, Default)]
1161struct AndEv;
1162
1163impl EvalCached for AndEv {
1164 const NAME: &str = "core_and";
1165 deftype!("fn(@args: bool) -> bool");
1166
1167 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1168 let mut res = Some(Value::Bool(true));
1169 for v in from.flat_iter() {
1170 match v {
1171 None => return None,
1172 Some(Value::Bool(true)) => (),
1173 Some(_) => {
1174 res = Some(Value::Bool(false));
1175 }
1176 }
1177 }
1178 res
1179 }
1180}
1181
1182type And = CachedArgs<AndEv>;
1183
1184#[derive(Debug, Default)]
1185struct OrEv;
1186
1187impl EvalCached for OrEv {
1188 const NAME: &str = "core_or";
1189 deftype!("fn(@args: bool) -> bool");
1190
1191 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1192 let mut res = Some(Value::Bool(false));
1193 for v in from.flat_iter() {
1194 match v {
1195 None => return None,
1196 Some(Value::Bool(true)) => {
1197 res = Some(Value::Bool(true));
1198 }
1199 Some(_) => (),
1200 }
1201 }
1202 res
1203 }
1204}
1205
1206type Or = CachedArgs<OrEv>;
1207
1208#[derive(Debug)]
1209struct Filter<R: Rt, E: UserEvent> {
1210 ready: bool,
1211 queue: VecDeque<Value>,
1212 pred: Node<R, E>,
1213 top_id: ExprId,
1214 fid: BindId,
1215 x: BindId,
1216 out: BindId,
1217}
1218
1219impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Filter<R, E> {
1220 const NAME: &str = "core_filter";
1221 deftype!("fn('a, fn('a) -> bool throws 'e) -> 'a throws 'e");
1222
1223 fn init<'a, 'b, 'c>(
1224 ctx: &'a mut ExecCtx<R, E>,
1225 typ: &'a graphix_compiler::typ::FnType,
1226 scope: &'b Scope,
1227 from: &'c [Node<R, E>],
1228 top_id: ExprId,
1229 ) -> Result<Box<dyn Apply<R, E>>> {
1230 match from {
1231 [_, _] => {
1232 let (x, xn) =
1233 genn::bind(ctx, &scope.lexical, "x", typ.args[0].typ.clone(), top_id);
1234 let fid = BindId::new();
1235 let ptyp = match &typ.args[1].typ {
1236 Type::Fn(ft) => ft.clone(),
1237 t => bail!("expected a function not {t}"),
1238 };
1239 let fnode = genn::reference(ctx, fid, Type::Fn(ptyp.clone()), top_id);
1240 let pred = genn::apply(fnode, scope.clone(), vec![xn], &ptyp, top_id);
1241 let queue = VecDeque::new();
1242 let out = BindId::new();
1243 ctx.rt.ref_var(out, top_id);
1244 Ok(Box::new(Self { ready: true, queue, pred, fid, x, out, top_id }))
1245 }
1246 _ => bail!("expected two arguments"),
1247 }
1248 }
1249}
1250
1251impl<R: Rt, E: UserEvent> Apply<R, E> for Filter<R, E> {
1252 fn update(
1253 &mut self,
1254 ctx: &mut ExecCtx<R, E>,
1255 from: &mut [Node<R, E>],
1256 event: &mut Event<E>,
1257 ) -> Option<Value> {
1258 macro_rules! set {
1259 ($v:expr) => {{
1260 self.ready = false;
1261 ctx.cached.insert(self.x, $v.clone());
1262 event.variables.insert(self.x, $v);
1263 }};
1264 }
1265 macro_rules! maybe_cont {
1266 () => {{
1267 if let Some(v) = self.queue.front().cloned() {
1268 set!(v);
1269 continue;
1270 }
1271 break;
1272 }};
1273 }
1274 if let Some(v) = from[0].update(ctx, event) {
1275 self.queue.push_back(v);
1276 }
1277 if let Some(v) = from[1].update(ctx, event) {
1278 ctx.cached.insert(self.fid, v.clone());
1279 event.variables.insert(self.fid, v);
1280 }
1281 if self.ready && self.queue.len() > 0 {
1282 let v = self.queue.front().unwrap().clone();
1283 set!(v);
1284 }
1285 loop {
1286 match self.pred.update(ctx, event) {
1287 None => break,
1288 Some(v) => {
1289 self.ready = true;
1290 match v {
1291 Value::Bool(true) => {
1292 ctx.rt.set_var(self.out, self.queue.pop_front().unwrap());
1293 maybe_cont!();
1294 }
1295 _ => {
1296 let _ = self.queue.pop_front();
1297 maybe_cont!();
1298 }
1299 }
1300 }
1301 }
1302 }
1303 event.variables.get(&self.out).map(|v| v.clone())
1304 }
1305
1306 fn typecheck(
1307 &mut self,
1308 ctx: &mut ExecCtx<R, E>,
1309 _from: &mut [Node<R, E>],
1310 ) -> anyhow::Result<()> {
1311 self.pred.typecheck(ctx)
1312 }
1313
1314 fn refs(&self, refs: &mut Refs) {
1315 self.pred.refs(refs)
1316 }
1317
1318 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1319 ctx.cached.remove(&self.fid);
1320 ctx.cached.remove(&self.out);
1321 ctx.cached.remove(&self.x);
1322 ctx.env.unbind_variable(self.x);
1323 self.pred.delete(ctx);
1324 ctx.rt.unref_var(self.out, self.top_id)
1325 }
1326
1327 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1328 ctx.rt.unref_var(self.out, self.top_id);
1329 self.out = BindId::new();
1330 ctx.rt.ref_var(self.out, self.top_id);
1331 self.queue.clear();
1332 self.pred.sleep(ctx);
1333 }
1334}
1335
1336#[derive(Debug)]
1337struct Queue {
1338 triggered: usize,
1339 queue: VecDeque<Value>,
1340 id: BindId,
1341 top_id: ExprId,
1342}
1343
1344impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Queue {
1345 const NAME: &str = "core_queue";
1346 deftype!("fn(#clock:Any, 'a) -> 'a");
1347
1348 fn init<'a, 'b, 'c>(
1349 ctx: &'a mut ExecCtx<R, E>,
1350 _typ: &'a graphix_compiler::typ::FnType,
1351 _scope: &'b Scope,
1352 from: &'c [Node<R, E>],
1353 top_id: ExprId,
1354 ) -> Result<Box<dyn Apply<R, E>>> {
1355 match from {
1356 [_, _] => {
1357 let id = BindId::new();
1358 ctx.rt.ref_var(id, top_id);
1359 Ok(Box::new(Self { triggered: 0, queue: VecDeque::new(), id, top_id }))
1360 }
1361 _ => bail!("expected two arguments"),
1362 }
1363 }
1364}
1365
1366impl<R: Rt, E: UserEvent> Apply<R, E> for Queue {
1367 fn update(
1368 &mut self,
1369 ctx: &mut ExecCtx<R, E>,
1370 from: &mut [Node<R, E>],
1371 event: &mut Event<E>,
1372 ) -> Option<Value> {
1373 if from[0].update(ctx, event).is_some() {
1374 self.triggered += 1;
1375 }
1376 if let Some(v) = from[1].update(ctx, event) {
1377 self.queue.push_back(v);
1378 }
1379 while self.triggered > 0 && self.queue.len() > 0 {
1380 self.triggered -= 1;
1381 ctx.rt.set_var(self.id, self.queue.pop_front().unwrap());
1382 }
1383 event.variables.get(&self.id).cloned()
1384 }
1385
1386 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1387 ctx.rt.unref_var(self.id, self.top_id);
1388 }
1389
1390 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1391 ctx.rt.unref_var(self.id, self.top_id);
1392 self.id = BindId::new();
1393 ctx.rt.ref_var(self.id, self.top_id);
1394 self.triggered = 0;
1395 self.queue.clear();
1396 }
1397}
1398
1399#[derive(Debug)]
1400struct Hold {
1401 triggered: usize,
1402 current: Option<Value>,
1403}
1404
1405impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Hold {
1406 const NAME: &str = "core_hold";
1407 deftype!("fn(#clock:Any, 'a) -> 'a");
1408
1409 fn init<'a, 'b, 'c>(
1410 _ctx: &'a mut ExecCtx<R, E>,
1411 _typ: &'a graphix_compiler::typ::FnType,
1412 _scope: &'b Scope,
1413 from: &'c [Node<R, E>],
1414 _top_id: ExprId,
1415 ) -> Result<Box<dyn Apply<R, E>>> {
1416 match from {
1417 [_, _] => Ok(Box::new(Self { triggered: 0, current: None })),
1418 _ => bail!("expected two arguments"),
1419 }
1420 }
1421}
1422
1423impl<R: Rt, E: UserEvent> Apply<R, E> for Hold {
1424 fn update(
1425 &mut self,
1426 ctx: &mut ExecCtx<R, E>,
1427 from: &mut [Node<R, E>],
1428 event: &mut Event<E>,
1429 ) -> Option<Value> {
1430 if from[0].update(ctx, event).is_some() {
1431 self.triggered += 1;
1432 }
1433 if let Some(v) = from[1].update(ctx, event) {
1434 self.current = Some(v);
1435 }
1436 if self.triggered > 0
1437 && let Some(v) = self.current.take()
1438 {
1439 self.triggered -= 1;
1440 Some(v)
1441 } else {
1442 None
1443 }
1444 }
1445
1446 fn delete(&mut self, _: &mut ExecCtx<R, E>) {}
1447
1448 fn sleep(&mut self, _: &mut ExecCtx<R, E>) {
1449 self.triggered = 0;
1450 self.current = None;
1451 }
1452}
1453
1454#[derive(Debug)]
1455struct Seq {
1456 id: BindId,
1457 top_id: ExprId,
1458 args: CachedVals,
1459}
1460
1461impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Seq {
1462 const NAME: &str = "core_seq";
1463 deftype!("fn(i64, i64) -> Result<i64, `SeqError(string)>");
1464
1465 fn init<'a, 'b, 'c>(
1466 ctx: &'a mut ExecCtx<R, E>,
1467 _typ: &'a graphix_compiler::typ::FnType,
1468 _scope: &'b Scope,
1469 from: &'c [Node<R, E>],
1470 top_id: ExprId,
1471 ) -> Result<Box<dyn Apply<R, E>>> {
1472 let id = BindId::new();
1473 ctx.rt.ref_var(id, top_id);
1474 let args = CachedVals::new(from);
1475 Ok(Box::new(Self { id, top_id, args }))
1476 }
1477}
1478
1479impl<R: Rt, E: UserEvent> Apply<R, E> for Seq {
1480 fn update(
1481 &mut self,
1482 ctx: &mut ExecCtx<R, E>,
1483 from: &mut [Node<R, E>],
1484 event: &mut Event<E>,
1485 ) -> Option<Value> {
1486 if self.args.update(ctx, from, event) {
1487 match &self.args.0[..] {
1488 [Some(Value::I64(i)), Some(Value::I64(j))] if i <= j => {
1489 for v in *i..*j {
1490 ctx.rt.set_var(self.id, Value::I64(v));
1491 }
1492 }
1493 _ => {
1494 let e = literal!("SeqError");
1495 return Some(err!(e, "invalid args i must be <= j"));
1496 }
1497 }
1498 }
1499 event.variables.get(&self.id).cloned()
1500 }
1501
1502 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1503 ctx.rt.unref_var(self.id, self.top_id);
1504 }
1505
1506 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1507 ctx.rt.unref_var(self.id, self.top_id);
1508 self.id = BindId::new();
1509 ctx.rt.ref_var(self.id, self.top_id);
1510 }
1511}
1512
1513#[derive(Debug)]
1514struct Throttle {
1515 wait: Duration,
1516 last: Option<Instant>,
1517 tid: Option<BindId>,
1518 top_id: ExprId,
1519 args: CachedVals,
1520}
1521
1522impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Throttle {
1523 const NAME: &str = "core_throttle";
1524 deftype!("fn(?#rate:duration, 'a) -> 'a");
1525
1526 fn init<'a, 'b, 'c>(
1527 _ctx: &'a mut ExecCtx<R, E>,
1528 _typ: &'a graphix_compiler::typ::FnType,
1529 _scope: &'b Scope,
1530 from: &'c [Node<R, E>],
1531 top_id: ExprId,
1532 ) -> Result<Box<dyn Apply<R, E>>> {
1533 let args = CachedVals::new(from);
1534 Ok(Box::new(Self { wait: Duration::ZERO, last: None, tid: None, top_id, args }))
1535 }
1536}
1537
1538impl<R: Rt, E: UserEvent> Apply<R, E> for Throttle {
1539 fn update(
1540 &mut self,
1541 ctx: &mut ExecCtx<R, E>,
1542 from: &mut [Node<R, E>],
1543 event: &mut Event<E>,
1544 ) -> Option<Value> {
1545 macro_rules! maybe_schedule {
1546 ($last:expr) => {{
1547 let now = Instant::now();
1548 if now - *$last >= self.wait {
1549 *$last = now;
1550 return self.args.0[1].clone();
1551 } else {
1552 let id = BindId::new();
1553 ctx.rt.ref_var(id, self.top_id);
1554 ctx.rt.set_timer(id, self.wait - (now - *$last));
1555 self.tid = Some(id);
1556 return None;
1557 }
1558 }};
1559 }
1560 let mut up = [false; 2];
1561 self.args.update_diff(&mut up, ctx, from, event);
1562 if up[0]
1563 && let Some(Value::Duration(d)) = &self.args.0[0]
1564 {
1565 self.wait = **d;
1566 if let Some(id) = self.tid.take()
1567 && let Some(last) = &mut self.last
1568 {
1569 ctx.rt.unref_var(id, self.top_id);
1570 maybe_schedule!(last)
1571 }
1572 }
1573 if up[1] && self.tid.is_none() {
1574 match &mut self.last {
1575 Some(last) => maybe_schedule!(last),
1576 None => {
1577 self.last = Some(Instant::now());
1578 return self.args.0[1].clone();
1579 }
1580 }
1581 }
1582 if let Some(id) = self.tid
1583 && let Some(_) = event.variables.get(&id)
1584 {
1585 ctx.rt.unref_var(id, self.top_id);
1586 self.tid = None;
1587 self.last = Some(Instant::now());
1588 return self.args.0[1].clone();
1589 }
1590 None
1591 }
1592
1593 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1594 if let Some(id) = self.tid.take() {
1595 ctx.rt.unref_var(id, self.top_id);
1596 }
1597 }
1598
1599 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1600 self.delete(ctx);
1601 self.last = None;
1602 self.wait = Duration::ZERO;
1603 self.args.clear();
1604 }
1605}
1606
1607#[derive(Debug)]
1608struct Count {
1609 count: i64,
1610}
1611
1612impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Count {
1613 const NAME: &str = "core_count";
1614 deftype!("fn(Any) -> i64");
1615
1616 fn init<'a, 'b, 'c>(
1617 _ctx: &'a mut ExecCtx<R, E>,
1618 _typ: &'a graphix_compiler::typ::FnType,
1619 _scope: &'b Scope,
1620 _from: &'c [Node<R, E>],
1621 _top_id: ExprId,
1622 ) -> Result<Box<dyn Apply<R, E>>> {
1623 Ok(Box::new(Count { count: 0 }))
1624 }
1625}
1626
1627impl<R: Rt, E: UserEvent> Apply<R, E> for Count {
1628 fn update(
1629 &mut self,
1630 ctx: &mut ExecCtx<R, E>,
1631 from: &mut [Node<R, E>],
1632 event: &mut Event<E>,
1633 ) -> Option<Value> {
1634 if from.into_iter().fold(false, |u, n| u || n.update(ctx, event).is_some()) {
1635 self.count += 1;
1636 Some(Value::I64(self.count))
1637 } else {
1638 None
1639 }
1640 }
1641
1642 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1643 self.count = 0
1644 }
1645}
1646
1647#[derive(Debug, Default)]
1648struct MeanEv;
1649
1650impl EvalCached for MeanEv {
1651 const NAME: &str = "core_mean";
1652 deftype!(
1653 "fn([Number, Array<Number>], @args: [Number, Array<Number>]) -> Result<f64, `MeanError(string)>"
1654 );
1655
1656 fn eval(&mut self, from: &CachedVals) -> Option<Value> {
1657 static TAG: ArcStr = literal!("MeanError");
1658 let mut total = 0.;
1659 let mut samples = 0;
1660 let mut error = None;
1661 for v in from.flat_iter() {
1662 if let Some(v) = v {
1663 match v.cast_to::<f64>() {
1664 Err(e) => error = Some(errf!(TAG, "{e:?}")),
1665 Ok(v) => {
1666 total += v;
1667 samples += 1;
1668 }
1669 }
1670 }
1671 }
1672 if let Some(e) = error {
1673 Some(e)
1674 } else if samples == 0 {
1675 Some(err!(TAG, "mean requires at least one argument"))
1676 } else {
1677 Some(Value::F64(total / samples as f64))
1678 }
1679 }
1680}
1681
1682type Mean = CachedArgs<MeanEv>;
1683
1684#[derive(Debug)]
1685struct Uniq(Option<Value>);
1686
1687impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Uniq {
1688 const NAME: &str = "core_uniq";
1689 deftype!("fn('a) -> 'a");
1690
1691 fn init<'a, 'b, 'c>(
1692 _ctx: &'a mut ExecCtx<R, E>,
1693 _typ: &'a graphix_compiler::typ::FnType,
1694 _scope: &'b Scope,
1695 _from: &'c [Node<R, E>],
1696 _top_id: ExprId,
1697 ) -> Result<Box<dyn Apply<R, E>>> {
1698 Ok(Box::new(Uniq(None)))
1699 }
1700}
1701
1702impl<R: Rt, E: UserEvent> Apply<R, E> for Uniq {
1703 fn update(
1704 &mut self,
1705 ctx: &mut ExecCtx<R, E>,
1706 from: &mut [Node<R, E>],
1707 event: &mut Event<E>,
1708 ) -> Option<Value> {
1709 from[0].update(ctx, event).and_then(|v| {
1710 if Some(&v) != self.0.as_ref() {
1711 self.0 = Some(v.clone());
1712 Some(v)
1713 } else {
1714 None
1715 }
1716 })
1717 }
1718
1719 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1720 self.0 = None
1721 }
1722}
1723
1724#[derive(Debug)]
1725struct Never;
1726
1727impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Never {
1728 const NAME: &str = "core_never";
1729 deftype!("fn(@args: Any) -> 'a");
1730
1731 fn init<'a, 'b, 'c>(
1732 _ctx: &'a mut ExecCtx<R, E>,
1733 _typ: &'a graphix_compiler::typ::FnType,
1734 _scope: &'b Scope,
1735 _from: &'c [Node<R, E>],
1736 _top_id: ExprId,
1737 ) -> Result<Box<dyn Apply<R, E>>> {
1738 Ok(Box::new(Never))
1739 }
1740}
1741
1742impl<R: Rt, E: UserEvent> Apply<R, E> for Never {
1743 fn update(
1744 &mut self,
1745 ctx: &mut ExecCtx<R, E>,
1746 from: &mut [Node<R, E>],
1747 event: &mut Event<E>,
1748 ) -> Option<Value> {
1749 for n in from {
1750 n.update(ctx, event);
1751 }
1752 None
1753 }
1754
1755 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1756}
1757
1758#[derive(Debug, Clone, Copy)]
1759enum Level {
1760 Trace,
1761 Debug,
1762 Info,
1763 Warn,
1764 Error,
1765}
1766
1767impl FromValue for Level {
1768 fn from_value(v: Value) -> Result<Self> {
1769 match &*v.cast_to::<ArcStr>()? {
1770 "Trace" => Ok(Self::Trace),
1771 "Debug" => Ok(Self::Debug),
1772 "Info" => Ok(Self::Info),
1773 "Warn" => Ok(Self::Warn),
1774 "Error" => Ok(Self::Error),
1775 v => bail!("invalid log level {v}"),
1776 }
1777 }
1778}
1779
1780#[derive(Debug, Clone, Copy)]
1781enum LogDest {
1782 Stdout,
1783 Stderr,
1784 Log(Level),
1785}
1786
1787impl FromValue for LogDest {
1788 fn from_value(v: Value) -> Result<Self> {
1789 match &*v.clone().cast_to::<ArcStr>()? {
1790 "Stdout" => Ok(Self::Stdout),
1791 "Stderr" => Ok(Self::Stderr),
1792 _ => Ok(Self::Log(v.cast_to()?)),
1793 }
1794 }
1795}
1796
1797#[derive(Debug)]
1798struct Dbg {
1799 spec: Expr,
1800 dest: LogDest,
1801 typ: Type,
1802}
1803
1804impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Dbg {
1805 const NAME: &str = "core_dbg";
1806 deftype!("fn(?#dest:[`Stdout, `Stderr, Log], 'a) -> 'a");
1807
1808 fn init<'a, 'b, 'c>(
1809 _ctx: &'a mut ExecCtx<R, E>,
1810 _typ: &'a graphix_compiler::typ::FnType,
1811 _scope: &'b Scope,
1812 from: &'c [Node<R, E>],
1813 _top_id: ExprId,
1814 ) -> Result<Box<dyn Apply<R, E>>> {
1815 Ok(Box::new(Dbg {
1816 spec: from[1].spec().clone(),
1817 dest: LogDest::Stderr,
1818 typ: Type::Bottom,
1819 }))
1820 }
1821}
1822
1823impl<R: Rt, E: UserEvent> Apply<R, E> for Dbg {
1824 fn update(
1825 &mut self,
1826 ctx: &mut ExecCtx<R, E>,
1827 from: &mut [Node<R, E>],
1828 event: &mut Event<E>,
1829 ) -> Option<Value> {
1830 if let Some(v) = from[0].update(ctx, event)
1831 && let Ok(d) = v.cast_to::<LogDest>()
1832 {
1833 self.dest = d;
1834 }
1835 from[1].update(ctx, event).map(|v| {
1836 let tv = TVal { env: &ctx.env, typ: &self.typ, v: &v };
1837 match self.dest {
1838 LogDest::Stderr => {
1839 eprintln!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1840 }
1841 LogDest::Stdout => {
1842 println!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1843 }
1844 LogDest::Log(level) => match level {
1845 Level::Trace => {
1846 log::trace!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1847 }
1848 Level::Debug => {
1849 log::debug!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1850 }
1851 Level::Info => {
1852 log::info!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1853 }
1854 Level::Warn => {
1855 log::warn!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1856 }
1857 Level::Error => {
1858 log::error!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
1859 }
1860 },
1861 };
1862 v
1863 })
1864 }
1865
1866 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1867
1868 fn typecheck(
1869 &mut self,
1870 _ctx: &mut ExecCtx<R, E>,
1871 from: &mut [Node<R, E>],
1872 ) -> Result<()> {
1873 self.typ = from[1].typ().clone();
1874 Ok(())
1875 }
1876}
1877
1878#[derive(Debug)]
1879struct Log {
1880 scope: Scope,
1881 dest: LogDest,
1882}
1883
1884impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Log {
1885 const NAME: &str = "core_log";
1886 deftype!("fn(?#dest:Log, 'a) -> _");
1887
1888 fn init<'a, 'b, 'c>(
1889 _ctx: &'a mut ExecCtx<R, E>,
1890 _typ: &'a graphix_compiler::typ::FnType,
1891 scope: &'b Scope,
1892 _from: &'c [Node<R, E>],
1893 _top_id: ExprId,
1894 ) -> Result<Box<dyn Apply<R, E>>> {
1895 Ok(Box::new(Self { scope: scope.clone(), dest: LogDest::Stdout }))
1896 }
1897}
1898
1899impl<R: Rt, E: UserEvent> Apply<R, E> for Log {
1900 fn update(
1901 &mut self,
1902 ctx: &mut ExecCtx<R, E>,
1903 from: &mut [Node<R, E>],
1904 event: &mut Event<E>,
1905 ) -> Option<Value> {
1906 if let Some(v) = from[0].update(ctx, event)
1907 && let Ok(d) = v.cast_to::<LogDest>()
1908 {
1909 self.dest = d;
1910 }
1911 if let Some(v) = from[1].update(ctx, event) {
1912 let tv = TVal { env: &ctx.env, typ: from[1].typ(), v: &v };
1913 match self.dest {
1914 LogDest::Stdout => println!("{}: {}", self.scope.lexical, tv),
1915 LogDest::Stderr => eprintln!("{}: {}", self.scope.lexical, tv),
1916 LogDest::Log(lvl) => match lvl {
1917 Level::Trace => log::trace!("{}: {}", self.scope.lexical, tv),
1918 Level::Debug => log::debug!("{}: {}", self.scope.lexical, tv),
1919 Level::Info => log::info!("{}: {}", self.scope.lexical, tv),
1920 Level::Warn => log::warn!("{}: {}", self.scope.lexical, tv),
1921 Level::Error => log::error!("{}: {}", self.scope.lexical, tv),
1922 },
1923 }
1924 }
1925 None
1926 }
1927
1928 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1929}
1930
1931macro_rules! printfn {
1932 ($type:ident, $name:literal, $print:ident, $eprint:ident) => {
1933 #[derive(Debug)]
1934 struct $type {
1935 dest: LogDest,
1936 buf: String,
1937 }
1938
1939 impl<R: Rt, E: UserEvent> BuiltIn<R, E> for $type {
1940 const NAME: &str = $name;
1941 deftype!("fn(?#dest:Log, 'a) -> _");
1942
1943 fn init<'a, 'b, 'c>(
1944 _ctx: &'a mut ExecCtx<R, E>,
1945 _typ: &'a graphix_compiler::typ::FnType,
1946 _scope: &'b Scope,
1947 _from: &'c [Node<R, E>],
1948 _top_id: ExprId,
1949 ) -> Result<Box<dyn Apply<R, E>>> {
1950 Ok(Box::new(Self { dest: LogDest::Stdout, buf: String::new() }))
1951 }
1952 }
1953
1954 impl<R: Rt, E: UserEvent> Apply<R, E> for $type {
1955 fn update(
1956 &mut self,
1957 ctx: &mut ExecCtx<R, E>,
1958 from: &mut [Node<R, E>],
1959 event: &mut Event<E>,
1960 ) -> Option<Value> {
1961 use std::fmt::Write;
1962 if let Some(v) = from[0].update(ctx, event)
1963 && let Ok(d) = v.cast_to::<LogDest>()
1964 {
1965 self.dest = d;
1966 }
1967 if let Some(v) = from[1].update(ctx, event) {
1968 self.buf.clear();
1969 match v {
1970 Value::String(s) => write!(self.buf, "{s}"),
1971 v => write!(
1972 self.buf,
1973 "{}",
1974 TVal { env: &ctx.env, typ: &from[1].typ(), v: &v }
1975 ),
1976 }
1977 .unwrap();
1978 match self.dest {
1979 LogDest::Stdout => $print!("{}", self.buf),
1980 LogDest::Stderr => $eprint!("{}", self.buf),
1981 LogDest::Log(lvl) => match lvl {
1982 Level::Trace => log::trace!("{}", self.buf),
1983 Level::Debug => log::debug!("{}", self.buf),
1984 Level::Info => log::info!("{}", self.buf),
1985 Level::Warn => log::warn!("{}", self.buf),
1986 Level::Error => log::error!("{}", self.buf),
1987 },
1988 }
1989 }
1990 None
1991 }
1992
1993 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1994 }
1995 };
1996}
1997
1998printfn!(Print, "core_print", print, eprint);
1999printfn!(Println, "core_println", println, eprintln);
2000
2001graphix_derive::defpackage! {
2004 builtins => [
2005 IsErr,
2006 FilterErr,
2007 ToError,
2008 Once,
2009 Take,
2010 Skip,
2011 All,
2012 Sum,
2013 Product,
2014 Divide,
2015 Min,
2016 Max,
2017 And,
2018 Or,
2019 Filter as Filter<GXRt<X>, X::UserEvent>,
2020 Queue,
2021 Hold,
2022 Seq,
2023 Throttle,
2024 Count,
2025 Mean,
2026 Uniq,
2027 Never,
2028 Dbg,
2029 Log,
2030 Print,
2031 Println,
2032 ],
2033}