Skip to main content

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