graphix_compiler/node/
mod.rs

1use crate::{
2    env, err,
3    expr::{self, Expr, ExprId, ExprKind, ModPath, Origin},
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    ori: Option<Origin>,
301    children: Box<[Node<C, E>]>,
302}
303
304impl<C: Ctx, E: UserEvent> Block<C, E> {
305    pub(crate) fn compile(
306        ctx: &mut ExecCtx<C, E>,
307        spec: Expr,
308        scope: &ModPath,
309        top_id: ExprId,
310        ori: Option<Origin>,
311        exprs: &Arc<[Expr]>,
312    ) -> Result<Node<C, E>> {
313        let children = exprs
314            .iter()
315            .map(|e| compile(ctx, e.clone(), scope, top_id))
316            .collect::<Result<Box<[Node<C, E>]>>>()?;
317        Ok(Box::new(Self { ori, spec, children }))
318    }
319}
320
321impl<C: Ctx, E: UserEvent> Update<C, E> for Block<C, E> {
322    fn update(&mut self, ctx: &mut ExecCtx<C, 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<C, E>) {
327        for n in &mut self.children {
328            n.delete(ctx)
329        }
330    }
331
332    fn sleep(&mut self, ctx: &mut ExecCtx<C, 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<C, E>) -> Result<()> {
349        for n in &mut self.children {
350            match &self.ori {
351                None => wrap!(n, n.typecheck(ctx))?,
352                Some(ori) => wrap!(n, n.typecheck(ctx)).with_context(|| ori.clone())?,
353            }
354        }
355        Ok(())
356    }
357
358    fn spec(&self) -> &Expr {
359        &self.spec
360    }
361}
362
363#[derive(Debug)]
364pub(crate) struct Bind<C: Ctx, E: UserEvent> {
365    spec: Expr,
366    typ: Type,
367    pattern: StructPatternNode,
368    node: Node<C, E>,
369}
370
371impl<C: Ctx, E: UserEvent> Bind<C, E> {
372    pub(crate) fn compile(
373        ctx: &mut ExecCtx<C, E>,
374        spec: Expr,
375        scope: &ModPath,
376        top_id: ExprId,
377        b: &expr::Bind,
378        pos: &SourcePosition,
379    ) -> Result<Node<C, E>> {
380        let expr::Bind { doc, pattern, typ, export: _, value } = b;
381        let node = compile(ctx, value.clone(), &scope, top_id)?;
382        let typ = match typ {
383            Some(typ) => typ.scope_refs(scope),
384            None => {
385                let typ = node.typ().clone();
386                let ptyp = pattern.infer_type_predicate(&ctx.env)?;
387                if !ptyp.contains(&ctx.env, &typ)? {
388                    typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
389                        bail!("at {pos} match error {typ} can't be matched by {ptyp}")
390                    })?
391                }
392                typ
393            }
394        };
395        let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
396            .with_context(|| format!("at {pos}"))?;
397        if pattern.is_refutable() {
398            bail!("at {pos} refutable patterns are not allowed in let");
399        }
400        if let Some(doc) = doc {
401            pattern.ids(&mut |id| {
402                if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
403                    b.doc = Some(doc.clone());
404                }
405            });
406        }
407        Ok(Box::new(Self { spec, typ, pattern, node }))
408    }
409}
410
411impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
412    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
413        if let Some(v) = self.node.update(ctx, event) {
414            self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
415        }
416        None
417    }
418
419    fn refs(&self, refs: &mut Refs) {
420        self.pattern.ids(&mut |id| {
421            refs.bound.insert(id);
422        });
423        self.node.refs(refs);
424    }
425
426    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
427        self.node.delete(ctx);
428        self.pattern.delete(ctx);
429    }
430
431    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
432        self.node.sleep(ctx);
433    }
434
435    fn typ(&self) -> &Type {
436        &self.typ
437    }
438
439    fn spec(&self) -> &Expr {
440        &self.spec
441    }
442
443    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
444        wrap!(self.node, self.node.typecheck(ctx))?;
445        wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
446        Ok(())
447    }
448}
449
450#[derive(Debug)]
451pub(crate) struct Ref {
452    spec: Arc<Expr>,
453    typ: Type,
454    id: BindId,
455    top_id: ExprId,
456}
457
458impl Ref {
459    pub(crate) fn compile<C: Ctx, E: UserEvent>(
460        ctx: &mut ExecCtx<C, E>,
461        spec: Expr,
462        scope: &ModPath,
463        top_id: ExprId,
464        name: &ModPath,
465        pos: &SourcePosition,
466    ) -> Result<Node<C, E>> {
467        match ctx.env.lookup_bind(scope, name) {
468            None => bail!("at {pos} {name} not defined"),
469            Some((_, bind)) => {
470                ctx.user.ref_var(bind.id, top_id);
471                let typ = bind.typ.clone();
472                let spec = Arc::new(spec);
473                Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
474            }
475        }
476    }
477}
478
479impl<C: Ctx, E: UserEvent> Update<C, E> for Ref {
480    fn update(
481        &mut self,
482        _ctx: &mut ExecCtx<C, E>,
483        event: &mut Event<E>,
484    ) -> Option<Value> {
485        event.variables.get(&self.id).map(|v| v.clone())
486    }
487
488    fn refs(&self, refs: &mut Refs) {
489        refs.refed.insert(self.id);
490    }
491
492    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
493        ctx.user.unref_var(self.id, self.top_id)
494    }
495
496    fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
497
498    fn spec(&self) -> &Expr {
499        &self.spec
500    }
501
502    fn typ(&self) -> &Type {
503        &self.typ
504    }
505
506    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
507        Ok(())
508    }
509}
510
511#[derive(Debug)]
512pub(crate) struct StringInterpolate<C: Ctx, E: UserEvent> {
513    spec: Expr,
514    typ: Type,
515    typs: Box<[Type]>,
516    args: Box<[Cached<C, E>]>,
517}
518
519impl<C: Ctx, E: UserEvent> StringInterpolate<C, E> {
520    pub(crate) fn compile(
521        ctx: &mut ExecCtx<C, E>,
522        spec: Expr,
523        scope: &ModPath,
524        top_id: ExprId,
525        args: &[Expr],
526    ) -> Result<Node<C, E>> {
527        let args: Box<[Cached<C, E>]> = args
528            .iter()
529            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
530            .collect::<Result<_>>()?;
531        let typs = args.iter().map(|c| c.node.typ().clone()).collect();
532        let typ = Type::Primitive(Typ::String.into());
533        Ok(Box::new(Self { spec, typ, typs, args }))
534    }
535}
536
537impl<C: Ctx, E: UserEvent> Update<C, E> for StringInterpolate<C, E> {
538    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
539        use std::fmt::Write;
540        thread_local! {
541            static BUF: RefCell<String> = RefCell::new(String::new());
542        }
543        let (updated, determined) = update_args!(self.args, ctx, event);
544        if updated && determined {
545            BUF.with_borrow_mut(|buf| {
546                buf.clear();
547                for (typ, c) in self.typs.iter().zip(self.args.iter()) {
548                    match c.cached.as_ref().unwrap() {
549                        Value::String(s) => write!(buf, "{s}"),
550                        v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
551                    }
552                    .unwrap()
553                }
554                Some(Value::String(buf.as_str().into()))
555            })
556        } else {
557            None
558        }
559    }
560
561    fn spec(&self) -> &Expr {
562        &self.spec
563    }
564
565    fn typ(&self) -> &Type {
566        &self.typ
567    }
568
569    fn refs(&self, refs: &mut Refs) {
570        for a in &self.args {
571            a.node.refs(refs)
572        }
573    }
574
575    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
576        for n in &mut self.args {
577            n.node.delete(ctx)
578        }
579    }
580
581    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
582        for n in &mut self.args {
583            n.sleep(ctx);
584        }
585    }
586
587    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
588        for (i, a) in self.args.iter_mut().enumerate() {
589            wrap!(a.node, a.node.typecheck(ctx))?;
590            self.typs[i] = a.node.typ().with_deref(|t| match t {
591                None => Type::Any,
592                Some(t) => t.clone(),
593            });
594        }
595        Ok(())
596    }
597}
598
599#[derive(Debug)]
600pub(crate) struct Connect<C: Ctx, E: UserEvent> {
601    spec: Expr,
602    node: Node<C, E>,
603    id: BindId,
604}
605
606impl<C: Ctx, E: UserEvent> Connect<C, E> {
607    pub(crate) fn compile(
608        ctx: &mut ExecCtx<C, E>,
609        spec: Expr,
610        scope: &ModPath,
611        top_id: ExprId,
612        name: &ModPath,
613        value: &Expr,
614        pos: &SourcePosition,
615    ) -> Result<Node<C, E>> {
616        let id = match ctx.env.lookup_bind(scope, name) {
617            None => bail!("at {pos} {name} is undefined"),
618            Some((_, env::Bind { id, .. })) => *id,
619        };
620        let node = compile(ctx, value.clone(), scope, top_id)?;
621        Ok(Box::new(Self { spec, node, id }))
622    }
623}
624
625impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
626    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
627        if let Some(v) = self.node.update(ctx, event) {
628            ctx.set_var(self.id, v)
629        }
630        None
631    }
632
633    fn spec(&self) -> &Expr {
634        &self.spec
635    }
636
637    fn typ(&self) -> &Type {
638        &Type::Bottom
639    }
640
641    fn refs(&self, refs: &mut Refs) {
642        self.node.refs(refs)
643    }
644
645    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
646        self.node.delete(ctx)
647    }
648
649    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
650        self.node.sleep(ctx);
651    }
652
653    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
654        wrap!(self.node, self.node.typecheck(ctx))?;
655        let bind = match ctx.env.by_id.get(&self.id) {
656            None => bail!("BUG missing bind {:?}", self.id),
657            Some(bind) => bind,
658        };
659        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
660    }
661}
662
663#[derive(Debug)]
664pub(crate) struct ConnectDeref<C: Ctx, E: UserEvent> {
665    spec: Expr,
666    rhs: Cached<C, E>,
667    src_id: BindId,
668    target_id: Option<BindId>,
669    top_id: ExprId,
670}
671
672impl<C: Ctx, E: UserEvent> ConnectDeref<C, E> {
673    pub(crate) fn compile(
674        ctx: &mut ExecCtx<C, E>,
675        spec: Expr,
676        scope: &ModPath,
677        top_id: ExprId,
678        name: &ModPath,
679        value: &Expr,
680        pos: &SourcePosition,
681    ) -> Result<Node<C, E>> {
682        let src_id = match ctx.env.lookup_bind(scope, name) {
683            None => bail!("at {pos} {name} is undefined"),
684            Some((_, env::Bind { id, .. })) => *id,
685        };
686        ctx.user.ref_var(src_id, top_id);
687        let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
688        Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
689    }
690}
691
692impl<C: Ctx, E: UserEvent> Update<C, E> for ConnectDeref<C, E> {
693    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
694        let mut up = self.rhs.update(ctx, event);
695        if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
696            if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
697                self.target_id = Some(*target_id);
698                up = true;
699            }
700        }
701        if up {
702            if let Some(v) = &self.rhs.cached {
703                if let Some(id) = self.target_id {
704                    ctx.set_var(id, v.clone())
705                }
706            }
707        }
708        None
709    }
710
711    fn spec(&self) -> &Expr {
712        &self.spec
713    }
714
715    fn typ(&self) -> &Type {
716        &Type::Bottom
717    }
718
719    fn refs(&self, refs: &mut Refs) {
720        refs.refed.insert(self.src_id);
721        self.rhs.node.refs(refs)
722    }
723
724    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
725        ctx.user.unref_var(self.src_id, self.top_id);
726        self.rhs.node.delete(ctx)
727    }
728
729    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
730        self.rhs.sleep(ctx);
731    }
732
733    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
734        wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
735        let bind = match ctx.env.by_id.get(&self.src_id) {
736            None => bail!("BUG missing bind {:?}", self.src_id),
737            Some(bind) => bind,
738        };
739        let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
740        wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
741    }
742}
743
744#[derive(Debug)]
745pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
746    spec: Expr,
747    typ: Type,
748    child: Node<C, E>,
749    id: BindId,
750}
751
752impl<C: Ctx, E: UserEvent> ByRef<C, E> {
753    pub(crate) fn compile(
754        ctx: &mut ExecCtx<C, E>,
755        spec: Expr,
756        scope: &ModPath,
757        top_id: ExprId,
758        expr: &Expr,
759    ) -> Result<Node<C, E>> {
760        let child = compile(ctx, expr.clone(), scope, top_id)?;
761        let id = BindId::new();
762        if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
763            ctx.env.byref_chain.insert_cow(id, c.id);
764        }
765        let typ = Type::ByRef(Arc::new(child.typ().clone()));
766        Ok(Box::new(Self { spec, typ, child, id }))
767    }
768}
769
770impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
771    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
772        if let Some(v) = self.child.update(ctx, event) {
773            ctx.set_var(self.id, v);
774        }
775        if event.init {
776            Some(Value::U64(self.id.inner()))
777        } else {
778            None
779        }
780    }
781
782    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
783        ctx.env.byref_chain.remove_cow(&self.id);
784        self.child.delete(ctx)
785    }
786
787    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
788        self.child.sleep(ctx);
789    }
790
791    fn spec(&self) -> &Expr {
792        &self.spec
793    }
794
795    fn typ(&self) -> &Type {
796        &self.typ
797    }
798
799    fn refs(&self, refs: &mut Refs) {
800        self.child.refs(refs)
801    }
802
803    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
804        wrap!(self.child, self.child.typecheck(ctx))?;
805        let t = Type::ByRef(Arc::new(self.child.typ().clone()));
806        wrap!(self, self.typ.check_contains(&ctx.env, &t))
807    }
808}
809
810#[derive(Debug)]
811pub(crate) struct Deref<C: Ctx, E: UserEvent> {
812    spec: Expr,
813    typ: Type,
814    child: Node<C, E>,
815    id: Option<BindId>,
816    top_id: ExprId,
817}
818
819impl<C: Ctx, E: UserEvent> Deref<C, E> {
820    pub(crate) fn compile(
821        ctx: &mut ExecCtx<C, E>,
822        spec: Expr,
823        scope: &ModPath,
824        top_id: ExprId,
825        expr: &Expr,
826    ) -> Result<Node<C, E>> {
827        let child = compile(ctx, expr.clone(), scope, top_id)?;
828        let typ = Type::empty_tvar();
829        Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
830    }
831}
832
833impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
834    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
835        if let Some(v) = self.child.update(ctx, event) {
836            match v {
837                Value::U64(i) | Value::V64(i) => {
838                    let new_id = BindId::from(i);
839                    if self.id != Some(new_id) {
840                        if let Some(old) = self.id {
841                            ctx.user.unref_var(old, self.top_id);
842                        }
843                        ctx.user.ref_var(new_id, self.top_id);
844                        self.id = Some(new_id);
845                    }
846                }
847                _ => return err!("expected u64 bind id"),
848            }
849        }
850        self.id.and_then(|id| event.variables.get(&id).cloned())
851    }
852
853    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
854        if let Some(id) = self.id.take() {
855            ctx.user.unref_var(id, self.top_id);
856        }
857        self.child.delete(ctx);
858    }
859
860    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
861        self.child.sleep(ctx);
862    }
863
864    fn spec(&self) -> &Expr {
865        &self.spec
866    }
867
868    fn typ(&self) -> &Type {
869        &self.typ
870    }
871
872    fn refs(&self, refs: &mut Refs) {
873        self.child.refs(refs);
874        if let Some(id) = self.id {
875            refs.refed.insert(id);
876        }
877    }
878
879    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
880        wrap!(self.child, self.child.typecheck(ctx))?;
881        let typ = match self.child.typ() {
882            Type::ByRef(t) => (**t).clone(),
883            _ => bail!("expected reference"),
884        };
885        wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
886        Ok(())
887    }
888}
889
890#[derive(Debug)]
891pub(crate) struct Qop<C: Ctx, E: UserEvent> {
892    spec: Expr,
893    typ: Type,
894    id: BindId,
895    n: Node<C, E>,
896}
897
898impl<C: Ctx, E: UserEvent> Qop<C, E> {
899    pub(crate) fn compile(
900        ctx: &mut ExecCtx<C, E>,
901        spec: Expr,
902        scope: &ModPath,
903        top_id: ExprId,
904        e: &Expr,
905        pos: &SourcePosition,
906    ) -> Result<Node<C, E>> {
907        let n = compile(ctx, e.clone(), scope, top_id)?;
908        match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
909            None => bail!("at {pos} BUG: errors is undefined"),
910            Some((_, bind)) => {
911                let typ = Type::empty_tvar();
912                Ok(Box::new(Self { spec, typ, id: bind.id, n }))
913            }
914        }
915    }
916}
917
918impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
919    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
920        match self.n.update(ctx, event) {
921            None => None,
922            Some(e @ Value::Error(_)) => {
923                ctx.set_var(self.id, e);
924                None
925            }
926            Some(v) => Some(v),
927        }
928    }
929
930    fn typ(&self) -> &Type {
931        &self.typ
932    }
933
934    fn spec(&self) -> &Expr {
935        &self.spec
936    }
937
938    fn refs(&self, refs: &mut Refs) {
939        self.n.refs(refs)
940    }
941
942    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
943        self.n.delete(ctx)
944    }
945
946    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
947        self.n.sleep(ctx);
948    }
949
950    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
951        wrap!(self.n, self.n.typecheck(ctx))?;
952        let bind =
953            ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
954        let err = Type::Primitive(Typ::Error.into());
955        wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
956        wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
957        if !self.n.typ().contains(&ctx.env, &err)? {
958            bail!("cannot use the ? operator on a non error type")
959        }
960        let rtyp = self.n.typ().diff(&ctx.env, &err)?;
961        wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
962        Ok(())
963    }
964}
965
966#[derive(Debug)]
967pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
968    spec: Expr,
969    typ: Type,
970    target: Type,
971    n: Node<C, E>,
972}
973
974impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
975    pub(crate) fn compile(
976        ctx: &mut ExecCtx<C, E>,
977        spec: Expr,
978        scope: &ModPath,
979        top_id: ExprId,
980        expr: &Expr,
981        typ: &Type,
982        pos: &SourcePosition,
983    ) -> Result<Node<C, E>> {
984        let n = compile(ctx, expr.clone(), scope, top_id)?;
985        let target = typ.scope_refs(scope);
986        if let Err(e) = target.check_cast(&ctx.env) {
987            bail!("in cast at {pos} {e}");
988        }
989        let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
990        Ok(Box::new(Self { spec, typ, target, n }))
991    }
992}
993
994impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
995    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
996        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
997    }
998
999    fn spec(&self) -> &Expr {
1000        &self.spec
1001    }
1002
1003    fn typ(&self) -> &Type {
1004        &self.typ
1005    }
1006
1007    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1008        self.n.delete(ctx)
1009    }
1010
1011    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1012        self.n.sleep(ctx);
1013    }
1014
1015    fn refs(&self, refs: &mut Refs) {
1016        self.n.refs(refs)
1017    }
1018
1019    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1020        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1021    }
1022}
1023
1024#[derive(Debug)]
1025pub(crate) struct Any<C: Ctx, E: UserEvent> {
1026    spec: Expr,
1027    typ: Type,
1028    n: Box<[Node<C, E>]>,
1029}
1030
1031impl<C: Ctx, E: UserEvent> Any<C, E> {
1032    pub(crate) fn compile(
1033        ctx: &mut ExecCtx<C, E>,
1034        spec: Expr,
1035        scope: &ModPath,
1036        top_id: ExprId,
1037        args: &[Expr],
1038    ) -> Result<Node<C, E>> {
1039        let n = args
1040            .iter()
1041            .map(|e| compile(ctx, e.clone(), scope, top_id))
1042            .collect::<Result<Box<[_]>>>()?;
1043        let typ =
1044            Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1045        Ok(Box::new(Self { spec, typ, n }))
1046    }
1047}
1048
1049impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1050    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1051        self.n
1052            .iter_mut()
1053            .filter_map(|s| s.update(ctx, event))
1054            .fold(None, |r, v| r.or(Some(v)))
1055    }
1056
1057    fn spec(&self) -> &Expr {
1058        &self.spec
1059    }
1060
1061    fn typ(&self) -> &Type {
1062        &self.typ
1063    }
1064
1065    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1066        self.n.iter_mut().for_each(|n| n.delete(ctx))
1067    }
1068
1069    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1070        self.n.iter_mut().for_each(|n| n.sleep(ctx))
1071    }
1072
1073    fn refs(&self, refs: &mut Refs) {
1074        self.n.iter().for_each(|n| n.refs(refs))
1075    }
1076
1077    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1078        for n in self.n.iter_mut() {
1079            wrap!(n, n.typecheck(ctx))?
1080        }
1081        let rtyp = Type::Primitive(BitFlags::empty());
1082        let rtyp = wrap!(
1083            self,
1084            self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1085        )?;
1086        Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1087    }
1088}
1089
1090#[derive(Debug)]
1091struct Sample<C: Ctx, E: UserEvent> {
1092    spec: Expr,
1093    triggered: usize,
1094    typ: Type,
1095    id: BindId,
1096    top_id: ExprId,
1097    trigger: Node<C, E>,
1098    arg: Cached<C, E>,
1099}
1100
1101impl<C: Ctx, E: UserEvent> Sample<C, E> {
1102    pub(crate) fn compile(
1103        ctx: &mut ExecCtx<C, E>,
1104        spec: Expr,
1105        scope: &ModPath,
1106        top_id: ExprId,
1107        lhs: &Arc<Expr>,
1108        rhs: &Arc<Expr>,
1109    ) -> Result<Node<C, E>> {
1110        let id = BindId::new();
1111        ctx.user.ref_var(id, top_id);
1112        let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1113        let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1114        let typ = arg.node.typ().clone();
1115        Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1116    }
1117}
1118
1119impl<C: Ctx, E: UserEvent> Update<C, E> for Sample<C, E> {
1120    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1121        if let Some(_) = self.trigger.update(ctx, event) {
1122            self.triggered += 1;
1123        }
1124        self.arg.update(ctx, event);
1125        let var = event.variables.get(&self.id).cloned();
1126        let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1127            self.triggered -= 1;
1128            self.arg.cached.clone()
1129        } else {
1130            var
1131        };
1132        if self.arg.cached.is_some() {
1133            while self.triggered > 0 {
1134                self.triggered -= 1;
1135                ctx.user.set_var(self.id, self.arg.cached.clone().unwrap());
1136            }
1137        }
1138        res
1139    }
1140
1141    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1142        ctx.user.unref_var(self.id, self.top_id);
1143        self.arg.node.delete(ctx);
1144        self.trigger.delete(ctx);
1145    }
1146
1147    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1148        self.arg.sleep(ctx);
1149        self.trigger.sleep(ctx);
1150    }
1151
1152    fn spec(&self) -> &Expr {
1153        &self.spec
1154    }
1155
1156    fn typ(&self) -> &Type {
1157        &self.typ
1158    }
1159
1160    fn refs(&self, refs: &mut Refs) {
1161        refs.refed.insert(self.id);
1162        self.arg.node.refs(refs);
1163        self.trigger.refs(refs);
1164    }
1165
1166    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1167        wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1168        wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1169    }
1170}