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