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