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, TypeRef},
13 Apply, BindId, BuiltIn, Event, ExecCtx, LambdaId, Node, Refs, Rt, Scope,
14 TypecheckPhase, UserEvent,
15};
16use graphix_rt::GXRt;
17use immutable_chunkmap::map::Map as CMap;
18use netidx::path::Path;
19use netidx::subscriber::Value;
20use netidx_core::utils::Either;
21use netidx_value::{FromValue, ValArray};
22use poolshark::local::LPooled;
23use std::{
24 any::Any,
25 collections::{hash_map::Entry, VecDeque},
26 fmt::Debug,
27 iter,
28 marker::PhantomData,
29 time::Duration,
30};
31use tokio::time::Instant;
32use triomphe::Arc as TArc;
33
34pub(crate) mod buffer;
35pub(crate) mod math;
36pub(crate) mod opt;
37pub(crate) mod queuefn;
38
39pub fn extract_cast_type(resolved_typ: Option<&FnType>) -> Option<Type> {
44 let ft = resolved_typ?;
45 let typ = match &ft.rtype {
46 Type::Ref (TypeRef { name, params, .. })
47 if Path::basename(&**name) == Some("Result") && params.len() == 2 =>
48 {
49 params[0].clone()
50 }
51 Type::Set(elements) if elements.len() == 2 => {
54 let mut success = None;
55 for elem in elements.iter() {
56 if !matches!(elem, Type::Error(_)) {
57 success = Some(elem.clone());
58 }
59 }
60 success?
61 }
62 _ => return None,
63 };
64 if typ.has_unbound() {
65 return None;
66 }
67 Some(typ)
68}
69
70#[derive(Default)]
74pub struct ProgramArgs(pub Vec<ArcStr>);
75
76#[macro_export]
81macro_rules! impl_no_pack {
82 ($t:ty) => {
83 impl ::netidx_core::pack::Pack for $t {
84 fn encoded_len(&self) -> usize {
85 0
86 }
87
88 fn encode(
89 &self,
90 _buf: &mut impl ::bytes::BufMut,
91 ) -> Result<(), ::netidx_core::pack::PackError> {
92 Err(::netidx_core::pack::PackError::Application(0))
93 }
94
95 fn decode(
96 _buf: &mut impl ::bytes::Buf,
97 ) -> Result<Self, ::netidx_core::pack::PackError> {
98 Err(::netidx_core::pack::PackError::Application(0))
99 }
100 }
101 };
102}
103
104#[macro_export]
108macro_rules! impl_abstract_arc {
109 ($name:ident, $wrapper_vis:vis static $wrapper:ident = [$($uuid:expr),* $(,)?]) => {
110 impl PartialEq for $name {
111 fn eq(&self, other: &Self) -> bool {
112 std::sync::Arc::ptr_eq(&self.inner, &other.inner)
113 }
114 }
115 impl Eq for $name {}
116 impl PartialOrd for $name {
117 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
118 Some(self.cmp(other))
119 }
120 }
121 impl Ord for $name {
122 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
123 std::sync::Arc::as_ptr(&self.inner).addr().cmp(&std::sync::Arc::as_ptr(&other.inner).addr())
124 }
125 }
126 impl std::hash::Hash for $name {
127 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
128 std::sync::Arc::as_ptr(&self.inner).hash(state)
129 }
130 }
131 $crate::impl_no_pack!($name);
132 $wrapper_vis static $wrapper: std::sync::LazyLock<
133 netidx_value::abstract_type::AbstractWrapper<$name>,
134 > = std::sync::LazyLock::new(|| {
135 let id = uuid::Uuid::from_bytes([$($uuid),*]);
136 netidx_value::Abstract::register::<$name>(id)
137 .expect(concat!("failed to register ", stringify!($name)))
138 });
139 };
140}
141
142#[macro_export]
143macro_rules! arity1 {
144 ($from:expr, $updates:expr) => {
145 match (&*$from, &*$updates) {
146 ([arg], [arg_up]) => (arg, arg_up),
147 (_, _) => unreachable!(),
148 }
149 };
150}
151
152#[macro_export]
153macro_rules! arity2 {
154 ($from:expr, $updates:expr) => {
155 match (&*$from, &*$updates) {
156 ([arg0, arg1], [arg0_up, arg1_up]) => ((arg0, arg1), (arg0_up, arg1_up)),
157 (_, _) => unreachable!(),
158 }
159 };
160}
161
162pub mod testing;
165
166pub fn is_struct(arr: &ValArray) -> bool {
171 if arr.is_empty() {
172 return false;
173 }
174 let mut prev: Option<&ArcStr> = None;
175 for v in arr.iter() {
176 match v {
177 Value::Array(pair) if pair.len() == 2 => match &pair[0] {
178 Value::String(k) => {
179 if let Some(p) = prev {
180 if k <= p {
181 return false;
182 }
183 }
184 prev = Some(k);
185 }
186 _ => return false,
187 },
188 _ => return false,
189 }
190 }
191 true
192}
193
194#[derive(Debug)]
197pub struct CachedVals(pub Box<[Option<Value>]>);
198
199impl CachedVals {
200 pub fn new<R: Rt, E: UserEvent>(from: &[Node<R, E>]) -> CachedVals {
201 CachedVals(from.into_iter().map(|_| None).collect())
202 }
203
204 pub fn clear(&mut self) {
205 for v in &mut self.0 {
206 *v = None
207 }
208 }
209
210 pub fn update<R: Rt, E: UserEvent>(
211 &mut self,
212 ctx: &mut ExecCtx<R, E>,
213 from: &mut [Node<R, E>],
214 event: &mut Event<E>,
215 ) -> bool {
216 from.into_iter().enumerate().fold(false, |res, (i, src)| {
217 match src.update(ctx, event) {
218 None => res,
219 v @ Some(_) => {
220 self.0[i] = v;
221 true
222 }
223 }
224 })
225 }
226
227 pub fn update_diff<R: Rt, E: UserEvent>(
230 &mut self,
231 up: &mut [bool],
232 ctx: &mut ExecCtx<R, E>,
233 from: &mut [Node<R, E>],
234 event: &mut Event<E>,
235 ) {
236 for (i, n) in from.iter_mut().enumerate() {
237 match n.update(ctx, event) {
238 None => (),
239 v => {
240 self.0[i] = v;
241 up[i] = true
242 }
243 }
244 }
245 }
246
247 pub fn flat_iter<'a>(&'a self) -> impl Iterator<Item = Option<Value>> + 'a {
248 self.0.iter().flat_map(|v| match v {
249 None => Either::Left(iter::once(None)),
250 Some(v) => Either::Right(v.clone().flatten().map(Some)),
251 })
252 }
253
254 pub fn get<T: FromValue>(&self, i: usize) -> Option<T> {
255 self.0.get(i).and_then(|v| v.as_ref()).and_then(|v| v.clone().cast_to::<T>().ok())
256 }
257}
258
259pub type ByRefChain = immutable_chunkmap::map::MapS<BindId, BindId>;
260
261pub trait EvalCached<R: Rt, E: UserEvent>:
262 Debug + Default + Send + Sync + 'static
263{
264 const NAME: &str;
265 const NEEDS_CALLSITE: bool;
266
267 fn init(
268 _ctx: &mut ExecCtx<R, E>,
269 _typ: &FnType,
270 _resolved: Option<&FnType>,
271 _scope: &Scope,
272 _from: &[Node<R, E>],
273 _top_id: ExprId,
274 ) -> Self {
275 Self::default()
276 }
277
278 fn eval(&mut self, ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value>;
279
280 fn typecheck(
281 &mut self,
282 _ctx: &mut ExecCtx<R, E>,
283 _from: &mut [Node<R, E>],
284 _phase: TypecheckPhase<'_>,
285 ) -> Result<()> {
286 Ok(())
287 }
288}
289
290#[derive(Debug)]
291pub struct CachedArgs<T> {
292 cached: CachedVals,
293 t: T,
294}
295
296impl<R: Rt, E: UserEvent, T: EvalCached<R, E>> BuiltIn<R, E> for CachedArgs<T> {
297 const NAME: &str = T::NAME;
298 const NEEDS_CALLSITE: bool = T::NEEDS_CALLSITE;
299
300 fn init<'a, 'b, 'c, 'd>(
301 ctx: &'a mut ExecCtx<R, E>,
302 typ: &'a graphix_compiler::typ::FnType,
303 resolved: Option<&'d FnType>,
304 scope: &'b Scope,
305 from: &'c [Node<R, E>],
306 top_id: ExprId,
307 ) -> Result<Box<dyn Apply<R, E>>> {
308 let t = CachedArgs::<T> {
309 cached: CachedVals::new(from),
310 t: T::init(ctx, typ, resolved, scope, from, top_id),
311 };
312 Ok(Box::new(t))
313 }
314}
315
316impl<R: Rt, E: UserEvent, T: EvalCached<R, E>> Apply<R, E> for CachedArgs<T> {
317 fn update(
318 &mut self,
319 ctx: &mut ExecCtx<R, E>,
320 from: &mut [Node<R, E>],
321 event: &mut Event<E>,
322 ) -> Option<Value> {
323 if self.cached.update(ctx, from, event) {
324 self.t.eval(ctx, &self.cached)
325 } else {
326 None
327 }
328 }
329
330 fn typecheck(
331 &mut self,
332 ctx: &mut ExecCtx<R, E>,
333 from: &mut [Node<R, E>],
334 phase: TypecheckPhase<'_>,
335 ) -> Result<()> {
336 self.t.typecheck(ctx, from, phase)
337 }
338
339 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
340 self.cached.clear()
341 }
342}
343
344pub trait EvalCachedAsync: Debug + Default + Send + Sync + 'static {
345 const NAME: &str;
346 const NEEDS_CALLSITE: bool;
347
348 type Args: Debug + Any + Send + Sync;
349
350 fn init<R: Rt, E: UserEvent>(
351 _ctx: &mut ExecCtx<R, E>,
352 _typ: &FnType,
353 _resolved: Option<&FnType>,
354 _scope: &Scope,
355 _from: &[Node<R, E>],
356 _top_id: ExprId,
357 ) -> Self {
358 Self::default()
359 }
360
361 fn map_value<R: Rt, E: UserEvent>(
363 &mut self,
364 _ctx: &mut ExecCtx<R, E>,
365 v: Value,
366 ) -> Option<Value> {
367 Some(v)
368 }
369
370 fn typecheck<R: Rt, E: UserEvent>(
371 &mut self,
372 _ctx: &mut ExecCtx<R, E>,
373 _from: &mut [Node<R, E>],
374 _phase: TypecheckPhase<'_>,
375 ) -> Result<()> {
376 Ok(())
377 }
378
379 fn prepare_args(&mut self, cached: &CachedVals) -> Option<Self::Args>;
380 fn eval(args: Self::Args) -> impl Future<Output = Value> + Send;
381}
382
383#[derive(Debug)]
384pub struct CachedArgsAsync<T: EvalCachedAsync> {
385 cached: CachedVals,
386 id: BindId,
387 top_id: ExprId,
388 queued: VecDeque<T::Args>,
389 running: bool,
390 t: T,
391}
392
393impl<R: Rt, E: UserEvent, T: EvalCachedAsync> BuiltIn<R, E> for CachedArgsAsync<T> {
394 const NAME: &str = T::NAME;
395 const NEEDS_CALLSITE: bool = T::NEEDS_CALLSITE;
396
397 fn init<'a, 'b, 'c, 'd>(
398 ctx: &'a mut ExecCtx<R, E>,
399 typ: &'a FnType,
400 resolved: Option<&'d FnType>,
401 scope: &'b Scope,
402 from: &'c [Node<R, E>],
403 top_id: ExprId,
404 ) -> Result<Box<dyn Apply<R, E>>> {
405 let id = BindId::new();
406 ctx.rt.ref_var(id, top_id);
407 let t = CachedArgsAsync::<T> {
408 id,
409 top_id,
410 cached: CachedVals::new(from),
411 queued: VecDeque::new(),
412 running: false,
413 t: T::init(ctx, typ, resolved, scope, from, top_id),
414 };
415 Ok(Box::new(t))
416 }
417}
418
419impl<R: Rt, E: UserEvent, T: EvalCachedAsync> Apply<R, E> for CachedArgsAsync<T> {
420 fn update(
421 &mut self,
422 ctx: &mut ExecCtx<R, E>,
423 from: &mut [Node<R, E>],
424 event: &mut Event<E>,
425 ) -> Option<Value> {
426 if self.cached.update(ctx, from, event)
427 && let Some(args) = self.t.prepare_args(&self.cached)
428 {
429 self.queued.push_back(args);
430 }
431 let res = event.variables.remove(&self.id).and_then(|v| {
432 self.running = false;
433 self.t.map_value(ctx, v)
434 });
435 if !self.running
436 && let Some(args) = self.queued.pop_front()
437 {
438 self.running = true;
439 let id = self.id;
440 ctx.rt.spawn_var(async move { (id, T::eval(args).await) });
441 }
442 res
443 }
444
445 fn typecheck(
446 &mut self,
447 ctx: &mut ExecCtx<R, E>,
448 from: &mut [Node<R, E>],
449 phase: TypecheckPhase<'_>,
450 ) -> Result<()> {
451 self.t.typecheck(ctx, from, phase)
452 }
453
454 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
455 ctx.rt.unref_var(self.id, self.top_id);
456 self.queued.clear();
457 self.cached.clear();
458 }
459
460 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
461 self.delete(ctx);
462 self.running = false;
463 let id = BindId::new();
464 ctx.rt.ref_var(id, self.top_id);
465 self.id = id;
466 }
467}
468
469pub trait MapCollection: Debug + Clone + Default + Send + Sync + 'static {
470 fn len(&self) -> usize;
472
473 fn iter_values(&self) -> impl Iterator<Item = Value>;
475
476 fn select(v: Value) -> Option<Self>;
479
480 fn project(self) -> Value;
482
483 fn etyp(ft: &FnType) -> Result<Type>;
485}
486
487impl MapCollection for ValArray {
488 fn iter_values(&self) -> impl Iterator<Item = Value> {
489 (**self).iter().cloned()
490 }
491
492 fn len(&self) -> usize {
493 (**self).len()
494 }
495
496 fn select(v: Value) -> Option<Self> {
497 match v {
498 Value::Array(a) => Some(a.clone()),
499 _ => None,
500 }
501 }
502
503 fn project(self) -> Value {
504 Value::Array(self)
505 }
506
507 fn etyp(ft: &FnType) -> Result<Type> {
508 match &ft.args[0].typ {
509 Type::Array(et) => Ok((**et).clone()),
510 _ => bail!("expected array"),
511 }
512 }
513}
514
515impl MapCollection for CMap<Value, Value, 32> {
516 fn iter_values(&self) -> impl Iterator<Item = Value> {
517 self.into_iter().map(|(k, v)| {
518 Value::Array(ValArray::from_iter_exact([k.clone(), v.clone()].into_iter()))
519 })
520 }
521
522 fn len(&self) -> usize {
523 CMap::len(self)
524 }
525
526 fn select(v: Value) -> Option<Self> {
527 match v {
528 Value::Map(m) => Some(m.clone()),
529 _ => None,
530 }
531 }
532
533 fn project(self) -> Value {
534 Value::Map(self)
535 }
536
537 fn etyp(ft: &FnType) -> Result<Type> {
538 match &ft.args[0].typ {
539 Type::Map { key, value } => {
540 Ok(Type::Tuple(TArc::from_iter([(**key).clone(), (**value).clone()])))
541 }
542 _ => bail!("expected Map, got {:?}", ft.args[0].typ),
543 }
544 }
545}
546
547pub trait MapFn<R: Rt, E: UserEvent>: Debug + Default + Send + Sync + 'static {
548 type Collection: MapCollection;
549
550 const NAME: &str;
551
552 fn finish(&mut self, slots: &[Slot<R, E>], a: &Self::Collection) -> Option<Value>;
558}
559
560#[derive(Debug)]
561pub struct Slot<R: Rt, E: UserEvent> {
562 pub id: BindId,
563 pub pred: Node<R, E>,
564 pub cur: Option<Value>,
565}
566
567impl<R: Rt, E: UserEvent> Slot<R, E> {
568 pub fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
569 self.pred.delete(ctx);
570 ctx.cached.remove(&self.id);
571 ctx.env.unbind_variable(self.id);
572 }
573}
574
575#[derive(Debug)]
576pub struct MapQ<R: Rt, E: UserEvent, T: MapFn<R, E>> {
577 scope: Scope,
578 predid: BindId,
579 top_id: ExprId,
580 mftyp: TArc<FnType>,
581 etyp: Type,
582 slots: Vec<Slot<R, E>>,
583 cur: T::Collection,
584 t: T,
585}
586
587impl<R: Rt, E: UserEvent, T: MapFn<R, E>> BuiltIn<R, E> for MapQ<R, E, T> {
588 const NAME: &str = T::NAME;
589 const NEEDS_CALLSITE: bool = false;
590
591 fn init<'a, 'b, 'c, 'd>(
592 _ctx: &'a mut ExecCtx<R, E>,
593 typ: &'a graphix_compiler::typ::FnType,
594 resolved: Option<&'d FnType>,
595 scope: &'b Scope,
596 from: &'c [Node<R, E>],
597 top_id: ExprId,
598 ) -> Result<Box<dyn Apply<R, E>>> {
599 match from {
600 [_, _] => {
601 let typ = resolved.unwrap_or(typ);
602 Ok(Box::new(Self {
603 scope: scope
604 .append(&format_compact!("fn{}", LambdaId::new().inner())),
605 predid: BindId::new(),
606 top_id,
607 etyp: T::Collection::etyp(typ)?,
608 mftyp: match &typ.args[1].typ {
609 Type::Fn(ft) => ft.clone(),
610 t => bail!("expected a function not {t}"),
611 },
612 slots: vec![],
613 cur: Default::default(),
614 t: T::default(),
615 }))
616 }
617 _ => bail!("expected two arguments"),
618 }
619 }
620}
621
622impl<R: Rt, E: UserEvent, T: MapFn<R, E>> Apply<R, E> for MapQ<R, E, T> {
623 fn update(
624 &mut self,
625 ctx: &mut ExecCtx<R, E>,
626 from: &mut [Node<R, E>],
627 event: &mut Event<E>,
628 ) -> Option<Value> {
629 let slen = self.slots.len();
630 if let Some(v) = from[1].update(ctx, event) {
631 ctx.cached.insert(self.predid, v.clone());
632 event.variables.insert(self.predid, v);
633 }
634 let (up, resized) =
635 match from[0].update(ctx, event).and_then(|v| T::Collection::select(v)) {
636 Some(a) if a.len() == slen => (Some(a), false),
637 Some(a) if a.len() < slen => {
638 while self.slots.len() > a.len() {
639 if let Some(mut s) = self.slots.pop() {
640 s.delete(ctx)
641 }
642 }
643 (Some(a), true)
644 }
645 Some(a) => {
646 while self.slots.len() < a.len() {
647 let (id, node) = genn::bind(
648 ctx,
649 &self.scope.lexical,
650 "x",
651 self.etyp.clone(),
652 self.top_id,
653 );
654 let fargs = vec![node];
655 let fnode = genn::reference(
656 ctx,
657 self.predid,
658 Type::Fn(self.mftyp.clone()),
659 self.top_id,
660 );
661 let pred = genn::apply(
662 fnode,
663 self.scope.clone(),
664 fargs,
665 &self.mftyp,
666 self.top_id,
667 );
668 self.slots.push(Slot { id, pred, cur: None });
669 }
670 (Some(a), true)
671 }
672 None => (None, false),
673 };
674 if let Some(a) = up {
675 for (s, v) in self.slots.iter().zip(a.iter_values()) {
676 ctx.cached.insert(s.id, v.clone());
677 event.variables.insert(s.id, v);
678 }
679 self.cur = a.clone();
680 if a.len() == 0 {
681 return Some(T::Collection::project(a));
682 }
683 }
684 let init = event.init;
685 let mut up = resized;
686 for (i, s) in self.slots.iter_mut().enumerate() {
687 if i == slen {
688 event.init = true;
690 if let Entry::Vacant(e) = event.variables.entry(self.predid)
691 && let Some(v) = ctx.cached.get(&self.predid)
692 {
693 e.insert(v.clone());
694 }
695 }
696 if let Some(v) = s.pred.update(ctx, event) {
697 s.cur = Some(v);
698 up = true;
699 }
700 }
701 event.init = init;
702 if up && self.slots.iter().all(|s| s.cur.is_some()) {
703 self.t.finish(&mut &self.slots, &self.cur)
704 } else {
705 None
706 }
707 }
708
709 fn typecheck(
710 &mut self,
711 ctx: &mut ExecCtx<R, E>,
712 from: &mut [Node<R, E>],
713 _phase: TypecheckPhase<'_>,
714 ) -> anyhow::Result<()> {
715 let mftyp = match &from[1].typ() {
716 Type::Fn(ft) => ft.clone(),
717 t => bail!("expected a function not {t}"),
718 };
719 let (_, node) =
720 genn::bind(ctx, &self.scope.lexical, "x", self.etyp.clone(), self.top_id);
721 let fargs = vec![node];
722 let ft = mftyp.clone();
723 let fnode = genn::reference(ctx, self.predid, Type::Fn(ft.clone()), self.top_id);
724 let mut node = genn::apply(fnode, self.scope.clone(), fargs, &ft, self.top_id);
725 node.typecheck(ctx)?;
726 node.delete(ctx);
727 Ok(())
728 }
729
730 fn refs(&self, refs: &mut Refs) {
731 for s in &self.slots {
732 s.pred.refs(refs)
733 }
734 }
735
736 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
737 ctx.cached.remove(&self.predid);
738 for sl in &mut self.slots {
739 sl.delete(ctx)
740 }
741 }
742
743 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
744 self.cur = Default::default();
745 for sl in &mut self.slots {
746 sl.cur = None;
747 sl.pred.sleep(ctx);
748 }
749 }
750}
751
752pub trait FoldFn<R: Rt, E: UserEvent>: Debug + Send + Sync + 'static {
753 type Collection: MapCollection;
754
755 const NAME: &str;
756}
757
758#[derive(Debug)]
759pub struct FoldQ<R: Rt, E: UserEvent, T: FoldFn<R, E>> {
760 top_id: ExprId,
761 fid: BindId,
762 scope: Scope,
763 binds: Vec<BindId>,
764 nodes: Vec<Node<R, E>>,
765 inits: Vec<Option<Value>>,
766 initids: Vec<BindId>,
767 initid: BindId,
768 mftype: TArc<FnType>,
769 etyp: Type,
770 ityp: Type,
771 init: Option<Value>,
772 t: PhantomData<T>,
773}
774
775impl<R: Rt, E: UserEvent, T: FoldFn<R, E>> BuiltIn<R, E> for FoldQ<R, E, T> {
776 const NAME: &str = T::NAME;
777 const NEEDS_CALLSITE: bool = false;
778
779 fn init<'a, 'b, 'c, 'd>(
780 _ctx: &'a mut ExecCtx<R, E>,
781 typ: &'a FnType,
782 resolved: Option<&'d FnType>,
783 scope: &'b Scope,
784 from: &'c [Node<R, E>],
785 top_id: ExprId,
786 ) -> Result<Box<dyn Apply<R, E>>> {
787 match from {
788 [_, _, _] => {
789 let typ = resolved.unwrap_or(typ);
790 Ok(Box::new(Self {
791 top_id,
792 scope: scope.clone(),
793 binds: vec![],
794 nodes: vec![],
795 inits: vec![],
796 initids: vec![],
797 initid: BindId::new(),
798 fid: BindId::new(),
799 etyp: T::Collection::etyp(typ)?,
800 ityp: typ.args[1].typ.clone(),
801 mftype: match &typ.args[2].typ {
802 Type::Fn(ft) => ft.clone(),
803 t => bail!("expected a function not {t}"),
804 },
805 init: None,
806 t: PhantomData,
807 }))
808 }
809 _ => bail!("expected three arguments"),
810 }
811 }
812}
813
814impl<R: Rt, E: UserEvent, T: FoldFn<R, E>> Apply<R, E> for FoldQ<R, E, T> {
815 fn update(
816 &mut self,
817 ctx: &mut ExecCtx<R, E>,
818 from: &mut [Node<R, E>],
819 event: &mut Event<E>,
820 ) -> Option<Value> {
821 let init = match from[0].update(ctx, event).and_then(|v| T::Collection::select(v))
822 {
823 None => self.nodes.len(),
824 Some(a) if a.len() == self.binds.len() => {
825 for (id, v) in self.binds.iter().zip(a.iter_values()) {
826 ctx.cached.insert(*id, v.clone());
827 event.variables.insert(*id, v.clone());
828 }
829 self.nodes.len()
830 }
831 Some(a) => {
832 let vals = a.iter_values().collect::<LPooled<Vec<Value>>>();
833 while self.binds.len() < a.len() {
834 self.binds.push(BindId::new());
835 self.inits.push(None);
836 self.initids.push(BindId::new());
837 }
838 while a.len() < self.binds.len() {
839 if let Some(id) = self.binds.pop() {
840 ctx.cached.remove(&id);
841 }
842 if let Some(id) = self.initids.pop() {
843 ctx.cached.remove(&id);
844 }
845 self.inits.pop();
846 if let Some(mut n) = self.nodes.pop() {
847 n.delete(ctx);
848 }
849 }
850 let init = self.nodes.len();
851 for i in 0..self.binds.len() {
852 ctx.cached.insert(self.binds[i], vals[i].clone());
853 event.variables.insert(self.binds[i], vals[i].clone());
854 if i >= self.nodes.len() {
855 let n = genn::reference(
856 ctx,
857 if i == 0 { self.initid } else { self.initids[i - 1] },
858 self.ityp.clone(),
859 self.top_id,
860 );
861 let x = genn::reference(
862 ctx,
863 self.binds[i],
864 self.etyp.clone(),
865 self.top_id,
866 );
867 let fnode = genn::reference(
868 ctx,
869 self.fid,
870 Type::Fn(self.mftype.clone()),
871 self.top_id,
872 );
873 let node = genn::apply(
874 fnode,
875 self.scope.clone(),
876 vec![n, x],
877 &self.mftype,
878 self.top_id,
879 );
880 self.nodes.push(node);
881 }
882 }
883 init
884 }
885 };
886 if let Some(v) = from[1].update(ctx, event) {
887 ctx.cached.insert(self.initid, v.clone());
888 event.variables.insert(self.initid, v.clone());
889 self.init = Some(v);
890 }
891 if let Some(v) = from[2].update(ctx, event) {
892 ctx.cached.insert(self.fid, v.clone());
893 event.variables.insert(self.fid, v);
894 }
895 let old_init = event.init;
896 for i in 0..self.nodes.len() {
897 if i == init {
898 event.init = true;
899 if let Some(v) = ctx.cached.get(&self.fid)
900 && let Entry::Vacant(e) = event.variables.entry(self.fid)
901 {
902 e.insert(v.clone());
903 }
904 if i == 0 {
905 if let Some(v) = self.init.as_ref()
906 && let Entry::Vacant(e) = event.variables.entry(self.initid)
907 {
908 e.insert(v.clone());
909 }
910 } else {
911 if let Some(v) = self.inits[i - 1].clone() {
912 event.variables.insert(self.initids[i - 1], v);
913 }
914 }
915 }
916 match self.nodes[i].update(ctx, event) {
917 Some(v) => {
918 ctx.cached.insert(self.initids[i], v.clone());
919 event.variables.insert(self.initids[i], v.clone());
920 self.inits[i] = Some(v);
921 }
922 None => {
923 ctx.cached.remove(&self.initids[i]);
924 event.variables.remove(&self.initids[i]);
925 self.inits[i] = None;
926 }
927 }
928 }
929 event.init = old_init;
930 self.inits.last().and_then(|v| v.clone())
931 }
932
933 fn typecheck(
934 &mut self,
935 ctx: &mut ExecCtx<R, E>,
936 _from: &mut [Node<R, E>],
937 _phase: TypecheckPhase<'_>,
938 ) -> anyhow::Result<()> {
939 let mut n = genn::reference(ctx, self.initid, self.ityp.clone(), self.top_id);
940 let x = genn::reference(ctx, BindId::new(), self.etyp.clone(), self.top_id);
941 let fnode =
942 genn::reference(ctx, self.fid, Type::Fn(self.mftype.clone()), self.top_id);
943 n = genn::apply(fnode, self.scope.clone(), vec![n, x], &self.mftype, self.top_id);
944 n.typecheck(ctx)?;
945 n.delete(ctx);
946 Ok(())
947 }
948
949 fn refs(&self, refs: &mut Refs) {
950 for n in &self.nodes {
951 n.refs(refs)
952 }
953 }
954
955 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
956 let i =
957 iter::once(&self.initid).chain(self.binds.iter()).chain(self.initids.iter());
958 for id in i {
959 ctx.cached.remove(id);
960 }
961 for n in &mut self.nodes {
962 n.delete(ctx);
963 }
964 }
965
966 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
967 self.init = None;
968 for v in &mut self.inits {
969 *v = None
970 }
971 for n in &mut self.nodes {
972 n.sleep(ctx)
973 }
974 }
975}
976
977#[derive(Debug)]
980struct IsErr;
981
982impl<R: Rt, E: UserEvent> BuiltIn<R, E> for IsErr {
983 const NAME: &str = "core_is_err";
984 const NEEDS_CALLSITE: bool = false;
985
986 fn init<'a, 'b, 'c, 'd>(
987 _ctx: &'a mut ExecCtx<R, E>,
988 _typ: &'a FnType,
989 _resolved: Option<&'d FnType>,
990 _scope: &'b Scope,
991 _from: &'c [Node<R, E>],
992 _top_id: ExprId,
993 ) -> Result<Box<dyn Apply<R, E>>> {
994 Ok(Box::new(IsErr))
995 }
996}
997
998impl<R: Rt, E: UserEvent> Apply<R, E> for IsErr {
999 fn update(
1000 &mut self,
1001 ctx: &mut ExecCtx<R, E>,
1002 from: &mut [Node<R, E>],
1003 event: &mut Event<E>,
1004 ) -> Option<Value> {
1005 from[0].update(ctx, event).map(|v| match v {
1006 Value::Error(_) => Value::Bool(true),
1007 _ => Value::Bool(false),
1008 })
1009 }
1010
1011 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1012}
1013
1014#[derive(Debug)]
1015struct FilterErr;
1016
1017impl<R: Rt, E: UserEvent> BuiltIn<R, E> for FilterErr {
1018 const NAME: &str = "core_filter_err";
1019 const NEEDS_CALLSITE: bool = false;
1020
1021 fn init<'a, 'b, 'c, 'd>(
1022 _ctx: &'a mut ExecCtx<R, E>,
1023 _typ: &'a FnType,
1024 _resolved: Option<&'d FnType>,
1025 _scope: &'b Scope,
1026 _from: &'c [Node<R, E>],
1027 _top_id: ExprId,
1028 ) -> Result<Box<dyn Apply<R, E>>> {
1029 Ok(Box::new(FilterErr))
1030 }
1031}
1032
1033impl<R: Rt, E: UserEvent> Apply<R, E> for FilterErr {
1034 fn update(
1035 &mut self,
1036 ctx: &mut ExecCtx<R, E>,
1037 from: &mut [Node<R, E>],
1038 event: &mut Event<E>,
1039 ) -> Option<Value> {
1040 from[0].update(ctx, event).and_then(|v| match v {
1041 v @ Value::Error(_) => Some(v),
1042 _ => None,
1043 })
1044 }
1045
1046 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1047}
1048
1049#[derive(Debug)]
1050struct ToError;
1051
1052impl<R: Rt, E: UserEvent> BuiltIn<R, E> for ToError {
1053 const NAME: &str = "core_error";
1054 const NEEDS_CALLSITE: bool = false;
1055
1056 fn init<'a, 'b, 'c, 'd>(
1057 _ctx: &'a mut ExecCtx<R, E>,
1058 _typ: &'a FnType,
1059 _resolved: Option<&'d FnType>,
1060 _scope: &'b Scope,
1061 _from: &'c [Node<R, E>],
1062 _top_id: ExprId,
1063 ) -> Result<Box<dyn Apply<R, E>>> {
1064 Ok(Box::new(ToError))
1065 }
1066}
1067
1068impl<R: Rt, E: UserEvent> Apply<R, E> for ToError {
1069 fn update(
1070 &mut self,
1071 ctx: &mut ExecCtx<R, E>,
1072 from: &mut [Node<R, E>],
1073 event: &mut Event<E>,
1074 ) -> Option<Value> {
1075 from[0].update(ctx, event).map(|e| Value::Error(triomphe::Arc::new(e)))
1076 }
1077
1078 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
1079}
1080
1081#[derive(Debug)]
1082struct Once {
1083 val: bool,
1084}
1085
1086impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Once {
1087 const NAME: &str = "core_once";
1088 const NEEDS_CALLSITE: bool = false;
1089
1090 fn init<'a, 'b, 'c, 'd>(
1091 _ctx: &'a mut ExecCtx<R, E>,
1092 _typ: &'a FnType,
1093 _resolved: Option<&'d FnType>,
1094 _scope: &'b Scope,
1095 _from: &'c [Node<R, E>],
1096 _top_id: ExprId,
1097 ) -> Result<Box<dyn Apply<R, E>>> {
1098 Ok(Box::new(Once { val: false }))
1099 }
1100}
1101
1102impl<R: Rt, E: UserEvent> Apply<R, E> for Once {
1103 fn update(
1104 &mut self,
1105 ctx: &mut ExecCtx<R, E>,
1106 from: &mut [Node<R, E>],
1107 event: &mut Event<E>,
1108 ) -> Option<Value> {
1109 match from {
1110 [s] => s.update(ctx, event).and_then(|v| {
1111 if self.val {
1112 None
1113 } else {
1114 self.val = true;
1115 Some(v)
1116 }
1117 }),
1118 _ => None,
1119 }
1120 }
1121
1122 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1123 self.val = false
1124 }
1125}
1126
1127#[derive(Debug)]
1128struct Take {
1129 n: Option<usize>,
1130}
1131
1132impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Take {
1133 const NAME: &str = "core_take";
1134 const NEEDS_CALLSITE: bool = false;
1135
1136 fn init<'a, 'b, 'c, 'd>(
1137 _ctx: &'a mut ExecCtx<R, E>,
1138 _typ: &'a FnType,
1139 _resolved: Option<&'d FnType>,
1140 _scope: &'b Scope,
1141 _from: &'c [Node<R, E>],
1142 _top_id: ExprId,
1143 ) -> Result<Box<dyn Apply<R, E>>> {
1144 Ok(Box::new(Take { n: None }))
1145 }
1146}
1147
1148impl<R: Rt, E: UserEvent> Apply<R, E> for Take {
1149 fn update(
1150 &mut self,
1151 ctx: &mut ExecCtx<R, E>,
1152 from: &mut [Node<R, E>],
1153 event: &mut Event<E>,
1154 ) -> Option<Value> {
1155 if let Some(n) =
1156 from[0].update(ctx, event).and_then(|v| v.cast_to::<usize>().ok())
1157 {
1158 self.n = Some(n)
1159 }
1160 match from[1].update(ctx, event) {
1161 None => None,
1162 Some(v) => match &mut self.n {
1163 None => None,
1164 Some(n) if *n > 0 => {
1165 *n -= 1;
1166 return Some(v);
1167 }
1168 Some(_) => None,
1169 },
1170 }
1171 }
1172
1173 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1174 self.n = None
1175 }
1176}
1177
1178#[derive(Debug)]
1179struct Skip {
1180 n: Option<usize>,
1181}
1182
1183impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Skip {
1184 const NAME: &str = "core_skip";
1185 const NEEDS_CALLSITE: bool = false;
1186
1187 fn init<'a, 'b, 'c, 'd>(
1188 _ctx: &'a mut ExecCtx<R, E>,
1189 _typ: &'a FnType,
1190 _resolved: Option<&'d FnType>,
1191 _scope: &'b Scope,
1192 _from: &'c [Node<R, E>],
1193 _top_id: ExprId,
1194 ) -> Result<Box<dyn Apply<R, E>>> {
1195 Ok(Box::new(Skip { n: None }))
1196 }
1197}
1198
1199impl<R: Rt, E: UserEvent> Apply<R, E> for Skip {
1200 fn update(
1201 &mut self,
1202 ctx: &mut ExecCtx<R, E>,
1203 from: &mut [Node<R, E>],
1204 event: &mut Event<E>,
1205 ) -> Option<Value> {
1206 if let Some(n) =
1207 from[0].update(ctx, event).and_then(|v| v.cast_to::<usize>().ok())
1208 {
1209 self.n = Some(n)
1210 }
1211 match from[1].update(ctx, event) {
1212 None => None,
1213 Some(v) => match &mut self.n {
1214 None => Some(v),
1215 Some(n) if *n > 0 => {
1216 *n -= 1;
1217 None
1218 }
1219 Some(_) => Some(v),
1220 },
1221 }
1222 }
1223
1224 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1225 self.n = None
1226 }
1227}
1228
1229#[derive(Debug, Default)]
1230struct AllEv;
1231
1232impl<R: Rt, E: UserEvent> EvalCached<R, E> for AllEv {
1233 const NAME: &str = "core_all";
1234 const NEEDS_CALLSITE: bool = false;
1235
1236 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1237 match &*from.0 {
1238 [] => None,
1239 [hd, tl @ ..] => match hd {
1240 None => None,
1241 v @ Some(_) => {
1242 if tl.into_iter().all(|v1| v1 == v) {
1243 v.clone()
1244 } else {
1245 None
1246 }
1247 }
1248 },
1249 }
1250 }
1251}
1252
1253type All = CachedArgs<AllEv>;
1254
1255fn add_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1256 match (lhs, rhs) {
1257 (None, None) | (Some(_), None) => None,
1258 (None, r @ Some(_)) => r,
1259 (Some(l), Some(r)) => Some(l + r),
1260 }
1261}
1262
1263#[derive(Debug, Default)]
1264struct SumEv;
1265
1266impl<R: Rt, E: UserEvent> EvalCached<R, E> for SumEv {
1267 const NAME: &str = "core_sum";
1268 const NEEDS_CALLSITE: bool = false;
1269
1270 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1271 from.flat_iter().fold(None, |res, v| match res {
1272 res @ Some(Value::Error(_)) => res,
1273 res => add_vals(res, v.clone()),
1274 })
1275 }
1276}
1277
1278type Sum = CachedArgs<SumEv>;
1279
1280#[derive(Debug, Default)]
1281struct ProductEv;
1282
1283fn prod_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1284 match (lhs, rhs) {
1285 (None, None) | (Some(_), None) => None,
1286 (None, r @ Some(_)) => r,
1287 (Some(l), Some(r)) => Some(l * r),
1288 }
1289}
1290
1291impl<R: Rt, E: UserEvent> EvalCached<R, E> for ProductEv {
1292 const NAME: &str = "core_product";
1293 const NEEDS_CALLSITE: bool = false;
1294
1295 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1296 from.flat_iter().fold(None, |res, v| match res {
1297 res @ Some(Value::Error(_)) => res,
1298 res => prod_vals(res, v.clone()),
1299 })
1300 }
1301}
1302
1303type Product = CachedArgs<ProductEv>;
1304
1305#[derive(Debug, Default)]
1306struct DivideEv;
1307
1308fn div_vals(lhs: Option<Value>, rhs: Option<Value>) -> Option<Value> {
1309 match (lhs, rhs) {
1310 (None, None) | (Some(_), None) => None,
1311 (None, r @ Some(_)) => r,
1312 (Some(l), Some(r)) => Some(l / r),
1313 }
1314}
1315
1316impl<R: Rt, E: UserEvent> EvalCached<R, E> for DivideEv {
1317 const NAME: &str = "core_divide";
1318 const NEEDS_CALLSITE: bool = false;
1319
1320 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1321 from.flat_iter().fold(None, |res, v| match res {
1322 res @ Some(Value::Error(_)) => res,
1323 res => div_vals(res, v.clone()),
1324 })
1325 }
1326}
1327
1328type Divide = CachedArgs<DivideEv>;
1329
1330#[derive(Debug, Default)]
1331struct MinEv;
1332
1333impl<R: Rt, E: UserEvent> EvalCached<R, E> for MinEv {
1334 const NAME: &str = "core_min";
1335 const NEEDS_CALLSITE: bool = false;
1336
1337 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1338 let mut res = None;
1339 for v in from.flat_iter() {
1340 match (res, v) {
1341 (None, None) | (Some(_), None) => return None,
1342 (None, Some(v)) => {
1343 res = Some(v);
1344 }
1345 (Some(v0), Some(v)) => {
1346 res = if v < v0 { Some(v) } else { Some(v0) };
1347 }
1348 }
1349 }
1350 res
1351 }
1352}
1353
1354type Min = CachedArgs<MinEv>;
1355
1356#[derive(Debug, Default)]
1357struct MaxEv;
1358
1359impl<R: Rt, E: UserEvent> EvalCached<R, E> for MaxEv {
1360 const NAME: &str = "core_max";
1361 const NEEDS_CALLSITE: bool = false;
1362
1363 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1364 let mut res = None;
1365 for v in from.flat_iter() {
1366 match (res, v) {
1367 (None, None) | (Some(_), None) => return None,
1368 (None, Some(v)) => {
1369 res = Some(v);
1370 }
1371 (Some(v0), Some(v)) => {
1372 res = if v > v0 { Some(v) } else { Some(v0) };
1373 }
1374 }
1375 }
1376 res
1377 }
1378}
1379
1380type Max = CachedArgs<MaxEv>;
1381
1382#[derive(Debug, Default)]
1383struct AndEv;
1384
1385impl<R: Rt, E: UserEvent> EvalCached<R, E> for AndEv {
1386 const NAME: &str = "core_and";
1387 const NEEDS_CALLSITE: bool = false;
1388
1389 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1390 let mut res = Some(Value::Bool(true));
1391 for v in from.flat_iter() {
1392 match v {
1393 None => return None,
1394 Some(Value::Bool(true)) => (),
1395 Some(_) => {
1396 res = Some(Value::Bool(false));
1397 }
1398 }
1399 }
1400 res
1401 }
1402}
1403
1404type And = CachedArgs<AndEv>;
1405
1406#[derive(Debug, Default)]
1407struct OrEv;
1408
1409impl<R: Rt, E: UserEvent> EvalCached<R, E> for OrEv {
1410 const NAME: &str = "core_or";
1411 const NEEDS_CALLSITE: bool = false;
1412
1413 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1414 let mut res = Some(Value::Bool(false));
1415 for v in from.flat_iter() {
1416 match v {
1417 None => return None,
1418 Some(Value::Bool(true)) => {
1419 res = Some(Value::Bool(true));
1420 }
1421 Some(_) => (),
1422 }
1423 }
1424 res
1425 }
1426}
1427
1428type Or = CachedArgs<OrEv>;
1429
1430macro_rules! int_binop {
1433 ($from:expr, $op:tt) => {
1434 match (&$from.0[0], &$from.0[1]) {
1435 (Some(Value::U8(l)), Some(Value::U8(r))) => Some(Value::U8(l $op r)),
1436 (Some(Value::I8(l)), Some(Value::I8(r))) => Some(Value::I8(l $op r)),
1437 (Some(Value::U16(l)), Some(Value::U16(r))) => Some(Value::U16(l $op r)),
1438 (Some(Value::I16(l)), Some(Value::I16(r))) => Some(Value::I16(l $op r)),
1439 (Some(Value::U32(l)), Some(Value::U32(r))) => Some(Value::U32(l $op r)),
1440 (Some(Value::V32(l)), Some(Value::V32(r))) => Some(Value::V32(l $op r)),
1441 (Some(Value::I32(l)), Some(Value::I32(r))) => Some(Value::I32(l $op r)),
1442 (Some(Value::Z32(l)), Some(Value::Z32(r))) => Some(Value::Z32(l $op r)),
1443 (Some(Value::U64(l)), Some(Value::U64(r))) => Some(Value::U64(l $op r)),
1444 (Some(Value::V64(l)), Some(Value::V64(r))) => Some(Value::V64(l $op r)),
1445 (Some(Value::I64(l)), Some(Value::I64(r))) => Some(Value::I64(l $op r)),
1446 (Some(Value::Z64(l)), Some(Value::Z64(r))) => Some(Value::Z64(l $op r)),
1447 _ => None,
1448 }
1449 };
1450}
1451
1452macro_rules! int_shift {
1453 ($from:expr, $method:ident) => {
1454 match (&$from.0[0], &$from.0[1]) {
1455 (Some(Value::U8(l)), Some(Value::U8(r))) => {
1456 Some(Value::U8(l.$method(*r as u32)))
1457 }
1458 (Some(Value::I8(l)), Some(Value::I8(r))) => {
1459 Some(Value::I8(l.$method(*r as u32)))
1460 }
1461 (Some(Value::U16(l)), Some(Value::U16(r))) => {
1462 Some(Value::U16(l.$method(*r as u32)))
1463 }
1464 (Some(Value::I16(l)), Some(Value::I16(r))) => {
1465 Some(Value::I16(l.$method(*r as u32)))
1466 }
1467 (Some(Value::U32(l)), Some(Value::U32(r))) => {
1468 Some(Value::U32(l.$method(*r as u32)))
1469 }
1470 (Some(Value::V32(l)), Some(Value::V32(r))) => {
1471 Some(Value::V32(l.$method(*r as u32)))
1472 }
1473 (Some(Value::I32(l)), Some(Value::I32(r))) => {
1474 Some(Value::I32(l.$method(*r as u32)))
1475 }
1476 (Some(Value::Z32(l)), Some(Value::Z32(r))) => {
1477 Some(Value::Z32(l.$method(*r as u32)))
1478 }
1479 (Some(Value::U64(l)), Some(Value::U64(r))) => {
1480 Some(Value::U64(l.$method(*r as u32)))
1481 }
1482 (Some(Value::V64(l)), Some(Value::V64(r))) => {
1483 Some(Value::V64(l.$method(*r as u32)))
1484 }
1485 (Some(Value::I64(l)), Some(Value::I64(r))) => {
1486 Some(Value::I64(l.$method(*r as u32)))
1487 }
1488 (Some(Value::Z64(l)), Some(Value::Z64(r))) => {
1489 Some(Value::Z64(l.$method(*r as u32)))
1490 }
1491 _ => None,
1492 }
1493 };
1494}
1495
1496#[derive(Debug, Default)]
1497struct BitAndEv;
1498
1499impl<R: Rt, E: UserEvent> EvalCached<R, E> for BitAndEv {
1500 const NAME: &str = "core_bit_and";
1501 const NEEDS_CALLSITE: bool = false;
1502
1503 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1504 int_binop!(from, &)
1505 }
1506}
1507
1508type BitAnd = CachedArgs<BitAndEv>;
1509
1510#[derive(Debug, Default)]
1511struct BitOrEv;
1512
1513impl<R: Rt, E: UserEvent> EvalCached<R, E> for BitOrEv {
1514 const NAME: &str = "core_bit_or";
1515 const NEEDS_CALLSITE: bool = false;
1516
1517 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1518 int_binop!(from, |)
1519 }
1520}
1521
1522type BitOr = CachedArgs<BitOrEv>;
1523
1524#[derive(Debug, Default)]
1525struct BitXorEv;
1526
1527impl<R: Rt, E: UserEvent> EvalCached<R, E> for BitXorEv {
1528 const NAME: &str = "core_bit_xor";
1529 const NEEDS_CALLSITE: bool = false;
1530
1531 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1532 int_binop!(from, ^)
1533 }
1534}
1535
1536type BitXor = CachedArgs<BitXorEv>;
1537
1538#[derive(Debug, Default)]
1539struct BitNotEv;
1540
1541impl<R: Rt, E: UserEvent> EvalCached<R, E> for BitNotEv {
1542 const NAME: &str = "core_bit_not";
1543 const NEEDS_CALLSITE: bool = false;
1544
1545 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1546 match &from.0[0] {
1547 Some(Value::U8(v)) => Some(Value::U8(!v)),
1548 Some(Value::I8(v)) => Some(Value::I8(!v)),
1549 Some(Value::U16(v)) => Some(Value::U16(!v)),
1550 Some(Value::I16(v)) => Some(Value::I16(!v)),
1551 Some(Value::U32(v)) => Some(Value::U32(!v)),
1552 Some(Value::V32(v)) => Some(Value::V32(!v)),
1553 Some(Value::I32(v)) => Some(Value::I32(!v)),
1554 Some(Value::Z32(v)) => Some(Value::Z32(!v)),
1555 Some(Value::U64(v)) => Some(Value::U64(!v)),
1556 Some(Value::V64(v)) => Some(Value::V64(!v)),
1557 Some(Value::I64(v)) => Some(Value::I64(!v)),
1558 Some(Value::Z64(v)) => Some(Value::Z64(!v)),
1559 _ => None,
1560 }
1561 }
1562}
1563
1564type BitNot = CachedArgs<BitNotEv>;
1565
1566#[derive(Debug, Default)]
1567struct ShlEv;
1568
1569impl<R: Rt, E: UserEvent> EvalCached<R, E> for ShlEv {
1570 const NAME: &str = "core_shl";
1571 const NEEDS_CALLSITE: bool = false;
1572
1573 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1574 int_shift!(from, wrapping_shl)
1575 }
1576}
1577
1578type Shl = CachedArgs<ShlEv>;
1579
1580#[derive(Debug, Default)]
1581struct ShrEv;
1582
1583impl<R: Rt, E: UserEvent> EvalCached<R, E> for ShrEv {
1584 const NAME: &str = "core_shr";
1585 const NEEDS_CALLSITE: bool = false;
1586
1587 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
1588 int_shift!(from, wrapping_shr)
1589 }
1590}
1591
1592type Shr = CachedArgs<ShrEv>;
1593
1594#[derive(Debug)]
1600struct Filter<R: Rt, E: UserEvent> {
1601 pred: Node<R, E>,
1602 pending: Option<Value>,
1603 fid: BindId,
1604 x: BindId,
1605}
1606
1607impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Filter<R, E> {
1608 const NAME: &str = "core_filter";
1609 const NEEDS_CALLSITE: bool = false;
1610
1611 fn init<'a, 'b, 'c, 'd>(
1612 ctx: &'a mut ExecCtx<R, E>,
1613 typ: &'a graphix_compiler::typ::FnType,
1614 resolved: Option<&'d FnType>,
1615 scope: &'b Scope,
1616 from: &'c [Node<R, E>],
1617 top_id: ExprId,
1618 ) -> Result<Box<dyn Apply<R, E>>> {
1619 match from {
1620 [_, _] => {
1621 let typ = resolved.unwrap_or(typ);
1622 let (x, xn) =
1623 genn::bind(ctx, &scope.lexical, "x", typ.args[0].typ.clone(), top_id);
1624 let fid = BindId::new();
1625 let ptyp = match &typ.args[1].typ {
1626 Type::Fn(ft) => ft.clone(),
1627 t => bail!("expected a function not {t}"),
1628 };
1629 let fnode = genn::reference(ctx, fid, Type::Fn(ptyp.clone()), top_id);
1630 let pred = genn::apply(fnode, scope.clone(), vec![xn], &ptyp, top_id);
1631 Ok(Box::new(Self { pred, pending: None, fid, x }))
1632 }
1633 _ => bail!("expected two arguments"),
1634 }
1635 }
1636}
1637
1638impl<R: Rt, E: UserEvent> Apply<R, E> for Filter<R, E> {
1639 fn update(
1640 &mut self,
1641 ctx: &mut ExecCtx<R, E>,
1642 from: &mut [Node<R, E>],
1643 event: &mut Event<E>,
1644 ) -> Option<Value> {
1645 if let Some(v) = from[1].update(ctx, event) {
1646 ctx.cached.insert(self.fid, v.clone());
1647 event.variables.insert(self.fid, v);
1648 }
1649 if let Some(v) = from[0].update(ctx, event) {
1650 self.pending = Some(v.clone());
1651 ctx.cached.insert(self.x, v.clone());
1652 event.variables.insert(self.x, v);
1653 }
1654 self.pred.update(ctx, event).and_then(|b| match b {
1655 Value::Bool(true) => self.pending.clone(),
1656 _ => None,
1657 })
1658 }
1659
1660 fn typecheck(
1661 &mut self,
1662 ctx: &mut ExecCtx<R, E>,
1663 _from: &mut [Node<R, E>],
1664 _phase: TypecheckPhase<'_>,
1665 ) -> anyhow::Result<()> {
1666 self.pred.typecheck(ctx)?;
1667 Ok(())
1668 }
1669
1670 fn refs(&self, refs: &mut Refs) {
1671 self.pred.refs(refs)
1672 }
1673
1674 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1675 ctx.cached.remove(&self.fid);
1676 ctx.cached.remove(&self.x);
1677 ctx.env.unbind_variable(self.x);
1678 self.pred.delete(ctx);
1679 }
1680
1681 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1682 self.pending = None;
1683 self.pred.sleep(ctx);
1684 }
1685}
1686
1687#[derive(Debug)]
1688struct Queue {
1689 triggered: usize,
1690 queue: VecDeque<Value>,
1691 id: BindId,
1692 top_id: ExprId,
1693}
1694
1695impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Queue {
1696 const NAME: &str = "core_queue";
1697 const NEEDS_CALLSITE: bool = false;
1698
1699 fn init<'a, 'b, 'c, 'd>(
1700 ctx: &'a mut ExecCtx<R, E>,
1701 _typ: &'a FnType,
1702 _resolved: Option<&'d FnType>,
1703 _scope: &'b Scope,
1704 from: &'c [Node<R, E>],
1705 top_id: ExprId,
1706 ) -> Result<Box<dyn Apply<R, E>>> {
1707 match from {
1708 [_, _] => {
1709 let id = BindId::new();
1710 ctx.rt.ref_var(id, top_id);
1711 Ok(Box::new(Self { triggered: 0, queue: VecDeque::new(), id, top_id }))
1712 }
1713 _ => bail!("expected two arguments"),
1714 }
1715 }
1716}
1717
1718impl<R: Rt, E: UserEvent> Apply<R, E> for Queue {
1719 fn update(
1720 &mut self,
1721 ctx: &mut ExecCtx<R, E>,
1722 from: &mut [Node<R, E>],
1723 event: &mut Event<E>,
1724 ) -> Option<Value> {
1725 if from[0].update(ctx, event).is_some() {
1726 self.triggered += 1;
1727 }
1728 if let Some(v) = from[1].update(ctx, event) {
1729 self.queue.push_back(v);
1730 }
1731 while self.triggered > 0 && self.queue.len() > 0 {
1732 self.triggered -= 1;
1733 ctx.rt.set_var(self.id, self.queue.pop_front().unwrap());
1734 }
1735 event.variables.get(&self.id).cloned()
1736 }
1737
1738 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1739 ctx.rt.unref_var(self.id, self.top_id);
1740 }
1741
1742 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1743 ctx.rt.unref_var(self.id, self.top_id);
1744 self.id = BindId::new();
1745 ctx.rt.ref_var(self.id, self.top_id);
1746 self.triggered = 0;
1747 self.queue.clear();
1748 }
1749}
1750
1751#[derive(Debug)]
1752struct Hold {
1753 triggered: usize,
1754 current: Option<Value>,
1755}
1756
1757impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Hold {
1758 const NAME: &str = "core_hold";
1759 const NEEDS_CALLSITE: bool = false;
1760
1761 fn init<'a, 'b, 'c, 'd>(
1762 _ctx: &'a mut ExecCtx<R, E>,
1763 _typ: &'a FnType,
1764 _resolved: Option<&'d FnType>,
1765 _scope: &'b Scope,
1766 from: &'c [Node<R, E>],
1767 _top_id: ExprId,
1768 ) -> Result<Box<dyn Apply<R, E>>> {
1769 match from {
1770 [_, _] => Ok(Box::new(Self { triggered: 0, current: None })),
1771 _ => bail!("expected two arguments"),
1772 }
1773 }
1774}
1775
1776impl<R: Rt, E: UserEvent> Apply<R, E> for Hold {
1777 fn update(
1778 &mut self,
1779 ctx: &mut ExecCtx<R, E>,
1780 from: &mut [Node<R, E>],
1781 event: &mut Event<E>,
1782 ) -> Option<Value> {
1783 if from[0].update(ctx, event).is_some() {
1784 self.triggered += 1;
1785 }
1786 if let Some(v) = from[1].update(ctx, event) {
1787 self.current = Some(v);
1788 }
1789 if self.triggered > 0
1790 && let Some(v) = self.current.take()
1791 {
1792 self.triggered -= 1;
1793 Some(v)
1794 } else {
1795 None
1796 }
1797 }
1798
1799 fn delete(&mut self, _: &mut ExecCtx<R, E>) {}
1800
1801 fn sleep(&mut self, _: &mut ExecCtx<R, E>) {
1802 self.triggered = 0;
1803 self.current = None;
1804 }
1805}
1806
1807#[derive(Debug)]
1808struct Seq {
1809 id: BindId,
1810 top_id: ExprId,
1811 args: CachedVals,
1812}
1813
1814impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Seq {
1815 const NAME: &str = "core_seq";
1816 const NEEDS_CALLSITE: bool = false;
1817
1818 fn init<'a, 'b, 'c, 'd>(
1819 ctx: &'a mut ExecCtx<R, E>,
1820 _typ: &'a FnType,
1821 _resolved: Option<&'d FnType>,
1822 _scope: &'b Scope,
1823 from: &'c [Node<R, E>],
1824 top_id: ExprId,
1825 ) -> Result<Box<dyn Apply<R, E>>> {
1826 let id = BindId::new();
1827 ctx.rt.ref_var(id, top_id);
1828 let args = CachedVals::new(from);
1829 Ok(Box::new(Self { id, top_id, args }))
1830 }
1831}
1832
1833impl<R: Rt, E: UserEvent> Apply<R, E> for Seq {
1834 fn update(
1835 &mut self,
1836 ctx: &mut ExecCtx<R, E>,
1837 from: &mut [Node<R, E>],
1838 event: &mut Event<E>,
1839 ) -> Option<Value> {
1840 if self.args.update(ctx, from, event) {
1841 match &self.args.0[..] {
1842 [Some(Value::I64(i)), Some(Value::I64(j))] if i <= j => {
1843 for v in *i..*j {
1844 ctx.rt.set_var(self.id, Value::I64(v));
1845 }
1846 }
1847 _ => {
1848 let e = literal!("SeqError");
1849 return Some(err!(e, "invalid args i must be <= j"));
1850 }
1851 }
1852 }
1853 event.variables.get(&self.id).cloned()
1854 }
1855
1856 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1857 ctx.rt.unref_var(self.id, self.top_id);
1858 }
1859
1860 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1861 ctx.rt.unref_var(self.id, self.top_id);
1862 self.id = BindId::new();
1863 ctx.rt.ref_var(self.id, self.top_id);
1864 }
1865}
1866
1867#[derive(Debug)]
1868struct Throttle {
1869 wait: Duration,
1870 last: Option<Instant>,
1871 tid: Option<BindId>,
1872 top_id: ExprId,
1873 args: CachedVals,
1874}
1875
1876impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Throttle {
1877 const NAME: &str = "core_throttle";
1878 const NEEDS_CALLSITE: bool = false;
1879
1880 fn init<'a, 'b, 'c, 'd>(
1881 _ctx: &'a mut ExecCtx<R, E>,
1882 _typ: &'a FnType,
1883 _resolved: Option<&'d FnType>,
1884 _scope: &'b Scope,
1885 from: &'c [Node<R, E>],
1886 top_id: ExprId,
1887 ) -> Result<Box<dyn Apply<R, E>>> {
1888 let args = CachedVals::new(from);
1889 Ok(Box::new(Self { wait: Duration::ZERO, last: None, tid: None, top_id, args }))
1890 }
1891}
1892
1893impl<R: Rt, E: UserEvent> Apply<R, E> for Throttle {
1894 fn update(
1895 &mut self,
1896 ctx: &mut ExecCtx<R, E>,
1897 from: &mut [Node<R, E>],
1898 event: &mut Event<E>,
1899 ) -> Option<Value> {
1900 macro_rules! maybe_schedule {
1901 ($last:expr) => {{
1902 let now = Instant::now();
1903 if now - *$last >= self.wait {
1904 *$last = now;
1905 return self.args.0[1].clone();
1906 } else {
1907 let id = BindId::new();
1908 ctx.rt.ref_var(id, self.top_id);
1909 ctx.rt.set_timer(id, self.wait - (now - *$last));
1910 self.tid = Some(id);
1911 return None;
1912 }
1913 }};
1914 }
1915 let mut up = [false; 2];
1916 self.args.update_diff(&mut up, ctx, from, event);
1917 if up[0]
1918 && let Some(Value::Duration(d)) = &self.args.0[0]
1919 {
1920 self.wait = **d;
1921 if let Some(id) = self.tid.take()
1922 && let Some(last) = &mut self.last
1923 {
1924 ctx.rt.unref_var(id, self.top_id);
1925 maybe_schedule!(last)
1926 }
1927 }
1928 if up[1] && self.tid.is_none() {
1929 match &mut self.last {
1930 Some(last) => maybe_schedule!(last),
1931 None => {
1932 self.last = Some(Instant::now());
1933 return self.args.0[1].clone();
1934 }
1935 }
1936 }
1937 if let Some(id) = self.tid
1938 && let Some(_) = event.variables.get(&id)
1939 {
1940 ctx.rt.unref_var(id, self.top_id);
1941 self.tid = None;
1942 self.last = Some(Instant::now());
1943 return self.args.0[1].clone();
1944 }
1945 None
1946 }
1947
1948 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1949 if let Some(id) = self.tid.take() {
1950 ctx.rt.unref_var(id, self.top_id);
1951 }
1952 }
1953
1954 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1955 self.delete(ctx);
1956 self.last = None;
1957 self.wait = Duration::ZERO;
1958 self.args.clear();
1959 }
1960}
1961
1962#[derive(Debug)]
1963struct Count {
1964 count: i64,
1965}
1966
1967impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Count {
1968 const NAME: &str = "core_count";
1969 const NEEDS_CALLSITE: bool = false;
1970
1971 fn init<'a, 'b, 'c, 'd>(
1972 _ctx: &'a mut ExecCtx<R, E>,
1973 _typ: &'a FnType,
1974 _resolved: Option<&'d FnType>,
1975 _scope: &'b Scope,
1976 _from: &'c [Node<R, E>],
1977 _top_id: ExprId,
1978 ) -> Result<Box<dyn Apply<R, E>>> {
1979 Ok(Box::new(Count { count: 0 }))
1980 }
1981}
1982
1983impl<R: Rt, E: UserEvent> Apply<R, E> for Count {
1984 fn update(
1985 &mut self,
1986 ctx: &mut ExecCtx<R, E>,
1987 from: &mut [Node<R, E>],
1988 event: &mut Event<E>,
1989 ) -> Option<Value> {
1990 if from.into_iter().fold(false, |u, n| u || n.update(ctx, event).is_some()) {
1991 self.count += 1;
1992 Some(Value::I64(self.count))
1993 } else {
1994 None
1995 }
1996 }
1997
1998 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
1999 self.count = 0
2000 }
2001}
2002
2003#[derive(Debug, Default)]
2004struct MeanEv;
2005
2006impl<R: Rt, E: UserEvent> EvalCached<R, E> for MeanEv {
2007 const NAME: &str = "core_mean";
2008 const NEEDS_CALLSITE: bool = false;
2009
2010 fn eval(&mut self, _ctx: &mut ExecCtx<R, E>, from: &CachedVals) -> Option<Value> {
2011 static TAG: ArcStr = literal!("MeanError");
2012 let mut total = 0.;
2013 let mut samples = 0;
2014 let mut error = None;
2015 for v in from.flat_iter() {
2016 if let Some(v) = v {
2017 match v.cast_to::<f64>() {
2018 Err(e) => error = Some(errf!(TAG, "{e:?}")),
2019 Ok(v) => {
2020 total += v;
2021 samples += 1;
2022 }
2023 }
2024 }
2025 }
2026 if let Some(e) = error {
2027 Some(e)
2028 } else if samples == 0 {
2029 Some(err!(TAG, "mean requires at least one argument"))
2030 } else {
2031 Some(Value::F64(total / samples as f64))
2032 }
2033 }
2034}
2035
2036type Mean = CachedArgs<MeanEv>;
2037
2038#[derive(Debug)]
2039struct Uniq(Option<Value>);
2040
2041impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Uniq {
2042 const NAME: &str = "core_uniq";
2043 const NEEDS_CALLSITE: bool = false;
2044
2045 fn init<'a, 'b, 'c, 'd>(
2046 _ctx: &'a mut ExecCtx<R, E>,
2047 _typ: &'a FnType,
2048 _resolved: Option<&'d FnType>,
2049 _scope: &'b Scope,
2050 _from: &'c [Node<R, E>],
2051 _top_id: ExprId,
2052 ) -> Result<Box<dyn Apply<R, E>>> {
2053 Ok(Box::new(Uniq(None)))
2054 }
2055}
2056
2057impl<R: Rt, E: UserEvent> Apply<R, E> for Uniq {
2058 fn update(
2059 &mut self,
2060 ctx: &mut ExecCtx<R, E>,
2061 from: &mut [Node<R, E>],
2062 event: &mut Event<E>,
2063 ) -> Option<Value> {
2064 from[0].update(ctx, event).and_then(|v| {
2065 if Some(&v) != self.0.as_ref() {
2066 self.0 = Some(v.clone());
2067 Some(v)
2068 } else {
2069 None
2070 }
2071 })
2072 }
2073
2074 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {
2075 self.0 = None
2076 }
2077}
2078
2079#[derive(Debug)]
2080struct Never;
2081
2082impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Never {
2083 const NAME: &str = "core_never";
2084 const NEEDS_CALLSITE: bool = false;
2085
2086 fn init<'a, 'b, 'c, 'd>(
2087 _ctx: &'a mut ExecCtx<R, E>,
2088 _typ: &'a FnType,
2089 _resolved: Option<&'d FnType>,
2090 _scope: &'b Scope,
2091 _from: &'c [Node<R, E>],
2092 _top_id: ExprId,
2093 ) -> Result<Box<dyn Apply<R, E>>> {
2094 Ok(Box::new(Never))
2095 }
2096}
2097
2098impl<R: Rt, E: UserEvent> Apply<R, E> for Never {
2099 fn update(
2100 &mut self,
2101 ctx: &mut ExecCtx<R, E>,
2102 from: &mut [Node<R, E>],
2103 event: &mut Event<E>,
2104 ) -> Option<Value> {
2105 for n in from {
2106 n.update(ctx, event);
2107 }
2108 None
2109 }
2110
2111 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
2112}
2113
2114#[derive(Debug, Clone, Copy)]
2115enum Level {
2116 Trace,
2117 Debug,
2118 Info,
2119 Warn,
2120 Error,
2121}
2122
2123impl FromValue for Level {
2124 fn from_value(v: Value) -> Result<Self> {
2125 match &*v.cast_to::<ArcStr>()? {
2126 "Trace" => Ok(Self::Trace),
2127 "Debug" => Ok(Self::Debug),
2128 "Info" => Ok(Self::Info),
2129 "Warn" => Ok(Self::Warn),
2130 "Error" => Ok(Self::Error),
2131 v => bail!("invalid log level {v}"),
2132 }
2133 }
2134}
2135
2136#[derive(Debug, Clone, Copy)]
2137enum LogDest {
2138 Stdout,
2139 Stderr,
2140 Log(Level),
2141}
2142
2143impl FromValue for LogDest {
2144 fn from_value(v: Value) -> Result<Self> {
2145 match &*v.clone().cast_to::<ArcStr>()? {
2146 "Stdout" => Ok(Self::Stdout),
2147 "Stderr" => Ok(Self::Stderr),
2148 _ => Ok(Self::Log(v.cast_to()?)),
2149 }
2150 }
2151}
2152
2153#[derive(Debug)]
2154struct Dbg {
2155 spec: Expr,
2156 dest: LogDest,
2157 typ: Type,
2158}
2159
2160impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Dbg {
2161 const NAME: &str = "core_dbg";
2162 const NEEDS_CALLSITE: bool = false;
2163
2164 fn init<'a, 'b, 'c, 'd>(
2165 _ctx: &'a mut ExecCtx<R, E>,
2166 _typ: &'a graphix_compiler::typ::FnType,
2167 _resolved: Option<&'d FnType>,
2168 _scope: &'b Scope,
2169 from: &'c [Node<R, E>],
2170 _top_id: ExprId,
2171 ) -> Result<Box<dyn Apply<R, E>>> {
2172 Ok(Box::new(Dbg {
2173 spec: from[1].spec().clone(),
2174 dest: LogDest::Stderr,
2175 typ: Type::Bottom,
2176 }))
2177 }
2178}
2179
2180impl<R: Rt, E: UserEvent> Apply<R, E> for Dbg {
2181 fn update(
2182 &mut self,
2183 ctx: &mut ExecCtx<R, E>,
2184 from: &mut [Node<R, E>],
2185 event: &mut Event<E>,
2186 ) -> Option<Value> {
2187 if let Some(v) = from[0].update(ctx, event)
2188 && let Ok(d) = v.cast_to::<LogDest>()
2189 {
2190 self.dest = d;
2191 }
2192 from[1].update(ctx, event).map(|v| {
2193 let tv = TVal { env: &ctx.env, typ: &self.typ, v: &v };
2194 match self.dest {
2195 LogDest::Stderr => {
2196 eprintln!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2197 }
2198 LogDest::Stdout => {
2199 println!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2200 }
2201 LogDest::Log(level) => match level {
2202 Level::Trace => {
2203 log::trace!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2204 }
2205 Level::Debug => {
2206 log::debug!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2207 }
2208 Level::Info => {
2209 log::info!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2210 }
2211 Level::Warn => {
2212 log::warn!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2213 }
2214 Level::Error => {
2215 log::error!("{} dbg({}): {}", self.spec.pos, self.spec, tv)
2216 }
2217 },
2218 };
2219 v
2220 })
2221 }
2222
2223 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
2224
2225 fn typecheck(
2226 &mut self,
2227 _ctx: &mut ExecCtx<R, E>,
2228 from: &mut [Node<R, E>],
2229 _phase: TypecheckPhase<'_>,
2230 ) -> Result<()> {
2231 self.typ = from[1].typ().clone();
2232 Ok(())
2233 }
2234}
2235
2236#[derive(Debug)]
2237struct Log {
2238 scope: Scope,
2239 dest: LogDest,
2240}
2241
2242impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Log {
2243 const NAME: &str = "core_log";
2244 const NEEDS_CALLSITE: bool = false;
2245
2246 fn init<'a, 'b, 'c, 'd>(
2247 _ctx: &'a mut ExecCtx<R, E>,
2248 _typ: &'a graphix_compiler::typ::FnType,
2249 _resolved: Option<&'d FnType>,
2250 scope: &'b Scope,
2251 _from: &'c [Node<R, E>],
2252 _top_id: ExprId,
2253 ) -> Result<Box<dyn Apply<R, E>>> {
2254 Ok(Box::new(Self { scope: scope.clone(), dest: LogDest::Stdout }))
2255 }
2256}
2257
2258impl<R: Rt, E: UserEvent> Apply<R, E> for Log {
2259 fn update(
2260 &mut self,
2261 ctx: &mut ExecCtx<R, E>,
2262 from: &mut [Node<R, E>],
2263 event: &mut Event<E>,
2264 ) -> Option<Value> {
2265 if let Some(v) = from[0].update(ctx, event)
2266 && let Ok(d) = v.cast_to::<LogDest>()
2267 {
2268 self.dest = d;
2269 }
2270 if let Some(v) = from[1].update(ctx, event) {
2271 let tv = TVal { env: &ctx.env, typ: from[1].typ(), v: &v };
2272 match self.dest {
2273 LogDest::Stdout => println!("{}: {}", self.scope.lexical, tv),
2274 LogDest::Stderr => eprintln!("{}: {}", self.scope.lexical, tv),
2275 LogDest::Log(lvl) => match lvl {
2276 Level::Trace => log::trace!("{}: {}", self.scope.lexical, tv),
2277 Level::Debug => log::debug!("{}: {}", self.scope.lexical, tv),
2278 Level::Info => log::info!("{}: {}", self.scope.lexical, tv),
2279 Level::Warn => log::warn!("{}: {}", self.scope.lexical, tv),
2280 Level::Error => log::error!("{}: {}", self.scope.lexical, tv),
2281 },
2282 }
2283 }
2284 None
2285 }
2286
2287 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
2288}
2289
2290macro_rules! printfn {
2291 ($type:ident, $name:literal, $print:ident, $eprint:ident) => {
2292 #[derive(Debug)]
2293 struct $type {
2294 dest: LogDest,
2295 buf: String,
2296 }
2297
2298 impl<R: Rt, E: UserEvent> BuiltIn<R, E> for $type {
2299 const NAME: &str = $name;
2300 const NEEDS_CALLSITE: bool = false;
2301
2302 fn init<'a, 'b, 'c, 'd>(
2303 _ctx: &'a mut ExecCtx<R, E>,
2304 _typ: &'a graphix_compiler::typ::FnType,
2305 _resolved: Option<&'d FnType>,
2306 _scope: &'b Scope,
2307 _from: &'c [Node<R, E>],
2308 _top_id: ExprId,
2309 ) -> Result<Box<dyn Apply<R, E>>> {
2310 Ok(Box::new(Self { dest: LogDest::Stdout, buf: String::new() }))
2311 }
2312 }
2313
2314 impl<R: Rt, E: UserEvent> Apply<R, E> for $type {
2315 fn update(
2316 &mut self,
2317 ctx: &mut ExecCtx<R, E>,
2318 from: &mut [Node<R, E>],
2319 event: &mut Event<E>,
2320 ) -> Option<Value> {
2321 use std::fmt::Write;
2322 if let Some(v) = from[0].update(ctx, event)
2323 && let Ok(d) = v.cast_to::<LogDest>()
2324 {
2325 self.dest = d;
2326 }
2327 if let Some(v) = from[1].update(ctx, event) {
2328 self.buf.clear();
2329 match v {
2330 Value::String(s) => write!(self.buf, "{s}"),
2331 v => write!(
2332 self.buf,
2333 "{}",
2334 TVal { env: &ctx.env, typ: &from[1].typ(), v: &v }
2335 ),
2336 }
2337 .unwrap();
2338 match self.dest {
2339 LogDest::Stdout => $print!("{}", self.buf),
2340 LogDest::Stderr => $eprint!("{}", self.buf),
2341 LogDest::Log(lvl) => match lvl {
2342 Level::Trace => log::trace!("{}", self.buf),
2343 Level::Debug => log::debug!("{}", self.buf),
2344 Level::Info => log::info!("{}", self.buf),
2345 Level::Warn => log::warn!("{}", self.buf),
2346 Level::Error => log::error!("{}", self.buf),
2347 },
2348 }
2349 }
2350 None
2351 }
2352
2353 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
2354 }
2355 };
2356}
2357
2358printfn!(Print, "core_print", print, eprint);
2359printfn!(Println, "core_println", println, eprintln);
2360
2361graphix_derive::defpackage! {
2364 builtins => [
2365 IsErr,
2366 FilterErr,
2367 ToError,
2368 Once,
2369 Take,
2370 Skip,
2371 All,
2372 Sum,
2373 Product,
2374 Divide,
2375 Min,
2376 Max,
2377 And,
2378 Or,
2379 BitAnd,
2380 BitOr,
2381 BitXor,
2382 BitNot,
2383 Shl,
2384 Shr,
2385 Filter as Filter<GXRt<X>, X::UserEvent>,
2386 Queue,
2387 queuefn::QueueFn as queuefn::QueueFn<GXRt<X>, X::UserEvent>,
2388 Hold,
2389 Seq,
2390 Throttle,
2391 Count,
2392 Mean,
2393 Uniq,
2394 Never,
2395 Dbg,
2396 Log,
2397 Print,
2398 Println,
2399 buffer::BytesToString,
2400 buffer::BytesToStringLossy,
2401 buffer::BytesFromString,
2402 buffer::BytesConcat,
2403 buffer::BytesToArray,
2404 buffer::BytesFromArray,
2405 buffer::BytesLen,
2406 buffer::BufferEncode,
2407 buffer::BufferDecode,
2408 math::MathSin,
2409 math::MathCos,
2410 math::MathTan,
2411 math::MathAsin,
2412 math::MathAcos,
2413 math::MathAtan,
2414 math::MathAtan2,
2415 math::MathSinh,
2416 math::MathCosh,
2417 math::MathTanh,
2418 math::MathAsinh,
2419 math::MathAcosh,
2420 math::MathAtanh,
2421 math::MathExp,
2422 math::MathExp2,
2423 math::MathExpM1,
2424 math::MathLn,
2425 math::MathLn1p,
2426 math::MathLog2,
2427 math::MathLog10,
2428 math::MathLog,
2429 math::MathPow,
2430 math::MathSqrt,
2431 math::MathCbrt,
2432 math::MathHypot,
2433 math::MathFloor,
2434 math::MathCeil,
2435 math::MathRound,
2436 math::MathTrunc,
2437 math::MathFract,
2438 math::MathAbs,
2439 math::MathSignum,
2440 math::MathCopysign,
2441 math::MathMin,
2442 math::MathMax,
2443 math::MathClamp,
2444 math::MathIsNan,
2445 math::MathIsFinite,
2446 math::MathIsInfinite,
2447 math::MathToDegrees,
2448 math::MathToRadians,
2449 opt::IsSome,
2450 opt::IsNone,
2451 opt::Contains,
2452 opt::OrNever,
2453 opt::OrDefault,
2454 opt::Or,
2455 opt::And,
2456 opt::Xor,
2457 opt::OkOr,
2458 opt::Zip,
2459 opt::Unzip,
2460 opt::OptMap as opt::OptMap<GXRt<X>, X::UserEvent>,
2461 opt::OptFlatMap as opt::OptFlatMap<GXRt<X>, X::UserEvent>,
2462 opt::OptFilter as opt::OptFilter<GXRt<X>, X::UserEvent>,
2463 opt::OptOrElse as opt::OptOrElse<GXRt<X>, X::UserEvent>,
2464 opt::OptOkOrElse as opt::OptOkOrElse<GXRt<X>, X::UserEvent>,
2465 opt::OptIsSomeAnd as opt::OptIsSomeAnd<GXRt<X>, X::UserEvent>,
2466 opt::OptIsNoneOr as opt::OptIsNoneOr<GXRt<X>, X::UserEvent>,
2467 ],
2468}