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