1use crate::{
2 env,
3 expr::{Expr, ExprId, ExprKind, ModPath},
4 typ::{TVal, TVar, Type},
5 BindId, CFlag, Event, ExecCtx, Node, Refs, Rt, Scope, Update, UserEvent, CAST_ERR,
6};
7use anyhow::{anyhow, bail, Context, Result};
8use arcstr::{literal, ArcStr};
9use compiler::compile;
10use enumflags2::BitFlags;
11use netidx_value::{Typ, Value};
12use std::{cell::RefCell, sync::LazyLock};
13use triomphe::Arc;
14
15pub(crate) mod array;
16pub(crate) mod bind;
17pub(crate) mod callsite;
18pub(crate) mod compiler;
19pub(crate) mod data;
20pub(crate) mod error;
21pub mod genn;
22pub mod lambda;
23pub(crate) mod map;
24pub(crate) mod module;
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
54#[macro_export]
55macro_rules! deref_typ {
56 ($name:literal, $ctx:expr, $typ:expr, $($pat:pat => $body:expr),+) => {
57 $typ.with_deref(|typ| {
58 let mut typ = typ.cloned();
59 let mut hist: poolshark::local::LPooled<fxhash::FxHashSet<usize>> = poolshark::local::LPooled::take();
60 loop {
61 #[allow(unreachable_patterns)]
62 match &typ {
63 $($pat => break $body),+,
64 Some(rt @ Type::Ref { .. }) => {
65 let rt = rt.lookup_ref(&$ctx.env)?;
66 if hist.insert(&rt as *const _ as usize) {
67 typ = Some(rt);
68 } else {
69 $crate::format_with_flags(PrintFlag::DerefTVars, || {
70 anyhow::bail!("expected {} not {rt}", $name)
71 })?
72 }
73 }
74 Some(t) => $crate::format_with_flags(PrintFlag::DerefTVars, || {
75 anyhow::bail!("expected {} not {t}", $name)
76 })?,
77 None => anyhow::bail!("type must be known, annotations needed")
78 }
79 }
80 })
81 };
82}
83
84pub(crate) static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
85 Arc::new(
86 ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
87 )
88});
89
90#[derive(Debug)]
91pub(crate) struct Nop {
92 pub typ: Type,
93}
94
95impl Nop {
96 pub(crate) fn new<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
97 Box::new(Nop { typ })
98 }
99}
100
101impl<R: Rt, E: UserEvent> Update<R, E> for Nop {
102 fn update(
103 &mut self,
104 _ctx: &mut ExecCtx<R, E>,
105 _event: &mut Event<E>,
106 ) -> Option<Value> {
107 None
108 }
109
110 fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
111
112 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
113
114 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
115 Ok(())
116 }
117
118 fn spec(&self) -> &Expr {
119 &NOP
120 }
121
122 fn typ(&self) -> &Type {
123 &self.typ
124 }
125
126 fn refs(&self, _refs: &mut Refs) {}
127}
128
129#[derive(Debug)]
130pub(crate) struct ExplicitParens<R: Rt, E: UserEvent> {
131 spec: Expr,
132 n: Node<R, E>,
133}
134
135impl<R: Rt, E: UserEvent> ExplicitParens<R, E> {
136 pub(crate) fn compile(
137 ctx: &mut ExecCtx<R, E>,
138 flags: BitFlags<CFlag>,
139 spec: Expr,
140 scope: &Scope,
141 top_id: ExprId,
142 ) -> Result<Node<R, E>> {
143 let n = compile(ctx, flags, spec.clone(), scope, top_id)?;
144 Ok(Box::new(ExplicitParens { spec, n }))
145 }
146}
147
148impl<R: Rt, E: UserEvent> Update<R, E> for ExplicitParens<R, E> {
149 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
150 self.n.update(ctx, event)
151 }
152
153 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
154 self.n.delete(ctx);
155 }
156
157 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
158 self.n.sleep(ctx);
159 }
160
161 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
162 self.n.typecheck(ctx)
163 }
164
165 fn spec(&self) -> &Expr {
166 &self.spec
167 }
168
169 fn typ(&self) -> &Type {
170 &self.n.typ()
171 }
172
173 fn refs(&self, refs: &mut Refs) {
174 self.n.refs(refs);
175 }
176}
177
178#[derive(Debug)]
179struct Cached<R: Rt, E: UserEvent> {
180 cached: Option<Value>,
181 node: Node<R, E>,
182}
183
184impl<R: Rt, E: UserEvent> Cached<R, E> {
185 fn new(node: Node<R, E>) -> Self {
186 Self { cached: None, node }
187 }
188
189 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> bool {
193 match self.node.update(ctx, event) {
194 None => false,
195 Some(v) => {
196 self.cached = Some(v);
197 true
198 }
199 }
200 }
201
202 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
203 self.cached = None;
204 self.node.sleep(ctx)
205 }
206}
207
208#[derive(Debug)]
209pub(crate) struct Use {
210 spec: Expr,
211 scope: Scope,
212 name: ModPath,
213}
214
215impl Use {
216 pub(crate) fn compile<R: Rt, E: UserEvent>(
217 ctx: &mut ExecCtx<R, E>,
218 spec: Expr,
219 scope: &Scope,
220 name: &ModPath,
221 ) -> Result<Node<R, E>> {
222 ctx.env
223 .use_in_scope(scope, name)
224 .map_err(|e| anyhow!("at {} {e:?}", spec.pos))?;
225 Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
226 }
227}
228
229impl<R: Rt, E: UserEvent> Update<R, E> for Use {
230 fn update(
231 &mut self,
232 _ctx: &mut ExecCtx<R, E>,
233 _event: &mut Event<E>,
234 ) -> Option<Value> {
235 None
236 }
237
238 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
239 Ok(())
240 }
241
242 fn refs(&self, _refs: &mut Refs) {}
243
244 fn spec(&self) -> &Expr {
245 &self.spec
246 }
247
248 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
249 ctx.env.stop_use_in_scope(&self.scope, &self.name);
250 }
251
252 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
253
254 fn typ(&self) -> &Type {
255 &Type::Bottom
256 }
257}
258
259#[derive(Debug)]
260pub(crate) struct TypeDef {
261 spec: Expr,
262 scope: ModPath,
263 name: ArcStr,
264}
265
266impl TypeDef {
267 pub(crate) fn compile<R: Rt, E: UserEvent>(
268 ctx: &mut ExecCtx<R, E>,
269 spec: Expr,
270 scope: &Scope,
271 name: &ArcStr,
272 params: &Arc<[(TVar, Option<Type>)]>,
273 typ: &Type,
274 ) -> Result<Node<R, E>> {
275 let typ = typ.scope_refs(&scope.lexical);
276 ctx.env
277 .deftype(&scope.lexical, name, params.clone(), typ, None)
278 .with_context(|| format!("in typedef at {}", spec.pos))?;
279 let name = name.clone();
280 Ok(Box::new(Self { spec, scope: scope.lexical.clone(), name }))
281 }
282}
283
284impl<R: Rt, E: UserEvent> Update<R, E> for TypeDef {
285 fn update(
286 &mut self,
287 _ctx: &mut ExecCtx<R, E>,
288 _event: &mut Event<E>,
289 ) -> Option<Value> {
290 None
291 }
292
293 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
294 Ok(())
295 }
296
297 fn refs(&self, _refs: &mut Refs) {}
298
299 fn spec(&self) -> &Expr {
300 &self.spec
301 }
302
303 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
304 ctx.env.undeftype(&self.scope, &self.name)
305 }
306
307 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
308
309 fn typ(&self) -> &Type {
310 &Type::Bottom
311 }
312}
313
314#[derive(Debug)]
315pub(crate) struct Constant {
316 spec: Arc<Expr>,
317 value: Value,
318 typ: Type,
319}
320
321impl Constant {
322 pub(crate) fn compile<R: Rt, E: UserEvent>(
323 spec: Expr,
324 value: &Value,
325 ) -> Result<Node<R, E>> {
326 let spec = Arc::new(spec);
327 let value = value.clone();
328 let typ = Type::Primitive(Typ::get(&value).into());
329 Ok(Box::new(Self { spec, value, typ }))
330 }
331}
332
333impl<R: Rt, E: UserEvent> Update<R, E> for Constant {
334 fn update(
335 &mut self,
336 _ctx: &mut ExecCtx<R, E>,
337 event: &mut Event<E>,
338 ) -> Option<Value> {
339 if event.init {
340 Some(self.value.clone())
341 } else {
342 None
343 }
344 }
345
346 fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
347
348 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
349
350 fn refs(&self, _refs: &mut Refs) {}
351
352 fn typ(&self) -> &Type {
353 &self.typ
354 }
355
356 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
357 Ok(())
358 }
359
360 fn spec(&self) -> &Expr {
361 &self.spec
362 }
363}
364
365#[derive(Debug)]
367pub(crate) struct Block<R: Rt, E: UserEvent> {
368 module: bool,
369 spec: Expr,
370 children: Box<[Node<R, E>]>,
371}
372
373impl<R: Rt, E: UserEvent> Block<R, E> {
374 pub(crate) fn compile(
375 ctx: &mut ExecCtx<R, E>,
376 flags: BitFlags<CFlag>,
377 spec: Expr,
378 scope: &Scope,
379 top_id: ExprId,
380 module: bool,
381 exprs: &Arc<[Expr]>,
382 ) -> Result<Node<R, E>> {
383 let children = exprs
384 .iter()
385 .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
386 .collect::<Result<Box<[Node<R, E>]>>>()?;
387 Ok(Box::new(Self { module, spec, children }))
388 }
389}
390
391impl<R: Rt, E: UserEvent> Update<R, E> for Block<R, E> {
392 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
393 let res = self.children.iter_mut().fold(None, |_, n| n.update(ctx, event));
394 if self.module {
395 None
396 } else {
397 res
398 }
399 }
400
401 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
402 for n in &mut self.children {
403 n.delete(ctx)
404 }
405 }
406
407 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
408 for n in &mut self.children {
409 n.sleep(ctx)
410 }
411 }
412
413 fn refs(&self, refs: &mut Refs) {
414 for n in &self.children {
415 n.refs(refs)
416 }
417 }
418
419 fn typ(&self) -> &Type {
420 &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
421 }
422
423 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
424 for n in &mut self.children {
425 if self.module {
426 wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
427 } else {
428 wrap!(n, n.typecheck(ctx))?
429 }
430 }
431 Ok(())
432 }
433
434 fn spec(&self) -> &Expr {
435 &self.spec
436 }
437}
438
439#[derive(Debug)]
440pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
441 spec: Expr,
442 typ: Type,
443 typs: Box<[Type]>,
444 args: Box<[Cached<R, E>]>,
445}
446
447impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
448 pub(crate) fn compile(
449 ctx: &mut ExecCtx<R, E>,
450 flags: BitFlags<CFlag>,
451 spec: Expr,
452 scope: &Scope,
453 top_id: ExprId,
454 args: &[Expr],
455 ) -> Result<Node<R, E>> {
456 let args: Box<[Cached<R, E>]> = args
457 .iter()
458 .map(|e| Ok(Cached::new(compile(ctx, flags, e.clone(), scope, top_id)?)))
459 .collect::<Result<_>>()?;
460 let typs = args.iter().map(|c| c.node.typ().clone()).collect();
461 let typ = Type::Primitive(Typ::String.into());
462 Ok(Box::new(Self { spec, typ, typs, args }))
463 }
464}
465
466impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
467 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
468 use std::fmt::Write;
469 thread_local! {
470 static BUF: RefCell<String> = RefCell::new(String::new());
471 }
472 let (updated, determined) = update_args!(self.args, ctx, event);
473 if updated && determined {
474 BUF.with_borrow_mut(|buf| {
475 buf.clear();
476 for (typ, c) in self.typs.iter().zip(self.args.iter()) {
477 match c.cached.as_ref().unwrap() {
478 Value::String(s) => write!(buf, "{s}"),
479 v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
480 }
481 .unwrap()
482 }
483 Some(Value::String(buf.as_str().into()))
484 })
485 } else {
486 None
487 }
488 }
489
490 fn spec(&self) -> &Expr {
491 &self.spec
492 }
493
494 fn typ(&self) -> &Type {
495 &self.typ
496 }
497
498 fn refs(&self, refs: &mut Refs) {
499 for a in &self.args {
500 a.node.refs(refs)
501 }
502 }
503
504 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
505 for n in &mut self.args {
506 n.node.delete(ctx)
507 }
508 }
509
510 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
511 for n in &mut self.args {
512 n.sleep(ctx);
513 }
514 }
515
516 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
517 for (i, a) in self.args.iter_mut().enumerate() {
518 wrap!(a.node, a.node.typecheck(ctx))?;
519 self.typs[i] = a.node.typ().with_deref(|t| match t {
520 None => Type::Any,
521 Some(t) => t.clone(),
522 });
523 }
524 Ok(())
525 }
526}
527
528#[derive(Debug)]
529pub(crate) struct Connect<R: Rt, E: UserEvent> {
530 spec: Expr,
531 node: Node<R, E>,
532 id: BindId,
533}
534
535impl<R: Rt, E: UserEvent> Connect<R, E> {
536 pub(crate) fn compile(
537 ctx: &mut ExecCtx<R, E>,
538 flags: BitFlags<CFlag>,
539 spec: Expr,
540 scope: &Scope,
541 top_id: ExprId,
542 name: &ModPath,
543 value: &Expr,
544 ) -> Result<Node<R, E>> {
545 let id = match ctx.env.lookup_bind(&scope.lexical, name) {
546 None => bail!("at {} {name} is undefined", spec.pos),
547 Some((_, env::Bind { id, .. })) => *id,
548 };
549 let node = compile(ctx, flags, value.clone(), scope, top_id)?;
550 Ok(Box::new(Self { spec, node, id }))
551 }
552}
553
554impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
555 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
556 if let Some(v) = self.node.update(ctx, event) {
557 ctx.set_var(self.id, v)
558 }
559 None
560 }
561
562 fn spec(&self) -> &Expr {
563 &self.spec
564 }
565
566 fn typ(&self) -> &Type {
567 &Type::Bottom
568 }
569
570 fn refs(&self, refs: &mut Refs) {
571 self.node.refs(refs)
572 }
573
574 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
575 self.node.delete(ctx)
576 }
577
578 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
579 self.node.sleep(ctx);
580 }
581
582 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
583 wrap!(self.node, self.node.typecheck(ctx))?;
584 let bind = match ctx.env.by_id.get(&self.id) {
585 None => bail!("BUG missing bind {:?}", self.id),
586 Some(bind) => bind,
587 };
588 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
589 }
590}
591
592#[derive(Debug)]
593pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
594 spec: Expr,
595 rhs: Cached<R, E>,
596 src_id: BindId,
597 target_id: Option<BindId>,
598 top_id: ExprId,
599}
600
601impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
602 pub(crate) fn compile(
603 ctx: &mut ExecCtx<R, E>,
604 flags: BitFlags<CFlag>,
605 spec: Expr,
606 scope: &Scope,
607 top_id: ExprId,
608 name: &ModPath,
609 value: &Expr,
610 ) -> Result<Node<R, E>> {
611 let src_id = match ctx.env.lookup_bind(&scope.lexical, name) {
612 None => bail!("at {} {name} is undefined", spec.pos),
613 Some((_, env::Bind { id, .. })) => *id,
614 };
615 ctx.rt.ref_var(src_id, top_id);
616 let rhs = Cached::new(compile(ctx, flags, value.clone(), scope, top_id)?);
617 Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
618 }
619}
620
621impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
622 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
623 let mut up = self.rhs.update(ctx, event);
624 if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
625 if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
626 self.target_id = Some(*target_id);
627 up = true;
628 }
629 }
630 if up {
631 if let Some(v) = &self.rhs.cached {
632 if let Some(id) = self.target_id {
633 ctx.set_var(id, v.clone());
634 }
635 }
636 }
637 None
638 }
639
640 fn spec(&self) -> &Expr {
641 &self.spec
642 }
643
644 fn typ(&self) -> &Type {
645 &Type::Bottom
646 }
647
648 fn refs(&self, refs: &mut Refs) {
649 refs.refed.insert(self.src_id);
650 self.rhs.node.refs(refs)
651 }
652
653 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
654 ctx.rt.unref_var(self.src_id, self.top_id);
655 self.rhs.node.delete(ctx)
656 }
657
658 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
659 self.rhs.sleep(ctx);
660 }
661
662 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
663 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
664 let bind = match ctx.env.by_id.get(&self.src_id) {
665 None => bail!("BUG missing bind {:?}", self.src_id),
666 Some(bind) => bind,
667 };
668 let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
669 wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
670 }
671}
672
673#[derive(Debug)]
674pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
675 spec: Expr,
676 typ: Type,
677 target: Type,
678 n: Node<R, E>,
679}
680
681impl<R: Rt, E: UserEvent> TypeCast<R, E> {
682 pub(crate) fn compile(
683 ctx: &mut ExecCtx<R, E>,
684 flags: BitFlags<CFlag>,
685 spec: Expr,
686 scope: &Scope,
687 top_id: ExprId,
688 expr: &Expr,
689 typ: &Type,
690 ) -> Result<Node<R, E>> {
691 let n = compile(ctx, flags, expr.clone(), scope, top_id)?;
692 let target = typ.scope_refs(&scope.lexical);
693 if let Err(e) = target.check_cast(&ctx.env) {
694 bail!("in cast at {} {e}", spec.pos);
695 }
696 let typ = target.union(&ctx.env, &CAST_ERR)?;
697 Ok(Box::new(Self { spec, typ, target, n }))
698 }
699}
700
701impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
702 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
703 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
704 }
705
706 fn spec(&self) -> &Expr {
707 &self.spec
708 }
709
710 fn typ(&self) -> &Type {
711 &self.typ
712 }
713
714 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
715 self.n.delete(ctx)
716 }
717
718 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
719 self.n.sleep(ctx);
720 }
721
722 fn refs(&self, refs: &mut Refs) {
723 self.n.refs(refs)
724 }
725
726 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
727 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
728 }
729}
730
731#[derive(Debug)]
732pub(crate) struct Any<R: Rt, E: UserEvent> {
733 spec: Expr,
734 typ: Type,
735 n: Box<[Node<R, E>]>,
736}
737
738impl<R: Rt, E: UserEvent> Any<R, E> {
739 pub(crate) fn compile(
740 ctx: &mut ExecCtx<R, E>,
741 flags: BitFlags<CFlag>,
742 spec: Expr,
743 scope: &Scope,
744 top_id: ExprId,
745 args: &[Expr],
746 ) -> Result<Node<R, E>> {
747 let n = args
748 .iter()
749 .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
750 .collect::<Result<Box<[_]>>>()?;
751 Ok(Box::new(Self { spec, typ: Type::empty_tvar(), n }))
752 }
753}
754
755impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
756 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
757 self.n
758 .iter_mut()
759 .filter_map(|s| s.update(ctx, event))
760 .fold(None, |r, v| r.or(Some(v)))
761 }
762
763 fn spec(&self) -> &Expr {
764 &self.spec
765 }
766
767 fn typ(&self) -> &Type {
768 &self.typ
769 }
770
771 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
772 self.n.iter_mut().for_each(|n| n.delete(ctx))
773 }
774
775 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
776 self.n.iter_mut().for_each(|n| n.sleep(ctx))
777 }
778
779 fn refs(&self, refs: &mut Refs) {
780 self.n.iter().for_each(|n| n.refs(refs))
781 }
782
783 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
784 for n in self.n.iter_mut() {
785 wrap!(n, n.typecheck(ctx))?
786 }
787 let rtyp = Type::Bottom;
788 let rtyp = wrap!(
789 self,
790 self.n.iter().fold(Ok(rtyp), |rtype, n| rtype?.union(&ctx.env, n.typ()))
791 )?;
792 let rtyp = if rtyp == Type::Bottom { Type::empty_tvar() } else { rtyp };
793 self.typ.check_contains(&ctx.env, &rtyp)?;
794 Ok(())
795 }
796}
797
798#[derive(Debug)]
799struct Sample<R: Rt, E: UserEvent> {
800 spec: Expr,
801 triggered: usize,
802 typ: Type,
803 id: BindId,
804 top_id: ExprId,
805 trigger: Node<R, E>,
806 arg: Cached<R, E>,
807}
808
809impl<R: Rt, E: UserEvent> Sample<R, E> {
810 pub(crate) fn compile(
811 ctx: &mut ExecCtx<R, E>,
812 flags: BitFlags<CFlag>,
813 spec: Expr,
814 scope: &Scope,
815 top_id: ExprId,
816 lhs: &Arc<Expr>,
817 rhs: &Arc<Expr>,
818 ) -> Result<Node<R, E>> {
819 let id = BindId::new();
820 ctx.rt.ref_var(id, top_id);
821 let trigger = compile(ctx, flags, (**lhs).clone(), scope, top_id)?;
822 let arg = Cached::new(compile(ctx, flags, (**rhs).clone(), scope, top_id)?);
823 let typ = arg.node.typ().clone();
824 Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
825 }
826}
827
828impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
829 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
830 if let Some(_) = self.trigger.update(ctx, event) {
831 self.triggered += 1;
832 }
833 self.arg.update(ctx, event);
834 let var = event.variables.get(&self.id).cloned();
835 let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
836 self.triggered -= 1;
837 self.arg.cached.clone()
838 } else {
839 var
840 };
841 if self.arg.cached.is_some() {
842 while self.triggered > 0 {
843 self.triggered -= 1;
844 ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
845 }
846 }
847 res
848 }
849
850 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
851 ctx.rt.unref_var(self.id, self.top_id);
852 self.arg.node.delete(ctx);
853 self.trigger.delete(ctx);
854 }
855
856 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
857 self.arg.sleep(ctx);
858 self.trigger.sleep(ctx);
859 }
860
861 fn spec(&self) -> &Expr {
862 &self.spec
863 }
864
865 fn typ(&self) -> &Type {
866 &self.typ
867 }
868
869 fn refs(&self, refs: &mut Refs) {
870 refs.refed.insert(self.id);
871 self.arg.node.refs(refs);
872 self.trigger.refs(refs);
873 }
874
875 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
876 wrap!(self.trigger, self.trigger.typecheck(ctx))?;
877 wrap!(self.arg.node, self.arg.node.typecheck(ctx))
878 }
879}