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