1use crate::{
2 env, err,
3 expr::{self, Expr, ExprId, ExprKind, ModPath},
4 format_with_flags,
5 typ::{TVal, TVar, Type},
6 wrap, BindId, Event, ExecCtx, Node, PrintFlag, Refs, Rt, Update, UserEvent,
7};
8use anyhow::{anyhow, bail, Context, Result};
9use arcstr::{literal, ArcStr};
10use compact_str::format_compact;
11use compiler::compile;
12use enumflags2::BitFlags;
13use netidx_value::{Typ, Value};
14use pattern::StructPatternNode;
15use std::{cell::RefCell, sync::LazyLock};
16use triomphe::Arc;
17
18pub(crate) mod array;
19pub(crate) mod callsite;
20pub(crate) mod compiler;
21pub(crate) mod data;
22pub(crate) mod dynamic;
23pub mod genn;
24pub(crate) mod lambda;
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
54static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
55 Arc::new(
56 ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
57 )
58});
59
60#[derive(Debug)]
61pub(crate) struct Nop {
62 pub typ: Type,
63}
64
65impl Nop {
66 pub(crate) fn new<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
67 Box::new(Nop { typ })
68 }
69}
70
71impl<R: Rt, E: UserEvent> Update<R, E> for Nop {
72 fn update(
73 &mut self,
74 _ctx: &mut ExecCtx<R, E>,
75 _event: &mut Event<E>,
76 ) -> Option<Value> {
77 None
78 }
79
80 fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
81
82 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
83
84 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
85 Ok(())
86 }
87
88 fn spec(&self) -> &Expr {
89 &NOP
90 }
91
92 fn typ(&self) -> &Type {
93 &self.typ
94 }
95
96 fn refs(&self, _refs: &mut Refs) {}
97}
98
99#[derive(Debug)]
100struct Cached<R: Rt, E: UserEvent> {
101 cached: Option<Value>,
102 node: Node<R, E>,
103}
104
105impl<R: Rt, E: UserEvent> Cached<R, E> {
106 fn new(node: Node<R, E>) -> Self {
107 Self { cached: None, node }
108 }
109
110 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> bool {
114 match self.node.update(ctx, event) {
115 None => false,
116 Some(v) => {
117 self.cached = Some(v);
118 true
119 }
120 }
121 }
122
123 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
124 self.cached = None;
125 self.node.sleep(ctx)
126 }
127}
128
129#[derive(Debug)]
130pub(crate) struct Use {
131 spec: Expr,
132 scope: ModPath,
133 name: ModPath,
134}
135
136impl Use {
137 pub(crate) fn compile<R: Rt, E: UserEvent>(
138 ctx: &mut ExecCtx<R, E>,
139 spec: Expr,
140 scope: &ModPath,
141 name: &ModPath,
142 ) -> Result<Node<R, E>> {
143 match ctx.env.canonical_modpath(scope, name) {
144 None => bail!("at {} no such module {name}", spec.pos),
145 Some(_) => {
146 let used = ctx.env.used.get_or_default_cow(scope.clone());
147 Arc::make_mut(used).push(name.clone());
148 Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
149 }
150 }
151 }
152}
153
154impl<R: Rt, E: UserEvent> Update<R, E> for Use {
155 fn update(
156 &mut self,
157 _ctx: &mut ExecCtx<R, E>,
158 _event: &mut Event<E>,
159 ) -> Option<Value> {
160 None
161 }
162
163 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
164 Ok(())
165 }
166
167 fn refs(&self, _refs: &mut Refs) {}
168
169 fn spec(&self) -> &Expr {
170 &self.spec
171 }
172
173 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
174 if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
175 Arc::make_mut(used).retain(|n| n != &self.name);
176 if used.is_empty() {
177 ctx.env.used.remove_cow(&self.scope);
178 }
179 }
180 }
181
182 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
183
184 fn typ(&self) -> &Type {
185 &Type::Bottom
186 }
187}
188
189#[derive(Debug)]
190pub(crate) struct TypeDef {
191 spec: Expr,
192 scope: ModPath,
193 name: ArcStr,
194}
195
196impl TypeDef {
197 pub(crate) fn compile<R: Rt, E: UserEvent>(
198 ctx: &mut ExecCtx<R, E>,
199 spec: Expr,
200 scope: &ModPath,
201 name: &ArcStr,
202 params: &Arc<[(TVar, Option<Type>)]>,
203 typ: &Type,
204 ) -> Result<Node<R, E>> {
205 let typ = typ.scope_refs(scope);
206 ctx.env
207 .deftype(scope, name, params.clone(), typ)
208 .with_context(|| format!("in typedef at {}", spec.pos))?;
209 let name = name.clone();
210 let scope = scope.clone();
211 Ok(Box::new(Self { spec, scope, name }))
212 }
213}
214
215impl<R: Rt, E: UserEvent> Update<R, E> for TypeDef {
216 fn update(
217 &mut self,
218 _ctx: &mut ExecCtx<R, E>,
219 _event: &mut Event<E>,
220 ) -> Option<Value> {
221 None
222 }
223
224 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
225 Ok(())
226 }
227
228 fn refs(&self, _refs: &mut Refs) {}
229
230 fn spec(&self) -> &Expr {
231 &self.spec
232 }
233
234 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
235 ctx.env.undeftype(&self.scope, &self.name)
236 }
237
238 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
239
240 fn typ(&self) -> &Type {
241 &Type::Bottom
242 }
243}
244
245#[derive(Debug)]
246pub(crate) struct Constant {
247 spec: Arc<Expr>,
248 value: Value,
249 typ: Type,
250}
251
252impl Constant {
253 pub(crate) fn compile<R: Rt, E: UserEvent>(
254 spec: Expr,
255 value: &Value,
256 ) -> Result<Node<R, E>> {
257 let spec = Arc::new(spec);
258 let value = value.clone();
259 let typ = Type::Primitive(Typ::get(&value).into());
260 Ok(Box::new(Self { spec, value, typ }))
261 }
262}
263
264impl<R: Rt, E: UserEvent> Update<R, E> for Constant {
265 fn update(
266 &mut self,
267 _ctx: &mut ExecCtx<R, E>,
268 event: &mut Event<E>,
269 ) -> Option<Value> {
270 if event.init {
271 Some(self.value.clone())
272 } else {
273 None
274 }
275 }
276
277 fn delete(&mut self, _ctx: &mut ExecCtx<R, E>) {}
278
279 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
280
281 fn refs(&self, _refs: &mut Refs) {}
282
283 fn typ(&self) -> &Type {
284 &self.typ
285 }
286
287 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
288 Ok(())
289 }
290
291 fn spec(&self) -> &Expr {
292 &self.spec
293 }
294}
295
296#[derive(Debug)]
298pub(crate) struct Block<R: Rt, E: UserEvent> {
299 module: bool,
300 spec: Expr,
301 children: Box<[Node<R, E>]>,
302}
303
304impl<R: Rt, E: UserEvent> Block<R, E> {
305 pub(crate) fn compile(
306 ctx: &mut ExecCtx<R, E>,
307 spec: Expr,
308 scope: &ModPath,
309 top_id: ExprId,
310 module: bool,
311 exprs: &Arc<[Expr]>,
312 ) -> Result<Node<R, E>> {
313 let children = exprs
314 .iter()
315 .map(|e| compile(ctx, e.clone(), scope, top_id))
316 .collect::<Result<Box<[Node<R, E>]>>>()?;
317 Ok(Box::new(Self { module, spec, children }))
318 }
319}
320
321impl<R: Rt, E: UserEvent> Update<R, E> for Block<R, E> {
322 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
323 self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
324 }
325
326 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
327 for n in &mut self.children {
328 n.delete(ctx)
329 }
330 }
331
332 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
333 for n in &mut self.children {
334 n.sleep(ctx)
335 }
336 }
337
338 fn refs(&self, refs: &mut Refs) {
339 for n in &self.children {
340 n.refs(refs)
341 }
342 }
343
344 fn typ(&self) -> &Type {
345 &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
346 }
347
348 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
349 for n in &mut self.children {
350 if self.module {
351 wrap!(n, n.typecheck(ctx)).with_context(|| self.spec.ori.clone())?
352 } else {
353 wrap!(n, n.typecheck(ctx))?
354 }
355 }
356 Ok(())
357 }
358
359 fn spec(&self) -> &Expr {
360 &self.spec
361 }
362}
363
364#[derive(Debug)]
365pub(crate) struct Bind<R: Rt, E: UserEvent> {
366 spec: Expr,
367 typ: Type,
368 pattern: StructPatternNode,
369 node: Node<R, E>,
370 top_id: ExprId,
371}
372
373impl<R: Rt, E: UserEvent> Bind<R, E> {
374 pub(crate) fn compile(
375 ctx: &mut ExecCtx<R, E>,
376 spec: Expr,
377 scope: &ModPath,
378 top_id: ExprId,
379 b: &expr::Bind,
380 ) -> Result<Node<R, E>> {
381 let expr::Bind { doc, pattern, typ, export: _, value } = b;
382 let node = compile(ctx, value.clone(), &scope, top_id)?;
383 let typ = match typ {
384 Some(typ) => typ.scope_refs(scope),
385 None => {
386 let typ = node.typ().clone();
387 let ptyp = pattern.infer_type_predicate(&ctx.env)?;
388 if !ptyp.contains(&ctx.env, &typ)? {
389 format_with_flags(PrintFlag::DerefTVars, || {
390 bail!(
391 "at {} match error {typ} can't be matched by {ptyp}",
392 spec.pos
393 )
394 })?
395 }
396 typ
397 }
398 };
399 let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
400 .with_context(|| format!("at {}", spec.pos))?;
401 if pattern.is_refutable() {
402 bail!("at {} refutable patterns are not allowed in let", spec.pos);
403 }
404 if let Some(doc) = doc {
405 pattern.ids(&mut |id| {
406 if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
407 b.doc = Some(doc.clone());
408 }
409 });
410 }
411 Ok(Box::new(Self { spec, typ, pattern, node, top_id }))
412 }
413
414 pub(crate) fn single_id(&self) -> Option<BindId> {
416 let mut id = None;
417 let mut n = 0;
418 self.pattern.ids(&mut |i| {
419 if n == 0 {
420 id = Some(i)
421 }
422 n += 1
423 });
424 if n == 1 {
425 id
426 } else {
427 None
428 }
429 }
430}
431
432impl<R: Rt, E: UserEvent> Update<R, E> for Bind<R, E> {
433 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
434 if let Some(v) = self.node.update(ctx, event) {
435 self.pattern.bind(&v, &mut |id, v| {
436 event.variables.insert(id, v.clone());
437 ctx.cached.insert(id, v);
438 if self.spec.id == self.top_id {
439 ctx.rt.notify_set(id);
440 }
441 })
442 }
443 None
444 }
445
446 fn refs(&self, refs: &mut Refs) {
447 self.pattern.ids(&mut |id| {
448 refs.bound.insert(id);
449 });
450 self.node.refs(refs);
451 }
452
453 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
454 self.node.delete(ctx);
455 self.pattern.delete(ctx);
456 }
457
458 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
459 self.node.sleep(ctx);
460 }
461
462 fn typ(&self) -> &Type {
463 &self.typ
464 }
465
466 fn spec(&self) -> &Expr {
467 &self.spec
468 }
469
470 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
471 wrap!(self.node, self.node.typecheck(ctx))?;
472 wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
473 Ok(())
474 }
475}
476
477#[derive(Debug)]
478pub(crate) struct Ref {
479 spec: Arc<Expr>,
480 typ: Type,
481 id: BindId,
482 top_id: ExprId,
483}
484
485impl Ref {
486 pub(crate) fn compile<R: Rt, E: UserEvent>(
487 ctx: &mut ExecCtx<R, E>,
488 spec: Expr,
489 scope: &ModPath,
490 top_id: ExprId,
491 name: &ModPath,
492 ) -> Result<Node<R, E>> {
493 match ctx.env.lookup_bind(scope, name) {
494 None => bail!("at {} {name} not defined", spec.pos),
495 Some((_, bind)) => {
496 ctx.rt.ref_var(bind.id, top_id);
497 let typ = bind.typ.clone();
498 let spec = Arc::new(spec);
499 Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
500 }
501 }
502 }
503}
504
505impl<R: Rt, E: UserEvent> Update<R, E> for Ref {
506 fn update(
507 &mut self,
508 _ctx: &mut ExecCtx<R, E>,
509 event: &mut Event<E>,
510 ) -> Option<Value> {
511 event.variables.get(&self.id).map(|v| v.clone())
512 }
513
514 fn refs(&self, refs: &mut Refs) {
515 refs.refed.insert(self.id);
516 }
517
518 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
519 ctx.rt.unref_var(self.id, self.top_id)
520 }
521
522 fn sleep(&mut self, _ctx: &mut ExecCtx<R, E>) {}
523
524 fn spec(&self) -> &Expr {
525 &self.spec
526 }
527
528 fn typ(&self) -> &Type {
529 &self.typ
530 }
531
532 fn typecheck(&mut self, _ctx: &mut ExecCtx<R, E>) -> Result<()> {
533 Ok(())
534 }
535}
536
537#[derive(Debug)]
538pub(crate) struct StringInterpolate<R: Rt, E: UserEvent> {
539 spec: Expr,
540 typ: Type,
541 typs: Box<[Type]>,
542 args: Box<[Cached<R, E>]>,
543}
544
545impl<R: Rt, E: UserEvent> StringInterpolate<R, E> {
546 pub(crate) fn compile(
547 ctx: &mut ExecCtx<R, E>,
548 spec: Expr,
549 scope: &ModPath,
550 top_id: ExprId,
551 args: &[Expr],
552 ) -> Result<Node<R, E>> {
553 let args: Box<[Cached<R, E>]> = args
554 .iter()
555 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
556 .collect::<Result<_>>()?;
557 let typs = args.iter().map(|c| c.node.typ().clone()).collect();
558 let typ = Type::Primitive(Typ::String.into());
559 Ok(Box::new(Self { spec, typ, typs, args }))
560 }
561}
562
563impl<R: Rt, E: UserEvent> Update<R, E> for StringInterpolate<R, E> {
564 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
565 use std::fmt::Write;
566 thread_local! {
567 static BUF: RefCell<String> = RefCell::new(String::new());
568 }
569 let (updated, determined) = update_args!(self.args, ctx, event);
570 if updated && determined {
571 BUF.with_borrow_mut(|buf| {
572 buf.clear();
573 for (typ, c) in self.typs.iter().zip(self.args.iter()) {
574 match c.cached.as_ref().unwrap() {
575 Value::String(s) => write!(buf, "{s}"),
576 v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
577 }
578 .unwrap()
579 }
580 Some(Value::String(buf.as_str().into()))
581 })
582 } else {
583 None
584 }
585 }
586
587 fn spec(&self) -> &Expr {
588 &self.spec
589 }
590
591 fn typ(&self) -> &Type {
592 &self.typ
593 }
594
595 fn refs(&self, refs: &mut Refs) {
596 for a in &self.args {
597 a.node.refs(refs)
598 }
599 }
600
601 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
602 for n in &mut self.args {
603 n.node.delete(ctx)
604 }
605 }
606
607 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
608 for n in &mut self.args {
609 n.sleep(ctx);
610 }
611 }
612
613 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
614 for (i, a) in self.args.iter_mut().enumerate() {
615 wrap!(a.node, a.node.typecheck(ctx))?;
616 self.typs[i] = a.node.typ().with_deref(|t| match t {
617 None => Type::Any,
618 Some(t) => t.clone(),
619 });
620 }
621 Ok(())
622 }
623}
624
625#[derive(Debug)]
626pub(crate) struct Connect<R: Rt, E: UserEvent> {
627 spec: Expr,
628 node: Node<R, E>,
629 id: BindId,
630}
631
632impl<R: Rt, E: UserEvent> Connect<R, E> {
633 pub(crate) fn compile(
634 ctx: &mut ExecCtx<R, E>,
635 spec: Expr,
636 scope: &ModPath,
637 top_id: ExprId,
638 name: &ModPath,
639 value: &Expr,
640 ) -> Result<Node<R, E>> {
641 let id = match ctx.env.lookup_bind(scope, name) {
642 None => bail!("at {} {name} is undefined", spec.pos),
643 Some((_, env::Bind { id, .. })) => *id,
644 };
645 let node = compile(ctx, value.clone(), scope, top_id)?;
646 Ok(Box::new(Self { spec, node, id }))
647 }
648}
649
650impl<R: Rt, E: UserEvent> Update<R, E> for Connect<R, E> {
651 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
652 if let Some(v) = self.node.update(ctx, event) {
653 ctx.set_var(self.id, v)
654 }
655 None
656 }
657
658 fn spec(&self) -> &Expr {
659 &self.spec
660 }
661
662 fn typ(&self) -> &Type {
663 &Type::Bottom
664 }
665
666 fn refs(&self, refs: &mut Refs) {
667 self.node.refs(refs)
668 }
669
670 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
671 self.node.delete(ctx)
672 }
673
674 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
675 self.node.sleep(ctx);
676 }
677
678 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
679 wrap!(self.node, self.node.typecheck(ctx))?;
680 let bind = match ctx.env.by_id.get(&self.id) {
681 None => bail!("BUG missing bind {:?}", self.id),
682 Some(bind) => bind,
683 };
684 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
685 }
686}
687
688#[derive(Debug)]
689pub(crate) struct ConnectDeref<R: Rt, E: UserEvent> {
690 spec: Expr,
691 rhs: Cached<R, E>,
692 src_id: BindId,
693 target_id: Option<BindId>,
694 top_id: ExprId,
695}
696
697impl<R: Rt, E: UserEvent> ConnectDeref<R, E> {
698 pub(crate) fn compile(
699 ctx: &mut ExecCtx<R, E>,
700 spec: Expr,
701 scope: &ModPath,
702 top_id: ExprId,
703 name: &ModPath,
704 value: &Expr,
705 ) -> Result<Node<R, E>> {
706 let src_id = match ctx.env.lookup_bind(scope, name) {
707 None => bail!("at {} {name} is undefined", spec.pos),
708 Some((_, env::Bind { id, .. })) => *id,
709 };
710 ctx.rt.ref_var(src_id, top_id);
711 let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
712 Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
713 }
714}
715
716impl<R: Rt, E: UserEvent> Update<R, E> for ConnectDeref<R, E> {
717 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
718 let mut up = self.rhs.update(ctx, event);
719 if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
720 if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
721 self.target_id = Some(*target_id);
722 up = true;
723 }
724 }
725 if up {
726 if let Some(v) = &self.rhs.cached {
727 if let Some(id) = self.target_id {
728 ctx.set_var(id, v.clone())
729 }
730 }
731 }
732 None
733 }
734
735 fn spec(&self) -> &Expr {
736 &self.spec
737 }
738
739 fn typ(&self) -> &Type {
740 &Type::Bottom
741 }
742
743 fn refs(&self, refs: &mut Refs) {
744 refs.refed.insert(self.src_id);
745 self.rhs.node.refs(refs)
746 }
747
748 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
749 ctx.rt.unref_var(self.src_id, self.top_id);
750 self.rhs.node.delete(ctx)
751 }
752
753 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
754 self.rhs.sleep(ctx);
755 }
756
757 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
758 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
759 let bind = match ctx.env.by_id.get(&self.src_id) {
760 None => bail!("BUG missing bind {:?}", self.src_id),
761 Some(bind) => bind,
762 };
763 let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
764 wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
765 }
766}
767
768#[derive(Debug)]
769pub(crate) struct ByRef<R: Rt, E: UserEvent> {
770 spec: Expr,
771 typ: Type,
772 child: Node<R, E>,
773 id: BindId,
774}
775
776impl<R: Rt, E: UserEvent> ByRef<R, E> {
777 pub(crate) fn compile(
778 ctx: &mut ExecCtx<R, E>,
779 spec: Expr,
780 scope: &ModPath,
781 top_id: ExprId,
782 expr: &Expr,
783 ) -> Result<Node<R, E>> {
784 let child = compile(ctx, expr.clone(), scope, top_id)?;
785 let id = BindId::new();
786 if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
787 ctx.env.byref_chain.insert_cow(id, c.id);
788 }
789 let typ = Type::ByRef(Arc::new(child.typ().clone()));
790 Ok(Box::new(Self { spec, typ, child, id }))
791 }
792}
793
794impl<R: Rt, E: UserEvent> Update<R, E> for ByRef<R, E> {
795 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
796 if let Some(v) = self.child.update(ctx, event) {
797 ctx.set_var(self.id, v);
798 }
799 if event.init {
800 Some(Value::U64(self.id.inner()))
801 } else {
802 None
803 }
804 }
805
806 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
807 ctx.env.byref_chain.remove_cow(&self.id);
808 self.child.delete(ctx)
809 }
810
811 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
812 self.child.sleep(ctx);
813 }
814
815 fn spec(&self) -> &Expr {
816 &self.spec
817 }
818
819 fn typ(&self) -> &Type {
820 &self.typ
821 }
822
823 fn refs(&self, refs: &mut Refs) {
824 self.child.refs(refs)
825 }
826
827 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
828 wrap!(self.child, self.child.typecheck(ctx))?;
829 let t = Type::ByRef(Arc::new(self.child.typ().clone()));
830 wrap!(self, self.typ.check_contains(&ctx.env, &t))
831 }
832}
833
834#[derive(Debug)]
835pub(crate) struct Deref<R: Rt, E: UserEvent> {
836 spec: Expr,
837 typ: Type,
838 child: Node<R, E>,
839 id: Option<BindId>,
840 top_id: ExprId,
841}
842
843impl<R: Rt, E: UserEvent> Deref<R, E> {
844 pub(crate) fn compile(
845 ctx: &mut ExecCtx<R, E>,
846 spec: Expr,
847 scope: &ModPath,
848 top_id: ExprId,
849 expr: &Expr,
850 ) -> Result<Node<R, E>> {
851 let child = compile(ctx, expr.clone(), scope, top_id)?;
852 let typ = Type::empty_tvar();
853 Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
854 }
855}
856
857impl<R: Rt, E: UserEvent> Update<R, E> for Deref<R, E> {
858 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
859 if let Some(v) = self.child.update(ctx, event) {
860 match v {
861 Value::U64(i) | Value::V64(i) => {
862 let new_id = BindId::from(i);
863 if self.id != Some(new_id) {
864 if let Some(old) = self.id {
865 ctx.rt.unref_var(old, self.top_id);
866 }
867 ctx.rt.ref_var(new_id, self.top_id);
868 self.id = Some(new_id);
869 }
870 }
871 _ => return err!("expected u64 bind id"),
872 }
873 }
874 self.id.and_then(|id| event.variables.get(&id).cloned())
875 }
876
877 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
878 if let Some(id) = self.id.take() {
879 ctx.rt.unref_var(id, self.top_id);
880 }
881 self.child.delete(ctx);
882 }
883
884 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
885 self.child.sleep(ctx);
886 }
887
888 fn spec(&self) -> &Expr {
889 &self.spec
890 }
891
892 fn typ(&self) -> &Type {
893 &self.typ
894 }
895
896 fn refs(&self, refs: &mut Refs) {
897 self.child.refs(refs);
898 if let Some(id) = self.id {
899 refs.refed.insert(id);
900 }
901 }
902
903 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
904 wrap!(self.child, self.child.typecheck(ctx))?;
905 let typ = match self.child.typ() {
906 Type::ByRef(t) => (**t).clone(),
907 _ => bail!("expected reference"),
908 };
909 wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
910 Ok(())
911 }
912}
913
914#[derive(Debug)]
915pub(crate) struct Qop<R: Rt, E: UserEvent> {
916 spec: Expr,
917 typ: Type,
918 id: BindId,
919 n: Node<R, E>,
920}
921
922impl<R: Rt, E: UserEvent> Qop<R, E> {
923 pub(crate) fn compile(
924 ctx: &mut ExecCtx<R, E>,
925 spec: Expr,
926 scope: &ModPath,
927 top_id: ExprId,
928 e: &Expr,
929 ) -> Result<Node<R, E>> {
930 let n = compile(ctx, e.clone(), scope, top_id)?;
931 match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
932 None => bail!("at {} BUG: errors is undefined", spec.pos),
933 Some((_, bind)) => {
934 let typ = Type::empty_tvar();
935 Ok(Box::new(Self { spec, typ, id: bind.id, n }))
936 }
937 }
938 }
939}
940
941impl<R: Rt, E: UserEvent> Update<R, E> for Qop<R, E> {
942 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
943 match self.n.update(ctx, event) {
944 None => None,
945 Some(Value::Error(e)) => {
946 let e = format_compact!("{} at {} {e}", self.spec.ori, self.spec.pos);
947 ctx.set_var(self.id, Value::Error(e.as_str().into()));
948 None
949 }
950 Some(v) => Some(v),
951 }
952 }
953
954 fn typ(&self) -> &Type {
955 &self.typ
956 }
957
958 fn spec(&self) -> &Expr {
959 &self.spec
960 }
961
962 fn refs(&self, refs: &mut Refs) {
963 self.n.refs(refs)
964 }
965
966 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
967 self.n.delete(ctx)
968 }
969
970 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
971 self.n.sleep(ctx);
972 }
973
974 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
975 wrap!(self.n, self.n.typecheck(ctx))?;
976 let bind =
977 ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
978 let err = Type::Primitive(Typ::Error.into());
979 wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
980 wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
981 if !self.n.typ().contains(&ctx.env, &err)? {
982 bail!("cannot use the ? operator on a non error type")
983 }
984 let rtyp = self.n.typ().diff(&ctx.env, &err)?;
985 wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
986 Ok(())
987 }
988}
989
990#[derive(Debug)]
991pub(crate) struct TypeCast<R: Rt, E: UserEvent> {
992 spec: Expr,
993 typ: Type,
994 target: Type,
995 n: Node<R, E>,
996}
997
998impl<R: Rt, E: UserEvent> TypeCast<R, E> {
999 pub(crate) fn compile(
1000 ctx: &mut ExecCtx<R, E>,
1001 spec: Expr,
1002 scope: &ModPath,
1003 top_id: ExprId,
1004 expr: &Expr,
1005 typ: &Type,
1006 ) -> Result<Node<R, E>> {
1007 let n = compile(ctx, expr.clone(), scope, top_id)?;
1008 let target = typ.scope_refs(scope);
1009 if let Err(e) = target.check_cast(&ctx.env) {
1010 bail!("in cast at {} {e}", spec.pos);
1011 }
1012 let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
1013 Ok(Box::new(Self { spec, typ, target, n }))
1014 }
1015}
1016
1017impl<R: Rt, E: UserEvent> Update<R, E> for TypeCast<R, E> {
1018 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1019 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
1020 }
1021
1022 fn spec(&self) -> &Expr {
1023 &self.spec
1024 }
1025
1026 fn typ(&self) -> &Type {
1027 &self.typ
1028 }
1029
1030 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1031 self.n.delete(ctx)
1032 }
1033
1034 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1035 self.n.sleep(ctx);
1036 }
1037
1038 fn refs(&self, refs: &mut Refs) {
1039 self.n.refs(refs)
1040 }
1041
1042 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1043 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1044 }
1045}
1046
1047#[derive(Debug)]
1048pub(crate) struct Any<R: Rt, E: UserEvent> {
1049 spec: Expr,
1050 typ: Type,
1051 n: Box<[Node<R, E>]>,
1052}
1053
1054impl<R: Rt, E: UserEvent> Any<R, E> {
1055 pub(crate) fn compile(
1056 ctx: &mut ExecCtx<R, E>,
1057 spec: Expr,
1058 scope: &ModPath,
1059 top_id: ExprId,
1060 args: &[Expr],
1061 ) -> Result<Node<R, E>> {
1062 let n = args
1063 .iter()
1064 .map(|e| compile(ctx, e.clone(), scope, top_id))
1065 .collect::<Result<Box<[_]>>>()?;
1066 let typ =
1067 Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1068 Ok(Box::new(Self { spec, typ, n }))
1069 }
1070}
1071
1072impl<R: Rt, E: UserEvent> Update<R, E> for Any<R, E> {
1073 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1074 self.n
1075 .iter_mut()
1076 .filter_map(|s| s.update(ctx, event))
1077 .fold(None, |r, v| r.or(Some(v)))
1078 }
1079
1080 fn spec(&self) -> &Expr {
1081 &self.spec
1082 }
1083
1084 fn typ(&self) -> &Type {
1085 &self.typ
1086 }
1087
1088 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1089 self.n.iter_mut().for_each(|n| n.delete(ctx))
1090 }
1091
1092 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1093 self.n.iter_mut().for_each(|n| n.sleep(ctx))
1094 }
1095
1096 fn refs(&self, refs: &mut Refs) {
1097 self.n.iter().for_each(|n| n.refs(refs))
1098 }
1099
1100 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1101 for n in self.n.iter_mut() {
1102 wrap!(n, n.typecheck(ctx))?
1103 }
1104 let rtyp = Type::Primitive(BitFlags::empty());
1105 let rtyp = wrap!(
1106 self,
1107 self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1108 )?;
1109 Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1110 }
1111}
1112
1113#[derive(Debug)]
1114struct Sample<R: Rt, E: UserEvent> {
1115 spec: Expr,
1116 triggered: usize,
1117 typ: Type,
1118 id: BindId,
1119 top_id: ExprId,
1120 trigger: Node<R, E>,
1121 arg: Cached<R, E>,
1122}
1123
1124impl<R: Rt, E: UserEvent> Sample<R, E> {
1125 pub(crate) fn compile(
1126 ctx: &mut ExecCtx<R, E>,
1127 spec: Expr,
1128 scope: &ModPath,
1129 top_id: ExprId,
1130 lhs: &Arc<Expr>,
1131 rhs: &Arc<Expr>,
1132 ) -> Result<Node<R, E>> {
1133 let id = BindId::new();
1134 ctx.rt.ref_var(id, top_id);
1135 let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1136 let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1137 let typ = arg.node.typ().clone();
1138 Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1139 }
1140}
1141
1142impl<R: Rt, E: UserEvent> Update<R, E> for Sample<R, E> {
1143 fn update(&mut self, ctx: &mut ExecCtx<R, E>, event: &mut Event<E>) -> Option<Value> {
1144 if let Some(_) = self.trigger.update(ctx, event) {
1145 self.triggered += 1;
1146 }
1147 self.arg.update(ctx, event);
1148 let var = event.variables.get(&self.id).cloned();
1149 let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1150 self.triggered -= 1;
1151 self.arg.cached.clone()
1152 } else {
1153 var
1154 };
1155 if self.arg.cached.is_some() {
1156 while self.triggered > 0 {
1157 self.triggered -= 1;
1158 ctx.rt.set_var(self.id, self.arg.cached.clone().unwrap());
1159 }
1160 }
1161 res
1162 }
1163
1164 fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
1165 ctx.rt.unref_var(self.id, self.top_id);
1166 self.arg.node.delete(ctx);
1167 self.trigger.delete(ctx);
1168 }
1169
1170 fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
1171 self.arg.sleep(ctx);
1172 self.trigger.sleep(ctx);
1173 }
1174
1175 fn spec(&self) -> &Expr {
1176 &self.spec
1177 }
1178
1179 fn typ(&self) -> &Type {
1180 &self.typ
1181 }
1182
1183 fn refs(&self, refs: &mut Refs) {
1184 refs.refed.insert(self.id);
1185 self.arg.node.refs(refs);
1186 self.trigger.refs(refs);
1187 }
1188
1189 fn typecheck(&mut self, ctx: &mut ExecCtx<R, E>) -> Result<()> {
1190 wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1191 wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1192 }
1193}