graphix_compiler/node/
mod.rs

1use crate::{
2    env, err,
3    expr::{self, Expr, ExprId, ExprKind, ModPath},
4    format_with_flags,
5    typ::{TVal, TVar, Type},
6    wrap, BindId, Event, ExecCtx, Node, PrintFlag, Refs, Rt, Update, UserEvent,
7};
8use anyhow::{anyhow, bail, Context, Result};
9use arcstr::{literal, ArcStr};
10use compact_str::format_compact;
11use compiler::compile;
12use enumflags2::BitFlags;
13use netidx_value::{Typ, Value};
14use pattern::StructPatternNode;
15use std::{cell::RefCell, sync::LazyLock};
16use triomphe::Arc;
17
18pub(crate) mod array;
19pub(crate) mod callsite;
20pub(crate) mod compiler;
21pub(crate) mod data;
22pub(crate) mod dynamic;
23pub mod genn;
24pub(crate) mod lambda;
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
54static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
55    Arc::new(
56        ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
57    )
58});
59
60#[derive(Debug)]
61pub(crate) struct Nop {
62    pub typ: Type,
63}
64
65impl Nop {
66    pub(crate) fn new<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
67        Box::new(Nop { typ })
68    }
69}
70
71impl<R: Rt, E: UserEvent> Update<R, E> for Nop {
72    fn update(
73        &mut self,
74        _ctx: &mut ExecCtx<R, E>,
75        _event: &mut Event<E>,
76    ) -> Option<Value> {
77        None
78    }
79
80    fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
81
82    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
83
84    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
85        Ok(())
86    }
87
88    fn spec(&self) -> &Expr {
89        &NOP
90    }
91
92    fn typ(&self) -> &Type {
93        &self.typ
94    }
95
96    fn refs(&self, _refs: &mut Refs) {}
97}
98
99#[derive(Debug)]
100struct Cached<R: Rt, E: UserEvent> {
101    cached: Option<Value>,
102    node: Node<R, E>,
103}
104
105impl<R: Rt, E: UserEvent> Cached<R, E> {
106    fn new(node: Node<R, E>) -> Self {
107        Self { cached: None, node }
108    }
109
110    /// update the node, return whether the node updated. If it did,
111    /// the updated value will be stored in the cached field, if not,
112    /// the previous value will remain there.
113    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> bool {
114        match self.node.update(ctx, event) {
115            None => false,
116            Some(v) => {
117                self.cached = Some(v);
118                true
119            }
120        }
121    }
122
123    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
124        self.cached = None;
125        self.node.sleep(ctx)
126    }
127}
128
129#[derive(Debug)]
130pub(crate) struct Use {
131    spec: Expr,
132    scope: ModPath,
133    name: ModPath,
134}
135
136impl Use {
137    pub(crate) fn compile<R: Rt, E: UserEvent>(
138        ctx: &mut ExecCtx<R, E>,
139        spec: Expr,
140        scope: &ModPath,
141        name: &ModPath,
142    ) -> Result<Node<R, E>> {
143        match ctx.env.canonical_modpath(scope, name) {
144            None => bail!("at {} no such module {name}", spec.pos),
145            Some(_) => {
146                let used = ctx.env.used.get_or_default_cow(scope.clone());
147                Arc::make_mut(used).push(name.clone());
148                Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
149            }
150        }
151    }
152}
153
154impl<R: Rt, E: UserEvent> Update<R, E> for Use {
155    fn update(
156        &mut self,
157        _ctx: &mut ExecCtx<R, E>,
158        _event: &mut Event<E>,
159    ) -> Option<Value> {
160        None
161    }
162
163    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
164        Ok(())
165    }
166
167    fn refs(&self, _refs: &mut Refs) {}
168
169    fn spec(&self) -> &Expr {
170        &self.spec
171    }
172
173    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
174        if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
175            Arc::make_mut(used).retain(|n| n != &self.name);
176            if used.is_empty() {
177                ctx.env.used.remove_cow(&self.scope);
178            }
179        }
180    }
181
182    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
183
184    fn typ(&self) -> &Type {
185        &Type::Bottom
186    }
187}
188
189#[derive(Debug)]
190pub(crate) struct TypeDef {
191    spec: Expr,
192    scope: ModPath,
193    name: ArcStr,
194}
195
196impl TypeDef {
197    pub(crate) fn compile<R: Rt, E: UserEvent>(
198        ctx: &mut ExecCtx<R, E>,
199        spec: Expr,
200        scope: &ModPath,
201        name: &ArcStr,
202        params: &Arc<[(TVar, Option<Type>)]>,
203        typ: &Type,
204    ) -> Result<Node<R, E>> {
205        let typ = typ.scope_refs(scope);
206        ctx.env
207            .deftype(scope, name, params.clone(), typ)
208            .with_context(|| format!("in typedef at {}", spec.pos))?;
209        let name = name.clone();
210        let scope = scope.clone();
211        Ok(Box::new(Self { spec, scope, name }))
212    }
213}
214
215impl<R: Rt, E: UserEvent> Update<R, E> for TypeDef {
216    fn update(
217        &mut self,
218        _ctx: &mut ExecCtx<R, E>,
219        _event: &mut Event<E>,
220    ) -> Option<Value> {
221        None
222    }
223
224    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
225        Ok(())
226    }
227
228    fn refs(&self, _refs: &mut Refs) {}
229
230    fn spec(&self) -> &Expr {
231        &self.spec
232    }
233
234    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
235        ctx.env.undeftype(&self.scope, &self.name)
236    }
237
238    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
239
240    fn typ(&self) -> &Type {
241        &Type::Bottom
242    }
243}
244
245#[derive(Debug)]
246pub(crate) struct Constant {
247    spec: Arc<Expr>,
248    value: Value,
249    typ: Type,
250}
251
252impl Constant {
253    pub(crate) fn compile<R: Rt, E: UserEvent>(
254        spec: Expr,
255        value: &Value,
256    ) -> Result<Node<R, E>> {
257        let spec = Arc::new(spec);
258        let value = value.clone();
259        let typ = Type::Primitive(Typ::get(&value).into());
260        Ok(Box::new(Self { spec, value, typ }))
261    }
262}
263
264impl<R: Rt, E: UserEvent> Update<R, E> for Constant {
265    fn update(
266        &mut self,
267        _ctx: &mut ExecCtx<R, E>,
268        event: &mut Event<E>,
269    ) -> Option<Value> {
270        if event.init {
271            Some(self.value.clone())
272        } else {
273            None
274        }
275    }
276
277    fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
278
279    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
280
281    fn refs(&self, _refs: &mut Refs) {}
282
283    fn typ(&self) -> &Type {
284        &self.typ
285    }
286
287    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
288        Ok(())
289    }
290
291    fn spec(&self) -> &Expr {
292        &self.spec
293    }
294}
295
296// used for both mod and do
297#[derive(Debug)]
298pub(crate) struct Block<R: Rt, E: UserEvent> {
299    module: bool,
300    spec: Expr,
301    children: Box<[Node<R, E>]>,
302}
303
304impl<R: Rt, E: UserEvent> Block<R, E> {
305    pub(crate) fn compile(
306        ctx: &mut ExecCtx<R, E>,
307        spec: Expr,
308        scope: &ModPath,
309        top_id: ExprId,
310        module: bool,
311        exprs: &Arc<[Expr]>,
312    ) -> Result<Node<R, E>> {
313        let children = exprs
314            .iter()
315            .map(|e| compile(ctx, e.clone(), scope, top_id))
316            .collect::<Result<Box<[Node<R, E>]>>>()?;
317        Ok(Box::new(Self { module, spec, children }))
318    }
319}
320
321impl<R: Rt, E: UserEvent> Update<R, E> for Block<R, E> {
322    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
323        self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
324    }
325
326    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
327        for n in &mut self.children {
328            n.delete(ctx)
329        }
330    }
331
332    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
333        for n in &mut self.children {
334            n.sleep(ctx)
335        }
336    }
337
338    fn refs(&self, refs: &mut Refs) {
339        for n in &self.children {
340            n.refs(refs)
341        }
342    }
343
344    fn typ(&self) -> &Type {
345        &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
346    }
347
348    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
349        for n in &mut self.children {
350            if self.module {
351                wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
352            } else {
353                wrap!(n, n.typecheck(ctx))?
354            }
355        }
356        Ok(())
357    }
358
359    fn spec(&self) -> &Expr {
360        &self.spec
361    }
362}
363
364#[derive(Debug)]
365pub(crate) struct Bind<R: Rt, E: UserEvent> {
366    spec: Expr,
367    typ: Type,
368    pattern: StructPatternNode,
369    node: Node<R, E>,
370    top_id: ExprId,
371}
372
373impl<R: Rt, E: UserEvent> Bind<R, E> {
374    pub(crate) fn compile(
375        ctx: &mut ExecCtx<R, E>,
376        spec: Expr,
377        scope: &ModPath,
378        top_id: ExprId,
379        b: &expr::Bind,
380    ) -> Result<Node<R, E>> {
381        let expr::Bind { rec, doc, pattern, typ, export: _, value } = b;
382        let (node, pattern, typ) = if *rec {
383            if !pattern.single_bind().is_some() {
384                bail!("at {} can't use rec on a complex pattern", spec.pos)
385            }
386            match value {
387                Expr { kind: ExprKind::Lambda(_), .. } => (),
388                _ => bail!("let rec may only be used for lambdas"),
389            }
390            let typ = match typ {
391                Some(typ) => typ.scope_refs(scope),
392                None => Type::empty_tvar(),
393            };
394            let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
395                .with_context(|| format!("at {}", spec.pos))?;
396            let node = compile(ctx, value.clone(), &scope, top_id)?;
397            let ntyp = node.typ();
398            if !typ.contains(&ctx.env, ntyp)? {
399                format_with_flags(PrintFlag::DerefTVars, || {
400                    bail!("at {} error {} can't be matched by {typ}", ntyp, spec.pos)
401                })?
402            }
403            (node, pattern, typ)
404        } else {
405            let node = compile(ctx, value.clone(), &scope, top_id)?;
406            let typ = match typ {
407                Some(typ) => typ.scope_refs(scope),
408                None => {
409                    let typ = node.typ().clone();
410                    let ptyp = pattern.infer_type_predicate(&ctx.env)?;
411                    if !ptyp.contains(&ctx.env, &typ)? {
412                        format_with_flags(PrintFlag::DerefTVars, || {
413                            bail!(
414                                "at {} match error {typ} can't be matched by {ptyp}",
415                                spec.pos
416                            )
417                        })?
418                    }
419                    typ
420                }
421            };
422            let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
423                .with_context(|| format!("at {}", spec.pos))?;
424            (node, pattern, typ)
425        };
426        if pattern.is_refutable() {
427            bail!("at {} refutable patterns are not allowed in let", spec.pos);
428        }
429        if let Some(doc) = doc {
430            pattern.ids(&mut |id| {
431                if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
432                    b.doc = Some(doc.clone());
433                }
434            });
435        }
436        Ok(Box::new(Self { spec, typ, pattern, node, top_id }))
437    }
438
439    /// Return the id if this bind has only a single binding, otherwise return None
440    pub(crate) fn single_id(&self) -> Option<BindId> {
441        let mut id = None;
442        let mut n = 0;
443        self.pattern.ids(&mut |i| {
444            if n == 0 {
445                id = Some(i)
446            }
447            n += 1
448        });
449        if n == 1 {
450            id
451        } else {
452            None
453        }
454    }
455}
456
457impl<R: Rt, E: UserEvent> Update<R, E> for Bind<R, E> {
458    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
459        if let Some(v) = self.node.update(ctx, event) {
460            self.pattern.bind(&v, &mut |id, v| {
461                event.variables.insert(id, v.clone());
462                ctx.cached.insert(id, v);
463                if self.spec.id == self.top_id {
464                    ctx.rt.notify_set(id);
465                }
466            })
467        }
468        None
469    }
470
471    fn refs(&self, refs: &mut Refs) {
472        self.pattern.ids(&mut |id| {
473            refs.bound.insert(id);
474        });
475        self.node.refs(refs);
476    }
477
478    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
479        self.node.delete(ctx);
480        self.pattern.delete(ctx);
481    }
482
483    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
484        self.node.sleep(ctx);
485    }
486
487    fn typ(&self) -> &Type {
488        &self.typ
489    }
490
491    fn spec(&self) -> &Expr {
492        &self.spec
493    }
494
495    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
496        wrap!(self.node, self.node.typecheck(ctx))?;
497        wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
498        Ok(())
499    }
500}
501
502#[derive(Debug)]
503pub(crate) struct Ref {
504    spec: Arc<Expr>,
505    typ: Type,
506    id: BindId,
507    top_id: ExprId,
508}
509
510impl Ref {
511    pub(crate) fn compile<R: Rt, E: UserEvent>(
512        ctx: &mut ExecCtx<R, E>,
513        spec: Expr,
514        scope: &ModPath,
515        top_id: ExprId,
516        name: &ModPath,
517    ) -> Result<Node<R, E>> {
518        match ctx.env.lookup_bind(scope, name) {
519            None => bail!("at {} {name} not defined", spec.pos),
520            Some((_, bind)) => {
521                ctx.rt.ref_var(bind.id, top_id);
522                let typ = bind.typ.clone();
523                let spec = Arc::new(spec);
524                Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
525            }
526        }
527    }
528}
529
530impl<R: Rt, E: UserEvent> Update<R, E> for Ref {
531    fn update(
532        &mut self,
533        _ctx: &mut ExecCtx<R, E>,
534        event: &mut Event<E>,
535    ) -> Option<Value> {
536        event.variables.get(&self.id).map(|v| v.clone())
537    }
538
539    fn refs(&self, refs: &mut Refs) {
540        refs.refed.insert(self.id);
541    }
542
543    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
544        ctx.rt.unref_var(self.id, self.top_id)
545    }
546
547    fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
548
549    fn spec(&self) -> &Expr {
550        &self.spec
551    }
552
553    fn typ(&self) -> &Type {
554        &self.typ
555    }
556
557    fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
558        Ok(())
559    }
560}
561
562#[derive(Debug)]
563pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
564    spec: Expr,
565    typ: Type,
566    typs: Box<[Type]>,
567    args: Box<[Cached<R, E>]>,
568}
569
570impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
571    pub(crate) fn compile(
572        ctx: &mut ExecCtx<R, E>,
573        spec: Expr,
574        scope: &ModPath,
575        top_id: ExprId,
576        args: &[Expr],
577    ) -> Result<Node<R, E>> {
578        let args: Box<[Cached<R, E>]> = args
579            .iter()
580            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
581            .collect::<Result<_>>()?;
582        let typs = args.iter().map(|c| c.node.typ().clone()).collect();
583        let typ = Type::Primitive(Typ::String.into());
584        Ok(Box::new(Self { spec, typ, typs, args }))
585    }
586}
587
588impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
589    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
590        use std::fmt::Write;
591        thread_local! {
592            static BUF: RefCell<String> = RefCell::new(String::new());
593        }
594        let (updated, determined) = update_args!(self.args, ctx, event);
595        if updated && determined {
596            BUF.with_borrow_mut(|buf| {
597                buf.clear();
598                for (typ, c) in self.typs.iter().zip(self.args.iter()) {
599                    match c.cached.as_ref().unwrap() {
600                        Value::String(s) => write!(buf, "{s}"),
601                        v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
602                    }
603                    .unwrap()
604                }
605                Some(Value::String(buf.as_str().into()))
606            })
607        } else {
608            None
609        }
610    }
611
612    fn spec(&self) -> &Expr {
613        &self.spec
614    }
615
616    fn typ(&self) -> &Type {
617        &self.typ
618    }
619
620    fn refs(&self, refs: &mut Refs) {
621        for a in &self.args {
622            a.node.refs(refs)
623        }
624    }
625
626    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
627        for n in &mut self.args {
628            n.node.delete(ctx)
629        }
630    }
631
632    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
633        for n in &mut self.args {
634            n.sleep(ctx);
635        }
636    }
637
638    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
639        for (i, a) in self.args.iter_mut().enumerate() {
640            wrap!(a.node, a.node.typecheck(ctx))?;
641            self.typs[i] = a.node.typ().with_deref(|t| match t {
642                None => Type::Any,
643                Some(t) => t.clone(),
644            });
645        }
646        Ok(())
647    }
648}
649
650#[derive(Debug)]
651pub(crate) struct Connect<R: Rt, E: UserEvent> {
652    spec: Expr,
653    node: Node<R, E>,
654    id: BindId,
655}
656
657impl<R: Rt, E: UserEvent> Connect<R, E> {
658    pub(crate) fn compile(
659        ctx: &mut ExecCtx<R, E>,
660        spec: Expr,
661        scope: &ModPath,
662        top_id: ExprId,
663        name: &ModPath,
664        value: &Expr,
665    ) -> Result<Node<R, E>> {
666        let id = match ctx.env.lookup_bind(scope, name) {
667            None => bail!("at {} {name} is undefined", spec.pos),
668            Some((_, env::Bind { id, .. })) => *id,
669        };
670        let node = compile(ctx, value.clone(), scope, top_id)?;
671        Ok(Box::new(Self { spec, node, id }))
672    }
673}
674
675impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
676    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
677        if let Some(v) = self.node.update(ctx, event) {
678            ctx.set_var(self.id, v)
679        }
680        None
681    }
682
683    fn spec(&self) -> &Expr {
684        &self.spec
685    }
686
687    fn typ(&self) -> &Type {
688        &Type::Bottom
689    }
690
691    fn refs(&self, refs: &mut Refs) {
692        self.node.refs(refs)
693    }
694
695    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
696        self.node.delete(ctx)
697    }
698
699    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
700        self.node.sleep(ctx);
701    }
702
703    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
704        wrap!(self.node, self.node.typecheck(ctx))?;
705        let bind = match ctx.env.by_id.get(&self.id) {
706            None => bail!("BUG missing bind {:?}", self.id),
707            Some(bind) => bind,
708        };
709        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
710    }
711}
712
713#[derive(Debug)]
714pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
715    spec: Expr,
716    rhs: Cached<R, E>,
717    src_id: BindId,
718    target_id: Option<BindId>,
719    top_id: ExprId,
720}
721
722impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
723    pub(crate) fn compile(
724        ctx: &mut ExecCtx<R, E>,
725        spec: Expr,
726        scope: &ModPath,
727        top_id: ExprId,
728        name: &ModPath,
729        value: &Expr,
730    ) -> Result<Node<R, E>> {
731        let src_id = match ctx.env.lookup_bind(scope, name) {
732            None => bail!("at {} {name} is undefined", spec.pos),
733            Some((_, env::Bind { id, .. })) => *id,
734        };
735        ctx.rt.ref_var(src_id, top_id);
736        let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
737        Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
738    }
739}
740
741impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
742    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
743        let mut up = self.rhs.update(ctx, event);
744        if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
745            if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
746                self.target_id = Some(*target_id);
747                up = true;
748            }
749        }
750        if up {
751            if let Some(v) = &self.rhs.cached {
752                if let Some(id) = self.target_id {
753                    ctx.set_var(id, v.clone())
754                }
755            }
756        }
757        None
758    }
759
760    fn spec(&self) -> &Expr {
761        &self.spec
762    }
763
764    fn typ(&self) -> &Type {
765        &Type::Bottom
766    }
767
768    fn refs(&self, refs: &mut Refs) {
769        refs.refed.insert(self.src_id);
770        self.rhs.node.refs(refs)
771    }
772
773    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
774        ctx.rt.unref_var(self.src_id, self.top_id);
775        self.rhs.node.delete(ctx)
776    }
777
778    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
779        self.rhs.sleep(ctx);
780    }
781
782    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
783        wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
784        let bind = match ctx.env.by_id.get(&self.src_id) {
785            None => bail!("BUG missing bind {:?}", self.src_id),
786            Some(bind) => bind,
787        };
788        let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
789        wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
790    }
791}
792
793#[derive(Debug)]
794pub(crate) struct ByRef<R: Rt, E: UserEvent> {
795    spec: Expr,
796    typ: Type,
797    child: Node<R, E>,
798    id: BindId,
799}
800
801impl<R: Rt, E: UserEvent> ByRef<R, E> {
802    pub(crate) fn compile(
803        ctx: &mut ExecCtx<R, E>,
804        spec: Expr,
805        scope: &ModPath,
806        top_id: ExprId,
807        expr: &Expr,
808    ) -> Result<Node<R, E>> {
809        let child = compile(ctx, expr.clone(), scope, top_id)?;
810        let id = BindId::new();
811        if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
812            ctx.env.byref_chain.insert_cow(id, c.id);
813        }
814        let typ = Type::ByRef(Arc::new(child.typ().clone()));
815        Ok(Box::new(Self { spec, typ, child, id }))
816    }
817}
818
819impl<R: Rt, E: UserEvent> Update<R, E> for ByRef<R, E> {
820    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
821        if let Some(v) = self.child.update(ctx, event) {
822            ctx.set_var(self.id, v);
823        }
824        if event.init {
825            Some(Value::U64(self.id.inner()))
826        } else {
827            None
828        }
829    }
830
831    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
832        ctx.env.byref_chain.remove_cow(&self.id);
833        self.child.delete(ctx)
834    }
835
836    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
837        self.child.sleep(ctx);
838    }
839
840    fn spec(&self) -> &Expr {
841        &self.spec
842    }
843
844    fn typ(&self) -> &Type {
845        &self.typ
846    }
847
848    fn refs(&self, refs: &mut Refs) {
849        self.child.refs(refs)
850    }
851
852    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
853        wrap!(self.child, self.child.typecheck(ctx))?;
854        let t = Type::ByRef(Arc::new(self.child.typ().clone()));
855        wrap!(self, self.typ.check_contains(&ctx.env, &t))
856    }
857}
858
859#[derive(Debug)]
860pub(crate) struct Deref<R: Rt, E: UserEvent> {
861    spec: Expr,
862    typ: Type,
863    child: Node<R, E>,
864    id: Option<BindId>,
865    top_id: ExprId,
866}
867
868impl<R: Rt, E: UserEvent> Deref<R, E> {
869    pub(crate) fn compile(
870        ctx: &mut ExecCtx<R, E>,
871        spec: Expr,
872        scope: &ModPath,
873        top_id: ExprId,
874        expr: &Expr,
875    ) -> Result<Node<R, E>> {
876        let child = compile(ctx, expr.clone(), scope, top_id)?;
877        let typ = Type::empty_tvar();
878        Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
879    }
880}
881
882impl<R: Rt, E: UserEvent> Update<R, E> for Deref<R, E> {
883    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
884        if let Some(v) = self.child.update(ctx, event) {
885            match v {
886                Value::U64(i) | Value::V64(i) => {
887                    let new_id = BindId::from(i);
888                    if self.id != Some(new_id) {
889                        if let Some(old) = self.id {
890                            ctx.rt.unref_var(old, self.top_id);
891                        }
892                        ctx.rt.ref_var(new_id, self.top_id);
893                        self.id = Some(new_id);
894                    }
895                }
896                _ => return err!("expected u64 bind id"),
897            }
898        }
899        self.id.and_then(|id| event.variables.get(&id).cloned())
900    }
901
902    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
903        if let Some(id) = self.id.take() {
904            ctx.rt.unref_var(id, self.top_id);
905        }
906        self.child.delete(ctx);
907    }
908
909    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
910        self.child.sleep(ctx);
911    }
912
913    fn spec(&self) -> &Expr {
914        &self.spec
915    }
916
917    fn typ(&self) -> &Type {
918        &self.typ
919    }
920
921    fn refs(&self, refs: &mut Refs) {
922        self.child.refs(refs);
923        if let Some(id) = self.id {
924            refs.refed.insert(id);
925        }
926    }
927
928    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
929        wrap!(self.child, self.child.typecheck(ctx))?;
930        let typ = match self.child.typ() {
931            Type::ByRef(t) => (**t).clone(),
932            _ => bail!("expected reference"),
933        };
934        wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
935        Ok(())
936    }
937}
938
939#[derive(Debug)]
940pub(crate) struct Qop<R: Rt, E: UserEvent> {
941    spec: Expr,
942    typ: Type,
943    id: BindId,
944    n: Node<R, E>,
945}
946
947impl<R: Rt, E: UserEvent> Qop<R, E> {
948    pub(crate) fn compile(
949        ctx: &mut ExecCtx<R, E>,
950        spec: Expr,
951        scope: &ModPath,
952        top_id: ExprId,
953        e: &Expr,
954    ) -> Result<Node<R, E>> {
955        let n = compile(ctx, e.clone(), scope, top_id)?;
956        match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
957            None => bail!("at {} BUG: errors is undefined", spec.pos),
958            Some((_, bind)) => {
959                let typ = Type::empty_tvar();
960                Ok(Box::new(Self { spec, typ, id: bind.id, n }))
961            }
962        }
963    }
964}
965
966impl<R: Rt, E: UserEvent> Update<R, E> for Qop<R, E> {
967    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
968        match self.n.update(ctx, event) {
969            None => None,
970            Some(Value::Error(e)) => {
971                let e = format_compact!("{} at {} {e}", self.spec.ori, self.spec.pos);
972                ctx.set_var(self.id, Value::Error(e.as_str().into()));
973                None
974            }
975            Some(v) => Some(v),
976        }
977    }
978
979    fn typ(&self) -> &Type {
980        &self.typ
981    }
982
983    fn spec(&self) -> &Expr {
984        &self.spec
985    }
986
987    fn refs(&self, refs: &mut Refs) {
988        self.n.refs(refs)
989    }
990
991    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
992        self.n.delete(ctx)
993    }
994
995    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
996        self.n.sleep(ctx);
997    }
998
999    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1000        wrap!(self.n, self.n.typecheck(ctx))?;
1001        let bind =
1002            ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
1003        let err = Type::Primitive(Typ::Error.into());
1004        wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
1005        wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
1006        if !self.n.typ().contains(&ctx.env, &err)? {
1007            bail!("cannot use the ? operator on a non error type")
1008        }
1009        let rtyp = self.n.typ().diff(&ctx.env, &err)?;
1010        wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
1011        Ok(())
1012    }
1013}
1014
1015#[derive(Debug)]
1016pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
1017    spec: Expr,
1018    typ: Type,
1019    target: Type,
1020    n: Node<R, E>,
1021}
1022
1023impl<R: Rt, E: UserEvent> TypeCast<R, E> {
1024    pub(crate) fn compile(
1025        ctx: &mut ExecCtx<R, E>,
1026        spec: Expr,
1027        scope: &ModPath,
1028        top_id: ExprId,
1029        expr: &Expr,
1030        typ: &Type,
1031    ) -> Result<Node<R, E>> {
1032        let n = compile(ctx, expr.clone(), scope, top_id)?;
1033        let target = typ.scope_refs(scope);
1034        if let Err(e) = target.check_cast(&ctx.env) {
1035            bail!("in cast at {} {e}", spec.pos);
1036        }
1037        let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
1038        Ok(Box::new(Self { spec, typ, target, n }))
1039    }
1040}
1041
1042impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
1043    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1044        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
1045    }
1046
1047    fn spec(&self) -> &Expr {
1048        &self.spec
1049    }
1050
1051    fn typ(&self) -> &Type {
1052        &self.typ
1053    }
1054
1055    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1056        self.n.delete(ctx)
1057    }
1058
1059    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1060        self.n.sleep(ctx);
1061    }
1062
1063    fn refs(&self, refs: &mut Refs) {
1064        self.n.refs(refs)
1065    }
1066
1067    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1068        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1069    }
1070}
1071
1072#[derive(Debug)]
1073pub(crate) struct Any<R: Rt, E: UserEvent> {
1074    spec: Expr,
1075    typ: Type,
1076    n: Box<[Node<R, E>]>,
1077}
1078
1079impl<R: Rt, E: UserEvent> Any<R, E> {
1080    pub(crate) fn compile(
1081        ctx: &mut ExecCtx<R, E>,
1082        spec: Expr,
1083        scope: &ModPath,
1084        top_id: ExprId,
1085        args: &[Expr],
1086    ) -> Result<Node<R, E>> {
1087        let n = args
1088            .iter()
1089            .map(|e| compile(ctx, e.clone(), scope, top_id))
1090            .collect::<Result<Box<[_]>>>()?;
1091        let typ =
1092            Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1093        Ok(Box::new(Self { spec, typ, n }))
1094    }
1095}
1096
1097impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
1098    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1099        self.n
1100            .iter_mut()
1101            .filter_map(|s| s.update(ctx, event))
1102            .fold(None, |r, v| r.or(Some(v)))
1103    }
1104
1105    fn spec(&self) -> &Expr {
1106        &self.spec
1107    }
1108
1109    fn typ(&self) -> &Type {
1110        &self.typ
1111    }
1112
1113    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1114        self.n.iter_mut().for_each(|n| n.delete(ctx))
1115    }
1116
1117    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1118        self.n.iter_mut().for_each(|n| n.sleep(ctx))
1119    }
1120
1121    fn refs(&self, refs: &mut Refs) {
1122        self.n.iter().for_each(|n| n.refs(refs))
1123    }
1124
1125    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1126        for n in self.n.iter_mut() {
1127            wrap!(n, n.typecheck(ctx))?
1128        }
1129        let rtyp = Type::Primitive(BitFlags::empty());
1130        let rtyp = wrap!(
1131            self,
1132            self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1133        )?;
1134        Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1135    }
1136}
1137
1138#[derive(Debug)]
1139struct Sample<R: Rt, E: UserEvent> {
1140    spec: Expr,
1141    triggered: usize,
1142    typ: Type,
1143    id: BindId,
1144    top_id: ExprId,
1145    trigger: Node<R, E>,
1146    arg: Cached<R, E>,
1147}
1148
1149impl<R: Rt, E: UserEvent> Sample<R, E> {
1150    pub(crate) fn compile(
1151        ctx: &mut ExecCtx<R, E>,
1152        spec: Expr,
1153        scope: &ModPath,
1154        top_id: ExprId,
1155        lhs: &Arc<Expr>,
1156        rhs: &Arc<Expr>,
1157    ) -> Result<Node<R, E>> {
1158        let id = BindId::new();
1159        ctx.rt.ref_var(id, top_id);
1160        let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1161        let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1162        let typ = arg.node.typ().clone();
1163        Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1164    }
1165}
1166
1167impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
1168    fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1169        if let Some(_) = self.trigger.update(ctx, event) {
1170            self.triggered += 1;
1171        }
1172        self.arg.update(ctx, event);
1173        let var = event.variables.get(&self.id).cloned();
1174        let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1175            self.triggered -= 1;
1176            self.arg.cached.clone()
1177        } else {
1178            var
1179        };
1180        if self.arg.cached.is_some() {
1181            while self.triggered > 0 {
1182                self.triggered -= 1;
1183                ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
1184            }
1185        }
1186        res
1187    }
1188
1189    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1190        ctx.rt.unref_var(self.id, self.top_id);
1191        self.arg.node.delete(ctx);
1192        self.trigger.delete(ctx);
1193    }
1194
1195    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1196        self.arg.sleep(ctx);
1197        self.trigger.sleep(ctx);
1198    }
1199
1200    fn spec(&self) -> &Expr {
1201        &self.spec
1202    }
1203
1204    fn typ(&self) -> &Type {
1205        &self.typ
1206    }
1207
1208    fn refs(&self, refs: &mut Refs) {
1209        refs.refed.insert(self.id);
1210        self.arg.node.refs(refs);
1211        self.trigger.refs(refs);
1212    }
1213
1214    fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1215        wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1216        wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1217    }
1218}