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