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 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 children: Box<[Node<C, E>]>,
301}
302
303impl<C: Ctx, E: UserEvent> Block<C, E> {
304 pub(crate) fn compile(
305 ctx: &mut ExecCtx<C, E>,
306 spec: Expr,
307 scope: &ModPath,
308 top_id: ExprId,
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 { 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 wrap!(n, n.typecheck(ctx))?
349 }
350 Ok(())
351 }
352
353 fn spec(&self) -> &Expr {
354 &self.spec
355 }
356}
357
358#[derive(Debug)]
359pub(crate) struct Bind<C: Ctx, E: UserEvent> {
360 spec: Expr,
361 typ: Type,
362 pattern: StructPatternNode,
363 node: Node<C, E>,
364}
365
366impl<C: Ctx, E: UserEvent> Bind<C, E> {
367 pub(crate) fn compile(
368 ctx: &mut ExecCtx<C, E>,
369 spec: Expr,
370 scope: &ModPath,
371 top_id: ExprId,
372 b: &expr::Bind,
373 pos: &SourcePosition,
374 ) -> Result<Node<C, E>> {
375 let expr::Bind { doc, pattern, typ, export: _, value } = b;
376 let node = compile(ctx, value.clone(), &scope, top_id)?;
377 let typ = match typ {
378 Some(typ) => typ.scope_refs(scope),
379 None => {
380 let typ = node.typ().clone();
381 let ptyp = pattern.infer_type_predicate(&ctx.env)?;
382 if !ptyp.contains(&ctx.env, &typ)? {
383 typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
384 bail!("at {pos} match error {typ} can't be matched by {ptyp}")
385 })?
386 }
387 typ
388 }
389 };
390 let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
391 .with_context(|| format!("at {pos}"))?;
392 if pattern.is_refutable() {
393 bail!("at {pos} refutable patterns are not allowed in let");
394 }
395 if let Some(doc) = doc {
396 pattern.ids(&mut |id| {
397 if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
398 b.doc = Some(doc.clone());
399 }
400 });
401 }
402 Ok(Box::new(Self { spec, typ, pattern, node }))
403 }
404}
405
406impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
407 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
408 if let Some(v) = self.node.update(ctx, event) {
409 self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
410 }
411 None
412 }
413
414 fn refs(&self, refs: &mut Refs) {
415 self.pattern.ids(&mut |id| {
416 refs.bound.insert(id);
417 });
418 self.node.refs(refs);
419 }
420
421 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
422 self.node.delete(ctx);
423 self.pattern.delete(ctx);
424 }
425
426 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
427 self.node.sleep(ctx);
428 }
429
430 fn typ(&self) -> &Type {
431 &self.typ
432 }
433
434 fn spec(&self) -> &Expr {
435 &self.spec
436 }
437
438 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
439 wrap!(self.node, self.node.typecheck(ctx))?;
440 wrap!(self.node, self.typ.check_contains(&ctx.env, self.node.typ()))?;
441 Ok(())
442 }
443}
444
445#[derive(Debug)]
446pub(crate) struct Ref {
447 spec: Arc<Expr>,
448 typ: Type,
449 id: BindId,
450 top_id: ExprId,
451}
452
453impl Ref {
454 pub(crate) fn compile<C: Ctx, E: UserEvent>(
455 ctx: &mut ExecCtx<C, E>,
456 spec: Expr,
457 scope: &ModPath,
458 top_id: ExprId,
459 name: &ModPath,
460 pos: &SourcePosition,
461 ) -> Result<Node<C, E>> {
462 match ctx.env.lookup_bind(scope, name) {
463 None => bail!("at {pos} {name} not defined"),
464 Some((_, bind)) => {
465 ctx.user.ref_var(bind.id, top_id);
466 let typ = bind.typ.clone();
467 let spec = Arc::new(spec);
468 Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
469 }
470 }
471 }
472}
473
474impl<C: Ctx, E: UserEvent> Update<C, E> for Ref {
475 fn update(
476 &mut self,
477 _ctx: &mut ExecCtx<C, E>,
478 event: &mut Event<E>,
479 ) -> Option<Value> {
480 event.variables.get(&self.id).map(|v| v.clone())
481 }
482
483 fn refs(&self, refs: &mut Refs) {
484 refs.refed.insert(self.id);
485 }
486
487 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
488 ctx.user.unref_var(self.id, self.top_id)
489 }
490
491 fn sleep(&mut self, _ctx: &mut ExecCtx<C, E>) {}
492
493 fn spec(&self) -> &Expr {
494 &self.spec
495 }
496
497 fn typ(&self) -> &Type {
498 &self.typ
499 }
500
501 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
502 Ok(())
503 }
504}
505
506#[derive(Debug)]
507pub(crate) struct StringInterpolate<C: Ctx, E: UserEvent> {
508 spec: Expr,
509 typ: Type,
510 typs: Box<[Type]>,
511 args: Box<[Cached<C, E>]>,
512}
513
514impl<C: Ctx, E: UserEvent> StringInterpolate<C, E> {
515 pub(crate) fn compile(
516 ctx: &mut ExecCtx<C, E>,
517 spec: Expr,
518 scope: &ModPath,
519 top_id: ExprId,
520 args: &[Expr],
521 ) -> Result<Node<C, E>> {
522 let args: Box<[Cached<C, E>]> = args
523 .iter()
524 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
525 .collect::<Result<_>>()?;
526 let typs = args.iter().map(|c| c.node.typ().clone()).collect();
527 let typ = Type::Primitive(Typ::String.into());
528 Ok(Box::new(Self { spec, typ, typs, args }))
529 }
530}
531
532impl<C: Ctx, E: UserEvent> Update<C, E> for StringInterpolate<C, E> {
533 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
534 use std::fmt::Write;
535 thread_local! {
536 static BUF: RefCell<String> = RefCell::new(String::new());
537 }
538 let (updated, determined) = update_args!(self.args, ctx, event);
539 if updated && determined {
540 BUF.with_borrow_mut(|buf| {
541 buf.clear();
542 for (typ, c) in self.typs.iter().zip(self.args.iter()) {
543 match c.cached.as_ref().unwrap() {
544 Value::String(s) => write!(buf, "{s}"),
545 v => write!(buf, "{}", TVal { env: &ctx.env, typ, v }),
546 }
547 .unwrap()
548 }
549 Some(Value::String(buf.as_str().into()))
550 })
551 } else {
552 None
553 }
554 }
555
556 fn spec(&self) -> &Expr {
557 &self.spec
558 }
559
560 fn typ(&self) -> &Type {
561 &self.typ
562 }
563
564 fn refs(&self, refs: &mut Refs) {
565 for a in &self.args {
566 a.node.refs(refs)
567 }
568 }
569
570 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
571 for n in &mut self.args {
572 n.node.delete(ctx)
573 }
574 }
575
576 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
577 for n in &mut self.args {
578 n.sleep(ctx);
579 }
580 }
581
582 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
583 for (i, a) in self.args.iter_mut().enumerate() {
584 wrap!(a.node, a.node.typecheck(ctx))?;
585 self.typs[i] = a.node.typ().with_deref(|t| match t {
586 None => Type::Any,
587 Some(t) => t.clone(),
588 });
589 }
590 Ok(())
591 }
592}
593
594#[derive(Debug)]
595pub(crate) struct Connect<C: Ctx, E: UserEvent> {
596 spec: Expr,
597 node: Node<C, E>,
598 id: BindId,
599}
600
601impl<C: Ctx, E: UserEvent> Connect<C, E> {
602 pub(crate) fn compile(
603 ctx: &mut ExecCtx<C, E>,
604 spec: Expr,
605 scope: &ModPath,
606 top_id: ExprId,
607 name: &ModPath,
608 value: &Expr,
609 pos: &SourcePosition,
610 ) -> Result<Node<C, E>> {
611 let id = match ctx.env.lookup_bind(scope, name) {
612 None => bail!("at {pos} {name} is undefined"),
613 Some((_, env::Bind { id, .. })) => *id,
614 };
615 let node = compile(ctx, value.clone(), scope, top_id)?;
616 Ok(Box::new(Self { spec, node, id }))
617 }
618}
619
620impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
621 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
622 if let Some(v) = self.node.update(ctx, event) {
623 ctx.set_var(self.id, v)
624 }
625 None
626 }
627
628 fn spec(&self) -> &Expr {
629 &self.spec
630 }
631
632 fn typ(&self) -> &Type {
633 &Type::Bottom
634 }
635
636 fn refs(&self, refs: &mut Refs) {
637 self.node.refs(refs)
638 }
639
640 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
641 self.node.delete(ctx)
642 }
643
644 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
645 self.node.sleep(ctx);
646 }
647
648 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
649 wrap!(self.node, self.node.typecheck(ctx))?;
650 let bind = match ctx.env.by_id.get(&self.id) {
651 None => bail!("BUG missing bind {:?}", self.id),
652 Some(bind) => bind,
653 };
654 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
655 }
656}
657
658#[derive(Debug)]
659pub(crate) struct ConnectDeref<C: Ctx, E: UserEvent> {
660 spec: Expr,
661 rhs: Cached<C, E>,
662 src_id: BindId,
663 target_id: Option<BindId>,
664 top_id: ExprId,
665}
666
667impl<C: Ctx, E: UserEvent> ConnectDeref<C, E> {
668 pub(crate) fn compile(
669 ctx: &mut ExecCtx<C, E>,
670 spec: Expr,
671 scope: &ModPath,
672 top_id: ExprId,
673 name: &ModPath,
674 value: &Expr,
675 pos: &SourcePosition,
676 ) -> Result<Node<C, E>> {
677 let src_id = match ctx.env.lookup_bind(scope, name) {
678 None => bail!("at {pos} {name} is undefined"),
679 Some((_, env::Bind { id, .. })) => *id,
680 };
681 ctx.user.ref_var(src_id, top_id);
682 let rhs = Cached::new(compile(ctx, value.clone(), scope, top_id)?);
683 Ok(Box::new(Self { spec, rhs, src_id, target_id: None, top_id }))
684 }
685}
686
687impl<C: Ctx, E: UserEvent> Update<C, E> for ConnectDeref<C, E> {
688 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
689 let mut up = self.rhs.update(ctx, event);
690 if let Some(Value::U64(id)) = event.variables.get(&self.src_id) {
691 if let Some(target_id) = ctx.env.byref_chain.get(&BindId::from(*id)) {
692 self.target_id = Some(*target_id);
693 up = true;
694 }
695 }
696 if up {
697 if let Some(v) = &self.rhs.cached {
698 if let Some(id) = self.target_id {
699 ctx.set_var(id, v.clone())
700 }
701 }
702 }
703 None
704 }
705
706 fn spec(&self) -> &Expr {
707 &self.spec
708 }
709
710 fn typ(&self) -> &Type {
711 &Type::Bottom
712 }
713
714 fn refs(&self, refs: &mut Refs) {
715 refs.refed.insert(self.src_id);
716 self.rhs.node.refs(refs)
717 }
718
719 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
720 ctx.user.unref_var(self.src_id, self.top_id);
721 self.rhs.node.delete(ctx)
722 }
723
724 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
725 self.rhs.sleep(ctx);
726 }
727
728 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
729 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
730 let bind = match ctx.env.by_id.get(&self.src_id) {
731 None => bail!("BUG missing bind {:?}", self.src_id),
732 Some(bind) => bind,
733 };
734 let typ = Type::ByRef(Arc::new(self.rhs.node.typ().clone()));
735 wrap!(self, bind.typ.check_contains(&ctx.env, &typ))
736 }
737}
738
739#[derive(Debug)]
740pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
741 spec: Expr,
742 typ: Type,
743 child: Node<C, E>,
744 id: BindId,
745}
746
747impl<C: Ctx, E: UserEvent> ByRef<C, E> {
748 pub(crate) fn compile(
749 ctx: &mut ExecCtx<C, E>,
750 spec: Expr,
751 scope: &ModPath,
752 top_id: ExprId,
753 expr: &Expr,
754 ) -> Result<Node<C, E>> {
755 let child = compile(ctx, expr.clone(), scope, top_id)?;
756 let id = BindId::new();
757 if let Some(c) = (&*child as &dyn std::any::Any).downcast_ref::<Ref>() {
758 ctx.env.byref_chain.insert_cow(id, c.id);
759 }
760 let typ = Type::ByRef(Arc::new(child.typ().clone()));
761 Ok(Box::new(Self { spec, typ, child, id }))
762 }
763}
764
765impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
766 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
767 if let Some(v) = self.child.update(ctx, event) {
768 ctx.set_var(self.id, v);
769 }
770 if event.init {
771 Some(Value::U64(self.id.inner()))
772 } else {
773 None
774 }
775 }
776
777 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
778 ctx.env.byref_chain.remove_cow(&self.id);
779 self.child.delete(ctx)
780 }
781
782 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
783 self.child.sleep(ctx);
784 }
785
786 fn spec(&self) -> &Expr {
787 &self.spec
788 }
789
790 fn typ(&self) -> &Type {
791 &self.typ
792 }
793
794 fn refs(&self, refs: &mut Refs) {
795 self.child.refs(refs)
796 }
797
798 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
799 wrap!(self.child, self.child.typecheck(ctx))?;
800 let t = Type::ByRef(Arc::new(self.child.typ().clone()));
801 wrap!(self, self.typ.check_contains(&ctx.env, &t))
802 }
803}
804
805#[derive(Debug)]
806pub(crate) struct Deref<C: Ctx, E: UserEvent> {
807 spec: Expr,
808 typ: Type,
809 child: Node<C, E>,
810 id: Option<BindId>,
811 top_id: ExprId,
812}
813
814impl<C: Ctx, E: UserEvent> Deref<C, E> {
815 pub(crate) fn compile(
816 ctx: &mut ExecCtx<C, E>,
817 spec: Expr,
818 scope: &ModPath,
819 top_id: ExprId,
820 expr: &Expr,
821 ) -> Result<Node<C, E>> {
822 let child = compile(ctx, expr.clone(), scope, top_id)?;
823 let typ = Type::empty_tvar();
824 Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
825 }
826}
827
828impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
829 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
830 if let Some(v) = self.child.update(ctx, event) {
831 match v {
832 Value::U64(i) | Value::V64(i) => {
833 let new_id = BindId::from(i);
834 if self.id != Some(new_id) {
835 if let Some(old) = self.id {
836 ctx.user.unref_var(old, self.top_id);
837 }
838 ctx.user.ref_var(new_id, self.top_id);
839 self.id = Some(new_id);
840 }
841 }
842 _ => return err!("expected u64 bind id"),
843 }
844 }
845 self.id.and_then(|id| event.variables.get(&id).cloned())
846 }
847
848 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
849 if let Some(id) = self.id.take() {
850 ctx.user.unref_var(id, self.top_id);
851 }
852 self.child.delete(ctx);
853 }
854
855 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
856 self.child.sleep(ctx);
857 }
858
859 fn spec(&self) -> &Expr {
860 &self.spec
861 }
862
863 fn typ(&self) -> &Type {
864 &self.typ
865 }
866
867 fn refs(&self, refs: &mut Refs) {
868 self.child.refs(refs);
869 if let Some(id) = self.id {
870 refs.refed.insert(id);
871 }
872 }
873
874 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
875 wrap!(self.child, self.child.typecheck(ctx))?;
876 let typ = match self.child.typ() {
877 Type::ByRef(t) => (**t).clone(),
878 _ => bail!("expected reference"),
879 };
880 wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
881 Ok(())
882 }
883}
884
885#[derive(Debug)]
886pub(crate) struct Qop<C: Ctx, E: UserEvent> {
887 spec: Expr,
888 typ: Type,
889 id: BindId,
890 n: Node<C, E>,
891}
892
893impl<C: Ctx, E: UserEvent> Qop<C, E> {
894 pub(crate) fn compile(
895 ctx: &mut ExecCtx<C, E>,
896 spec: Expr,
897 scope: &ModPath,
898 top_id: ExprId,
899 e: &Expr,
900 pos: &SourcePosition,
901 ) -> Result<Node<C, E>> {
902 let n = compile(ctx, e.clone(), scope, top_id)?;
903 match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
904 None => bail!("at {pos} BUG: errors is undefined"),
905 Some((_, bind)) => {
906 let typ = Type::empty_tvar();
907 Ok(Box::new(Self { spec, typ, id: bind.id, n }))
908 }
909 }
910 }
911}
912
913impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
914 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
915 match self.n.update(ctx, event) {
916 None => None,
917 Some(e @ Value::Error(_)) => {
918 ctx.set_var(self.id, e);
919 None
920 }
921 Some(v) => Some(v),
922 }
923 }
924
925 fn typ(&self) -> &Type {
926 &self.typ
927 }
928
929 fn spec(&self) -> &Expr {
930 &self.spec
931 }
932
933 fn refs(&self, refs: &mut Refs) {
934 self.n.refs(refs)
935 }
936
937 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
938 self.n.delete(ctx)
939 }
940
941 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
942 self.n.sleep(ctx);
943 }
944
945 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
946 wrap!(self.n, self.n.typecheck(ctx))?;
947 let bind =
948 ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
949 let err = Type::Primitive(Typ::Error.into());
950 wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
951 wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
952 if !self.n.typ().contains(&ctx.env, &err)? {
953 bail!("cannot use the ? operator on a non error type")
954 }
955 let rtyp = self.n.typ().diff(&ctx.env, &err)?;
956 wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
957 Ok(())
958 }
959}
960
961#[derive(Debug)]
962pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
963 spec: Expr,
964 typ: Type,
965 target: Type,
966 n: Node<C, E>,
967}
968
969impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
970 pub(crate) fn compile(
971 ctx: &mut ExecCtx<C, E>,
972 spec: Expr,
973 scope: &ModPath,
974 top_id: ExprId,
975 expr: &Expr,
976 typ: &Type,
977 pos: &SourcePosition,
978 ) -> Result<Node<C, E>> {
979 let n = compile(ctx, expr.clone(), scope, top_id)?;
980 let target = typ.scope_refs(scope);
981 if let Err(e) = target.check_cast(&ctx.env) {
982 bail!("in cast at {pos} {e}");
983 }
984 let typ = target.union(&ctx.env, &Type::Primitive(Typ::Error.into()))?;
985 Ok(Box::new(Self { spec, typ, target, n }))
986 }
987}
988
989impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
990 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
991 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
992 }
993
994 fn spec(&self) -> &Expr {
995 &self.spec
996 }
997
998 fn typ(&self) -> &Type {
999 &self.typ
1000 }
1001
1002 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1003 self.n.delete(ctx)
1004 }
1005
1006 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1007 self.n.sleep(ctx);
1008 }
1009
1010 fn refs(&self, refs: &mut Refs) {
1011 self.n.refs(refs)
1012 }
1013
1014 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1015 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1016 }
1017}
1018
1019#[derive(Debug)]
1020pub(crate) struct Any<C: Ctx, E: UserEvent> {
1021 spec: Expr,
1022 typ: Type,
1023 n: Box<[Node<C, E>]>,
1024}
1025
1026impl<C: Ctx, E: UserEvent> Any<C, E> {
1027 pub(crate) fn compile(
1028 ctx: &mut ExecCtx<C, E>,
1029 spec: Expr,
1030 scope: &ModPath,
1031 top_id: ExprId,
1032 args: &[Expr],
1033 ) -> Result<Node<C, E>> {
1034 let n = args
1035 .iter()
1036 .map(|e| compile(ctx, e.clone(), scope, top_id))
1037 .collect::<Result<Box<[_]>>>()?;
1038 let typ =
1039 Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1040 Ok(Box::new(Self { spec, typ, n }))
1041 }
1042}
1043
1044impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1045 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1046 self.n
1047 .iter_mut()
1048 .filter_map(|s| s.update(ctx, event))
1049 .fold(None, |r, v| r.or(Some(v)))
1050 }
1051
1052 fn spec(&self) -> &Expr {
1053 &self.spec
1054 }
1055
1056 fn typ(&self) -> &Type {
1057 &self.typ
1058 }
1059
1060 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1061 self.n.iter_mut().for_each(|n| n.delete(ctx))
1062 }
1063
1064 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1065 self.n.iter_mut().for_each(|n| n.sleep(ctx))
1066 }
1067
1068 fn refs(&self, refs: &mut Refs) {
1069 self.n.iter().for_each(|n| n.refs(refs))
1070 }
1071
1072 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1073 for n in self.n.iter_mut() {
1074 wrap!(n, n.typecheck(ctx))?
1075 }
1076 let rtyp = Type::Primitive(BitFlags::empty());
1077 let rtyp = wrap!(
1078 self,
1079 self.n.iter().fold(Ok(rtyp), |rtype, n| n.typ().union(&ctx.env, &rtype?))
1080 )?;
1081 Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1082 }
1083}
1084
1085#[derive(Debug)]
1086struct Sample<C: Ctx, E: UserEvent> {
1087 spec: Expr,
1088 triggered: usize,
1089 typ: Type,
1090 id: BindId,
1091 top_id: ExprId,
1092 trigger: Node<C, E>,
1093 arg: Cached<C, E>,
1094}
1095
1096impl<C: Ctx, E: UserEvent> Sample<C, E> {
1097 pub(crate) fn compile(
1098 ctx: &mut ExecCtx<C, E>,
1099 spec: Expr,
1100 scope: &ModPath,
1101 top_id: ExprId,
1102 lhs: &Arc<Expr>,
1103 rhs: &Arc<Expr>,
1104 ) -> Result<Node<C, E>> {
1105 let id = BindId::new();
1106 ctx.user.ref_var(id, top_id);
1107 let trigger = compile(ctx, (**lhs).clone(), scope, top_id)?;
1108 let arg = Cached::new(compile(ctx, (**rhs).clone(), scope, top_id)?);
1109 let typ = arg.node.typ().clone();
1110 Ok(Box::new(Self { triggered: 0, id, top_id, spec, typ, trigger, arg }))
1111 }
1112}
1113
1114impl<C: Ctx, E: UserEvent> Update<C, E> for Sample<C, E> {
1115 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1116 if let Some(_) = self.trigger.update(ctx, event) {
1117 self.triggered += 1;
1118 }
1119 self.arg.update(ctx, event);
1120 let var = event.variables.get(&self.id).cloned();
1121 let res = if self.triggered > 0 && self.arg.cached.is_some() && var.is_none() {
1122 self.triggered -= 1;
1123 self.arg.cached.clone()
1124 } else {
1125 var
1126 };
1127 if self.arg.cached.is_some() {
1128 while self.triggered > 0 {
1129 self.triggered -= 1;
1130 ctx.user.set_var(self.id, self.arg.cached.clone().unwrap());
1131 }
1132 }
1133 res
1134 }
1135
1136 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1137 ctx.user.unref_var(self.id, self.top_id);
1138 self.arg.node.delete(ctx);
1139 self.trigger.delete(ctx);
1140 }
1141
1142 fn sleep(&mut self, ctx: &mut ExecCtx<C, E>) {
1143 self.arg.sleep(ctx);
1144 self.trigger.sleep(ctx);
1145 }
1146
1147 fn spec(&self) -> &Expr {
1148 &self.spec
1149 }
1150
1151 fn typ(&self) -> &Type {
1152 &self.typ
1153 }
1154
1155 fn refs(&self, refs: &mut Refs) {
1156 refs.refed.insert(self.id);
1157 self.arg.node.refs(refs);
1158 self.trigger.refs(refs);
1159 }
1160
1161 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1162 wrap!(self.trigger, self.trigger.typecheck(ctx))?;
1163 wrap!(self.arg.node, self.arg.node.typecheck(ctx))
1164 }
1165}