graphix_compiler/node/
mod.rs

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