graphix_compiler/node/
mod.rs

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