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