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(crate) 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 self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
393 }
394
395 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
396 for n in &mut self.children {
397 n.delete(ctx)
398 }
399 }
400
401 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
402 for n in &mut self.children {
403 n.sleep(ctx)
404 }
405 }
406
407 fn refs(&self, refs: &mut Refs) {
408 for n in &self.children {
409 n.refs(refs)
410 }
411 }
412
413 fn typ(&self) -> &Type {
414 &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
415 }
416
417 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
418 for n in &mut self.children {
419 if self.module {
420 wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
421 } else {
422 wrap!(n, n.typecheck(ctx))?
423 }
424 }
425 Ok(())
426 }
427
428 fn spec(&self) -> &Expr {
429 &self.spec
430 }
431}
432
433#[derive(Debug)]
434pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
435 spec: Expr,
436 typ: Type,
437 typs: Box<[Type]>,
438 args: Box<[Cached<R, E>]>,
439}
440
441impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
442 pub(crate) fn compile(
443 ctx: &mut ExecCtx<R, E>,
444 flags: BitFlags<CFlag>,
445 spec: Expr,
446 scope: &Scope,
447 top_id: ExprId,
448 args: &[Expr],
449 ) -> Result<Node<R, E>> {
450 let args: Box<[Cached<R, E>]> = args
451 .iter()
452 .map(|e| Ok(Cached::new(compile(ctx, flags, e.clone(), scope, top_id)?)))
453 .collect::<Result<_>>()?;
454 let typs = args.iter().map(|c| c.node.typ().clone()).collect();
455 let typ = Type::Primitive(Typ::String.into());
456 Ok(Box::new(Self { spec, typ, typs, args }))
457 }
458}
459
460impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
461 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
462 use std::fmt::Write;
463 thread_local! {
464 static BUF: RefCell<String> = RefCell::new(String::new());
465 }
466 let (updated, determined) = update_args!(self.args, ctx, event);
467 if updated && determined {
468 BUF.with_borrow_mut(|buf| {
469 buf.clear();
470 for (typ, c) in self.typs.iter().zip(self.args.iter()) {
471 match c.cached.as_ref().unwrap() {
472 Value::String(s) => write!(buf, "{s}"),
473 v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
474 }
475 .unwrap()
476 }
477 Some(Value::String(buf.as_str().into()))
478 })
479 } else {
480 None
481 }
482 }
483
484 fn spec(&self) -> &Expr {
485 &self.spec
486 }
487
488 fn typ(&self) -> &Type {
489 &self.typ
490 }
491
492 fn refs(&self, refs: &mut Refs) {
493 for a in &self.args {
494 a.node.refs(refs)
495 }
496 }
497
498 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
499 for n in &mut self.args {
500 n.node.delete(ctx)
501 }
502 }
503
504 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
505 for n in &mut self.args {
506 n.sleep(ctx);
507 }
508 }
509
510 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
511 for (i, a) in self.args.iter_mut().enumerate() {
512 wrap!(a.node, a.node.typecheck(ctx))?;
513 self.typs[i] = a.node.typ().with_deref(|t| match t {
514 None => Type::Any,
515 Some(t) => t.clone(),
516 });
517 }
518 Ok(())
519 }
520}
521
522#[derive(Debug)]
523pub(crate) struct Connect<R: Rt, E: UserEvent> {
524 spec: Expr,
525 node: Node<R, E>,
526 id: BindId,
527}
528
529impl<R: Rt, E: UserEvent> Connect<R, E> {
530 pub(crate) fn compile(
531 ctx: &mut ExecCtx<R, E>,
532 flags: BitFlags<CFlag>,
533 spec: Expr,
534 scope: &Scope,
535 top_id: ExprId,
536 name: &ModPath,
537 value: &Expr,
538 ) -> Result<Node<R, E>> {
539 let id = match ctx.env.lookup_bind(&scope.lexical, name) {
540 None => bail!("at {} {name} is undefined", spec.pos),
541 Some((_, env::Bind { id, .. })) => *id,
542 };
543 let node = compile(ctx, flags, value.clone(), scope, top_id)?;
544 Ok(Box::new(Self { spec, node, id }))
545 }
546}
547
548impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
549 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
550 if let Some(v) = self.node.update(ctx, event) {
551 ctx.set_var(self.id, v)
552 }
553 None
554 }
555
556 fn spec(&self) -> &Expr {
557 &self.spec
558 }
559
560 fn typ(&self) -> &Type {
561 &Type::Bottom
562 }
563
564 fn refs(&self, refs: &mut Refs) {
565 self.node.refs(refs)
566 }
567
568 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
569 self.node.delete(ctx)
570 }
571
572 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
573 self.node.sleep(ctx);
574 }
575
576 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
577 wrap!(self.node, self.node.typecheck(ctx))?;
578 let bind = match ctx.env.by_id.get(&self.id) {
579 None => bail!("BUG missing bind {:?}", self.id),
580 Some(bind) => bind,
581 };
582 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
583 }
584}
585
586#[derive(Debug)]
587pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
588 spec: Expr,
589 rhs: Cached<R, E>,
590 src_id: BindId,
591 target_id: Option<BindId>,
592 top_id: ExprId,
593}
594
595impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
596 pub(crate) fn compile(
597 ctx: &mut ExecCtx<R, E>,
598 flags: BitFlags<CFlag>,
599 spec: Expr,
600 scope: &Scope,
601 top_id: ExprId,
602 name: &ModPath,
603 value: &Expr,
604 ) -> Result<Node<R, E>> {
605 let src_id = match ctx.env.lookup_bind(&scope.lexical, name) {
606 None => bail!("at {} {name} is undefined", spec.pos),
607 Some((_, env::Bind { id, .. })) => *id,
608 };
609 ctx.rt.ref_var(src_id, top_id);
610 let rhs = Cached::new(compile(ctx, flags, value.clone(), scope, top_id)?);
611 Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
612 }
613}
614
615impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
616 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
617 let mut up = self.rhs.update(ctx, event);
618 if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
619 if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
620 self.target_id = Some(*target_id);
621 up = true;
622 }
623 }
624 if up {
625 if let Some(v) = &self.rhs.cached {
626 if let Some(id) = self.target_id {
627 ctx.set_var(id, v.clone());
628 }
629 }
630 }
631 None
632 }
633
634 fn spec(&self) -> &Expr {
635 &self.spec
636 }
637
638 fn typ(&self) -> &Type {
639 &Type::Bottom
640 }
641
642 fn refs(&self, refs: &mut Refs) {
643 refs.refed.insert(self.src_id);
644 self.rhs.node.refs(refs)
645 }
646
647 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
648 ctx.rt.unref_var(self.src_id, self.top_id);
649 self.rhs.node.delete(ctx)
650 }
651
652 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
653 self.rhs.sleep(ctx);
654 }
655
656 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
657 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
658 let bind = match ctx.env.by_id.get(&self.src_id) {
659 None => bail!("BUG missing bind {:?}", self.src_id),
660 Some(bind) => bind,
661 };
662 let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
663 wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
664 }
665}
666
667#[derive(Debug)]
668pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
669 spec: Expr,
670 typ: Type,
671 target: Type,
672 n: Node<R, E>,
673}
674
675impl<R: Rt, E: UserEvent> TypeCast<R, E> {
676 pub(crate) fn compile(
677 ctx: &mut ExecCtx<R, E>,
678 flags: BitFlags<CFlag>,
679 spec: Expr,
680 scope: &Scope,
681 top_id: ExprId,
682 expr: &Expr,
683 typ: &Type,
684 ) -> Result<Node<R, E>> {
685 let n = compile(ctx, flags, expr.clone(), scope, top_id)?;
686 let target = typ.scope_refs(&scope.lexical);
687 if let Err(e) = target.check_cast(&ctx.env) {
688 bail!("in cast at {} {e}", spec.pos);
689 }
690 let typ = target.union(&ctx.env, &CAST_ERR)?;
691 Ok(Box::new(Self { spec, typ, target, n }))
692 }
693}
694
695impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
696 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
697 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
698 }
699
700 fn spec(&self) -> &Expr {
701 &self.spec
702 }
703
704 fn typ(&self) -> &Type {
705 &self.typ
706 }
707
708 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
709 self.n.delete(ctx)
710 }
711
712 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
713 self.n.sleep(ctx);
714 }
715
716 fn refs(&self, refs: &mut Refs) {
717 self.n.refs(refs)
718 }
719
720 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
721 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
722 }
723}
724
725#[derive(Debug)]
726pub(crate) struct Any<R: Rt, E: UserEvent> {
727 spec: Expr,
728 typ: Type,
729 n: Box<[Node<R, E>]>,
730}
731
732impl<R: Rt, E: UserEvent> Any<R, E> {
733 pub(crate) fn compile(
734 ctx: &mut ExecCtx<R, E>,
735 flags: BitFlags<CFlag>,
736 spec: Expr,
737 scope: &Scope,
738 top_id: ExprId,
739 args: &[Expr],
740 ) -> Result<Node<R, E>> {
741 let n = args
742 .iter()
743 .map(|e| compile(ctx, flags, e.clone(), scope, top_id))
744 .collect::<Result<Box<[_]>>>()?;
745 Ok(Box::new(Self { spec, typ: Type::empty_tvar(), n }))
746 }
747}
748
749impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
750 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
751 self.n
752 .iter_mut()
753 .filter_map(|s| s.update(ctx, event))
754 .fold(None, |r, v| r.or(Some(v)))
755 }
756
757 fn spec(&self) -> &Expr {
758 &self.spec
759 }
760
761 fn typ(&self) -> &Type {
762 &self.typ
763 }
764
765 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
766 self.n.iter_mut().for_each(|n| n.delete(ctx))
767 }
768
769 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
770 self.n.iter_mut().for_each(|n| n.sleep(ctx))
771 }
772
773 fn refs(&self, refs: &mut Refs) {
774 self.n.iter().for_each(|n| n.refs(refs))
775 }
776
777 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
778 for n in self.n.iter_mut() {
779 wrap!(n, n.typecheck(ctx))?
780 }
781 let rtyp = Type::Bottom;
782 let rtyp = wrap!(
783 self,
784 self.n.iter().fold(Ok(rtyp), |rtype, n| rtype?.union(&ctx.env, n.typ()))
785 )?;
786 let rtyp = if rtyp == Type::Bottom { Type::empty_tvar() } else { rtyp };
787 self.typ.check_contains(&ctx.env, &rtyp)?;
788 Ok(())
789 }
790}
791
792#[derive(Debug)]
793struct Sample<R: Rt, E: UserEvent> {
794 spec: Expr,
795 triggered: usize,
796 typ: Type,
797 id: BindId,
798 top_id: ExprId,
799 trigger: Node<R, E>,
800 arg: Cached<R, E>,
801}
802
803impl<R: Rt, E: UserEvent> Sample<R, E> {
804 pub(crate) fn compile(
805 ctx: &mut ExecCtx<R, E>,
806 flags: BitFlags<CFlag>,
807 spec: Expr,
808 scope: &Scope,
809 top_id: ExprId,
810 lhs: &Arc<Expr>,
811 rhs: &Arc<Expr>,
812 ) -> Result<Node<R, E>> {
813 let id = BindId::new();
814 ctx.rt.ref_var(id, top_id);
815 let trigger = compile(ctx, flags, (**lhs).clone(), scope, top_id)?;
816 let arg = Cached::new(compile(ctx, flags, (**rhs).clone(), scope, top_id)?);
817 let typ = arg.node.typ().clone();
818 Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
819 }
820}
821
822impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
823 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
824 if let Some(_) = self.trigger.update(ctx, event) {
825 self.triggered += 1;
826 }
827 self.arg.update(ctx, event);
828 let var = event.variables.get(&self.id).cloned();
829 let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
830 self.triggered -= 1;
831 self.arg.cached.clone()
832 } else {
833 var
834 };
835 if self.arg.cached.is_some() {
836 while self.triggered > 0 {
837 self.triggered -= 1;
838 ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
839 }
840 }
841 res
842 }
843
844 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
845 ctx.rt.unref_var(self.id, self.top_id);
846 self.arg.node.delete(ctx);
847 self.trigger.delete(ctx);
848 }
849
850 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
851 self.arg.sleep(ctx);
852 self.trigger.sleep(ctx);
853 }
854
855 fn spec(&self) -> &Expr {
856 &self.spec
857 }
858
859 fn typ(&self) -> &Type {
860 &self.typ
861 }
862
863 fn refs(&self, refs: &mut Refs) {
864 refs.refed.insert(self.id);
865 self.arg.node.refs(refs);
866 self.trigger.refs(refs);
867 }
868
869 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
870 wrap!(self.trigger, self.trigger.typecheck(ctx))?;
871 wrap!(self.arg.node, self.arg.node.typecheck(ctx))
872 }
873}