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