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 compact_str::format_compact;
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    ) -> Result<Node<C, E>> {
141        match ctx.env.canonical_modpath(scope, name) {
142            None => bail!("at {} no such module {name}", spec.pos),
143            Some(_) => {
144                let used = ctx.env.used.get_or_default_cow(scope.clone());
145                Arc::make_mut(used).push(name.clone());
146                Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
147            }
148        }
149    }
150}
151
152impl<C: Ctx, E: UserEvent> Update<C, E> for Use {
153    fn update(
154        &mut self,
155        _ctx: &mut ExecCtx<C, E>,
156        _event: &mut Event<E>,
157    ) -> Option<Value> {
158        None
159    }
160
161    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
162        Ok(())
163    }
164
165    fn refs(&self, _refs: &mut Refs) {}
166
167    fn spec(&self) -> &Expr {
168        &self.spec
169    }
170
171    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
172        if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
173            Arc::make_mut(used).retain(|n| n != &self.name);
174            if used.is_empty() {
175                ctx.env.used.remove_cow(&self.scope);
176            }
177        }
178    }
179
180    fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
181
182    fn typ(&self) -> &Type {
183        &Type::Bottom
184    }
185}
186
187#[derive(Debug)]
188pub(crate) struct TypeDef {
189    spec: Expr,
190    scope: ModPath,
191    name: ArcStr,
192}
193
194impl TypeDef {
195    pub(crate) fn compile<C: Ctx, E: UserEvent>(
196        ctx: &mut ExecCtx<C, E>,
197        spec: Expr,
198        scope: &ModPath,
199        name: &ArcStr,
200        params: &Arc<[(TVar, Option<Type>)]>,
201        typ: &Type,
202    ) -> Result<Node<C, E>> {
203        let typ = typ.scope_refs(scope);
204        ctx.env
205            .deftype(scope, name, params.clone(), typ)
206            .with_context(|| format!("in typedef at {}", spec.pos))?;
207        let name = name.clone();
208        let scope = scope.clone();
209        Ok(Box::new(Self { spec, scope, name }))
210    }
211}
212
213impl<C: Ctx, E: UserEvent> Update<C, E> for TypeDef {
214    fn update(
215        &mut self,
216        _ctx: &mut ExecCtx<C, E>,
217        _event: &mut Event<E>,
218    ) -> Option<Value> {
219        None
220    }
221
222    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
223        Ok(())
224    }
225
226    fn refs(&self, _refs: &mut Refs) {}
227
228    fn spec(&self) -> &Expr {
229        &self.spec
230    }
231
232    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
233        ctx.env.undeftype(&self.scope, &self.name)
234    }
235
236    fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
237
238    fn typ(&self) -> &Type {
239        &Type::Bottom
240    }
241}
242
243#[derive(Debug)]
244pub(crate) struct Constant {
245    spec: Arc<Expr>,
246    value: Value,
247    typ: Type,
248}
249
250impl Constant {
251    pub(crate) fn compile<C: Ctx, E: UserEvent>(
252        spec: Expr,
253        value: &Value,
254    ) -> Result<Node<C, E>> {
255        let spec = Arc::new(spec);
256        let value = value.clone();
257        let typ = Type::Primitive(Typ::get(&value).into());
258        Ok(Box::new(Self { spec, value, typ }))
259    }
260}
261
262impl<C: Ctx, E: UserEvent> Update<C, E> for Constant {
263    fn update(
264        &mut self,
265        _ctx: &mut ExecCtx<C, E>,
266        event: &mut Event<E>,
267    ) -> Option<Value> {
268        if event.init {
269            Some(self.value.clone())
270        } else {
271            None
272        }
273    }
274
275    fn delete(&mut self, _ctx: &mut ExecCtx<C, E>) {}
276
277    fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
278
279    fn refs(&self, _refs: &mut Refs) {}
280
281    fn typ(&self) -> &Type {
282        &self.typ
283    }
284
285    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
286        Ok(())
287    }
288
289    fn spec(&self) -> &Expr {
290        &self.spec
291    }
292}
293
294// used for both mod and do
295#[derive(Debug)]
296pub(crate) struct Block<C: Ctx, E: UserEvent> {
297    module: bool,
298    spec: Expr,
299    children: Box<[Node<C, E>]>,
300}
301
302impl<C: Ctx, E: UserEvent> Block<C, E> {
303    pub(crate) fn compile(
304        ctx: &mut ExecCtx<C, E>,
305        spec: Expr,
306        scope: &ModPath,
307        top_id: ExprId,
308        module: bool,
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 { module, 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            if self.module {
349                wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
350            } else {
351                wrap!(n, n.typecheck(ctx))?
352            }
353        }
354        Ok(())
355    }
356
357    fn spec(&self) -> &Expr {
358        &self.spec
359    }
360}
361
362#[derive(Debug)]
363pub(crate) struct Bind<C: Ctx, E: UserEvent> {
364    spec: Expr,
365    typ: Type,
366    pattern: StructPatternNode,
367    node: Node<C, E>,
368}
369
370impl<C: Ctx, E: UserEvent> Bind<C, E> {
371    pub(crate) fn compile(
372        ctx: &mut ExecCtx<C, E>,
373        spec: Expr,
374        scope: &ModPath,
375        top_id: ExprId,
376        b: &expr::Bind,
377    ) -> Result<Node<C, E>> {
378        let expr::Bind { doc, pattern, typ, export: _, value } = b;
379        let node = compile(ctx, value.clone(), &scope, top_id)?;
380        let typ = match typ {
381            Some(typ) => typ.scope_refs(scope),
382            None => {
383                let typ = node.typ().clone();
384                let ptyp = pattern.infer_type_predicate(&ctx.env)?;
385                if !ptyp.contains(&ctx.env, &typ)? {
386                    typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
387                        bail!(
388                            "at {} match error {typ} can't be matched by {ptyp}",
389                            spec.pos
390                        )
391                    })?
392                }
393                typ
394            }
395        };
396        let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
397            .with_context(|| format!("at {}", spec.pos))?;
398        if pattern.is_refutable() {
399            bail!("at {} refutable patterns are not allowed in let", spec.pos);
400        }
401        if let Some(doc) = doc {
402            pattern.ids(&mut |id| {
403                if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
404                    b.doc = Some(doc.clone());
405                }
406            });
407        }
408        Ok(Box::new(Self { spec, typ, pattern, node }))
409    }
410}
411
412impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
413    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
414        if let Some(v) = self.node.update(ctx, event) {
415            self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
416        }
417        None
418    }
419
420    fn refs(&self, refs: &mut Refs) {
421        self.pattern.ids(&mut |id| {
422            refs.bound.insert(id);
423        });
424        self.node.refs(refs);
425    }
426
427    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
428        self.node.delete(ctx);
429        self.pattern.delete(ctx);
430    }
431
432    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
433        self.node.sleep(ctx);
434    }
435
436    fn typ(&self) -> &Type {
437        &self.typ
438    }
439
440    fn spec(&self) -> &Expr {
441        &self.spec
442    }
443
444    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
445        wrap!(self.node, self.node.typecheck(ctx))?;
446        wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
447        Ok(())
448    }
449}
450
451#[derive(Debug)]
452pub(crate) struct Ref {
453    spec: Arc<Expr>,
454    typ: Type,
455    id: BindId,
456    top_id: ExprId,
457}
458
459impl Ref {
460    pub(crate) fn compile<C: Ctx, E: UserEvent>(
461        ctx: &mut ExecCtx<C, E>,
462        spec: Expr,
463        scope: &ModPath,
464        top_id: ExprId,
465        name: &ModPath,
466    ) -> Result<Node<C, E>> {
467        match ctx.env.lookup_bind(scope, name) {
468            None => bail!("at {} {name} not defined", spec.pos),
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    ) -> Result<Node<C, E>> {
615        let id = match ctx.env.lookup_bind(scope, name) {
616            None => bail!("at {} {name} is undefined", spec.pos),
617            Some((_, env::Bind { id, .. })) => *id,
618        };
619        let node = compile(ctx, value.clone(), scope, top_id)?;
620        Ok(Box::new(Self { spec, node, id }))
621    }
622}
623
624impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
625    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
626        if let Some(v) = self.node.update(ctx, event) {
627            ctx.set_var(self.id, v)
628        }
629        None
630    }
631
632    fn spec(&self) -> &Expr {
633        &self.spec
634    }
635
636    fn typ(&self) -> &Type {
637        &Type::Bottom
638    }
639
640    fn refs(&self, refs: &mut Refs) {
641        self.node.refs(refs)
642    }
643
644    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
645        self.node.delete(ctx)
646    }
647
648    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
649        self.node.sleep(ctx);
650    }
651
652    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
653        wrap!(self.node, self.node.typecheck(ctx))?;
654        let bind = match ctx.env.by_id.get(&self.id) {
655            None => bail!("BUG missing bind {:?}", self.id),
656            Some(bind) => bind,
657        };
658        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
659    }
660}
661
662#[derive(Debug)]
663pub(crate) struct ConnectDeref<C: Ctx, E: UserEvent> {
664    spec: Expr,
665    rhs: Cached<C, E>,
666    src_id: BindId,
667    target_id: Option<BindId>,
668    top_id: ExprId,
669}
670
671impl<C: Ctx, E: UserEvent> ConnectDeref<C, E> {
672    pub(crate) fn compile(
673        ctx: &mut ExecCtx<C, E>,
674        spec: Expr,
675        scope: &ModPath,
676        top_id: ExprId,
677        name: &ModPath,
678        value: &Expr,
679    ) -> Result<Node<C, E>> {
680        let src_id = match ctx.env.lookup_bind(scope, name) {
681            None => bail!("at {} {name} is undefined", spec.pos),
682            Some((_, env::Bind { id, .. })) => *id,
683        };
684        ctx.user.ref_var(src_id, top_id);
685        let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
686        Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
687    }
688}
689
690impl<C: Ctx, E: UserEvent> Update<C, E> for ConnectDeref<C, E> {
691    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
692        let mut up = self.rhs.update(ctx, event);
693        if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
694            if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
695                self.target_id = Some(*target_id);
696                up = true;
697            }
698        }
699        if up {
700            if let Some(v) = &self.rhs.cached {
701                if let Some(id) = self.target_id {
702                    ctx.set_var(id, v.clone())
703                }
704            }
705        }
706        None
707    }
708
709    fn spec(&self) -> &Expr {
710        &self.spec
711    }
712
713    fn typ(&self) -> &Type {
714        &Type::Bottom
715    }
716
717    fn refs(&self, refs: &mut Refs) {
718        refs.refed.insert(self.src_id);
719        self.rhs.node.refs(refs)
720    }
721
722    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
723        ctx.user.unref_var(self.src_id, self.top_id);
724        self.rhs.node.delete(ctx)
725    }
726
727    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
728        self.rhs.sleep(ctx);
729    }
730
731    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
732        wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
733        let bind = match ctx.env.by_id.get(&self.src_id) {
734            None => bail!("BUG missing bind {:?}", self.src_id),
735            Some(bind) => bind,
736        };
737        let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
738        wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
739    }
740}
741
742#[derive(Debug)]
743pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
744    spec: Expr,
745    typ: Type,
746    child: Node<C, E>,
747    id: BindId,
748}
749
750impl<C: Ctx, E: UserEvent> ByRef<C, E> {
751    pub(crate) fn compile(
752        ctx: &mut ExecCtx<C, E>,
753        spec: Expr,
754        scope: &ModPath,
755        top_id: ExprId,
756        expr: &Expr,
757    ) -> Result<Node<C, E>> {
758        let child = compile(ctx, expr.clone(), scope, top_id)?;
759        let id = BindId::new();
760        if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
761            ctx.env.byref_chain.insert_cow(id, c.id);
762        }
763        let typ = Type::ByRef(Arc::new(child.typ().clone()));
764        Ok(Box::new(Self { spec, typ, child, id }))
765    }
766}
767
768impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
769    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
770        if let Some(v) = self.child.update(ctx, event) {
771            ctx.set_var(self.id, v);
772        }
773        if event.init {
774            Some(Value::U64(self.id.inner()))
775        } else {
776            None
777        }
778    }
779
780    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
781        ctx.env.byref_chain.remove_cow(&self.id);
782        self.child.delete(ctx)
783    }
784
785    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
786        self.child.sleep(ctx);
787    }
788
789    fn spec(&self) -> &Expr {
790        &self.spec
791    }
792
793    fn typ(&self) -> &Type {
794        &self.typ
795    }
796
797    fn refs(&self, refs: &mut Refs) {
798        self.child.refs(refs)
799    }
800
801    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
802        wrap!(self.child, self.child.typecheck(ctx))?;
803        let t = Type::ByRef(Arc::new(self.child.typ().clone()));
804        wrap!(self, self.typ.check_contains(&ctx.env, &t))
805    }
806}
807
808#[derive(Debug)]
809pub(crate) struct Deref<C: Ctx, E: UserEvent> {
810    spec: Expr,
811    typ: Type,
812    child: Node<C, E>,
813    id: Option<BindId>,
814    top_id: ExprId,
815}
816
817impl<C: Ctx, E: UserEvent> Deref<C, E> {
818    pub(crate) fn compile(
819        ctx: &mut ExecCtx<C, E>,
820        spec: Expr,
821        scope: &ModPath,
822        top_id: ExprId,
823        expr: &Expr,
824    ) -> Result<Node<C, E>> {
825        let child = compile(ctx, expr.clone(), scope, top_id)?;
826        let typ = Type::empty_tvar();
827        Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
828    }
829}
830
831impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
832    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
833        if let Some(v) = self.child.update(ctx, event) {
834            match v {
835                Value::U64(i) | Value::V64(i) => {
836                    let new_id = BindId::from(i);
837                    if self.id != Some(new_id) {
838                        if let Some(old) = self.id {
839                            ctx.user.unref_var(old, self.top_id);
840                        }
841                        ctx.user.ref_var(new_id, self.top_id);
842                        self.id = Some(new_id);
843                    }
844                }
845                _ => return err!("expected u64 bind id"),
846            }
847        }
848        self.id.and_then(|id| event.variables.get(&id).cloned())
849    }
850
851    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
852        if let Some(id) = self.id.take() {
853            ctx.user.unref_var(id, self.top_id);
854        }
855        self.child.delete(ctx);
856    }
857
858    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
859        self.child.sleep(ctx);
860    }
861
862    fn spec(&self) -> &Expr {
863        &self.spec
864    }
865
866    fn typ(&self) -> &Type {
867        &self.typ
868    }
869
870    fn refs(&self, refs: &mut Refs) {
871        self.child.refs(refs);
872        if let Some(id) = self.id {
873            refs.refed.insert(id);
874        }
875    }
876
877    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
878        wrap!(self.child, self.child.typecheck(ctx))?;
879        let typ = match self.child.typ() {
880            Type::ByRef(t) => (**t).clone(),
881            _ => bail!("expected reference"),
882        };
883        wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
884        Ok(())
885    }
886}
887
888#[derive(Debug)]
889pub(crate) struct Qop<C: Ctx, E: UserEvent> {
890    spec: Expr,
891    typ: Type,
892    id: BindId,
893    n: Node<C, E>,
894}
895
896impl<C: Ctx, E: UserEvent> Qop<C, E> {
897    pub(crate) fn compile(
898        ctx: &mut ExecCtx<C, E>,
899        spec: Expr,
900        scope: &ModPath,
901        top_id: ExprId,
902        e: &Expr,
903    ) -> Result<Node<C, E>> {
904        let n = compile(ctx, e.clone(), scope, top_id)?;
905        match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
906            None => bail!("at {} BUG: errors is undefined", spec.pos),
907            Some((_, bind)) => {
908                let typ = Type::empty_tvar();
909                Ok(Box::new(Self { spec, typ, id: bind.id, n }))
910            }
911        }
912    }
913}
914
915impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
916    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
917        match self.n.update(ctx, event) {
918            None => None,
919            Some(Value::Error(e)) => {
920                let e = format_compact!("{} at {} {e}", self.spec.ori, self.spec.pos);
921                ctx.set_var(self.id, Value::Error(e.as_str().into()));
922                None
923            }
924            Some(v) => Some(v),
925        }
926    }
927
928    fn typ(&self) -> &Type {
929        &self.typ
930    }
931
932    fn spec(&self) -> &Expr {
933        &self.spec
934    }
935
936    fn refs(&self, refs: &mut Refs) {
937        self.n.refs(refs)
938    }
939
940    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
941        self.n.delete(ctx)
942    }
943
944    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
945        self.n.sleep(ctx);
946    }
947
948    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
949        wrap!(self.n, self.n.typecheck(ctx))?;
950        let bind =
951            ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
952        let err = Type::Primitive(Typ::Error.into());
953        wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
954        wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
955        if !self.n.typ().contains(&ctx.env, &err)? {
956            bail!("cannot use the ? operator on a non error type")
957        }
958        let rtyp = self.n.typ().diff(&ctx.env, &err)?;
959        wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
960        Ok(())
961    }
962}
963
964#[derive(Debug)]
965pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
966    spec: Expr,
967    typ: Type,
968    target: Type,
969    n: Node<C, E>,
970}
971
972impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
973    pub(crate) fn compile(
974        ctx: &mut ExecCtx<C, E>,
975        spec: Expr,
976        scope: &ModPath,
977        top_id: ExprId,
978        expr: &Expr,
979        typ: &Type,
980    ) -> Result<Node<C, E>> {
981        let n = compile(ctx, expr.clone(), scope, top_id)?;
982        let target = typ.scope_refs(scope);
983        if let Err(e) = target.check_cast(&ctx.env) {
984            bail!("in cast at {} {e}", spec.pos);
985        }
986        let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
987        Ok(Box::new(Self { spec, typ, target, n }))
988    }
989}
990
991impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
992    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
993        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
994    }
995
996    fn spec(&self) -> &Expr {
997        &self.spec
998    }
999
1000    fn typ(&self) -> &Type {
1001        &self.typ
1002    }
1003
1004    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1005        self.n.delete(ctx)
1006    }
1007
1008    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1009        self.n.sleep(ctx);
1010    }
1011
1012    fn refs(&self, refs: &mut Refs) {
1013        self.n.refs(refs)
1014    }
1015
1016    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1017        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1018    }
1019}
1020
1021#[derive(Debug)]
1022pub(crate) struct Any<C: Ctx, E: UserEvent> {
1023    spec: Expr,
1024    typ: Type,
1025    n: Box<[Node<C, E>]>,
1026}
1027
1028impl<C: Ctx, E: UserEvent> Any<C, E> {
1029    pub(crate) fn compile(
1030        ctx: &mut ExecCtx<C, E>,
1031        spec: Expr,
1032        scope: &ModPath,
1033        top_id: ExprId,
1034        args: &[Expr],
1035    ) -> Result<Node<C, E>> {
1036        let n = args
1037            .iter()
1038            .map(|e| compile(ctx, e.clone(), scope, top_id))
1039            .collect::<Result<Box<[_]>>>()?;
1040        let typ =
1041            Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1042        Ok(Box::new(Self { spec, typ, n }))
1043    }
1044}
1045
1046impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1047    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1048        self.n
1049            .iter_mut()
1050            .filter_map(|s| s.update(ctx, event))
1051            .fold(None, |r, v| r.or(Some(v)))
1052    }
1053
1054    fn spec(&self) -> &Expr {
1055        &self.spec
1056    }
1057
1058    fn typ(&self) -> &Type {
1059        &self.typ
1060    }
1061
1062    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1063        self.n.iter_mut().for_each(|n| n.delete(ctx))
1064    }
1065
1066    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1067        self.n.iter_mut().for_each(|n| n.sleep(ctx))
1068    }
1069
1070    fn refs(&self, refs: &mut Refs) {
1071        self.n.iter().for_each(|n| n.refs(refs))
1072    }
1073
1074    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1075        for n in self.n.iter_mut() {
1076            wrap!(n, n.typecheck(ctx))?
1077        }
1078        let rtyp = Type::Primitive(BitFlags::empty());
1079        let rtyp = wrap!(
1080            self,
1081            self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1082        )?;
1083        Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1084    }
1085}
1086
1087#[derive(Debug)]
1088struct Sample<C: Ctx, E: UserEvent> {
1089    spec: Expr,
1090    triggered: usize,
1091    typ: Type,
1092    id: BindId,
1093    top_id: ExprId,
1094    trigger: Node<C, E>,
1095    arg: Cached<C, E>,
1096}
1097
1098impl<C: Ctx, E: UserEvent> Sample<C, E> {
1099    pub(crate) fn compile(
1100        ctx: &mut ExecCtx<C, E>,
1101        spec: Expr,
1102        scope: &ModPath,
1103        top_id: ExprId,
1104        lhs: &Arc<Expr>,
1105        rhs: &Arc<Expr>,
1106    ) -> Result<Node<C, E>> {
1107        let id = BindId::new();
1108        ctx.user.ref_var(id, top_id);
1109        let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1110        let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1111        let typ = arg.node.typ().clone();
1112        Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1113    }
1114}
1115
1116impl<C: Ctx, E: UserEvent> Update<C, E> for Sample<C, E> {
1117    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1118        if let Some(_) = self.trigger.update(ctx, event) {
1119            self.triggered += 1;
1120        }
1121        self.arg.update(ctx, event);
1122        let var = event.variables.get(&self.id).cloned();
1123        let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1124            self.triggered -= 1;
1125            self.arg.cached.clone()
1126        } else {
1127            var
1128        };
1129        if self.arg.cached.is_some() {
1130            while self.triggered > 0 {
1131                self.triggered -= 1;
1132                ctx.user.set_var(self.id, self.arg.cached.clone().unwrap());
1133            }
1134        }
1135        res
1136    }
1137
1138    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1139        ctx.user.unref_var(self.id, self.top_id);
1140        self.arg.node.delete(ctx);
1141        self.trigger.delete(ctx);
1142    }
1143
1144    fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1145        self.arg.sleep(ctx);
1146        self.trigger.sleep(ctx);
1147    }
1148
1149    fn spec(&self) -> &Expr {
1150        &self.spec
1151    }
1152
1153    fn typ(&self) -> &Type {
1154        &self.typ
1155    }
1156
1157    fn refs(&self, refs: &mut Refs) {
1158        refs.refed.insert(self.id);
1159        self.arg.node.refs(refs);
1160        self.trigger.refs(refs);
1161    }
1162
1163    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1164        wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1165        wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1166    }
1167}