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