graphix_compiler/node/
mod.rs

1use crate::{
2    env,
3    expr::{Expr, ExprId, ExprKind, ModPath},
4    typ::{TVal, TVar, Type},
5    BindId, CFlag, Event, ExecCtx, Node, Refs, Rt, Scope, Update, UserEvent, CAST_ERR,
6};
7use anyhow::{anyhow, bail, Context, Result};
8use arcstr::{literal, ArcStr};
9use compiler::compile;
10use enumflags2::BitFlags;
11use netidx_value::{Typ, Value};
12use std::{cell::RefCell, sync::LazyLock};
13use triomphe::Arc;
14
15pub(crate) mod array;
16pub(crate) mod bind;
17pub(crate) mod callsite;
18pub(crate) mod compiler;
19pub(crate) mod data;
20pub(crate) mod error;
21pub mod genn;
22pub(crate) mod lambda;
23pub(crate) mod map;
24pub(crate) mod module;
25pub(crate) mod op;
26pub(crate) mod pattern;
27pub(crate) mod select;
28
29#[macro_export]
30macro_rules! wrap {
31    ($n:expr, $e:expr) => {
32        match $e {
33            Ok(x) => Ok(x),
34            e => {
35                anyhow::Context::context(e, $crate::expr::ErrorContext($n.spec().clone()))
36            }
37        }
38    };
39}
40
41#[macro_export]
42macro_rules! update_args {
43    ($args:expr, $ctx:expr, $event:expr) => {{
44        let mut updated = false;
45        let mut determined = true;
46        for n in $args.iter_mut() {
47            updated |= n.update($ctx, $event);
48            determined &= n.cached.is_some();
49        }
50        (updated, determined)
51    }};
52}
53
54#[macro_export]
55macro_rules! deref_typ {
56    ($name:literal, $ctx:expr, $typ:expr, $($pat:pat => $body:expr),+) => {
57        $typ.with_deref(|typ| {
58            let mut typ = typ.cloned();
59            let mut hist: poolshark::local::LPooled<fxhash::FxHashSet<usize>> = poolshark::local::LPooled::take();
60            loop {
61                match &typ {
62                    $($pat => break $body),+,
63                    Some(rt @ Type::Ref { .. }) => {
64                        let rt = rt.lookup_ref(&$ctx.env)?;
65                        if hist.insert(rt as *const _ as usize) {
66                            typ = Some(rt.clone());
67                        } else {
68                            $crate::format_with_flags(PrintFlag::DerefTVars, || {
69                                anyhow::bail!("expected {} not {rt}", $name)
70                            })?
71                        }
72                    }
73                    Some(t) => $crate::format_with_flags(PrintFlag::DerefTVars, || {
74                        anyhow::bail!("expected {} not {t}", $name)
75                    })?,
76                    None => anyhow::bail!("type must be known, annotations needed"),
77                }
78            }
79        })
80    };
81}
82
83static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
84    Arc::new(
85        ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
86    )
87});
88
89#[derive(Debug)]
90pub(crate) struct Nop {
91    pub typ: Type,
92}
93
94impl Nop {
95    pub(crate) fn new<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
96        Box::new(Nop { typ })
97    }
98}
99
100impl<R: Rt, E: UserEvent> Update<R, E> for Nop {
101    fn update(
102        &mut self,
103        _ctx: &mut ExecCtx<R, E>,
104        _event: &mut Event<E>,
105    ) -> Option<Value> {
106        None
107    }
108
109    fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
110
111    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
112
113    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
114        Ok(())
115    }
116
117    fn spec(&self) -> &Expr {
118        &NOP
119    }
120
121    fn typ(&self) -> &Type {
122        &self.typ
123    }
124
125    fn refs(&self, _refs: &mut Refs) {}
126}
127
128#[derive(Debug)]
129pub(crate) struct ExplicitParens<R: Rt, E: UserEvent> {
130    spec: Expr,
131    n: Node<R, E>,
132}
133
134impl<R: Rt, E: UserEvent> ExplicitParens<R, E> {
135    pub(crate) fn compile(
136        ctx: &mut ExecCtx<R, E>,
137        flags: BitFlags<CFlag>,
138        spec: Expr,
139        scope: &Scope,
140        top_id: ExprId,
141    ) -> Result<Node<R, E>> {
142        let n = compile(ctx, flags, spec.clone(), scope, top_id)?;
143        Ok(Box::new(ExplicitParens { spec, n }))
144    }
145}
146
147impl<R: Rt, E: UserEvent> Update<R, E> for ExplicitParens<R, E> {
148    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
149        self.n.update(ctx, event)
150    }
151
152    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
153        self.n.delete(ctx);
154    }
155
156    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
157        self.n.sleep(ctx);
158    }
159
160    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
161        self.n.typecheck(ctx)
162    }
163
164    fn spec(&self) -> &Expr {
165        &self.spec
166    }
167
168    fn typ(&self) -> &Type {
169        &self.n.typ()
170    }
171
172    fn refs(&self, refs: &mut Refs) {
173        self.n.refs(refs);
174    }
175}
176
177#[derive(Debug)]
178struct Cached<R: Rt, E: UserEvent> {
179    cached: Option<Value>,
180    node: Node<R, E>,
181}
182
183impl<R: Rt, E: UserEvent> Cached<R, E> {
184    fn new(node: Node<R, E>) -> Self {
185        Self { cached: None, node }
186    }
187
188    /// update the node, return whether the node updated. If it did,
189    /// the updated value will be stored in the cached field, if not,
190    /// the previous value will remain there.
191    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> bool {
192        match self.node.update(ctx, event) {
193            None => false,
194            Some(v) => {
195                self.cached = Some(v);
196                true
197            }
198        }
199    }
200
201    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
202        self.cached = None;
203        self.node.sleep(ctx)
204    }
205}
206
207#[derive(Debug)]
208pub(crate) struct Use {
209    spec: Expr,
210    scope: Scope,
211    name: ModPath,
212}
213
214impl Use {
215    pub(crate) fn compile<R: Rt, E: UserEvent>(
216        ctx: &mut ExecCtx<R, E>,
217        spec: Expr,
218        scope: &Scope,
219        name: &ModPath,
220    ) -> Result<Node<R, E>> {
221        ctx.env
222            .use_in_scope(scope, name)
223            .map_err(|e| anyhow!("at {} {e:?}", spec.pos))?;
224        Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
225    }
226}
227
228impl<R: Rt, E: UserEvent> Update<R, E> for Use {
229    fn update(
230        &mut self,
231        _ctx: &mut ExecCtx<R, E>,
232        _event: &mut Event<E>,
233    ) -> Option<Value> {
234        None
235    }
236
237    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
238        Ok(())
239    }
240
241    fn refs(&self, _refs: &mut Refs) {}
242
243    fn spec(&self) -> &Expr {
244        &self.spec
245    }
246
247    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
248        ctx.env.stop_use_in_scope(&self.scope, &self.name);
249    }
250
251    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
252
253    fn typ(&self) -> &Type {
254        &Type::Bottom
255    }
256}
257
258#[derive(Debug)]
259pub(crate) struct TypeDef {
260    spec: Expr,
261    scope: ModPath,
262    name: ArcStr,
263}
264
265impl TypeDef {
266    pub(crate) fn compile<R: Rt, E: UserEvent>(
267        ctx: &mut ExecCtx<R, E>,
268        spec: Expr,
269        scope: &Scope,
270        name: &ArcStr,
271        params: &Arc<[(TVar, Option<Type>)]>,
272        typ: &Type,
273    ) -> Result<Node<R, E>> {
274        let typ = typ.scope_refs(&scope.lexical);
275        ctx.env
276            .deftype(&scope.lexical, name, params.clone(), typ, None)
277            .with_context(|| format!("in typedef at {}", spec.pos))?;
278        let name = name.clone();
279        Ok(Box::new(Self { spec, scope: scope.lexical.clone(), name }))
280    }
281}
282
283impl<R: Rt, E: UserEvent> Update<R, E> for TypeDef {
284    fn update(
285        &mut self,
286        _ctx: &mut ExecCtx<R, E>,
287        _event: &mut Event<E>,
288    ) -> Option<Value> {
289        None
290    }
291
292    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
293        Ok(())
294    }
295
296    fn refs(&self, _refs: &mut Refs) {}
297
298    fn spec(&self) -> &Expr {
299        &self.spec
300    }
301
302    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
303        ctx.env.undeftype(&self.scope, &self.name)
304    }
305
306    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
307
308    fn typ(&self) -> &Type {
309        &Type::Bottom
310    }
311}
312
313#[derive(Debug)]
314pub(crate) struct Constant {
315    spec: Arc<Expr>,
316    value: Value,
317    typ: Type,
318}
319
320impl Constant {
321    pub(crate) fn compile<R: Rt, E: UserEvent>(
322        spec: Expr,
323        value: &Value,
324    ) -> Result<Node<R, E>> {
325        let spec = Arc::new(spec);
326        let value = value.clone();
327        let typ = Type::Primitive(Typ::get(&value).into());
328        Ok(Box::new(Self { spec, value, typ }))
329    }
330}
331
332impl<R: Rt, E: UserEvent> Update<R, E> for Constant {
333    fn update(
334        &mut self,
335        _ctx: &mut ExecCtx<R, E>,
336        event: &mut Event<E>,
337    ) -> Option<Value> {
338        if event.init {
339            Some(self.value.clone())
340        } else {
341            None
342        }
343    }
344
345    fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
346
347    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
348
349    fn refs(&self, _refs: &mut Refs) {}
350
351    fn typ(&self) -> &Type {
352        &self.typ
353    }
354
355    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
356        Ok(())
357    }
358
359    fn spec(&self) -> &Expr {
360        &self.spec
361    }
362}
363
364// used for both mod and do
365#[derive(Debug)]
366pub(crate) struct Block<R: Rt, E: UserEvent> {
367    module: bool,
368    spec: Expr,
369    children: Box<[Node<R, E>]>,
370}
371
372impl<R: Rt, E: UserEvent> Block<R, E> {
373    pub(crate) fn compile(
374        ctx: &mut ExecCtx<R, E>,
375        flags: BitFlags<CFlag>,
376        spec: Expr,
377        scope: &Scope,
378        top_id: ExprId,
379        module: bool,
380        exprs: &Arc<[Expr]>,
381    ) -> Result<Node<R, E>> {
382        let children = exprs
383            .iter()
384            .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
385            .collect::<Result<Box<[Node<R, E>]>>>()?;
386        Ok(Box::new(Self { module, spec, children }))
387    }
388}
389
390impl<R: Rt, E: UserEvent> Update<R, E> for Block<R, E> {
391    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
392        self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
393    }
394
395    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
396        for n in &mut self.children {
397            n.delete(ctx)
398        }
399    }
400
401    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
402        for n in &mut self.children {
403            n.sleep(ctx)
404        }
405    }
406
407    fn refs(&self, refs: &mut Refs) {
408        for n in &self.children {
409            n.refs(refs)
410        }
411    }
412
413    fn typ(&self) -> &Type {
414        &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
415    }
416
417    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
418        for n in &mut self.children {
419            if self.module {
420                wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
421            } else {
422                wrap!(n, n.typecheck(ctx))?
423            }
424        }
425        Ok(())
426    }
427
428    fn spec(&self) -> &Expr {
429        &self.spec
430    }
431}
432
433#[derive(Debug)]
434pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
435    spec: Expr,
436    typ: Type,
437    typs: Box<[Type]>,
438    args: Box<[Cached<R, E>]>,
439}
440
441impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
442    pub(crate) fn compile(
443        ctx: &mut ExecCtx<R, E>,
444        flags: BitFlags<CFlag>,
445        spec: Expr,
446        scope: &Scope,
447        top_id: ExprId,
448        args: &[Expr],
449    ) -> Result<Node<R, E>> {
450        let args: Box<[Cached<R, E>]> = args
451            .iter()
452            .map(|e| Ok(Cached::new(compile(ctx, flags, e.clone(), scope, top_id)?)))
453            .collect::<Result<_>>()?;
454        let typs = args.iter().map(|c| c.node.typ().clone()).collect();
455        let typ = Type::Primitive(Typ::String.into());
456        Ok(Box::new(Self { spec, typ, typs, args }))
457    }
458}
459
460impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
461    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
462        use std::fmt::Write;
463        thread_local! {
464            static BUF: RefCell<String> = RefCell::new(String::new());
465        }
466        let (updated, determined) = update_args!(self.args, ctx, event);
467        if updated && determined {
468            BUF.with_borrow_mut(|buf| {
469                buf.clear();
470                for (typ, c) in self.typs.iter().zip(self.args.iter()) {
471                    match c.cached.as_ref().unwrap() {
472                        Value::String(s) => write!(buf, "{s}"),
473                        v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
474                    }
475                    .unwrap()
476                }
477                Some(Value::String(buf.as_str().into()))
478            })
479        } else {
480            None
481        }
482    }
483
484    fn spec(&self) -> &Expr {
485        &self.spec
486    }
487
488    fn typ(&self) -> &Type {
489        &self.typ
490    }
491
492    fn refs(&self, refs: &mut Refs) {
493        for a in &self.args {
494            a.node.refs(refs)
495        }
496    }
497
498    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
499        for n in &mut self.args {
500            n.node.delete(ctx)
501        }
502    }
503
504    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
505        for n in &mut self.args {
506            n.sleep(ctx);
507        }
508    }
509
510    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
511        for (i, a) in self.args.iter_mut().enumerate() {
512            wrap!(a.node, a.node.typecheck(ctx))?;
513            self.typs[i] = a.node.typ().with_deref(|t| match t {
514                None => Type::Any,
515                Some(t) => t.clone(),
516            });
517        }
518        Ok(())
519    }
520}
521
522#[derive(Debug)]
523pub(crate) struct Connect<R: Rt, E: UserEvent> {
524    spec: Expr,
525    node: Node<R, E>,
526    id: BindId,
527}
528
529impl<R: Rt, E: UserEvent> Connect<R, E> {
530    pub(crate) fn compile(
531        ctx: &mut ExecCtx<R, E>,
532        flags: BitFlags<CFlag>,
533        spec: Expr,
534        scope: &Scope,
535        top_id: ExprId,
536        name: &ModPath,
537        value: &Expr,
538    ) -> Result<Node<R, E>> {
539        let id = match ctx.env.lookup_bind(&scope.lexical, name) {
540            None => bail!("at {} {name} is undefined", spec.pos),
541            Some((_, env::Bind { id, .. })) => *id,
542        };
543        let node = compile(ctx, flags, value.clone(), scope, top_id)?;
544        Ok(Box::new(Self { spec, node, id }))
545    }
546}
547
548impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
549    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
550        if let Some(v) = self.node.update(ctx, event) {
551            ctx.set_var(self.id, v)
552        }
553        None
554    }
555
556    fn spec(&self) -> &Expr {
557        &self.spec
558    }
559
560    fn typ(&self) -> &Type {
561        &Type::Bottom
562    }
563
564    fn refs(&self, refs: &mut Refs) {
565        self.node.refs(refs)
566    }
567
568    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
569        self.node.delete(ctx)
570    }
571
572    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
573        self.node.sleep(ctx);
574    }
575
576    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
577        wrap!(self.node, self.node.typecheck(ctx))?;
578        let bind = match ctx.env.by_id.get(&self.id) {
579            None => bail!("BUG missing bind {:?}", self.id),
580            Some(bind) => bind,
581        };
582        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
583    }
584}
585
586#[derive(Debug)]
587pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
588    spec: Expr,
589    rhs: Cached<R, E>,
590    src_id: BindId,
591    target_id: Option<BindId>,
592    top_id: ExprId,
593}
594
595impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
596    pub(crate) fn compile(
597        ctx: &mut ExecCtx<R, E>,
598        flags: BitFlags<CFlag>,
599        spec: Expr,
600        scope: &Scope,
601        top_id: ExprId,
602        name: &ModPath,
603        value: &Expr,
604    ) -> Result<Node<R, E>> {
605        let src_id = match ctx.env.lookup_bind(&scope.lexical, name) {
606            None => bail!("at {} {name} is undefined", spec.pos),
607            Some((_, env::Bind { id, .. })) => *id,
608        };
609        ctx.rt.ref_var(src_id, top_id);
610        let rhs = Cached::new(compile(ctx, flags, value.clone(), scope, top_id)?);
611        Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
612    }
613}
614
615impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
616    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
617        let mut up = self.rhs.update(ctx, event);
618        if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
619            if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
620                self.target_id = Some(*target_id);
621                up = true;
622            }
623        }
624        if up {
625            if let Some(v) = &self.rhs.cached {
626                if let Some(id) = self.target_id {
627                    ctx.set_var(id, v.clone());
628                }
629            }
630        }
631        None
632    }
633
634    fn spec(&self) -> &Expr {
635        &self.spec
636    }
637
638    fn typ(&self) -> &Type {
639        &Type::Bottom
640    }
641
642    fn refs(&self, refs: &mut Refs) {
643        refs.refed.insert(self.src_id);
644        self.rhs.node.refs(refs)
645    }
646
647    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
648        ctx.rt.unref_var(self.src_id, self.top_id);
649        self.rhs.node.delete(ctx)
650    }
651
652    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
653        self.rhs.sleep(ctx);
654    }
655
656    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
657        wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
658        let bind = match ctx.env.by_id.get(&self.src_id) {
659            None => bail!("BUG missing bind {:?}", self.src_id),
660            Some(bind) => bind,
661        };
662        let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
663        wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
664    }
665}
666
667#[derive(Debug)]
668pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
669    spec: Expr,
670    typ: Type,
671    target: Type,
672    n: Node<R, E>,
673}
674
675impl<R: Rt, E: UserEvent> TypeCast<R, E> {
676    pub(crate) fn compile(
677        ctx: &mut ExecCtx<R, E>,
678        flags: BitFlags<CFlag>,
679        spec: Expr,
680        scope: &Scope,
681        top_id: ExprId,
682        expr: &Expr,
683        typ: &Type,
684    ) -> Result<Node<R, E>> {
685        let n = compile(ctx, flags, expr.clone(), scope, top_id)?;
686        let target = typ.scope_refs(&scope.lexical);
687        if let Err(e) = target.check_cast(&ctx.env) {
688            bail!("in cast at {} {e}", spec.pos);
689        }
690        let typ = target.union(&ctx.env, &CAST_ERR)?;
691        Ok(Box::new(Self { spec, typ, target, n }))
692    }
693}
694
695impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
696    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
697        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
698    }
699
700    fn spec(&self) -> &Expr {
701        &self.spec
702    }
703
704    fn typ(&self) -> &Type {
705        &self.typ
706    }
707
708    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
709        self.n.delete(ctx)
710    }
711
712    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
713        self.n.sleep(ctx);
714    }
715
716    fn refs(&self, refs: &mut Refs) {
717        self.n.refs(refs)
718    }
719
720    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
721        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
722    }
723}
724
725#[derive(Debug)]
726pub(crate) struct Any<R: Rt, E: UserEvent> {
727    spec: Expr,
728    typ: Type,
729    n: Box<[Node<R, E>]>,
730}
731
732impl<R: Rt, E: UserEvent> Any<R, E> {
733    pub(crate) fn compile(
734        ctx: &mut ExecCtx<R, E>,
735        flags: BitFlags<CFlag>,
736        spec: Expr,
737        scope: &Scope,
738        top_id: ExprId,
739        args: &[Expr],
740    ) -> Result<Node<R, E>> {
741        let n = args
742            .iter()
743            .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
744            .collect::<Result<Box<[_]>>>()?;
745        Ok(Box::new(Self { spec, typ: Type::empty_tvar(), n }))
746    }
747}
748
749impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
750    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
751        self.n
752            .iter_mut()
753            .filter_map(|s| s.update(ctx, event))
754            .fold(None, |r, v| r.or(Some(v)))
755    }
756
757    fn spec(&self) -> &Expr {
758        &self.spec
759    }
760
761    fn typ(&self) -> &Type {
762        &self.typ
763    }
764
765    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
766        self.n.iter_mut().for_each(|n| n.delete(ctx))
767    }
768
769    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
770        self.n.iter_mut().for_each(|n| n.sleep(ctx))
771    }
772
773    fn refs(&self, refs: &mut Refs) {
774        self.n.iter().for_each(|n| n.refs(refs))
775    }
776
777    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
778        for n in self.n.iter_mut() {
779            wrap!(n, n.typecheck(ctx))?
780        }
781        let rtyp = Type::Bottom;
782        let rtyp = wrap!(
783            self,
784            self.n.iter().fold(Ok(rtyp), |rtype, n| rtype?.union(&ctx.env, n.typ()))
785        )?;
786        let rtyp = if rtyp == Type::Bottom { Type::empty_tvar() } else { rtyp };
787        self.typ.check_contains(&ctx.env, &rtyp)?;
788        Ok(())
789    }
790}
791
792#[derive(Debug)]
793struct Sample<R: Rt, E: UserEvent> {
794    spec: Expr,
795    triggered: usize,
796    typ: Type,
797    id: BindId,
798    top_id: ExprId,
799    trigger: Node<R, E>,
800    arg: Cached<R, E>,
801}
802
803impl<R: Rt, E: UserEvent> Sample<R, E> {
804    pub(crate) fn compile(
805        ctx: &mut ExecCtx<R, E>,
806        flags: BitFlags<CFlag>,
807        spec: Expr,
808        scope: &Scope,
809        top_id: ExprId,
810        lhs: &Arc<Expr>,
811        rhs: &Arc<Expr>,
812    ) -> Result<Node<R, E>> {
813        let id = BindId::new();
814        ctx.rt.ref_var(id, top_id);
815        let trigger = compile(ctx, flags, (**lhs).clone(), scope, top_id)?;
816        let arg = Cached::new(compile(ctx, flags, (**rhs).clone(), scope, top_id)?);
817        let typ = arg.node.typ().clone();
818        Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
819    }
820}
821
822impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
823    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
824        if let Some(_) = self.trigger.update(ctx, event) {
825            self.triggered += 1;
826        }
827        self.arg.update(ctx, event);
828        let var = event.variables.get(&self.id).cloned();
829        let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
830            self.triggered -= 1;
831            self.arg.cached.clone()
832        } else {
833            var
834        };
835        if self.arg.cached.is_some() {
836            while self.triggered > 0 {
837                self.triggered -= 1;
838                ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
839            }
840        }
841        res
842    }
843
844    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
845        ctx.rt.unref_var(self.id, self.top_id);
846        self.arg.node.delete(ctx);
847        self.trigger.delete(ctx);
848    }
849
850    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
851        self.arg.sleep(ctx);
852        self.trigger.sleep(ctx);
853    }
854
855    fn spec(&self) -> &Expr {
856        &self.spec
857    }
858
859    fn typ(&self) -> &Type {
860        &self.typ
861    }
862
863    fn refs(&self, refs: &mut Refs) {
864        refs.refed.insert(self.id);
865        self.arg.node.refs(refs);
866        self.trigger.refs(refs);
867    }
868
869    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
870        wrap!(self.trigger, self.trigger.typecheck(ctx))?;
871        wrap!(self.arg.node, self.arg.node.typecheck(ctx))
872    }
873}