netidx_bscript/node/
mod.rs

1use crate::{
2    env, err,
3    expr::{self, Expr, ExprId, ExprKind, ModPath},
4    typ::{self, TVar, Type},
5    BindId, Ctx, Event, ExecCtx, Node, Update, UserEvent,
6};
7use anyhow::{anyhow, bail, Context, Result};
8use arcstr::{literal, ArcStr};
9use combine::stream::position::SourcePosition;
10use compiler::compile;
11use enumflags2::BitFlags;
12use netidx_netproto::{
13    valarray::ValArray,
14    value::{NakedValue, Typ, Value},
15};
16use pattern::StructPatternNode;
17use smallvec::{smallvec, SmallVec};
18use std::{cell::RefCell, iter, sync::LazyLock};
19use triomphe::Arc;
20
21pub(crate) mod callsite;
22pub(crate) mod compiler;
23pub mod genn;
24pub(crate) mod lambda;
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            Err(e) => Err(anyhow!("in expr: {}, type error: {e}", $n.spec())),
34        }
35    };
36}
37
38macro_rules! update_args {
39    ($args:expr, $ctx:expr, $event:expr) => {{
40        let mut updated = false;
41        let mut determined = true;
42        for n in $args.iter_mut() {
43            updated |= n.update($ctx, $event);
44            determined &= n.cached.is_some();
45        }
46        (updated, determined)
47    }};
48}
49
50static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
51    Arc::new(
52        ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
53    )
54});
55
56#[derive(Debug)]
57pub(crate) struct Nop {
58    pub typ: Type,
59}
60
61impl Nop {
62    pub(crate) fn new<C: Ctx, E: UserEvent>(typ: Type) -> Node<C, E> {
63        Box::new(Nop { typ })
64    }
65}
66
67impl<C: Ctx, E: UserEvent> Update<C, E> for Nop {
68    fn update(
69        &mut self,
70        _ctx: &mut ExecCtx<C, E>,
71        _event: &mut Event<E>,
72    ) -> Option<Value> {
73        None
74    }
75
76    fn delete(&mut self, _ctx: &mut ExecCtx<C, E>) {}
77
78    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
79        Ok(())
80    }
81
82    fn spec(&self) -> &Expr {
83        &NOP
84    }
85
86    fn typ(&self) -> &Type {
87        &self.typ
88    }
89
90    fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
91}
92
93#[derive(Debug)]
94struct Cached<C: Ctx, E: UserEvent> {
95    cached: Option<Value>,
96    node: Node<C, E>,
97}
98
99impl<C: Ctx, E: UserEvent> Cached<C, E> {
100    fn new(node: Node<C, E>) -> Self {
101        Self { cached: None, node }
102    }
103
104    /// update the node, return whether the node updated. If it did,
105    /// the updated value will be stored in the cached field, if not,
106    /// the previous value will remain there.
107    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> bool {
108        match self.node.update(ctx, event) {
109            None => false,
110            Some(v) => {
111                self.cached = Some(v);
112                true
113            }
114        }
115    }
116}
117
118#[derive(Debug)]
119pub(crate) struct ArrayRef<C: Ctx, E: UserEvent> {
120    source: Cached<C, E>,
121    i: Cached<C, E>,
122    spec: Expr,
123    typ: Type,
124}
125
126impl<C: Ctx, E: UserEvent> ArrayRef<C, E> {
127    pub(crate) fn compile(
128        ctx: &mut ExecCtx<C, E>,
129        spec: Expr,
130        scope: &ModPath,
131        top_id: ExprId,
132        source: &Expr,
133        i: &Expr,
134    ) -> Result<Node<C, E>> {
135        let source = Cached::new(compile(ctx, source.clone(), scope, top_id)?);
136        let i = Cached::new(compile(ctx, i.clone(), scope, top_id)?);
137        let ert = Type::Primitive(Typ::Error.into());
138        let typ = match &source.node.typ() {
139            Type::Array(et) => Type::Set(Arc::from_iter([(**et).clone(), ert.clone()])),
140            _ => Type::Set(Arc::from_iter([Type::empty_tvar(), ert.clone()])),
141        };
142        Ok(Box::new(Self { source, i, spec, typ }))
143    }
144}
145
146impl<C: Ctx, E: UserEvent> Update<C, E> for ArrayRef<C, E> {
147    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
148        let up = self.source.update(ctx, event);
149        let up = self.i.update(ctx, event) || up;
150        if !up {
151            return None;
152        }
153        let i = match &self.i.cached {
154            Some(Value::I64(i)) => *i,
155            Some(v) => match v.clone().cast_to::<i64>() {
156                Ok(i) => i,
157                Err(_) => return err!("op::index(array, index): expected an integer"),
158            },
159            None => return None,
160        };
161        match &self.source.cached {
162            Some(Value::Array(elts)) if i >= 0 => {
163                let i = i as usize;
164                if i < elts.len() {
165                    Some(elts[i].clone())
166                } else {
167                    err!("array index out of bounds")
168                }
169            }
170            Some(Value::Array(elts)) if i < 0 => {
171                let len = elts.len();
172                let i = len as i64 + i;
173                if i > 0 {
174                    Some(elts[i as usize].clone())
175                } else {
176                    err!("array index out of bounds")
177                }
178            }
179            None => None,
180            _ => err!("op::index(array, index): expected an array"),
181        }
182    }
183
184    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
185        wrap!(self.source.node, self.source.node.typecheck(ctx))?;
186        wrap!(self.i.node, self.i.node.typecheck(ctx))?;
187        let at = Type::Array(Arc::new(self.typ.clone()));
188        wrap!(self, at.check_contains(&ctx.env, self.source.node.typ()))?;
189        let int = Type::Primitive(Typ::integer());
190        wrap!(self.i.node, int.check_contains(&ctx.env, self.i.node.typ()))
191    }
192
193    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
194        self.source.node.refs(f);
195        self.i.node.refs(f);
196    }
197
198    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
199        self.source.node.delete(ctx);
200        self.i.node.delete(ctx);
201    }
202
203    fn typ(&self) -> &Type {
204        &self.typ
205    }
206
207    fn spec(&self) -> &Expr {
208        &self.spec
209    }
210}
211
212#[derive(Debug)]
213pub(crate) struct ArraySlice<C: Ctx, E: UserEvent> {
214    source: Cached<C, E>,
215    start: Option<Cached<C, E>>,
216    end: Option<Cached<C, E>>,
217    spec: Expr,
218    typ: Type,
219}
220
221impl<C: Ctx, E: UserEvent> ArraySlice<C, E> {
222    pub(crate) fn compile(
223        ctx: &mut ExecCtx<C, E>,
224        spec: Expr,
225        scope: &ModPath,
226        top_id: ExprId,
227        source: &Expr,
228        start: &Option<Arc<Expr>>,
229        end: &Option<Arc<Expr>>,
230    ) -> Result<Node<C, E>> {
231        let source = Cached::new(compile(ctx, source.clone(), scope, top_id)?);
232        let start = start
233            .as_ref()
234            .map(|e| compile(ctx, (**e).clone(), scope, top_id).map(Cached::new))
235            .transpose()?;
236        let end = end
237            .as_ref()
238            .map(|e| compile(ctx, (**e).clone(), scope, top_id).map(Cached::new))
239            .transpose()?;
240        let typ = Type::Set(Arc::from_iter([
241            source.node.typ().clone(),
242            Type::Primitive(Typ::Error.into()),
243        ]));
244        Ok(Box::new(Self { spec, typ, source, start, end }))
245    }
246}
247
248impl<C: Ctx, E: UserEvent> Update<C, E> for ArraySlice<C, E> {
249    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
250        macro_rules! number {
251            ($e:expr) => {
252                match $e.clone().cast_to::<usize>() {
253                    Ok(i) => i,
254                    Err(_) => return err!("expected a non negative number"),
255                }
256            };
257        }
258        macro_rules! bound {
259            ($bound:expr) => {{
260                match $bound.cached.as_ref() {
261                    None => return None,
262                    Some(Value::U64(i) | Value::V64(i)) => Some(*i as usize),
263                    Some(v) => Some(number!(v)),
264                }
265            }};
266        }
267        let up = self.source.update(ctx, event);
268        let up = self.start.as_mut().map(|c| c.update(ctx, event)).unwrap_or(false) || up;
269        let up = self.end.as_mut().map(|c| c.update(ctx, event)).unwrap_or(false) || up;
270        if !up {
271            return None;
272        }
273        let (start, end) = match (&self.start, &self.end) {
274            (None, None) => (None, None),
275            (Some(c), None) => (bound!(c), None),
276            (None, Some(c)) => (None, bound!(c)),
277            (Some(c0), Some(c1)) => (bound!(c0), bound!(c1)),
278        };
279        match &self.source.cached {
280            Some(Value::Array(elts)) => match (start, end) {
281                (None, None) => Some(Value::Array(elts.clone())),
282                (Some(i), Some(j)) => match elts.subslice(i..j) {
283                    Ok(a) => Some(Value::Array(a)),
284                    Err(e) => Some(Value::Error(e.to_string().into())),
285                },
286                (Some(i), None) => match elts.subslice(i..) {
287                    Ok(a) => Some(Value::Array(a)),
288                    Err(e) => Some(Value::Error(e.to_string().into())),
289                },
290                (None, Some(i)) => match elts.subslice(..i) {
291                    Ok(a) => Some(Value::Array(a)),
292                    Err(e) => Some(Value::Error(e.to_string().into())),
293                },
294            },
295            Some(_) => err!("expected array"),
296            None => None,
297        }
298    }
299
300    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
301        wrap!(self.source.node, self.source.node.typecheck(ctx))?;
302        let it = Type::Primitive(Typ::unsigned_integer());
303        wrap!(
304            self.source.node,
305            self.typ.check_contains(&ctx.env, &self.source.node.typ())
306        )?;
307        if let Some(start) = self.start.as_mut() {
308            wrap!(start.node, start.node.typecheck(ctx))?;
309            wrap!(start.node, it.check_contains(&ctx.env, &start.node.typ()))?;
310        }
311        if let Some(end) = self.end.as_mut() {
312            wrap!(end.node, end.node.typecheck(ctx))?;
313            wrap!(end.node, it.check_contains(&ctx.env, &end.node.typ()))?;
314        }
315        Ok(())
316    }
317
318    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
319        self.source.node.refs(f);
320        if let Some(start) = &self.start {
321            start.node.refs(f)
322        }
323        if let Some(end) = &self.end {
324            end.node.refs(f)
325        }
326    }
327
328    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
329        self.source.node.delete(ctx);
330        if let Some(start) = &mut self.start {
331            start.node.delete(ctx);
332        }
333        if let Some(end) = &mut self.end {
334            end.node.delete(ctx);
335        }
336    }
337
338    fn typ(&self) -> &Type {
339        &self.typ
340    }
341
342    fn spec(&self) -> &Expr {
343        &self.spec
344    }
345}
346
347#[derive(Debug)]
348pub(crate) struct Use {
349    spec: Expr,
350    scope: ModPath,
351    name: ModPath,
352}
353
354impl Use {
355    pub(crate) fn compile<C: Ctx, E: UserEvent>(
356        ctx: &mut ExecCtx<C, E>,
357        spec: Expr,
358        scope: &ModPath,
359        name: &ModPath,
360        pos: &SourcePosition,
361    ) -> Result<Node<C, E>> {
362        match ctx.env.canonical_modpath(scope, name) {
363            None => bail!("at {pos} no such module {name}"),
364            Some(_) => {
365                let used = ctx.env.used.get_or_default_cow(scope.clone());
366                Arc::make_mut(used).push(name.clone());
367                Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
368            }
369        }
370    }
371}
372
373impl<C: Ctx, E: UserEvent> Update<C, E> for Use {
374    fn update(
375        &mut self,
376        _ctx: &mut ExecCtx<C, E>,
377        _event: &mut Event<E>,
378    ) -> Option<Value> {
379        None
380    }
381
382    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
383        Ok(())
384    }
385
386    fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
387
388    fn spec(&self) -> &Expr {
389        &self.spec
390    }
391
392    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
393        if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
394            Arc::make_mut(used).retain(|n| n != &self.name);
395            if used.is_empty() {
396                ctx.env.used.remove_cow(&self.scope);
397            }
398        }
399    }
400
401    fn typ(&self) -> &Type {
402        &Type::Bottom
403    }
404}
405
406#[derive(Debug)]
407pub(crate) struct TypeDef {
408    spec: Expr,
409    scope: ModPath,
410    name: ArcStr,
411}
412
413impl TypeDef {
414    pub(crate) fn compile<C: Ctx, E: UserEvent>(
415        ctx: &mut ExecCtx<C, E>,
416        spec: Expr,
417        scope: &ModPath,
418        name: &ArcStr,
419        params: &Arc<[(TVar, Option<Type>)]>,
420        typ: &Type,
421        pos: &SourcePosition,
422    ) -> Result<Node<C, E>> {
423        let typ = typ.scope_refs(scope);
424        ctx.env
425            .deftype(scope, name, params.clone(), typ)
426            .with_context(|| format!("in typedef at {pos}"))?;
427        let name = name.clone();
428        let scope = scope.clone();
429        Ok(Box::new(Self { spec, scope, name }))
430    }
431}
432
433impl<C: Ctx, E: UserEvent> Update<C, E> for TypeDef {
434    fn update(
435        &mut self,
436        _ctx: &mut ExecCtx<C, E>,
437        _event: &mut Event<E>,
438    ) -> Option<Value> {
439        None
440    }
441
442    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
443        Ok(())
444    }
445
446    fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
447
448    fn spec(&self) -> &Expr {
449        &self.spec
450    }
451
452    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
453        ctx.env.undeftype(&self.scope, &self.name)
454    }
455
456    fn typ(&self) -> &Type {
457        &Type::Bottom
458    }
459}
460
461#[derive(Debug)]
462pub(crate) struct Constant {
463    spec: Arc<Expr>,
464    value: Value,
465    typ: Type,
466}
467
468impl Constant {
469    pub(crate) fn compile<C: Ctx, E: UserEvent>(
470        spec: Expr,
471        value: &Value,
472    ) -> Result<Node<C, E>> {
473        let spec = Arc::new(spec);
474        let value = value.clone();
475        let typ = Type::Primitive(Typ::get(&value).into());
476        Ok(Box::new(Self { spec, value, typ }))
477    }
478}
479
480impl<C: Ctx, E: UserEvent> Update<C, E> for Constant {
481    fn update(
482        &mut self,
483        _ctx: &mut ExecCtx<C, E>,
484        event: &mut Event<E>,
485    ) -> Option<Value> {
486        if event.init {
487            Some(self.value.clone())
488        } else {
489            None
490        }
491    }
492
493    fn delete(&mut self, _ctx: &mut ExecCtx<C, E>) {}
494
495    fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
496
497    fn typ(&self) -> &Type {
498        &self.typ
499    }
500
501    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
502        Ok(())
503    }
504
505    fn spec(&self) -> &Expr {
506        &self.spec
507    }
508}
509
510// used for both mod and do
511#[derive(Debug)]
512pub(crate) struct Block<C: Ctx, E: UserEvent> {
513    spec: Expr,
514    children: Box<[Node<C, E>]>,
515}
516
517impl<C: Ctx, E: UserEvent> Block<C, E> {
518    pub(crate) fn compile(
519        ctx: &mut ExecCtx<C, E>,
520        spec: Expr,
521        scope: &ModPath,
522        top_id: ExprId,
523        exprs: &Arc<[Expr]>,
524    ) -> Result<Node<C, E>> {
525        let children = exprs
526            .iter()
527            .map(|e| compile(ctx, e.clone(), scope, top_id))
528            .collect::<Result<Box<[Node<C, E>]>>>()?;
529        Ok(Box::new(Self { spec, children }))
530    }
531}
532
533impl<C: Ctx, E: UserEvent> Update<C, E> for Block<C, E> {
534    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
535        self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
536    }
537
538    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
539        for n in &mut self.children {
540            n.delete(ctx)
541        }
542    }
543
544    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
545        for n in &self.children {
546            n.refs(f)
547        }
548    }
549
550    fn typ(&self) -> &Type {
551        &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
552    }
553
554    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
555        for n in &mut self.children {
556            wrap!(n, n.typecheck(ctx))?
557        }
558        Ok(())
559    }
560
561    fn spec(&self) -> &Expr {
562        &self.spec
563    }
564}
565
566#[derive(Debug)]
567pub(crate) struct Bind<C: Ctx, E: UserEvent> {
568    spec: Expr,
569    typ: Type,
570    pattern: StructPatternNode,
571    node: Node<C, E>,
572}
573
574impl<C: Ctx, E: UserEvent> Bind<C, E> {
575    pub(crate) fn compile(
576        ctx: &mut ExecCtx<C, E>,
577        spec: Expr,
578        scope: &ModPath,
579        top_id: ExprId,
580        b: &expr::Bind,
581        pos: &SourcePosition,
582    ) -> Result<Node<C, E>> {
583        let expr::Bind { doc, pattern, typ, export: _, value } = b;
584        let node = compile(ctx, value.clone(), &scope, top_id)?;
585        let typ = match typ {
586            Some(typ) => typ.scope_refs(scope),
587            None => {
588                let typ = node.typ().clone();
589                let ptyp = pattern.infer_type_predicate();
590                if !ptyp.contains(&ctx.env, &typ)? {
591                    typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
592                        bail!("at {pos} match error {typ} can't be matched by {ptyp}")
593                    })?
594                }
595                typ
596            }
597        };
598        let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
599            .with_context(|| format!("at {pos}"))?;
600        if pattern.is_refutable() {
601            bail!("at {pos} refutable patterns are not allowed in let");
602        }
603        if let Some(doc) = doc {
604            pattern.ids(&mut |id| {
605                if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
606                    b.doc = Some(doc.clone());
607                }
608            });
609        }
610        Ok(Box::new(Self { spec, typ, pattern, node }))
611    }
612}
613
614impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
615    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
616        if let Some(v) = self.node.update(ctx, event) {
617            self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
618        }
619        None
620    }
621
622    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
623        self.pattern.ids(f);
624        self.node.refs(f);
625    }
626
627    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
628        self.node.delete(ctx);
629    }
630
631    fn typ(&self) -> &Type {
632        &self.typ
633    }
634
635    fn spec(&self) -> &Expr {
636        &self.spec
637    }
638
639    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
640        wrap!(self.node, self.node.typecheck(ctx))?;
641        wrap!(self.node, self.typ.check_contains(&ctx.env, &self.node.typ()))?;
642        Ok(())
643    }
644}
645
646#[derive(Debug)]
647pub(crate) struct Ref {
648    spec: Arc<Expr>,
649    typ: Type,
650    id: BindId,
651    top_id: ExprId,
652}
653
654impl Ref {
655    pub(crate) fn compile<C: Ctx, E: UserEvent>(
656        ctx: &mut ExecCtx<C, E>,
657        spec: Expr,
658        scope: &ModPath,
659        top_id: ExprId,
660        name: &ModPath,
661        pos: &SourcePosition,
662    ) -> Result<Node<C, E>> {
663        match ctx.env.lookup_bind(scope, name) {
664            None => bail!("at {pos} {name} not defined"),
665            Some((_, bind)) => {
666                ctx.user.ref_var(bind.id, top_id);
667                let typ = bind.typ.clone();
668                let spec = Arc::new(spec);
669                Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
670            }
671        }
672    }
673}
674
675impl<C: Ctx, E: UserEvent> Update<C, E> for Ref {
676    fn update(
677        &mut self,
678        _ctx: &mut ExecCtx<C, E>,
679        event: &mut Event<E>,
680    ) -> Option<Value> {
681        event.variables.get(&self.id).map(|v| v.clone())
682    }
683
684    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
685        f(self.id)
686    }
687
688    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
689        ctx.user.unref_var(self.id, self.top_id)
690    }
691
692    fn spec(&self) -> &Expr {
693        &self.spec
694    }
695
696    fn typ(&self) -> &Type {
697        &self.typ
698    }
699
700    fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
701        Ok(())
702    }
703}
704
705#[derive(Debug)]
706pub(crate) struct StructRef<C: Ctx, E: UserEvent> {
707    spec: Expr,
708    typ: Type,
709    source: Node<C, E>,
710    field: usize,
711}
712
713impl<C: Ctx, E: UserEvent> StructRef<C, E> {
714    pub(crate) fn compile(
715        ctx: &mut ExecCtx<C, E>,
716        spec: Expr,
717        scope: &ModPath,
718        top_id: ExprId,
719        source: &Expr,
720        field: &ArcStr,
721    ) -> Result<Node<C, E>> {
722        let source = compile(ctx, source.clone(), scope, top_id)?;
723        let (typ, field) = match &source.typ() {
724            Type::Struct(flds) => flds
725                .iter()
726                .enumerate()
727                .find_map(
728                    |(i, (n, t))| {
729                        if field == n {
730                            Some((t.clone(), i))
731                        } else {
732                            None
733                        }
734                    },
735                )
736                .unwrap_or_else(|| (Type::empty_tvar(), 0)),
737            _ => (Type::empty_tvar(), 0),
738        };
739        // typcheck will resolve the field index if we didn't find it already
740        Ok(Box::new(Self { spec, typ, source, field }))
741    }
742}
743
744impl<C: Ctx, E: UserEvent> Update<C, E> for StructRef<C, E> {
745    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
746        match self.source.update(ctx, event) {
747            Some(Value::Array(a)) => a.get(self.field).and_then(|v| match v {
748                Value::Array(a) if a.len() == 2 => Some(a[1].clone()),
749                _ => None,
750            }),
751            Some(_) | None => None,
752        }
753    }
754
755    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
756        self.source.refs(f)
757    }
758
759    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
760        self.source.delete(ctx)
761    }
762
763    fn typ(&self) -> &Type {
764        &self.typ
765    }
766
767    fn spec(&self) -> &Expr {
768        &self.spec
769    }
770
771    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
772        wrap!(self.source, self.source.typecheck(ctx))?;
773        let field = match &self.spec.kind {
774            ExprKind::StructRef { source: _, field } => field.clone(),
775            _ => bail!("BUG: miscompiled struct ref"),
776        };
777        let etyp = self.source.typ().with_deref(|typ| match typ {
778            Some(Type::Struct(flds)) => {
779                let typ = flds.iter().enumerate().find_map(|(i, (n, t))| {
780                    if &field == n {
781                        Some((i, t.clone()))
782                    } else {
783                        None
784                    }
785                });
786                match typ {
787                    Some((i, t)) => Ok((i, t)),
788                    None => bail!("in struct, unknown field {field}"),
789                }
790            }
791            None => bail!("type must be known, annotations needed"),
792            _ => bail!("expected struct"),
793        });
794        let (idx, typ) = wrap!(self, etyp)?;
795        self.field = idx;
796        wrap!(self, self.typ.check_contains(&ctx.env, &typ))
797    }
798}
799
800#[derive(Debug)]
801pub(crate) struct TupleRef<C: Ctx, E: UserEvent> {
802    spec: Expr,
803    typ: Type,
804    source: Node<C, E>,
805    field: usize,
806}
807
808impl<C: Ctx, E: UserEvent> TupleRef<C, E> {
809    pub(crate) fn compile(
810        ctx: &mut ExecCtx<C, E>,
811        spec: Expr,
812        scope: &ModPath,
813        top_id: ExprId,
814        source: &Expr,
815        field: &usize,
816    ) -> Result<Node<C, E>> {
817        let source = compile(ctx, source.clone(), scope, top_id)?;
818        let field = *field;
819        let typ = match &source.typ() {
820            Type::Tuple(ts) => {
821                ts.get(field).map(|t| t.clone()).unwrap_or_else(Type::empty_tvar)
822            }
823            _ => Type::empty_tvar(),
824        };
825        Ok(Box::new(Self { spec, typ, source, field }))
826    }
827}
828
829impl<C: Ctx, E: UserEvent> Update<C, E> for TupleRef<C, E> {
830    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
831        self.source.update(ctx, event).and_then(|v| match v {
832            Value::Array(a) => a.get(self.field).map(|v| v.clone()),
833            _ => None,
834        })
835    }
836
837    fn spec(&self) -> &Expr {
838        &self.spec
839    }
840
841    fn typ(&self) -> &Type {
842        &self.typ
843    }
844
845    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
846        self.source.refs(f)
847    }
848
849    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
850        self.source.delete(ctx)
851    }
852
853    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
854        wrap!(self.source, self.source.typecheck(ctx))?;
855        let etyp = self.source.typ().with_deref(|typ| match typ {
856            Some(Type::Tuple(flds)) if flds.len() > self.field => {
857                Ok(flds[self.field].clone())
858            }
859            None => bail!("type must be known, annotations needed"),
860            _ => bail!("expected tuple with at least {} elements", self.field),
861        });
862        let etyp = wrap!(self, etyp)?;
863        wrap!(self, self.typ.check_contains(&ctx.env, &etyp))
864    }
865}
866
867#[derive(Debug)]
868pub(crate) struct StringInterpolate<C: Ctx, E: UserEvent> {
869    spec: Expr,
870    typ: Type,
871    args: Box<[Cached<C, E>]>,
872}
873
874impl<C: Ctx, E: UserEvent> StringInterpolate<C, E> {
875    pub(crate) fn compile(
876        ctx: &mut ExecCtx<C, E>,
877        spec: Expr,
878        scope: &ModPath,
879        top_id: ExprId,
880        args: &[Expr],
881    ) -> Result<Node<C, E>> {
882        let args = args
883            .iter()
884            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
885            .collect::<Result<_>>()?;
886        let typ = Type::Primitive(Typ::String.into());
887        Ok(Box::new(Self { spec, typ, args }))
888    }
889}
890
891impl<C: Ctx, E: UserEvent> Update<C, E> for StringInterpolate<C, E> {
892    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
893        use std::fmt::Write;
894        thread_local! {
895            static BUF: RefCell<String> = RefCell::new(String::new());
896        }
897        let (updated, determined) = update_args!(self.args, ctx, event);
898        if updated && determined {
899            BUF.with_borrow_mut(|buf| {
900                buf.clear();
901                for c in &self.args {
902                    match c.cached.as_ref().unwrap() {
903                        Value::String(s) => write!(buf, "{s}"),
904                        v => write!(buf, "{}", NakedValue(v)),
905                    }
906                    .unwrap()
907                }
908                Some(Value::String(buf.as_str().into()))
909            })
910        } else {
911            None
912        }
913    }
914
915    fn spec(&self) -> &Expr {
916        &self.spec
917    }
918
919    fn typ(&self) -> &Type {
920        &self.typ
921    }
922
923    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
924        for a in &self.args {
925            a.node.refs(f)
926        }
927    }
928
929    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
930        for n in &mut self.args {
931            n.node.delete(ctx)
932        }
933    }
934
935    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
936        for a in &mut self.args {
937            wrap!(a.node, a.node.typecheck(ctx))?
938        }
939        Ok(())
940    }
941}
942
943#[derive(Debug)]
944pub(crate) struct Connect<C: Ctx, E: UserEvent> {
945    spec: Expr,
946    node: Node<C, E>,
947    id: BindId,
948}
949
950impl<C: Ctx, E: UserEvent> Connect<C, E> {
951    pub(crate) fn compile(
952        ctx: &mut ExecCtx<C, E>,
953        spec: Expr,
954        scope: &ModPath,
955        top_id: ExprId,
956        name: &ModPath,
957        value: &Expr,
958        pos: &SourcePosition,
959    ) -> Result<Node<C, E>> {
960        let id = match ctx.env.lookup_bind(scope, name) {
961            None => bail!("at {pos} {name} is undefined"),
962            Some((_, env::Bind { id, .. })) => *id,
963        };
964        let node = compile(ctx, value.clone(), scope, top_id)?;
965        Ok(Box::new(Self { spec, node, id }))
966    }
967}
968
969impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
970    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
971        if let Some(v) = self.node.update(ctx, event) {
972            ctx.set_var(self.id, v)
973        }
974        None
975    }
976
977    fn spec(&self) -> &Expr {
978        &self.spec
979    }
980
981    fn typ(&self) -> &Type {
982        &Type::Bottom
983    }
984
985    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
986        self.node.refs(f)
987    }
988
989    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
990        self.node.delete(ctx)
991    }
992
993    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
994        wrap!(self.node, self.node.typecheck(ctx))?;
995        let bind = match ctx.env.by_id.get(&self.id) {
996            None => bail!("BUG missing bind {:?}", self.id),
997            Some(bind) => bind,
998        };
999        wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
1000    }
1001}
1002
1003#[derive(Debug)]
1004pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
1005    spec: Expr,
1006    typ: Type,
1007    child: Node<C, E>,
1008    id: BindId,
1009}
1010
1011impl<C: Ctx, E: UserEvent> ByRef<C, E> {
1012    pub(crate) fn compile(
1013        ctx: &mut ExecCtx<C, E>,
1014        spec: Expr,
1015        scope: &ModPath,
1016        top_id: ExprId,
1017        expr: &Expr,
1018    ) -> Result<Node<C, E>> {
1019        let child = compile(ctx, expr.clone(), scope, top_id)?;
1020        let id = BindId::new();
1021        let typ = Type::ByRef(Arc::new(child.typ().clone()));
1022        Ok(Box::new(Self { spec, typ, child, id }))
1023    }
1024}
1025
1026impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
1027    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1028        if let Some(v) = self.child.update(ctx, event) {
1029            ctx.set_var(self.id, v);
1030        }
1031        if event.init {
1032            Some(Value::U64(self.id.inner()))
1033        } else {
1034            None
1035        }
1036    }
1037
1038    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1039        self.child.delete(ctx)
1040    }
1041
1042    fn spec(&self) -> &Expr {
1043        &self.spec
1044    }
1045
1046    fn typ(&self) -> &Type {
1047        &self.typ
1048    }
1049
1050    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1051        self.child.refs(f)
1052    }
1053
1054    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1055        wrap!(self.child, self.child.typecheck(ctx))?;
1056        let t = Type::ByRef(Arc::new(self.child.typ().clone()));
1057        wrap!(self, self.typ.check_contains(&ctx.env, &t))
1058    }
1059}
1060
1061#[derive(Debug)]
1062pub(crate) struct Deref<C: Ctx, E: UserEvent> {
1063    spec: Expr,
1064    typ: Type,
1065    child: Node<C, E>,
1066    id: Option<BindId>,
1067    top_id: ExprId,
1068}
1069
1070impl<C: Ctx, E: UserEvent> Deref<C, E> {
1071    pub(crate) fn compile(
1072        ctx: &mut ExecCtx<C, E>,
1073        spec: Expr,
1074        scope: &ModPath,
1075        top_id: ExprId,
1076        expr: &Expr,
1077    ) -> Result<Node<C, E>> {
1078        let child = compile(ctx, expr.clone(), scope, top_id)?;
1079        let typ = Type::empty_tvar();
1080        Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
1081    }
1082}
1083
1084impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
1085    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1086        if let Some(v) = self.child.update(ctx, event) {
1087            match v {
1088                Value::U64(i) | Value::V64(i) => {
1089                    let new_id = BindId::from_u64(i);
1090                    if self.id != Some(new_id) {
1091                        if let Some(old) = self.id {
1092                            ctx.user.unref_var(old, self.top_id);
1093                        }
1094                        ctx.user.ref_var(new_id, self.top_id);
1095                        self.id = Some(new_id);
1096                    }
1097                }
1098                _ => return err!("expected u64 bind id"),
1099            }
1100        }
1101        self.id.and_then(|id| event.variables.get(&id).cloned())
1102    }
1103
1104    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1105        if let Some(id) = self.id.take() {
1106            ctx.user.unref_var(id, self.top_id);
1107        }
1108        self.child.delete(ctx);
1109    }
1110
1111    fn spec(&self) -> &Expr {
1112        &self.spec
1113    }
1114
1115    fn typ(&self) -> &Type {
1116        &self.typ
1117    }
1118
1119    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1120        self.child.refs(f);
1121        if let Some(id) = self.id {
1122            f(id);
1123        }
1124    }
1125
1126    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1127        wrap!(self.child, self.child.typecheck(ctx))?;
1128        let typ = match self.child.typ() {
1129            Type::ByRef(t) => (**t).clone(),
1130            _ => bail!("expected reference"),
1131        };
1132        wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
1133        Ok(())
1134    }
1135}
1136
1137#[derive(Debug)]
1138pub(crate) struct Qop<C: Ctx, E: UserEvent> {
1139    spec: Expr,
1140    typ: Type,
1141    id: BindId,
1142    n: Node<C, E>,
1143}
1144
1145impl<C: Ctx, E: UserEvent> Qop<C, E> {
1146    pub(crate) fn compile(
1147        ctx: &mut ExecCtx<C, E>,
1148        spec: Expr,
1149        scope: &ModPath,
1150        top_id: ExprId,
1151        e: &Expr,
1152        pos: &SourcePosition,
1153    ) -> Result<Node<C, E>> {
1154        let n = compile(ctx, e.clone(), scope, top_id)?;
1155        match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
1156            None => bail!("at {pos} BUG: errors is undefined"),
1157            Some((_, bind)) => {
1158                let typ = Type::empty_tvar();
1159                Ok(Box::new(Self { spec, typ, id: bind.id, n }))
1160            }
1161        }
1162    }
1163}
1164
1165impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
1166    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1167        match self.n.update(ctx, event) {
1168            None => None,
1169            Some(e @ Value::Error(_)) => {
1170                ctx.set_var(self.id, e);
1171                None
1172            }
1173            Some(v) => Some(v),
1174        }
1175    }
1176
1177    fn typ(&self) -> &Type {
1178        &self.typ
1179    }
1180
1181    fn spec(&self) -> &Expr {
1182        &self.spec
1183    }
1184
1185    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1186        self.n.refs(f)
1187    }
1188
1189    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1190        self.n.delete(ctx)
1191    }
1192
1193    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1194        wrap!(self.n, self.n.typecheck(ctx))?;
1195        let bind =
1196            ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
1197        let err = Type::Primitive(Typ::Error.into());
1198        wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
1199        wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
1200        if !self.n.typ().contains(&ctx.env, &err)? {
1201            bail!("cannot use the ? operator on a non error type")
1202        }
1203        let rtyp = self.n.typ().diff(&ctx.env, &err)?;
1204        wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
1205        Ok(())
1206    }
1207}
1208
1209#[derive(Debug)]
1210pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
1211    spec: Expr,
1212    typ: Type,
1213    target: Type,
1214    n: Node<C, E>,
1215}
1216
1217impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
1218    pub(crate) fn compile(
1219        ctx: &mut ExecCtx<C, E>,
1220        spec: Expr,
1221        scope: &ModPath,
1222        top_id: ExprId,
1223        expr: &Expr,
1224        typ: &Type,
1225        pos: &SourcePosition,
1226    ) -> Result<Node<C, E>> {
1227        let n = compile(ctx, expr.clone(), scope, top_id)?;
1228        let target = typ.scope_refs(scope);
1229        if let Err(e) = target.check_cast(&ctx.env) {
1230            bail!("in cast at {pos} {e}");
1231        }
1232        let typ = target.union(&Type::Primitive(Typ::Error.into()));
1233        Ok(Box::new(Self { spec, typ, target, n }))
1234    }
1235}
1236
1237impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
1238    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1239        self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
1240    }
1241
1242    fn spec(&self) -> &Expr {
1243        &self.spec
1244    }
1245
1246    fn typ(&self) -> &Type {
1247        &self.typ
1248    }
1249
1250    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1251        self.n.delete(ctx)
1252    }
1253
1254    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1255        self.n.refs(f)
1256    }
1257
1258    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1259        Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1260    }
1261}
1262
1263#[derive(Debug)]
1264pub(crate) struct Any<C: Ctx, E: UserEvent> {
1265    spec: Expr,
1266    typ: Type,
1267    n: Box<[Node<C, E>]>,
1268}
1269
1270impl<C: Ctx, E: UserEvent> Any<C, E> {
1271    pub(crate) fn compile(
1272        ctx: &mut ExecCtx<C, E>,
1273        spec: Expr,
1274        scope: &ModPath,
1275        top_id: ExprId,
1276        args: &[Expr],
1277    ) -> Result<Node<C, E>> {
1278        let n = args
1279            .iter()
1280            .map(|e| compile(ctx, e.clone(), scope, top_id))
1281            .collect::<Result<Box<[_]>>>()?;
1282        let typ =
1283            Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1284        Ok(Box::new(Self { spec, typ, n }))
1285    }
1286}
1287
1288impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1289    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1290        self.n
1291            .iter_mut()
1292            .filter_map(|s| s.update(ctx, event))
1293            .fold(None, |r, v| r.or(Some(v)))
1294    }
1295
1296    fn spec(&self) -> &Expr {
1297        &self.spec
1298    }
1299
1300    fn typ(&self) -> &Type {
1301        &self.typ
1302    }
1303
1304    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1305        self.n.iter_mut().for_each(|n| n.delete(ctx))
1306    }
1307
1308    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1309        self.n.iter().for_each(|n| n.refs(f))
1310    }
1311
1312    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1313        for n in self.n.iter_mut() {
1314            wrap!(n, n.typecheck(ctx))?
1315        }
1316        let rtyp = Type::Primitive(BitFlags::empty());
1317        let rtyp = self.n.iter().fold(rtyp, |rtype, n| n.typ().union(&rtype));
1318        Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1319    }
1320}
1321
1322#[derive(Debug)]
1323pub(crate) struct Array<C: Ctx, E: UserEvent> {
1324    spec: Expr,
1325    typ: Type,
1326    n: Box<[Cached<C, E>]>,
1327}
1328
1329impl<C: Ctx, E: UserEvent> Array<C, E> {
1330    pub(crate) fn compile(
1331        ctx: &mut ExecCtx<C, E>,
1332        spec: Expr,
1333        scope: &ModPath,
1334        top_id: ExprId,
1335        args: &Arc<[Expr]>,
1336    ) -> Result<Node<C, E>> {
1337        let n = args
1338            .iter()
1339            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1340            .collect::<Result<_>>()?;
1341        let typ = Type::Array(Arc::new(Type::empty_tvar()));
1342        Ok(Box::new(Self { spec, typ, n }))
1343    }
1344}
1345
1346impl<C: Ctx, E: UserEvent> Update<C, E> for Array<C, E> {
1347    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1348        if self.n.is_empty() && event.init {
1349            return Some(Value::Array(ValArray::from([])));
1350        }
1351        let (updated, determined) = update_args!(self.n, ctx, event);
1352        if updated && determined {
1353            let iter = self.n.iter().map(|n| n.cached.clone().unwrap());
1354            Some(Value::Array(ValArray::from_iter_exact(iter)))
1355        } else {
1356            None
1357        }
1358    }
1359
1360    fn spec(&self) -> &Expr {
1361        &self.spec
1362    }
1363
1364    fn typ(&self) -> &Type {
1365        &self.typ
1366    }
1367
1368    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1369        self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1370    }
1371
1372    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1373        self.n.iter().for_each(|n| n.node.refs(f))
1374    }
1375
1376    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1377        for n in &mut self.n {
1378            wrap!(n.node, n.node.typecheck(ctx))?
1379        }
1380        let rtype = Type::Bottom;
1381        let rtype = self.n.iter().fold(rtype, |rtype, n| n.node.typ().union(&rtype));
1382        let rtype = Type::Array(Arc::new(rtype));
1383        Ok(self.typ.check_contains(&ctx.env, &rtype)?)
1384    }
1385}
1386
1387#[derive(Debug)]
1388pub(crate) struct Tuple<C: Ctx, E: UserEvent> {
1389    spec: Expr,
1390    typ: Type,
1391    n: Box<[Cached<C, E>]>,
1392}
1393
1394impl<C: Ctx, E: UserEvent> Tuple<C, E> {
1395    pub(crate) fn compile(
1396        ctx: &mut ExecCtx<C, E>,
1397        spec: Expr,
1398        scope: &ModPath,
1399        top_id: ExprId,
1400        args: &[Expr],
1401    ) -> Result<Node<C, E>> {
1402        let n = args
1403            .iter()
1404            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1405            .collect::<Result<Box<[_]>>>()?;
1406        let typ = Type::Tuple(Arc::from_iter(n.iter().map(|n| n.node.typ().clone())));
1407        Ok(Box::new(Self { spec, typ, n }))
1408    }
1409}
1410
1411impl<C: Ctx, E: UserEvent> Update<C, E> for Tuple<C, E> {
1412    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1413        if self.n.is_empty() && event.init {
1414            return Some(Value::Array(ValArray::from([])));
1415        }
1416        let (updated, determined) = update_args!(self.n, ctx, event);
1417        if updated && determined {
1418            let iter = self.n.iter().map(|n| n.cached.clone().unwrap());
1419            Some(Value::Array(ValArray::from_iter_exact(iter)))
1420        } else {
1421            None
1422        }
1423    }
1424
1425    fn spec(&self) -> &Expr {
1426        &self.spec
1427    }
1428
1429    fn typ(&self) -> &Type {
1430        &self.typ
1431    }
1432
1433    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1434        self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1435    }
1436
1437    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1438        self.n.iter().for_each(|n| n.node.refs(f))
1439    }
1440
1441    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1442        for n in self.n.iter_mut() {
1443            wrap!(n.node, n.node.typecheck(ctx))?
1444        }
1445        match &self.typ {
1446            Type::Tuple(typs) => {
1447                if self.n.len() != typs.len() {
1448                    bail!("tuple arity mismatch {} vs {}", self.n.len(), typs.len())
1449                }
1450                for (t, n) in typs.iter().zip(self.n.iter()) {
1451                    t.check_contains(&ctx.env, &n.node.typ())?
1452                }
1453            }
1454            _ => bail!("BUG: unexpected tuple rtype"),
1455        }
1456        Ok(())
1457    }
1458}
1459
1460#[derive(Debug)]
1461pub(crate) struct Variant<C: Ctx, E: UserEvent> {
1462    spec: Expr,
1463    typ: Type,
1464    tag: ArcStr,
1465    n: Box<[Cached<C, E>]>,
1466}
1467
1468impl<C: Ctx, E: UserEvent> Variant<C, E> {
1469    pub(crate) fn compile(
1470        ctx: &mut ExecCtx<C, E>,
1471        spec: Expr,
1472        scope: &ModPath,
1473        top_id: ExprId,
1474        tag: &ArcStr,
1475        args: &[Expr],
1476    ) -> Result<Node<C, E>> {
1477        let n = args
1478            .iter()
1479            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1480            .collect::<Result<Box<[_]>>>()?;
1481        let typs = Arc::from_iter(n.iter().map(|n| n.node.typ().clone()));
1482        let typ = Type::Variant(tag.clone(), typs);
1483        let tag = tag.clone();
1484        Ok(Box::new(Self { spec, typ, tag, n }))
1485    }
1486}
1487
1488impl<C: Ctx, E: UserEvent> Update<C, E> for Variant<C, E> {
1489    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1490        if self.n.len() == 0 {
1491            if event.init {
1492                Some(Value::String(self.tag.clone()))
1493            } else {
1494                None
1495            }
1496        } else {
1497            let (updated, determined) = update_args!(self.n, ctx, event);
1498            if updated && determined {
1499                let a = iter::once(Value::String(self.tag.clone()))
1500                    .chain(self.n.iter().map(|n| n.cached.clone().unwrap()));
1501                Some(Value::Array(ValArray::from_iter(a)))
1502            } else {
1503                None
1504            }
1505        }
1506    }
1507
1508    fn spec(&self) -> &Expr {
1509        &self.spec
1510    }
1511
1512    fn typ(&self) -> &Type {
1513        &self.typ
1514    }
1515
1516    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1517        self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1518    }
1519
1520    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1521        self.n.iter().for_each(|n| n.node.refs(f))
1522    }
1523
1524    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1525        for n in self.n.iter_mut() {
1526            wrap!(n.node, n.node.typecheck(ctx))?
1527        }
1528        match &self.typ {
1529            Type::Variant(ttag, typs) => {
1530                if ttag != &self.tag {
1531                    bail!("expected {ttag} not {}", self.tag)
1532                }
1533                if self.n.len() != typs.len() {
1534                    bail!("arity mismatch {} vs {}", self.n.len(), typs.len())
1535                }
1536                for (t, n) in typs.iter().zip(self.n.iter()) {
1537                    wrap!(n.node, t.check_contains(&ctx.env, &n.node.typ()))?
1538                }
1539            }
1540            _ => bail!("BUG: unexpected variant rtype"),
1541        }
1542        Ok(())
1543    }
1544}
1545
1546#[derive(Debug)]
1547pub(crate) struct Struct<C: Ctx, E: UserEvent> {
1548    spec: Expr,
1549    typ: Type,
1550    names: Box<[ArcStr]>,
1551    n: Box<[Cached<C, E>]>,
1552}
1553
1554impl<C: Ctx, E: UserEvent> Struct<C, E> {
1555    pub(crate) fn compile(
1556        ctx: &mut ExecCtx<C, E>,
1557        spec: Expr,
1558        scope: &ModPath,
1559        top_id: ExprId,
1560        args: &[(ArcStr, Expr)],
1561    ) -> Result<Node<C, E>> {
1562        let mut names: SmallVec<[ArcStr; 8]> = smallvec![];
1563        let n = args.iter().map(|(n, s)| {
1564            names.push(n.clone());
1565            s
1566        });
1567        let n = n
1568            .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1569            .collect::<Result<Box<[_]>>>()?;
1570        let names = Box::from_iter(names);
1571        let typs =
1572            names.iter().zip(n.iter()).map(|(n, a)| (n.clone(), a.node.typ().clone()));
1573        let typ = Type::Struct(Arc::from_iter(typs));
1574        Ok(Box::new(Self { spec, typ, names, n }))
1575    }
1576}
1577
1578impl<C: Ctx, E: UserEvent> Update<C, E> for Struct<C, E> {
1579    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1580        if self.n.is_empty() && event.init {
1581            return Some(Value::Array(ValArray::from([])));
1582        }
1583        let (updated, determined) = update_args!(self.n, ctx, event);
1584        if updated && determined {
1585            let iter = self.names.iter().zip(self.n.iter()).map(|(name, n)| {
1586                let name = Value::String(name.clone());
1587                let v = n.cached.clone().unwrap();
1588                Value::Array(ValArray::from_iter_exact([name, v].into_iter()))
1589            });
1590            Some(Value::Array(ValArray::from_iter_exact(iter)))
1591        } else {
1592            None
1593        }
1594    }
1595
1596    fn spec(&self) -> &Expr {
1597        &self.spec
1598    }
1599
1600    fn typ(&self) -> &Type {
1601        &self.typ
1602    }
1603
1604    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1605        self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1606    }
1607
1608    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1609        self.n.iter().for_each(|n| n.node.refs(f))
1610    }
1611
1612    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1613        for n in self.n.iter_mut() {
1614            wrap!(n.node, n.node.typecheck(ctx))?
1615        }
1616        match &self.typ {
1617            Type::Struct(typs) => {
1618                if self.n.len() != typs.len() {
1619                    bail!(
1620                        "struct length mismatch {} fields expected vs {}",
1621                        typs.len(),
1622                        self.n.len()
1623                    )
1624                }
1625                for ((_, t), n) in typs.iter().zip(self.n.iter()) {
1626                    t.check_contains(&ctx.env, &n.node.typ())?
1627                }
1628            }
1629            _ => bail!("BUG: expected a struct rtype"),
1630        }
1631        Ok(())
1632    }
1633}
1634
1635#[derive(Debug)]
1636pub(crate) struct StructWith<C: Ctx, E: UserEvent> {
1637    spec: Expr,
1638    typ: Type,
1639    source: Node<C, E>,
1640    current: Option<ValArray>,
1641    replace: Box<[(usize, Cached<C, E>)]>,
1642}
1643
1644impl<C: Ctx, E: UserEvent> StructWith<C, E> {
1645    pub(crate) fn compile(
1646        ctx: &mut ExecCtx<C, E>,
1647        spec: Expr,
1648        scope: &ModPath,
1649        top_id: ExprId,
1650        source: &Expr,
1651        replace: &[(ArcStr, Expr)],
1652    ) -> Result<Node<C, E>> {
1653        let source = compile(ctx, source.clone(), scope, top_id)?;
1654        let replace = replace
1655            .iter()
1656            .map(|(_, e)| Ok((0, Cached::new(compile(ctx, e.clone(), scope, top_id)?))))
1657            .collect::<Result<Box<[_]>>>()?;
1658        let typ = source.typ().clone();
1659        Ok(Box::new(Self { spec, typ, source, current: None, replace }))
1660    }
1661}
1662
1663impl<C: Ctx, E: UserEvent> Update<C, E> for StructWith<C, E> {
1664    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1665        let mut updated = self
1666            .source
1667            .update(ctx, event)
1668            .map(|v| match v {
1669                Value::Array(a) => {
1670                    self.current = Some(a.clone());
1671                    true
1672                }
1673                _ => false,
1674            })
1675            .unwrap_or(false);
1676        let mut determined = self.current.is_some();
1677        for (_, n) in self.replace.iter_mut() {
1678            updated |= n.update(ctx, event);
1679            determined &= n.cached.is_some();
1680        }
1681        if updated && determined {
1682            let mut si = 0;
1683            let iter =
1684                self.current.as_ref().unwrap().iter().enumerate().map(|(i, v)| match v {
1685                    Value::Array(v) if v.len() == 2 => {
1686                        if si < self.replace.len() && i == self.replace[si].0 {
1687                            let r = self.replace[si].1.cached.clone().unwrap();
1688                            si += 1;
1689                            Value::Array(ValArray::from_iter_exact(
1690                                [v[0].clone(), r].into_iter(),
1691                            ))
1692                        } else {
1693                            Value::Array(v.clone())
1694                        }
1695                    }
1696                    _ => v.clone(),
1697                });
1698            Some(Value::Array(ValArray::from_iter_exact(iter)))
1699        } else {
1700            None
1701        }
1702    }
1703
1704    fn spec(&self) -> &Expr {
1705        &self.spec
1706    }
1707
1708    fn typ(&self) -> &Type {
1709        &self.typ
1710    }
1711
1712    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1713        self.source.delete(ctx);
1714        self.replace.iter_mut().for_each(|(_, n)| n.node.delete(ctx))
1715    }
1716
1717    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1718        self.source.refs(f);
1719        self.replace.iter().for_each(|(_, n)| n.node.refs(f))
1720    }
1721
1722    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1723        wrap!(self.source, self.source.typecheck(ctx))?;
1724        let fields = match &self.spec.kind {
1725            ExprKind::StructWith { source: _, replace } => {
1726                replace.iter().map(|(n, _)| n.clone()).collect::<SmallVec<[ArcStr; 8]>>()
1727            }
1728            _ => bail!("BUG: miscompiled structwith"),
1729        };
1730        wrap!(
1731            self,
1732            self.source.typ().with_deref(|typ| match typ {
1733                Some(Type::Struct(flds)) => {
1734                    for ((i, c), n) in self.replace.iter_mut().zip(fields.iter()) {
1735                        let r = flds.iter().enumerate().find_map(|(i, (field, typ))| {
1736                            if field == n {
1737                                Some((i, typ))
1738                            } else {
1739                                None
1740                            }
1741                        });
1742                        match r {
1743                            None => bail!("struct has no field named {n}"),
1744                            Some((j, typ)) => {
1745                                typ.check_contains(&ctx.env, &c.node.typ())?;
1746                                *i = j;
1747                            }
1748                        }
1749                    }
1750                    Ok(())
1751                }
1752                None => bail!("type must be known, annotations needed"),
1753                _ => bail!("expected a struct"),
1754            })
1755        )?;
1756        wrap!(self, self.typ.check_contains(&ctx.env, self.source.typ()))
1757    }
1758}
1759
1760macro_rules! compare_op {
1761    ($name:ident, $op:tt) => {
1762        #[derive(Debug)]
1763        pub(crate) struct $name<C: Ctx, E: UserEvent> {
1764            spec: Expr,
1765            typ: Type,
1766            lhs: Cached<C, E>,
1767            rhs: Cached<C, E>,
1768        }
1769
1770        impl<C: Ctx, E: UserEvent> $name<C, E> {
1771            pub(crate) fn compile(
1772                ctx: &mut ExecCtx<C, E>,
1773                spec: Expr,
1774                scope: &ModPath,
1775                top_id: ExprId,
1776                lhs: &Expr,
1777                rhs: &Expr
1778            ) -> Result<Node<C, E>> {
1779                let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1780                let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1781                let typ = Type::Primitive(Typ::Bool.into());
1782                Ok(Box::new(Self { spec, typ, lhs, rhs }))
1783            }
1784        }
1785
1786        impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1787            fn update(
1788                &mut self,
1789                ctx: &mut ExecCtx<C, E>,
1790                event: &mut Event<E>,
1791            ) -> Option<Value> {
1792                let lhs_up = self.lhs.update(ctx, event);
1793                let rhs_up = self.rhs.update(ctx, event);
1794                if lhs_up || rhs_up {
1795                    return self.lhs.cached.as_ref().and_then(|lhs| {
1796                        self.rhs.cached.as_ref().map(|rhs| (lhs $op rhs).into())
1797                    })
1798                }
1799                None
1800            }
1801
1802            fn spec(&self) -> &Expr {
1803                &self.spec
1804            }
1805
1806            fn typ(&self) -> &Type {
1807                &self.typ
1808            }
1809
1810            fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1811                self.lhs.node.refs(f);
1812                self.rhs.node.refs(f);
1813            }
1814
1815            fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1816                self.lhs.node.delete(ctx);
1817                self.rhs.node.delete(ctx)
1818            }
1819
1820            fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1821                wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
1822                wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
1823                wrap!(
1824                    self,
1825                    self.lhs.node.typ().check_contains(&ctx.env, &self.rhs.node.typ())
1826                )?;
1827                wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1828            }
1829        }
1830    };
1831}
1832
1833compare_op!(Eq, ==);
1834compare_op!(Ne, !=);
1835compare_op!(Lt, <);
1836compare_op!(Gt, >);
1837compare_op!(Lte, <=);
1838compare_op!(Gte, >=);
1839
1840macro_rules! bool_op {
1841    ($name:ident, $op:tt) => {
1842        #[derive(Debug)]
1843        pub(crate) struct $name<C: Ctx, E: UserEvent> {
1844            spec: Expr,
1845            typ: Type,
1846            lhs: Cached<C, E>,
1847            rhs: Cached<C, E>,
1848        }
1849
1850        impl<C: Ctx, E: UserEvent> $name<C, E> {
1851            pub(crate) fn compile(
1852                ctx: &mut ExecCtx<C, E>,
1853                spec: Expr,
1854                scope: &ModPath,
1855                top_id: ExprId,
1856                lhs: &Expr,
1857                rhs: &Expr
1858            ) -> Result<Node<C, E>> {
1859                let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1860                let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1861                let typ = Type::Primitive(Typ::Bool.into());
1862                Ok(Box::new(Self { spec, typ, lhs, rhs }))
1863            }
1864        }
1865
1866        impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1867            fn update(
1868                &mut self,
1869                ctx: &mut ExecCtx<C, E>,
1870                event: &mut Event<E>,
1871            ) -> Option<Value> {
1872                let lhs_up = self.lhs.update(ctx, event);
1873                let rhs_up = self.rhs.update(ctx, event);
1874                if lhs_up || rhs_up {
1875                    return match (self.lhs.cached.as_ref(), self.rhs.cached.as_ref()) {
1876                        (Some(Value::Bool(b0)), Some(Value::Bool(b1))) => Some(Value::Bool(*b0 $op *b1)),
1877                        (_, _) => None
1878                    }
1879                }
1880                None
1881            }
1882
1883            fn spec(&self) -> &Expr {
1884                &self.spec
1885            }
1886
1887            fn typ(&self) -> &Type {
1888                &self.typ
1889            }
1890
1891            fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1892                self.lhs.node.refs(f);
1893                self.rhs.node.refs(f);
1894            }
1895
1896            fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1897                self.lhs.node.delete(ctx);
1898                self.rhs.node.delete(ctx)
1899            }
1900
1901            fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1902                wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
1903                wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
1904                let bt = Type::Primitive(Typ::Bool.into());
1905                wrap!(self.lhs.node, bt.check_contains(&ctx.env, self.lhs.node.typ()))?;
1906                wrap!(self.rhs.node, bt.check_contains(&ctx.env, self.rhs.node.typ()))?;
1907                wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1908            }
1909        }
1910    };
1911}
1912
1913bool_op!(And, &&);
1914bool_op!(Or, ||);
1915
1916#[derive(Debug)]
1917pub(crate) struct Not<C: Ctx, E: UserEvent> {
1918    spec: Expr,
1919    typ: Type,
1920    n: Node<C, E>,
1921}
1922
1923impl<C: Ctx, E: UserEvent> Not<C, E> {
1924    pub(crate) fn compile(
1925        ctx: &mut ExecCtx<C, E>,
1926        spec: Expr,
1927        scope: &ModPath,
1928        top_id: ExprId,
1929        n: &Expr,
1930    ) -> Result<Node<C, E>> {
1931        let n = compile(ctx, n.clone(), scope, top_id)?;
1932        let typ = Type::Primitive(Typ::Bool.into());
1933        Ok(Box::new(Self { spec, typ, n }))
1934    }
1935}
1936
1937impl<C: Ctx, E: UserEvent> Update<C, E> for Not<C, E> {
1938    fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1939        self.n.update(ctx, event).and_then(|v| match v {
1940            Value::Bool(b) => Some(Value::Bool(!b)),
1941            _ => None,
1942        })
1943    }
1944
1945    fn spec(&self) -> &Expr {
1946        &self.spec
1947    }
1948
1949    fn typ(&self) -> &Type {
1950        &self.typ
1951    }
1952
1953    fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1954        self.n.refs(f);
1955    }
1956
1957    fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1958        self.n.delete(ctx);
1959    }
1960
1961    fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1962        wrap!(self.n, self.n.typecheck(ctx))?;
1963        let bt = Type::Primitive(Typ::Bool.into());
1964        wrap!(self.n, bt.check_contains(&ctx.env, self.n.typ()))?;
1965        wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1966    }
1967}
1968
1969macro_rules! arith_op {
1970    ($name:ident, $op:tt) => {
1971        #[derive(Debug)]
1972        pub(crate) struct $name<C: Ctx, E: UserEvent> {
1973            spec: Expr,
1974            typ: Type,
1975            lhs: Cached<C, E>,
1976            rhs: Cached<C, E>
1977        }
1978
1979        impl<C: Ctx, E: UserEvent> $name<C, E> {
1980            pub(crate) fn compile(
1981                ctx: &mut ExecCtx<C, E>,
1982                spec: Expr,
1983                scope: &ModPath,
1984                top_id: ExprId,
1985                lhs: &Expr,
1986                rhs: &Expr
1987            ) -> Result<Node<C, E>> {
1988                let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1989                let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1990                let typ = Type::empty_tvar();
1991                Ok(Box::new(Self { spec, typ, lhs, rhs }))
1992            }
1993        }
1994
1995        impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1996            fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1997                let lhs_up = self.lhs.update(ctx, event);
1998                let rhs_up = self.rhs.update(ctx, event);
1999                if lhs_up || rhs_up {
2000                    return self.lhs.cached.as_ref().and_then(|lhs| {
2001                        self.rhs.cached.as_ref().map(|rhs| (lhs.clone() $op rhs.clone()).into())
2002                    })
2003                }
2004                None
2005            }
2006
2007            fn spec(&self) -> &Expr {
2008                &self.spec
2009            }
2010
2011            fn typ(&self) -> &Type {
2012                &self.typ
2013            }
2014
2015            fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
2016                self.lhs.node.refs(f);
2017                self.rhs.node.refs(f);
2018            }
2019
2020            fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
2021                self.lhs.node.delete(ctx);
2022                self.rhs.node.delete(ctx);
2023            }
2024
2025            fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
2026                wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
2027                wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
2028                let typ = Type::Primitive(Typ::number());
2029                let lhs = self.lhs.node.typ();
2030                let rhs = self.rhs.node.typ();
2031                wrap!(self.lhs.node, typ.check_contains(&ctx.env, lhs))?;
2032                wrap!(self.rhs.node, typ.check_contains(&ctx.env, rhs))?;
2033                wrap!(self,self.typ.check_contains(&ctx.env, &lhs.union(rhs)))
2034            }
2035        }
2036    }
2037}
2038
2039arith_op!(Add, +);
2040arith_op!(Sub, -);
2041arith_op!(Mul, *);
2042arith_op!(Div, /);