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                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        let res = self.children.iter_mut().fold(None, |_, n| n.update(ctx, event));
393        if self.module {
394            None
395        } else {
396            res
397        }
398    }
399
400    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
401        for n in &mut self.children {
402            n.delete(ctx)
403        }
404    }
405
406    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
407        for n in &mut self.children {
408            n.sleep(ctx)
409        }
410    }
411
412    fn refs(&self, refs: &mut Refs) {
413        for n in &self.children {
414            n.refs(refs)
415        }
416    }
417
418    fn typ(&self) -> &Type {
419        &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
420    }
421
422    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
423        for n in &mut self.children {
424            if self.module {
425                wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
426            } else {
427                wrap!(n, n.typecheck(ctx))?
428            }
429        }
430        Ok(())
431    }
432
433    fn spec(&self) -> &Expr {
434        &self.spec
435    }
436}
437
438#[derive(Debug)]
439pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
440    spec: Expr,
441    typ: Type,
442    typs: Box<[Type]>,
443    args: Box<[Cached<R, E>]>,
444}
445
446impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
447    pub(crate) fn compile(
448        ctx: &mut ExecCtx<R, E>,
449        flags: BitFlags<CFlag>,
450        spec: Expr,
451        scope: &Scope,
452        top_id: ExprId,
453        args: &[Expr],
454    ) -> Result<Node<R, E>> {
455        let args: Box<[Cached<R, E>]> = args
456            .iter()
457            .map(|e| Ok(Cached::new(compile(ctx, flags, e.clone(), scope, top_id)?)))
458            .collect::<Result<_>>()?;
459        let typs = args.iter().map(|c| c.node.typ().clone()).collect();
460        let typ = Type::Primitive(Typ::String.into());
461        Ok(Box::new(Self { spec, typ, typs, args }))
462    }
463}
464
465impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
466    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
467        use std::fmt::Write;
468        thread_local! {
469            static BUF: RefCell<String> = RefCell::new(String::new());
470        }
471        let (updated, determined) = update_args!(self.args, ctx, event);
472        if updated && determined {
473            BUF.with_borrow_mut(|buf| {
474                buf.clear();
475                for (typ, c) in self.typs.iter().zip(self.args.iter()) {
476                    match c.cached.as_ref().unwrap() {
477                        Value::String(s) => write!(buf, "{s}"),
478                        v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
479                    }
480                    .unwrap()
481                }
482                Some(Value::String(buf.as_str().into()))
483            })
484        } else {
485            None
486        }
487    }
488
489    fn spec(&self) -> &Expr {
490        &self.spec
491    }
492
493    fn typ(&self) -> &Type {
494        &self.typ
495    }
496
497    fn refs(&self, refs: &mut Refs) {
498        for a in &self.args {
499            a.node.refs(refs)
500        }
501    }
502
503    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
504        for n in &mut self.args {
505            n.node.delete(ctx)
506        }
507    }
508
509    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
510        for n in &mut self.args {
511            n.sleep(ctx);
512        }
513    }
514
515    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
516        for (i, a) in self.args.iter_mut().enumerate() {
517            wrap!(a.node, a.node.typecheck(ctx))?;
518            self.typs[i] = a.node.typ().with_deref(|t| match t {
519                None => Type::Any,
520                Some(t) => t.clone(),
521            });
522        }
523        Ok(())
524    }
525}
526
527#[derive(Debug)]
528pub(crate) struct Connect<R: Rt, E: UserEvent> {
529    spec: Expr,
530    node: Node<R, E>,
531    id: BindId,
532}
533
534impl<R: Rt, E: UserEvent> Connect<R, E> {
535    pub(crate) fn compile(
536        ctx: &mut ExecCtx<R, E>,
537        flags: BitFlags<CFlag>,
538        spec: Expr,
539        scope: &Scope,
540        top_id: ExprId,
541        name: &ModPath,
542        value: &Expr,
543    ) -> Result<Node<R, E>> {
544        let id = match ctx.env.lookup_bind(&scope.lexical, name) {
545            None => bail!("at {} {name} is undefined", spec.pos),
546            Some((_, env::Bind { id, .. })) => *id,
547        };
548        let node = compile(ctx, flags, value.clone(), scope, top_id)?;
549        Ok(Box::new(Self { spec, node, id }))
550    }
551}
552
553impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
554    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
555        if let Some(v) = self.node.update(ctx, event) {
556            ctx.set_var(self.id, v)
557        }
558        None
559    }
560
561    fn spec(&self) -> &Expr {
562        &self.spec
563    }
564
565    fn typ(&self) -> &Type {
566        &Type::Bottom
567    }
568
569    fn refs(&self, refs: &mut Refs) {
570        self.node.refs(refs)
571    }
572
573    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
574        self.node.delete(ctx)
575    }
576
577    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
578        self.node.sleep(ctx);
579    }
580
581    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
582        wrap!(self.node, self.node.typecheck(ctx))?;
583        let bind = match ctx.env.by_id.get(&self.id) {
584            None => bail!("BUG missing bind {:?}", self.id),
585            Some(bind) => bind,
586        };
587        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
588    }
589}
590
591#[derive(Debug)]
592pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
593    spec: Expr,
594    rhs: Cached<R, E>,
595    src_id: BindId,
596    target_id: Option<BindId>,
597    top_id: ExprId,
598}
599
600impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
601    pub(crate) fn compile(
602        ctx: &mut ExecCtx<R, E>,
603        flags: BitFlags<CFlag>,
604        spec: Expr,
605        scope: &Scope,
606        top_id: ExprId,
607        name: &ModPath,
608        value: &Expr,
609    ) -> Result<Node<R, E>> {
610        let src_id = match ctx.env.lookup_bind(&scope.lexical, name) {
611            None => bail!("at {} {name} is undefined", spec.pos),
612            Some((_, env::Bind { id, .. })) => *id,
613        };
614        ctx.rt.ref_var(src_id, top_id);
615        let rhs = Cached::new(compile(ctx, flags, value.clone(), scope, top_id)?);
616        Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
617    }
618}
619
620impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
621    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
622        let mut up = self.rhs.update(ctx, event);
623        if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
624            if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
625                self.target_id = Some(*target_id);
626                up = true;
627            }
628        }
629        if up {
630            if let Some(v) = &self.rhs.cached {
631                if let Some(id) = self.target_id {
632                    ctx.set_var(id, v.clone());
633                }
634            }
635        }
636        None
637    }
638
639    fn spec(&self) -> &Expr {
640        &self.spec
641    }
642
643    fn typ(&self) -> &Type {
644        &Type::Bottom
645    }
646
647    fn refs(&self, refs: &mut Refs) {
648        refs.refed.insert(self.src_id);
649        self.rhs.node.refs(refs)
650    }
651
652    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
653        ctx.rt.unref_var(self.src_id, self.top_id);
654        self.rhs.node.delete(ctx)
655    }
656
657    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
658        self.rhs.sleep(ctx);
659    }
660
661    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
662        wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
663        let bind = match ctx.env.by_id.get(&self.src_id) {
664            None => bail!("BUG missing bind {:?}", self.src_id),
665            Some(bind) => bind,
666        };
667        let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
668        wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
669    }
670}
671
672#[derive(Debug)]
673pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
674    spec: Expr,
675    typ: Type,
676    target: Type,
677    n: Node<R, E>,
678}
679
680impl<R: Rt, E: UserEvent> TypeCast<R, E> {
681    pub(crate) fn compile(
682        ctx: &mut ExecCtx<R, E>,
683        flags: BitFlags<CFlag>,
684        spec: Expr,
685        scope: &Scope,
686        top_id: ExprId,
687        expr: &Expr,
688        typ: &Type,
689    ) -> Result<Node<R, E>> {
690        let n = compile(ctx, flags, expr.clone(), scope, top_id)?;
691        let target = typ.scope_refs(&scope.lexical);
692        if let Err(e) = target.check_cast(&ctx.env) {
693            bail!("in cast at {} {e}", spec.pos);
694        }
695        let typ = target.union(&ctx.env, &CAST_ERR)?;
696        Ok(Box::new(Self { spec, typ, target, n }))
697    }
698}
699
700impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
701    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
702        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
703    }
704
705    fn spec(&self) -> &Expr {
706        &self.spec
707    }
708
709    fn typ(&self) -> &Type {
710        &self.typ
711    }
712
713    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
714        self.n.delete(ctx)
715    }
716
717    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
718        self.n.sleep(ctx);
719    }
720
721    fn refs(&self, refs: &mut Refs) {
722        self.n.refs(refs)
723    }
724
725    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
726        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
727    }
728}
729
730#[derive(Debug)]
731pub(crate) struct Any<R: Rt, E: UserEvent> {
732    spec: Expr,
733    typ: Type,
734    n: Box<[Node<R, E>]>,
735}
736
737impl<R: Rt, E: UserEvent> Any<R, E> {
738    pub(crate) fn compile(
739        ctx: &mut ExecCtx<R, E>,
740        flags: BitFlags<CFlag>,
741        spec: Expr,
742        scope: &Scope,
743        top_id: ExprId,
744        args: &[Expr],
745    ) -> Result<Node<R, E>> {
746        let n = args
747            .iter()
748            .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
749            .collect::<Result<Box<[_]>>>()?;
750        Ok(Box::new(Self { spec, typ: Type::empty_tvar(), n }))
751    }
752}
753
754impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
755    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
756        self.n
757            .iter_mut()
758            .filter_map(|s| s.update(ctx, event))
759            .fold(None, |r, v| r.or(Some(v)))
760    }
761
762    fn spec(&self) -> &Expr {
763        &self.spec
764    }
765
766    fn typ(&self) -> &Type {
767        &self.typ
768    }
769
770    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
771        self.n.iter_mut().for_each(|n| n.delete(ctx))
772    }
773
774    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
775        self.n.iter_mut().for_each(|n| n.sleep(ctx))
776    }
777
778    fn refs(&self, refs: &mut Refs) {
779        self.n.iter().for_each(|n| n.refs(refs))
780    }
781
782    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
783        for n in self.n.iter_mut() {
784            wrap!(n, n.typecheck(ctx))?
785        }
786        let rtyp = Type::Bottom;
787        let rtyp = wrap!(
788            self,
789            self.n.iter().fold(Ok(rtyp), |rtype, n| rtype?.union(&ctx.env, n.typ()))
790        )?;
791        let rtyp = if rtyp == Type::Bottom { Type::empty_tvar() } else { rtyp };
792        self.typ.check_contains(&ctx.env, &rtyp)?;
793        Ok(())
794    }
795}
796
797#[derive(Debug)]
798struct Sample<R: Rt, E: UserEvent> {
799    spec: Expr,
800    triggered: usize,
801    typ: Type,
802    id: BindId,
803    top_id: ExprId,
804    trigger: Node<R, E>,
805    arg: Cached<R, E>,
806}
807
808impl<R: Rt, E: UserEvent> Sample<R, E> {
809    pub(crate) fn compile(
810        ctx: &mut ExecCtx<R, E>,
811        flags: BitFlags<CFlag>,
812        spec: Expr,
813        scope: &Scope,
814        top_id: ExprId,
815        lhs: &Arc<Expr>,
816        rhs: &Arc<Expr>,
817    ) -> Result<Node<R, E>> {
818        let id = BindId::new();
819        ctx.rt.ref_var(id, top_id);
820        let trigger = compile(ctx, flags, (**lhs).clone(), scope, top_id)?;
821        let arg = Cached::new(compile(ctx, flags, (**rhs).clone(), scope, top_id)?);
822        let typ = arg.node.typ().clone();
823        Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
824    }
825}
826
827impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
828    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
829        if let Some(_) = self.trigger.update(ctx, event) {
830            self.triggered += 1;
831        }
832        self.arg.update(ctx, event);
833        let var = event.variables.get(&self.id).cloned();
834        let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
835            self.triggered -= 1;
836            self.arg.cached.clone()
837        } else {
838            var
839        };
840        if self.arg.cached.is_some() {
841            while self.triggered > 0 {
842                self.triggered -= 1;
843                ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
844            }
845        }
846        res
847    }
848
849    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
850        ctx.rt.unref_var(self.id, self.top_id);
851        self.arg.node.delete(ctx);
852        self.trigger.delete(ctx);
853    }
854
855    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
856        self.arg.sleep(ctx);
857        self.trigger.sleep(ctx);
858    }
859
860    fn spec(&self) -> &Expr {
861        &self.spec
862    }
863
864    fn typ(&self) -> &Type {
865        &self.typ
866    }
867
868    fn refs(&self, refs: &mut Refs) {
869        refs.refed.insert(self.id);
870        self.arg.node.refs(refs);
871        self.trigger.refs(refs);
872    }
873
874    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
875        wrap!(self.trigger, self.trigger.typecheck(ctx))?;
876        wrap!(self.arg.node, self.arg.node.typecheck(ctx))
877    }
878}