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