1use crate::{
2 env, err,
3 expr::{self, Expr, ExprId, ExprKind, ModPath, Origin},
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 combine::stream::position::SourcePosition;
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 pos: &SourcePosition,
141 ) -> Result<Node<C, E>> {
142 match ctx.env.canonical_modpath(scope, name) {
143 None => bail!("at {pos} no such module {name}"),
144 Some(_) => {
145 let used = ctx.env.used.get_or_default_cow(scope.clone());
146 Arc::make_mut(used).push(name.clone());
147 Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
148 }
149 }
150 }
151}
152
153impl<C: Ctx, E: UserEvent> Update<C, E> for Use {
154 fn update(
155 &mut self,
156 _ctx: &mut ExecCtx<C, E>,
157 _event: &mut Event<E>,
158 ) -> Option<Value> {
159 None
160 }
161
162 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
163 Ok(())
164 }
165
166 fn refs(&self, _refs: &mut Refs) {}
167
168 fn spec(&self) -> &Expr {
169 &self.spec
170 }
171
172 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
173 if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
174 Arc::make_mut(used).retain(|n| n != &self.name);
175 if used.is_empty() {
176 ctx.env.used.remove_cow(&self.scope);
177 }
178 }
179 }
180
181 fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
182
183 fn typ(&self) -> &Type {
184 &Type::Bottom
185 }
186}
187
188#[derive(Debug)]
189pub(crate) struct TypeDef {
190 spec: Expr,
191 scope: ModPath,
192 name: ArcStr,
193}
194
195impl TypeDef {
196 pub(crate) fn compile<C: Ctx, E: UserEvent>(
197 ctx: &mut ExecCtx<C, E>,
198 spec: Expr,
199 scope: &ModPath,
200 name: &ArcStr,
201 params: &Arc<[(TVar, Option<Type>)]>,
202 typ: &Type,
203 pos: &SourcePosition,
204 ) -> Result<Node<C, 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 {pos}"))?;
209 let name = name.clone();
210 let scope = scope.clone();
211 Ok(Box::new(Self { spec, scope, name }))
212 }
213}
214
215impl<C: Ctx, E: UserEvent> Update<C, E> for TypeDef {
216 fn update(
217 &mut self,
218 _ctx: &mut ExecCtx<C, E>,
219 _event: &mut Event<E>,
220 ) -> Option<Value> {
221 None
222 }
223
224 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, 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<C, E>) {
235 ctx.env.undeftype(&self.scope, &self.name)
236 }
237
238 fn sleep(&mut self, _ctx: &mut ExecCtx<C, 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<C: Ctx, E: UserEvent>(
254 spec: Expr,
255 value: &Value,
256 ) -> Result<Node<C, 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<C: Ctx, E: UserEvent> Update<C, E> for Constant {
265 fn update(
266 &mut self,
267 _ctx: &mut ExecCtx<C, 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<C, E>) {}
278
279 fn sleep(&mut self, _ctx: &mut ExecCtx<C, 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<C, E>) -> Result<()> {
288 Ok(())
289 }
290
291 fn spec(&self) -> &Expr {
292 &self.spec
293 }
294}
295
296#[derive(Debug)]
298pub(crate) struct Block<C: Ctx, E: UserEvent> {
299 spec: Expr,
300 ori: Option<Origin>,
301 children: Box<[Node<C, E>]>,
302}
303
304impl<C: Ctx, E: UserEvent> Block<C, E> {
305 pub(crate) fn compile(
306 ctx: &mut ExecCtx<C, E>,
307 spec: Expr,
308 scope: &ModPath,
309 top_id: ExprId,
310 ori: Option<Origin>,
311 exprs: &Arc<[Expr]>,
312 ) -> Result<Node<C, E>> {
313 let children = exprs
314 .iter()
315 .map(|e| compile(ctx, e.clone(), scope, top_id))
316 .collect::<Result<Box<[Node<C, E>]>>>()?;
317 Ok(Box::new(Self { ori, spec, children }))
318 }
319}
320
321impl<C: Ctx, E: UserEvent> Update<C, E> for Block<C, E> {
322 fn update(&mut self, ctx: &mut ExecCtx<C, 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<C, E>) {
327 for n in &mut self.children {
328 n.delete(ctx)
329 }
330 }
331
332 fn sleep(&mut self, ctx: &mut ExecCtx<C, 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<C, E>) -> Result<()> {
349 for n in &mut self.children {
350 match &self.ori {
351 None => wrap!(n, n.typecheck(ctx))?,
352 Some(ori) => wrap!(n, n.typecheck(ctx)).with_context(|| ori.clone())?,
353 }
354 }
355 Ok(())
356 }
357
358 fn spec(&self) -> &Expr {
359 &self.spec
360 }
361}
362
363#[derive(Debug)]
364pub(crate) struct Bind<C: Ctx, E: UserEvent> {
365 spec: Expr,
366 typ: Type,
367 pattern: StructPatternNode,
368 node: Node<C, E>,
369}
370
371impl<C: Ctx, E: UserEvent> Bind<C, E> {
372 pub(crate) fn compile(
373 ctx: &mut ExecCtx<C, E>,
374 spec: Expr,
375 scope: &ModPath,
376 top_id: ExprId,
377 b: &expr::Bind,
378 pos: &SourcePosition,
379 ) -> Result<Node<C, E>> {
380 let expr::Bind { doc, pattern, typ, export: _, value } = b;
381 let node = compile(ctx, value.clone(), &scope, top_id)?;
382 let typ = match typ {
383 Some(typ) => typ.scope_refs(scope),
384 None => {
385 let typ = node.typ().clone();
386 let ptyp = pattern.infer_type_predicate(&ctx.env)?;
387 if !ptyp.contains(&ctx.env, &typ)? {
388 typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
389 bail!("at {pos} match error {typ} can't be matched by {ptyp}")
390 })?
391 }
392 typ
393 }
394 };
395 let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
396 .with_context(|| format!("at {pos}"))?;
397 if pattern.is_refutable() {
398 bail!("at {pos} refutable patterns are not allowed in let");
399 }
400 if let Some(doc) = doc {
401 pattern.ids(&mut |id| {
402 if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
403 b.doc = Some(doc.clone());
404 }
405 });
406 }
407 Ok(Box::new(Self { spec, typ, pattern, node }))
408 }
409}
410
411impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
412 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
413 if let Some(v) = self.node.update(ctx, event) {
414 self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
415 }
416 None
417 }
418
419 fn refs(&self, refs: &mut Refs) {
420 self.pattern.ids(&mut |id| {
421 refs.bound.insert(id);
422 });
423 self.node.refs(refs);
424 }
425
426 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
427 self.node.delete(ctx);
428 self.pattern.delete(ctx);
429 }
430
431 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
432 self.node.sleep(ctx);
433 }
434
435 fn typ(&self) -> &Type {
436 &self.typ
437 }
438
439 fn spec(&self) -> &Expr {
440 &self.spec
441 }
442
443 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
444 wrap!(self.node, self.node.typecheck(ctx))?;
445 wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
446 Ok(())
447 }
448}
449
450#[derive(Debug)]
451pub(crate) struct Ref {
452 spec: Arc<Expr>,
453 typ: Type,
454 id: BindId,
455 top_id: ExprId,
456}
457
458impl Ref {
459 pub(crate) fn compile<C: Ctx, E: UserEvent>(
460 ctx: &mut ExecCtx<C, E>,
461 spec: Expr,
462 scope: &ModPath,
463 top_id: ExprId,
464 name: &ModPath,
465 pos: &SourcePosition,
466 ) -> Result<Node<C, E>> {
467 match ctx.env.lookup_bind(scope, name) {
468 None => bail!("at {pos} {name} not defined"),
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 pos: &SourcePosition,
615 ) -> Result<Node<C, E>> {
616 let id = match ctx.env.lookup_bind(scope, name) {
617 None => bail!("at {pos} {name} is undefined"),
618 Some((_, env::Bind { id, .. })) => *id,
619 };
620 let node = compile(ctx, value.clone(), scope, top_id)?;
621 Ok(Box::new(Self { spec, node, id }))
622 }
623}
624
625impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
626 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
627 if let Some(v) = self.node.update(ctx, event) {
628 ctx.set_var(self.id, v)
629 }
630 None
631 }
632
633 fn spec(&self) -> &Expr {
634 &self.spec
635 }
636
637 fn typ(&self) -> &Type {
638 &Type::Bottom
639 }
640
641 fn refs(&self, refs: &mut Refs) {
642 self.node.refs(refs)
643 }
644
645 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
646 self.node.delete(ctx)
647 }
648
649 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
650 self.node.sleep(ctx);
651 }
652
653 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
654 wrap!(self.node, self.node.typecheck(ctx))?;
655 let bind = match ctx.env.by_id.get(&self.id) {
656 None => bail!("BUG missing bind {:?}", self.id),
657 Some(bind) => bind,
658 };
659 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
660 }
661}
662
663#[derive(Debug)]
664pub(crate) struct ConnectDeref<C: Ctx, E: UserEvent> {
665 spec: Expr,
666 rhs: Cached<C, E>,
667 src_id: BindId,
668 target_id: Option<BindId>,
669 top_id: ExprId,
670}
671
672impl<C: Ctx, E: UserEvent> ConnectDeref<C, E> {
673 pub(crate) fn compile(
674 ctx: &mut ExecCtx<C, E>,
675 spec: Expr,
676 scope: &ModPath,
677 top_id: ExprId,
678 name: &ModPath,
679 value: &Expr,
680 pos: &SourcePosition,
681 ) -> Result<Node<C, E>> {
682 let src_id = match ctx.env.lookup_bind(scope, name) {
683 None => bail!("at {pos} {name} is undefined"),
684 Some((_, env::Bind { id, .. })) => *id,
685 };
686 ctx.user.ref_var(src_id, top_id);
687 let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
688 Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
689 }
690}
691
692impl<C: Ctx, E: UserEvent> Update<C, E> for ConnectDeref<C, E> {
693 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
694 let mut up = self.rhs.update(ctx, event);
695 if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
696 if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
697 self.target_id = Some(*target_id);
698 up = true;
699 }
700 }
701 if up {
702 if let Some(v) = &self.rhs.cached {
703 if let Some(id) = self.target_id {
704 ctx.set_var(id, v.clone())
705 }
706 }
707 }
708 None
709 }
710
711 fn spec(&self) -> &Expr {
712 &self.spec
713 }
714
715 fn typ(&self) -> &Type {
716 &Type::Bottom
717 }
718
719 fn refs(&self, refs: &mut Refs) {
720 refs.refed.insert(self.src_id);
721 self.rhs.node.refs(refs)
722 }
723
724 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
725 ctx.user.unref_var(self.src_id, self.top_id);
726 self.rhs.node.delete(ctx)
727 }
728
729 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
730 self.rhs.sleep(ctx);
731 }
732
733 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
734 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
735 let bind = match ctx.env.by_id.get(&self.src_id) {
736 None => bail!("BUG missing bind {:?}", self.src_id),
737 Some(bind) => bind,
738 };
739 let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
740 wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
741 }
742}
743
744#[derive(Debug)]
745pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
746 spec: Expr,
747 typ: Type,
748 child: Node<C, E>,
749 id: BindId,
750}
751
752impl<C: Ctx, E: UserEvent> ByRef<C, E> {
753 pub(crate) fn compile(
754 ctx: &mut ExecCtx<C, E>,
755 spec: Expr,
756 scope: &ModPath,
757 top_id: ExprId,
758 expr: &Expr,
759 ) -> Result<Node<C, E>> {
760 let child = compile(ctx, expr.clone(), scope, top_id)?;
761 let id = BindId::new();
762 if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
763 ctx.env.byref_chain.insert_cow(id, c.id);
764 }
765 let typ = Type::ByRef(Arc::new(child.typ().clone()));
766 Ok(Box::new(Self { spec, typ, child, id }))
767 }
768}
769
770impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
771 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
772 if let Some(v) = self.child.update(ctx, event) {
773 ctx.set_var(self.id, v);
774 }
775 if event.init {
776 Some(Value::U64(self.id.inner()))
777 } else {
778 None
779 }
780 }
781
782 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
783 ctx.env.byref_chain.remove_cow(&self.id);
784 self.child.delete(ctx)
785 }
786
787 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
788 self.child.sleep(ctx);
789 }
790
791 fn spec(&self) -> &Expr {
792 &self.spec
793 }
794
795 fn typ(&self) -> &Type {
796 &self.typ
797 }
798
799 fn refs(&self, refs: &mut Refs) {
800 self.child.refs(refs)
801 }
802
803 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
804 wrap!(self.child, self.child.typecheck(ctx))?;
805 let t = Type::ByRef(Arc::new(self.child.typ().clone()));
806 wrap!(self, self.typ.check_contains(&ctx.env, &t))
807 }
808}
809
810#[derive(Debug)]
811pub(crate) struct Deref<C: Ctx, E: UserEvent> {
812 spec: Expr,
813 typ: Type,
814 child: Node<C, E>,
815 id: Option<BindId>,
816 top_id: ExprId,
817}
818
819impl<C: Ctx, E: UserEvent> Deref<C, E> {
820 pub(crate) fn compile(
821 ctx: &mut ExecCtx<C, E>,
822 spec: Expr,
823 scope: &ModPath,
824 top_id: ExprId,
825 expr: &Expr,
826 ) -> Result<Node<C, E>> {
827 let child = compile(ctx, expr.clone(), scope, top_id)?;
828 let typ = Type::empty_tvar();
829 Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
830 }
831}
832
833impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
834 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
835 if let Some(v) = self.child.update(ctx, event) {
836 match v {
837 Value::U64(i) | Value::V64(i) => {
838 let new_id = BindId::from(i);
839 if self.id != Some(new_id) {
840 if let Some(old) = self.id {
841 ctx.user.unref_var(old, self.top_id);
842 }
843 ctx.user.ref_var(new_id, self.top_id);
844 self.id = Some(new_id);
845 }
846 }
847 _ => return err!("expected u64 bind id"),
848 }
849 }
850 self.id.and_then(|id| event.variables.get(&id).cloned())
851 }
852
853 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
854 if let Some(id) = self.id.take() {
855 ctx.user.unref_var(id, self.top_id);
856 }
857 self.child.delete(ctx);
858 }
859
860 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
861 self.child.sleep(ctx);
862 }
863
864 fn spec(&self) -> &Expr {
865 &self.spec
866 }
867
868 fn typ(&self) -> &Type {
869 &self.typ
870 }
871
872 fn refs(&self, refs: &mut Refs) {
873 self.child.refs(refs);
874 if let Some(id) = self.id {
875 refs.refed.insert(id);
876 }
877 }
878
879 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
880 wrap!(self.child, self.child.typecheck(ctx))?;
881 let typ = match self.child.typ() {
882 Type::ByRef(t) => (**t).clone(),
883 _ => bail!("expected reference"),
884 };
885 wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
886 Ok(())
887 }
888}
889
890#[derive(Debug)]
891pub(crate) struct Qop<C: Ctx, E: UserEvent> {
892 spec: Expr,
893 typ: Type,
894 id: BindId,
895 n: Node<C, E>,
896}
897
898impl<C: Ctx, E: UserEvent> Qop<C, E> {
899 pub(crate) fn compile(
900 ctx: &mut ExecCtx<C, E>,
901 spec: Expr,
902 scope: &ModPath,
903 top_id: ExprId,
904 e: &Expr,
905 pos: &SourcePosition,
906 ) -> Result<Node<C, E>> {
907 let n = compile(ctx, e.clone(), scope, top_id)?;
908 match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
909 None => bail!("at {pos} BUG: errors is undefined"),
910 Some((_, bind)) => {
911 let typ = Type::empty_tvar();
912 Ok(Box::new(Self { spec, typ, id: bind.id, n }))
913 }
914 }
915 }
916}
917
918impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
919 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
920 match self.n.update(ctx, event) {
921 None => None,
922 Some(e @ Value::Error(_)) => {
923 ctx.set_var(self.id, e);
924 None
925 }
926 Some(v) => Some(v),
927 }
928 }
929
930 fn typ(&self) -> &Type {
931 &self.typ
932 }
933
934 fn spec(&self) -> &Expr {
935 &self.spec
936 }
937
938 fn refs(&self, refs: &mut Refs) {
939 self.n.refs(refs)
940 }
941
942 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
943 self.n.delete(ctx)
944 }
945
946 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
947 self.n.sleep(ctx);
948 }
949
950 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
951 wrap!(self.n, self.n.typecheck(ctx))?;
952 let bind =
953 ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
954 let err = Type::Primitive(Typ::Error.into());
955 wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
956 wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
957 if !self.n.typ().contains(&ctx.env, &err)? {
958 bail!("cannot use the ? operator on a non error type")
959 }
960 let rtyp = self.n.typ().diff(&ctx.env, &err)?;
961 wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
962 Ok(())
963 }
964}
965
966#[derive(Debug)]
967pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
968 spec: Expr,
969 typ: Type,
970 target: Type,
971 n: Node<C, E>,
972}
973
974impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
975 pub(crate) fn compile(
976 ctx: &mut ExecCtx<C, E>,
977 spec: Expr,
978 scope: &ModPath,
979 top_id: ExprId,
980 expr: &Expr,
981 typ: &Type,
982 pos: &SourcePosition,
983 ) -> Result<Node<C, E>> {
984 let n = compile(ctx, expr.clone(), scope, top_id)?;
985 let target = typ.scope_refs(scope);
986 if let Err(e) = target.check_cast(&ctx.env) {
987 bail!("in cast at {pos} {e}");
988 }
989 let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
990 Ok(Box::new(Self { spec, typ, target, n }))
991 }
992}
993
994impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
995 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
996 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
997 }
998
999 fn spec(&self) -> &Expr {
1000 &self.spec
1001 }
1002
1003 fn typ(&self) -> &Type {
1004 &self.typ
1005 }
1006
1007 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1008 self.n.delete(ctx)
1009 }
1010
1011 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1012 self.n.sleep(ctx);
1013 }
1014
1015 fn refs(&self, refs: &mut Refs) {
1016 self.n.refs(refs)
1017 }
1018
1019 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1020 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1021 }
1022}
1023
1024#[derive(Debug)]
1025pub(crate) struct Any<C: Ctx, E: UserEvent> {
1026 spec: Expr,
1027 typ: Type,
1028 n: Box<[Node<C, E>]>,
1029}
1030
1031impl<C: Ctx, E: UserEvent> Any<C, E> {
1032 pub(crate) fn compile(
1033 ctx: &mut ExecCtx<C, E>,
1034 spec: Expr,
1035 scope: &ModPath,
1036 top_id: ExprId,
1037 args: &[Expr],
1038 ) -> Result<Node<C, E>> {
1039 let n = args
1040 .iter()
1041 .map(|e| compile(ctx, e.clone(), scope, top_id))
1042 .collect::<Result<Box<[_]>>>()?;
1043 let typ =
1044 Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1045 Ok(Box::new(Self { spec, typ, n }))
1046 }
1047}
1048
1049impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1050 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1051 self.n
1052 .iter_mut()
1053 .filter_map(|s| s.update(ctx, event))
1054 .fold(None, |r, v| r.or(Some(v)))
1055 }
1056
1057 fn spec(&self) -> &Expr {
1058 &self.spec
1059 }
1060
1061 fn typ(&self) -> &Type {
1062 &self.typ
1063 }
1064
1065 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1066 self.n.iter_mut().for_each(|n| n.delete(ctx))
1067 }
1068
1069 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1070 self.n.iter_mut().for_each(|n| n.sleep(ctx))
1071 }
1072
1073 fn refs(&self, refs: &mut Refs) {
1074 self.n.iter().for_each(|n| n.refs(refs))
1075 }
1076
1077 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1078 for n in self.n.iter_mut() {
1079 wrap!(n, n.typecheck(ctx))?
1080 }
1081 let rtyp = Type::Primitive(BitFlags::empty());
1082 let rtyp = wrap!(
1083 self,
1084 self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1085 )?;
1086 Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1087 }
1088}
1089
1090#[derive(Debug)]
1091struct Sample<C: Ctx, E: UserEvent> {
1092 spec: Expr,
1093 triggered: usize,
1094 typ: Type,
1095 id: BindId,
1096 top_id: ExprId,
1097 trigger: Node<C, E>,
1098 arg: Cached<C, E>,
1099}
1100
1101impl<C: Ctx, E: UserEvent> Sample<C, E> {
1102 pub(crate) fn compile(
1103 ctx: &mut ExecCtx<C, E>,
1104 spec: Expr,
1105 scope: &ModPath,
1106 top_id: ExprId,
1107 lhs: &Arc<Expr>,
1108 rhs: &Arc<Expr>,
1109 ) -> Result<Node<C, E>> {
1110 let id = BindId::new();
1111 ctx.user.ref_var(id, top_id);
1112 let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1113 let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1114 let typ = arg.node.typ().clone();
1115 Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1116 }
1117}
1118
1119impl<C: Ctx, E: UserEvent> Update<C, E> for Sample<C, E> {
1120 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1121 if let Some(_) = self.trigger.update(ctx, event) {
1122 self.triggered += 1;
1123 }
1124 self.arg.update(ctx, event);
1125 let var = event.variables.get(&self.id).cloned();
1126 let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1127 self.triggered -= 1;
1128 self.arg.cached.clone()
1129 } else {
1130 var
1131 };
1132 if self.arg.cached.is_some() {
1133 while self.triggered > 0 {
1134 self.triggered -= 1;
1135 ctx.user.set_var(self.id, self.arg.cached.clone().unwrap());
1136 }
1137 }
1138 res
1139 }
1140
1141 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1142 ctx.user.unref_var(self.id, self.top_id);
1143 self.arg.node.delete(ctx);
1144 self.trigger.delete(ctx);
1145 }
1146
1147 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1148 self.arg.sleep(ctx);
1149 self.trigger.sleep(ctx);
1150 }
1151
1152 fn spec(&self) -> &Expr {
1153 &self.spec
1154 }
1155
1156 fn typ(&self) -> &Type {
1157 &self.typ
1158 }
1159
1160 fn refs(&self, refs: &mut Refs) {
1161 refs.refed.insert(self.id);
1162 self.arg.node.refs(refs);
1163 self.trigger.refs(refs);
1164 }
1165
1166 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1167 wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1168 wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1169 }
1170}