1use crate::{
2 env, err,
3 expr::{self, Expr, ExprId, ExprKind, ModPath},
4 typ::{self, TVar, Type},
5 BindId, Ctx, Event, ExecCtx, Node, 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_netproto::{
13 valarray::ValArray,
14 value::{NakedValue, Typ, Value},
15};
16use pattern::StructPatternNode;
17use smallvec::{smallvec, SmallVec};
18use std::{cell::RefCell, iter, sync::LazyLock};
19use triomphe::Arc;
20
21pub(crate) mod callsite;
22pub(crate) mod compiler;
23pub mod genn;
24pub(crate) mod lambda;
25pub(crate) mod pattern;
26pub(crate) mod select;
27
28#[macro_export]
29macro_rules! wrap {
30 ($n:expr, $e:expr) => {
31 match $e {
32 Ok(x) => Ok(x),
33 Err(e) => Err(anyhow!("in expr: {}, type error: {e}", $n.spec())),
34 }
35 };
36}
37
38macro_rules! update_args {
39 ($args:expr, $ctx:expr, $event:expr) => {{
40 let mut updated = false;
41 let mut determined = true;
42 for n in $args.iter_mut() {
43 updated |= n.update($ctx, $event);
44 determined &= n.cached.is_some();
45 }
46 (updated, determined)
47 }};
48}
49
50static NOP: LazyLock<Arc<Expr>> = LazyLock::new(|| {
51 Arc::new(
52 ExprKind::Constant(Value::String(literal!("nop"))).to_expr(Default::default()),
53 )
54});
55
56#[derive(Debug)]
57pub(crate) struct Nop {
58 pub typ: Type,
59}
60
61impl Nop {
62 pub(crate) fn new<C: Ctx, E: UserEvent>(typ: Type) -> Node<C, E> {
63 Box::new(Nop { typ })
64 }
65}
66
67impl<C: Ctx, E: UserEvent> Update<C, E> for Nop {
68 fn update(
69 &mut self,
70 _ctx: &mut ExecCtx<C, E>,
71 _event: &mut Event<E>,
72 ) -> Option<Value> {
73 None
74 }
75
76 fn delete(&mut self, _ctx: &mut ExecCtx<C, E>) {}
77
78 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
79 Ok(())
80 }
81
82 fn spec(&self) -> &Expr {
83 &NOP
84 }
85
86 fn typ(&self) -> &Type {
87 &self.typ
88 }
89
90 fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
91}
92
93#[derive(Debug)]
94struct Cached<C: Ctx, E: UserEvent> {
95 cached: Option<Value>,
96 node: Node<C, E>,
97}
98
99impl<C: Ctx, E: UserEvent> Cached<C, E> {
100 fn new(node: Node<C, E>) -> Self {
101 Self { cached: None, node }
102 }
103
104 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> bool {
108 match self.node.update(ctx, event) {
109 None => false,
110 Some(v) => {
111 self.cached = Some(v);
112 true
113 }
114 }
115 }
116}
117
118#[derive(Debug)]
119pub(crate) struct ArrayRef<C: Ctx, E: UserEvent> {
120 source: Cached<C, E>,
121 i: Cached<C, E>,
122 spec: Expr,
123 typ: Type,
124}
125
126impl<C: Ctx, E: UserEvent> ArrayRef<C, E> {
127 pub(crate) fn compile(
128 ctx: &mut ExecCtx<C, E>,
129 spec: Expr,
130 scope: &ModPath,
131 top_id: ExprId,
132 source: &Expr,
133 i: &Expr,
134 ) -> Result<Node<C, E>> {
135 let source = Cached::new(compile(ctx, source.clone(), scope, top_id)?);
136 let i = Cached::new(compile(ctx, i.clone(), scope, top_id)?);
137 let ert = Type::Primitive(Typ::Error.into());
138 let typ = match &source.node.typ() {
139 Type::Array(et) => Type::Set(Arc::from_iter([(**et).clone(), ert.clone()])),
140 _ => Type::Set(Arc::from_iter([Type::empty_tvar(), ert.clone()])),
141 };
142 Ok(Box::new(Self { source, i, spec, typ }))
143 }
144}
145
146impl<C: Ctx, E: UserEvent> Update<C, E> for ArrayRef<C, E> {
147 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
148 let up = self.source.update(ctx, event);
149 let up = self.i.update(ctx, event) || up;
150 if !up {
151 return None;
152 }
153 let i = match &self.i.cached {
154 Some(Value::I64(i)) => *i,
155 Some(v) => match v.clone().cast_to::<i64>() {
156 Ok(i) => i,
157 Err(_) => return err!("op::index(array, index): expected an integer"),
158 },
159 None => return None,
160 };
161 match &self.source.cached {
162 Some(Value::Array(elts)) if i >= 0 => {
163 let i = i as usize;
164 if i < elts.len() {
165 Some(elts[i].clone())
166 } else {
167 err!("array index out of bounds")
168 }
169 }
170 Some(Value::Array(elts)) if i < 0 => {
171 let len = elts.len();
172 let i = len as i64 + i;
173 if i > 0 {
174 Some(elts[i as usize].clone())
175 } else {
176 err!("array index out of bounds")
177 }
178 }
179 None => None,
180 _ => err!("op::index(array, index): expected an array"),
181 }
182 }
183
184 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
185 wrap!(self.source.node, self.source.node.typecheck(ctx))?;
186 wrap!(self.i.node, self.i.node.typecheck(ctx))?;
187 let at = Type::Array(Arc::new(self.typ.clone()));
188 wrap!(self, at.check_contains(&ctx.env, self.source.node.typ()))?;
189 let int = Type::Primitive(Typ::integer());
190 wrap!(self.i.node, int.check_contains(&ctx.env, self.i.node.typ()))
191 }
192
193 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
194 self.source.node.refs(f);
195 self.i.node.refs(f);
196 }
197
198 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
199 self.source.node.delete(ctx);
200 self.i.node.delete(ctx);
201 }
202
203 fn typ(&self) -> &Type {
204 &self.typ
205 }
206
207 fn spec(&self) -> &Expr {
208 &self.spec
209 }
210}
211
212#[derive(Debug)]
213pub(crate) struct ArraySlice<C: Ctx, E: UserEvent> {
214 source: Cached<C, E>,
215 start: Option<Cached<C, E>>,
216 end: Option<Cached<C, E>>,
217 spec: Expr,
218 typ: Type,
219}
220
221impl<C: Ctx, E: UserEvent> ArraySlice<C, E> {
222 pub(crate) fn compile(
223 ctx: &mut ExecCtx<C, E>,
224 spec: Expr,
225 scope: &ModPath,
226 top_id: ExprId,
227 source: &Expr,
228 start: &Option<Arc<Expr>>,
229 end: &Option<Arc<Expr>>,
230 ) -> Result<Node<C, E>> {
231 let source = Cached::new(compile(ctx, source.clone(), scope, top_id)?);
232 let start = start
233 .as_ref()
234 .map(|e| compile(ctx, (**e).clone(), scope, top_id).map(Cached::new))
235 .transpose()?;
236 let end = end
237 .as_ref()
238 .map(|e| compile(ctx, (**e).clone(), scope, top_id).map(Cached::new))
239 .transpose()?;
240 let typ = Type::Set(Arc::from_iter([
241 source.node.typ().clone(),
242 Type::Primitive(Typ::Error.into()),
243 ]));
244 Ok(Box::new(Self { spec, typ, source, start, end }))
245 }
246}
247
248impl<C: Ctx, E: UserEvent> Update<C, E> for ArraySlice<C, E> {
249 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
250 macro_rules! number {
251 ($e:expr) => {
252 match $e.clone().cast_to::<usize>() {
253 Ok(i) => i,
254 Err(_) => return err!("expected a non negative number"),
255 }
256 };
257 }
258 macro_rules! bound {
259 ($bound:expr) => {{
260 match $bound.cached.as_ref() {
261 None => return None,
262 Some(Value::U64(i) | Value::V64(i)) => Some(*i as usize),
263 Some(v) => Some(number!(v)),
264 }
265 }};
266 }
267 let up = self.source.update(ctx, event);
268 let up = self.start.as_mut().map(|c| c.update(ctx, event)).unwrap_or(false) || up;
269 let up = self.end.as_mut().map(|c| c.update(ctx, event)).unwrap_or(false) || up;
270 if !up {
271 return None;
272 }
273 let (start, end) = match (&self.start, &self.end) {
274 (None, None) => (None, None),
275 (Some(c), None) => (bound!(c), None),
276 (None, Some(c)) => (None, bound!(c)),
277 (Some(c0), Some(c1)) => (bound!(c0), bound!(c1)),
278 };
279 match &self.source.cached {
280 Some(Value::Array(elts)) => match (start, end) {
281 (None, None) => Some(Value::Array(elts.clone())),
282 (Some(i), Some(j)) => match elts.subslice(i..j) {
283 Ok(a) => Some(Value::Array(a)),
284 Err(e) => Some(Value::Error(e.to_string().into())),
285 },
286 (Some(i), None) => match elts.subslice(i..) {
287 Ok(a) => Some(Value::Array(a)),
288 Err(e) => Some(Value::Error(e.to_string().into())),
289 },
290 (None, Some(i)) => match elts.subslice(..i) {
291 Ok(a) => Some(Value::Array(a)),
292 Err(e) => Some(Value::Error(e.to_string().into())),
293 },
294 },
295 Some(_) => err!("expected array"),
296 None => None,
297 }
298 }
299
300 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
301 wrap!(self.source.node, self.source.node.typecheck(ctx))?;
302 let it = Type::Primitive(Typ::unsigned_integer());
303 wrap!(
304 self.source.node,
305 self.typ.check_contains(&ctx.env, &self.source.node.typ())
306 )?;
307 if let Some(start) = self.start.as_mut() {
308 wrap!(start.node, start.node.typecheck(ctx))?;
309 wrap!(start.node, it.check_contains(&ctx.env, &start.node.typ()))?;
310 }
311 if let Some(end) = self.end.as_mut() {
312 wrap!(end.node, end.node.typecheck(ctx))?;
313 wrap!(end.node, it.check_contains(&ctx.env, &end.node.typ()))?;
314 }
315 Ok(())
316 }
317
318 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
319 self.source.node.refs(f);
320 if let Some(start) = &self.start {
321 start.node.refs(f)
322 }
323 if let Some(end) = &self.end {
324 end.node.refs(f)
325 }
326 }
327
328 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
329 self.source.node.delete(ctx);
330 if let Some(start) = &mut self.start {
331 start.node.delete(ctx);
332 }
333 if let Some(end) = &mut self.end {
334 end.node.delete(ctx);
335 }
336 }
337
338 fn typ(&self) -> &Type {
339 &self.typ
340 }
341
342 fn spec(&self) -> &Expr {
343 &self.spec
344 }
345}
346
347#[derive(Debug)]
348pub(crate) struct Use {
349 spec: Expr,
350 scope: ModPath,
351 name: ModPath,
352}
353
354impl Use {
355 pub(crate) fn compile<C: Ctx, E: UserEvent>(
356 ctx: &mut ExecCtx<C, E>,
357 spec: Expr,
358 scope: &ModPath,
359 name: &ModPath,
360 pos: &SourcePosition,
361 ) -> Result<Node<C, E>> {
362 match ctx.env.canonical_modpath(scope, name) {
363 None => bail!("at {pos} no such module {name}"),
364 Some(_) => {
365 let used = ctx.env.used.get_or_default_cow(scope.clone());
366 Arc::make_mut(used).push(name.clone());
367 Ok(Box::new(Self { spec, scope: scope.clone(), name: name.clone() }))
368 }
369 }
370 }
371}
372
373impl<C: Ctx, E: UserEvent> Update<C, E> for Use {
374 fn update(
375 &mut self,
376 _ctx: &mut ExecCtx<C, E>,
377 _event: &mut Event<E>,
378 ) -> Option<Value> {
379 None
380 }
381
382 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
383 Ok(())
384 }
385
386 fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
387
388 fn spec(&self) -> &Expr {
389 &self.spec
390 }
391
392 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
393 if let Some(used) = ctx.env.used.get_mut_cow(&self.scope) {
394 Arc::make_mut(used).retain(|n| n != &self.name);
395 if used.is_empty() {
396 ctx.env.used.remove_cow(&self.scope);
397 }
398 }
399 }
400
401 fn typ(&self) -> &Type {
402 &Type::Bottom
403 }
404}
405
406#[derive(Debug)]
407pub(crate) struct TypeDef {
408 spec: Expr,
409 scope: ModPath,
410 name: ArcStr,
411}
412
413impl TypeDef {
414 pub(crate) fn compile<C: Ctx, E: UserEvent>(
415 ctx: &mut ExecCtx<C, E>,
416 spec: Expr,
417 scope: &ModPath,
418 name: &ArcStr,
419 params: &Arc<[(TVar, Option<Type>)]>,
420 typ: &Type,
421 pos: &SourcePosition,
422 ) -> Result<Node<C, E>> {
423 let typ = typ.scope_refs(scope);
424 ctx.env
425 .deftype(scope, name, params.clone(), typ)
426 .with_context(|| format!("in typedef at {pos}"))?;
427 let name = name.clone();
428 let scope = scope.clone();
429 Ok(Box::new(Self { spec, scope, name }))
430 }
431}
432
433impl<C: Ctx, E: UserEvent> Update<C, E> for TypeDef {
434 fn update(
435 &mut self,
436 _ctx: &mut ExecCtx<C, E>,
437 _event: &mut Event<E>,
438 ) -> Option<Value> {
439 None
440 }
441
442 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
443 Ok(())
444 }
445
446 fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
447
448 fn spec(&self) -> &Expr {
449 &self.spec
450 }
451
452 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
453 ctx.env.undeftype(&self.scope, &self.name)
454 }
455
456 fn typ(&self) -> &Type {
457 &Type::Bottom
458 }
459}
460
461#[derive(Debug)]
462pub(crate) struct Constant {
463 spec: Arc<Expr>,
464 value: Value,
465 typ: Type,
466}
467
468impl Constant {
469 pub(crate) fn compile<C: Ctx, E: UserEvent>(
470 spec: Expr,
471 value: &Value,
472 ) -> Result<Node<C, E>> {
473 let spec = Arc::new(spec);
474 let value = value.clone();
475 let typ = Type::Primitive(Typ::get(&value).into());
476 Ok(Box::new(Self { spec, value, typ }))
477 }
478}
479
480impl<C: Ctx, E: UserEvent> Update<C, E> for Constant {
481 fn update(
482 &mut self,
483 _ctx: &mut ExecCtx<C, E>,
484 event: &mut Event<E>,
485 ) -> Option<Value> {
486 if event.init {
487 Some(self.value.clone())
488 } else {
489 None
490 }
491 }
492
493 fn delete(&mut self, _ctx: &mut ExecCtx<C, E>) {}
494
495 fn refs<'a>(&'a self, _f: &'a mut (dyn FnMut(BindId) + 'a)) {}
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 fn spec(&self) -> &Expr {
506 &self.spec
507 }
508}
509
510#[derive(Debug)]
512pub(crate) struct Block<C: Ctx, E: UserEvent> {
513 spec: Expr,
514 children: Box<[Node<C, E>]>,
515}
516
517impl<C: Ctx, E: UserEvent> Block<C, E> {
518 pub(crate) fn compile(
519 ctx: &mut ExecCtx<C, E>,
520 spec: Expr,
521 scope: &ModPath,
522 top_id: ExprId,
523 exprs: &Arc<[Expr]>,
524 ) -> Result<Node<C, E>> {
525 let children = exprs
526 .iter()
527 .map(|e| compile(ctx, e.clone(), scope, top_id))
528 .collect::<Result<Box<[Node<C, E>]>>>()?;
529 Ok(Box::new(Self { spec, children }))
530 }
531}
532
533impl<C: Ctx, E: UserEvent> Update<C, E> for Block<C, E> {
534 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
535 self.children.iter_mut().fold(None, |_, n| n.update(ctx, event))
536 }
537
538 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
539 for n in &mut self.children {
540 n.delete(ctx)
541 }
542 }
543
544 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
545 for n in &self.children {
546 n.refs(f)
547 }
548 }
549
550 fn typ(&self) -> &Type {
551 &self.children.last().map(|n| n.typ()).unwrap_or(&Type::Bottom)
552 }
553
554 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
555 for n in &mut self.children {
556 wrap!(n, n.typecheck(ctx))?
557 }
558 Ok(())
559 }
560
561 fn spec(&self) -> &Expr {
562 &self.spec
563 }
564}
565
566#[derive(Debug)]
567pub(crate) struct Bind<C: Ctx, E: UserEvent> {
568 spec: Expr,
569 typ: Type,
570 pattern: StructPatternNode,
571 node: Node<C, E>,
572}
573
574impl<C: Ctx, E: UserEvent> Bind<C, E> {
575 pub(crate) fn compile(
576 ctx: &mut ExecCtx<C, E>,
577 spec: Expr,
578 scope: &ModPath,
579 top_id: ExprId,
580 b: &expr::Bind,
581 pos: &SourcePosition,
582 ) -> Result<Node<C, E>> {
583 let expr::Bind { doc, pattern, typ, export: _, value } = b;
584 let node = compile(ctx, value.clone(), &scope, top_id)?;
585 let typ = match typ {
586 Some(typ) => typ.scope_refs(scope),
587 None => {
588 let typ = node.typ().clone();
589 let ptyp = pattern.infer_type_predicate();
590 if !ptyp.contains(&ctx.env, &typ)? {
591 typ::format_with_flags(typ::PrintFlag::DerefTVars.into(), || {
592 bail!("at {pos} match error {typ} can't be matched by {ptyp}")
593 })?
594 }
595 typ
596 }
597 };
598 let pattern = StructPatternNode::compile(ctx, &typ, pattern, scope)
599 .with_context(|| format!("at {pos}"))?;
600 if pattern.is_refutable() {
601 bail!("at {pos} refutable patterns are not allowed in let");
602 }
603 if let Some(doc) = doc {
604 pattern.ids(&mut |id| {
605 if let Some(b) = ctx.env.by_id.get_mut_cow(&id) {
606 b.doc = Some(doc.clone());
607 }
608 });
609 }
610 Ok(Box::new(Self { spec, typ, pattern, node }))
611 }
612}
613
614impl<C: Ctx, E: UserEvent> Update<C, E> for Bind<C, E> {
615 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
616 if let Some(v) = self.node.update(ctx, event) {
617 self.pattern.bind(&v, &mut |id, v| ctx.set_var(id, v))
618 }
619 None
620 }
621
622 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
623 self.pattern.ids(f);
624 self.node.refs(f);
625 }
626
627 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
628 self.node.delete(ctx);
629 }
630
631 fn typ(&self) -> &Type {
632 &self.typ
633 }
634
635 fn spec(&self) -> &Expr {
636 &self.spec
637 }
638
639 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
640 wrap!(self.node, self.node.typecheck(ctx))?;
641 wrap!(self.node, self.typ.check_contains(&ctx.env, &self.node.typ()))?;
642 Ok(())
643 }
644}
645
646#[derive(Debug)]
647pub(crate) struct Ref {
648 spec: Arc<Expr>,
649 typ: Type,
650 id: BindId,
651 top_id: ExprId,
652}
653
654impl Ref {
655 pub(crate) fn compile<C: Ctx, E: UserEvent>(
656 ctx: &mut ExecCtx<C, E>,
657 spec: Expr,
658 scope: &ModPath,
659 top_id: ExprId,
660 name: &ModPath,
661 pos: &SourcePosition,
662 ) -> Result<Node<C, E>> {
663 match ctx.env.lookup_bind(scope, name) {
664 None => bail!("at {pos} {name} not defined"),
665 Some((_, bind)) => {
666 ctx.user.ref_var(bind.id, top_id);
667 let typ = bind.typ.clone();
668 let spec = Arc::new(spec);
669 Ok(Box::new(Self { spec, typ, id: bind.id, top_id }))
670 }
671 }
672 }
673}
674
675impl<C: Ctx, E: UserEvent> Update<C, E> for Ref {
676 fn update(
677 &mut self,
678 _ctx: &mut ExecCtx<C, E>,
679 event: &mut Event<E>,
680 ) -> Option<Value> {
681 event.variables.get(&self.id).map(|v| v.clone())
682 }
683
684 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
685 f(self.id)
686 }
687
688 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
689 ctx.user.unref_var(self.id, self.top_id)
690 }
691
692 fn spec(&self) -> &Expr {
693 &self.spec
694 }
695
696 fn typ(&self) -> &Type {
697 &self.typ
698 }
699
700 fn typecheck(&mut self, _ctx: &mut ExecCtx<C, E>) -> Result<()> {
701 Ok(())
702 }
703}
704
705#[derive(Debug)]
706pub(crate) struct StructRef<C: Ctx, E: UserEvent> {
707 spec: Expr,
708 typ: Type,
709 source: Node<C, E>,
710 field: usize,
711}
712
713impl<C: Ctx, E: UserEvent> StructRef<C, E> {
714 pub(crate) fn compile(
715 ctx: &mut ExecCtx<C, E>,
716 spec: Expr,
717 scope: &ModPath,
718 top_id: ExprId,
719 source: &Expr,
720 field: &ArcStr,
721 ) -> Result<Node<C, E>> {
722 let source = compile(ctx, source.clone(), scope, top_id)?;
723 let (typ, field) = match &source.typ() {
724 Type::Struct(flds) => flds
725 .iter()
726 .enumerate()
727 .find_map(
728 |(i, (n, t))| {
729 if field == n {
730 Some((t.clone(), i))
731 } else {
732 None
733 }
734 },
735 )
736 .unwrap_or_else(|| (Type::empty_tvar(), 0)),
737 _ => (Type::empty_tvar(), 0),
738 };
739 Ok(Box::new(Self { spec, typ, source, field }))
741 }
742}
743
744impl<C: Ctx, E: UserEvent> Update<C, E> for StructRef<C, E> {
745 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
746 match self.source.update(ctx, event) {
747 Some(Value::Array(a)) => a.get(self.field).and_then(|v| match v {
748 Value::Array(a) if a.len() == 2 => Some(a[1].clone()),
749 _ => None,
750 }),
751 Some(_) | None => None,
752 }
753 }
754
755 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
756 self.source.refs(f)
757 }
758
759 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
760 self.source.delete(ctx)
761 }
762
763 fn typ(&self) -> &Type {
764 &self.typ
765 }
766
767 fn spec(&self) -> &Expr {
768 &self.spec
769 }
770
771 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
772 wrap!(self.source, self.source.typecheck(ctx))?;
773 let field = match &self.spec.kind {
774 ExprKind::StructRef { source: _, field } => field.clone(),
775 _ => bail!("BUG: miscompiled struct ref"),
776 };
777 let etyp = self.source.typ().with_deref(|typ| match typ {
778 Some(Type::Struct(flds)) => {
779 let typ = flds.iter().enumerate().find_map(|(i, (n, t))| {
780 if &field == n {
781 Some((i, t.clone()))
782 } else {
783 None
784 }
785 });
786 match typ {
787 Some((i, t)) => Ok((i, t)),
788 None => bail!("in struct, unknown field {field}"),
789 }
790 }
791 None => bail!("type must be known, annotations needed"),
792 _ => bail!("expected struct"),
793 });
794 let (idx, typ) = wrap!(self, etyp)?;
795 self.field = idx;
796 wrap!(self, self.typ.check_contains(&ctx.env, &typ))
797 }
798}
799
800#[derive(Debug)]
801pub(crate) struct TupleRef<C: Ctx, E: UserEvent> {
802 spec: Expr,
803 typ: Type,
804 source: Node<C, E>,
805 field: usize,
806}
807
808impl<C: Ctx, E: UserEvent> TupleRef<C, E> {
809 pub(crate) fn compile(
810 ctx: &mut ExecCtx<C, E>,
811 spec: Expr,
812 scope: &ModPath,
813 top_id: ExprId,
814 source: &Expr,
815 field: &usize,
816 ) -> Result<Node<C, E>> {
817 let source = compile(ctx, source.clone(), scope, top_id)?;
818 let field = *field;
819 let typ = match &source.typ() {
820 Type::Tuple(ts) => {
821 ts.get(field).map(|t| t.clone()).unwrap_or_else(Type::empty_tvar)
822 }
823 _ => Type::empty_tvar(),
824 };
825 Ok(Box::new(Self { spec, typ, source, field }))
826 }
827}
828
829impl<C: Ctx, E: UserEvent> Update<C, E> for TupleRef<C, E> {
830 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
831 self.source.update(ctx, event).and_then(|v| match v {
832 Value::Array(a) => a.get(self.field).map(|v| v.clone()),
833 _ => None,
834 })
835 }
836
837 fn spec(&self) -> &Expr {
838 &self.spec
839 }
840
841 fn typ(&self) -> &Type {
842 &self.typ
843 }
844
845 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
846 self.source.refs(f)
847 }
848
849 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
850 self.source.delete(ctx)
851 }
852
853 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
854 wrap!(self.source, self.source.typecheck(ctx))?;
855 let etyp = self.source.typ().with_deref(|typ| match typ {
856 Some(Type::Tuple(flds)) if flds.len() > self.field => {
857 Ok(flds[self.field].clone())
858 }
859 None => bail!("type must be known, annotations needed"),
860 _ => bail!("expected tuple with at least {} elements", self.field),
861 });
862 let etyp = wrap!(self, etyp)?;
863 wrap!(self, self.typ.check_contains(&ctx.env, &etyp))
864 }
865}
866
867#[derive(Debug)]
868pub(crate) struct StringInterpolate<C: Ctx, E: UserEvent> {
869 spec: Expr,
870 typ: Type,
871 args: Box<[Cached<C, E>]>,
872}
873
874impl<C: Ctx, E: UserEvent> StringInterpolate<C, E> {
875 pub(crate) fn compile(
876 ctx: &mut ExecCtx<C, E>,
877 spec: Expr,
878 scope: &ModPath,
879 top_id: ExprId,
880 args: &[Expr],
881 ) -> Result<Node<C, E>> {
882 let args = args
883 .iter()
884 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
885 .collect::<Result<_>>()?;
886 let typ = Type::Primitive(Typ::String.into());
887 Ok(Box::new(Self { spec, typ, args }))
888 }
889}
890
891impl<C: Ctx, E: UserEvent> Update<C, E> for StringInterpolate<C, E> {
892 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
893 use std::fmt::Write;
894 thread_local! {
895 static BUF: RefCell<String> = RefCell::new(String::new());
896 }
897 let (updated, determined) = update_args!(self.args, ctx, event);
898 if updated && determined {
899 BUF.with_borrow_mut(|buf| {
900 buf.clear();
901 for c in &self.args {
902 match c.cached.as_ref().unwrap() {
903 Value::String(s) => write!(buf, "{s}"),
904 v => write!(buf, "{}", NakedValue(v)),
905 }
906 .unwrap()
907 }
908 Some(Value::String(buf.as_str().into()))
909 })
910 } else {
911 None
912 }
913 }
914
915 fn spec(&self) -> &Expr {
916 &self.spec
917 }
918
919 fn typ(&self) -> &Type {
920 &self.typ
921 }
922
923 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
924 for a in &self.args {
925 a.node.refs(f)
926 }
927 }
928
929 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
930 for n in &mut self.args {
931 n.node.delete(ctx)
932 }
933 }
934
935 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
936 for a in &mut self.args {
937 wrap!(a.node, a.node.typecheck(ctx))?
938 }
939 Ok(())
940 }
941}
942
943#[derive(Debug)]
944pub(crate) struct Connect<C: Ctx, E: UserEvent> {
945 spec: Expr,
946 node: Node<C, E>,
947 id: BindId,
948}
949
950impl<C: Ctx, E: UserEvent> Connect<C, E> {
951 pub(crate) fn compile(
952 ctx: &mut ExecCtx<C, E>,
953 spec: Expr,
954 scope: &ModPath,
955 top_id: ExprId,
956 name: &ModPath,
957 value: &Expr,
958 pos: &SourcePosition,
959 ) -> Result<Node<C, E>> {
960 let id = match ctx.env.lookup_bind(scope, name) {
961 None => bail!("at {pos} {name} is undefined"),
962 Some((_, env::Bind { id, .. })) => *id,
963 };
964 let node = compile(ctx, value.clone(), scope, top_id)?;
965 Ok(Box::new(Self { spec, node, id }))
966 }
967}
968
969impl<C: Ctx, E: UserEvent> Update<C, E> for Connect<C, E> {
970 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
971 if let Some(v) = self.node.update(ctx, event) {
972 ctx.set_var(self.id, v)
973 }
974 None
975 }
976
977 fn spec(&self) -> &Expr {
978 &self.spec
979 }
980
981 fn typ(&self) -> &Type {
982 &Type::Bottom
983 }
984
985 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
986 self.node.refs(f)
987 }
988
989 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
990 self.node.delete(ctx)
991 }
992
993 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
994 wrap!(self.node, self.node.typecheck(ctx))?;
995 let bind = match ctx.env.by_id.get(&self.id) {
996 None => bail!("BUG missing bind {:?}", self.id),
997 Some(bind) => bind,
998 };
999 wrap!(self, bind.typ.check_contains(&ctx.env, self.node.typ()))
1000 }
1001}
1002
1003#[derive(Debug)]
1004pub(crate) struct ByRef<C: Ctx, E: UserEvent> {
1005 spec: Expr,
1006 typ: Type,
1007 child: Node<C, E>,
1008 id: BindId,
1009}
1010
1011impl<C: Ctx, E: UserEvent> ByRef<C, E> {
1012 pub(crate) fn compile(
1013 ctx: &mut ExecCtx<C, E>,
1014 spec: Expr,
1015 scope: &ModPath,
1016 top_id: ExprId,
1017 expr: &Expr,
1018 ) -> Result<Node<C, E>> {
1019 let child = compile(ctx, expr.clone(), scope, top_id)?;
1020 let id = BindId::new();
1021 let typ = Type::ByRef(Arc::new(child.typ().clone()));
1022 Ok(Box::new(Self { spec, typ, child, id }))
1023 }
1024}
1025
1026impl<C: Ctx, E: UserEvent> Update<C, E> for ByRef<C, E> {
1027 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1028 if let Some(v) = self.child.update(ctx, event) {
1029 ctx.set_var(self.id, v);
1030 }
1031 if event.init {
1032 Some(Value::U64(self.id.inner()))
1033 } else {
1034 None
1035 }
1036 }
1037
1038 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1039 self.child.delete(ctx)
1040 }
1041
1042 fn spec(&self) -> &Expr {
1043 &self.spec
1044 }
1045
1046 fn typ(&self) -> &Type {
1047 &self.typ
1048 }
1049
1050 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1051 self.child.refs(f)
1052 }
1053
1054 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1055 wrap!(self.child, self.child.typecheck(ctx))?;
1056 let t = Type::ByRef(Arc::new(self.child.typ().clone()));
1057 wrap!(self, self.typ.check_contains(&ctx.env, &t))
1058 }
1059}
1060
1061#[derive(Debug)]
1062pub(crate) struct Deref<C: Ctx, E: UserEvent> {
1063 spec: Expr,
1064 typ: Type,
1065 child: Node<C, E>,
1066 id: Option<BindId>,
1067 top_id: ExprId,
1068}
1069
1070impl<C: Ctx, E: UserEvent> Deref<C, E> {
1071 pub(crate) fn compile(
1072 ctx: &mut ExecCtx<C, E>,
1073 spec: Expr,
1074 scope: &ModPath,
1075 top_id: ExprId,
1076 expr: &Expr,
1077 ) -> Result<Node<C, E>> {
1078 let child = compile(ctx, expr.clone(), scope, top_id)?;
1079 let typ = Type::empty_tvar();
1080 Ok(Box::new(Self { spec, typ, child, id: None, top_id }))
1081 }
1082}
1083
1084impl<C: Ctx, E: UserEvent> Update<C, E> for Deref<C, E> {
1085 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1086 if let Some(v) = self.child.update(ctx, event) {
1087 match v {
1088 Value::U64(i) | Value::V64(i) => {
1089 let new_id = BindId::from_u64(i);
1090 if self.id != Some(new_id) {
1091 if let Some(old) = self.id {
1092 ctx.user.unref_var(old, self.top_id);
1093 }
1094 ctx.user.ref_var(new_id, self.top_id);
1095 self.id = Some(new_id);
1096 }
1097 }
1098 _ => return err!("expected u64 bind id"),
1099 }
1100 }
1101 self.id.and_then(|id| event.variables.get(&id).cloned())
1102 }
1103
1104 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1105 if let Some(id) = self.id.take() {
1106 ctx.user.unref_var(id, self.top_id);
1107 }
1108 self.child.delete(ctx);
1109 }
1110
1111 fn spec(&self) -> &Expr {
1112 &self.spec
1113 }
1114
1115 fn typ(&self) -> &Type {
1116 &self.typ
1117 }
1118
1119 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1120 self.child.refs(f);
1121 if let Some(id) = self.id {
1122 f(id);
1123 }
1124 }
1125
1126 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1127 wrap!(self.child, self.child.typecheck(ctx))?;
1128 let typ = match self.child.typ() {
1129 Type::ByRef(t) => (**t).clone(),
1130 _ => bail!("expected reference"),
1131 };
1132 wrap!(self, self.typ.check_contains(&ctx.env, &typ))?;
1133 Ok(())
1134 }
1135}
1136
1137#[derive(Debug)]
1138pub(crate) struct Qop<C: Ctx, E: UserEvent> {
1139 spec: Expr,
1140 typ: Type,
1141 id: BindId,
1142 n: Node<C, E>,
1143}
1144
1145impl<C: Ctx, E: UserEvent> Qop<C, E> {
1146 pub(crate) fn compile(
1147 ctx: &mut ExecCtx<C, E>,
1148 spec: Expr,
1149 scope: &ModPath,
1150 top_id: ExprId,
1151 e: &Expr,
1152 pos: &SourcePosition,
1153 ) -> Result<Node<C, E>> {
1154 let n = compile(ctx, e.clone(), scope, top_id)?;
1155 match ctx.env.lookup_bind(scope, &ModPath::from(["errors"])) {
1156 None => bail!("at {pos} BUG: errors is undefined"),
1157 Some((_, bind)) => {
1158 let typ = Type::empty_tvar();
1159 Ok(Box::new(Self { spec, typ, id: bind.id, n }))
1160 }
1161 }
1162 }
1163}
1164
1165impl<C: Ctx, E: UserEvent> Update<C, E> for Qop<C, E> {
1166 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1167 match self.n.update(ctx, event) {
1168 None => None,
1169 Some(e @ Value::Error(_)) => {
1170 ctx.set_var(self.id, e);
1171 None
1172 }
1173 Some(v) => Some(v),
1174 }
1175 }
1176
1177 fn typ(&self) -> &Type {
1178 &self.typ
1179 }
1180
1181 fn spec(&self) -> &Expr {
1182 &self.spec
1183 }
1184
1185 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1186 self.n.refs(f)
1187 }
1188
1189 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1190 self.n.delete(ctx)
1191 }
1192
1193 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1194 wrap!(self.n, self.n.typecheck(ctx))?;
1195 let bind =
1196 ctx.env.by_id.get(&self.id).ok_or_else(|| anyhow!("BUG: missing bind"))?;
1197 let err = Type::Primitive(Typ::Error.into());
1198 wrap!(self, bind.typ.check_contains(&ctx.env, &err))?;
1199 wrap!(self, err.check_contains(&ctx.env, &bind.typ))?;
1200 if !self.n.typ().contains(&ctx.env, &err)? {
1201 bail!("cannot use the ? operator on a non error type")
1202 }
1203 let rtyp = self.n.typ().diff(&ctx.env, &err)?;
1204 wrap!(self, self.typ.check_contains(&ctx.env, &rtyp))?;
1205 Ok(())
1206 }
1207}
1208
1209#[derive(Debug)]
1210pub(crate) struct TypeCast<C: Ctx, E: UserEvent> {
1211 spec: Expr,
1212 typ: Type,
1213 target: Type,
1214 n: Node<C, E>,
1215}
1216
1217impl<C: Ctx, E: UserEvent> TypeCast<C, E> {
1218 pub(crate) fn compile(
1219 ctx: &mut ExecCtx<C, E>,
1220 spec: Expr,
1221 scope: &ModPath,
1222 top_id: ExprId,
1223 expr: &Expr,
1224 typ: &Type,
1225 pos: &SourcePosition,
1226 ) -> Result<Node<C, E>> {
1227 let n = compile(ctx, expr.clone(), scope, top_id)?;
1228 let target = typ.scope_refs(scope);
1229 if let Err(e) = target.check_cast(&ctx.env) {
1230 bail!("in cast at {pos} {e}");
1231 }
1232 let typ = target.union(&Type::Primitive(Typ::Error.into()));
1233 Ok(Box::new(Self { spec, typ, target, n }))
1234 }
1235}
1236
1237impl<C: Ctx, E: UserEvent> Update<C, E> for TypeCast<C, E> {
1238 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1239 self.n.update(ctx, event).map(|v| self.target.cast_value(&ctx.env, v))
1240 }
1241
1242 fn spec(&self) -> &Expr {
1243 &self.spec
1244 }
1245
1246 fn typ(&self) -> &Type {
1247 &self.typ
1248 }
1249
1250 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1251 self.n.delete(ctx)
1252 }
1253
1254 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1255 self.n.refs(f)
1256 }
1257
1258 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1259 Ok(wrap!(self.n, self.n.typecheck(ctx))?)
1260 }
1261}
1262
1263#[derive(Debug)]
1264pub(crate) struct Any<C: Ctx, E: UserEvent> {
1265 spec: Expr,
1266 typ: Type,
1267 n: Box<[Node<C, E>]>,
1268}
1269
1270impl<C: Ctx, E: UserEvent> Any<C, E> {
1271 pub(crate) fn compile(
1272 ctx: &mut ExecCtx<C, E>,
1273 spec: Expr,
1274 scope: &ModPath,
1275 top_id: ExprId,
1276 args: &[Expr],
1277 ) -> Result<Node<C, E>> {
1278 let n = args
1279 .iter()
1280 .map(|e| compile(ctx, e.clone(), scope, top_id))
1281 .collect::<Result<Box<[_]>>>()?;
1282 let typ =
1283 Type::Set(Arc::from_iter(n.iter().map(|n| n.typ().clone()))).normalize();
1284 Ok(Box::new(Self { spec, typ, n }))
1285 }
1286}
1287
1288impl<C: Ctx, E: UserEvent> Update<C, E> for Any<C, E> {
1289 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1290 self.n
1291 .iter_mut()
1292 .filter_map(|s| s.update(ctx, event))
1293 .fold(None, |r, v| r.or(Some(v)))
1294 }
1295
1296 fn spec(&self) -> &Expr {
1297 &self.spec
1298 }
1299
1300 fn typ(&self) -> &Type {
1301 &self.typ
1302 }
1303
1304 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1305 self.n.iter_mut().for_each(|n| n.delete(ctx))
1306 }
1307
1308 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1309 self.n.iter().for_each(|n| n.refs(f))
1310 }
1311
1312 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1313 for n in self.n.iter_mut() {
1314 wrap!(n, n.typecheck(ctx))?
1315 }
1316 let rtyp = Type::Primitive(BitFlags::empty());
1317 let rtyp = self.n.iter().fold(rtyp, |rtype, n| n.typ().union(&rtype));
1318 Ok(self.typ.check_contains(&ctx.env, &rtyp)?)
1319 }
1320}
1321
1322#[derive(Debug)]
1323pub(crate) struct Array<C: Ctx, E: UserEvent> {
1324 spec: Expr,
1325 typ: Type,
1326 n: Box<[Cached<C, E>]>,
1327}
1328
1329impl<C: Ctx, E: UserEvent> Array<C, E> {
1330 pub(crate) fn compile(
1331 ctx: &mut ExecCtx<C, E>,
1332 spec: Expr,
1333 scope: &ModPath,
1334 top_id: ExprId,
1335 args: &Arc<[Expr]>,
1336 ) -> Result<Node<C, E>> {
1337 let n = args
1338 .iter()
1339 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1340 .collect::<Result<_>>()?;
1341 let typ = Type::Array(Arc::new(Type::empty_tvar()));
1342 Ok(Box::new(Self { spec, typ, n }))
1343 }
1344}
1345
1346impl<C: Ctx, E: UserEvent> Update<C, E> for Array<C, E> {
1347 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1348 if self.n.is_empty() && event.init {
1349 return Some(Value::Array(ValArray::from([])));
1350 }
1351 let (updated, determined) = update_args!(self.n, ctx, event);
1352 if updated && determined {
1353 let iter = self.n.iter().map(|n| n.cached.clone().unwrap());
1354 Some(Value::Array(ValArray::from_iter_exact(iter)))
1355 } else {
1356 None
1357 }
1358 }
1359
1360 fn spec(&self) -> &Expr {
1361 &self.spec
1362 }
1363
1364 fn typ(&self) -> &Type {
1365 &self.typ
1366 }
1367
1368 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1369 self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1370 }
1371
1372 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1373 self.n.iter().for_each(|n| n.node.refs(f))
1374 }
1375
1376 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1377 for n in &mut self.n {
1378 wrap!(n.node, n.node.typecheck(ctx))?
1379 }
1380 let rtype = Type::Bottom;
1381 let rtype = self.n.iter().fold(rtype, |rtype, n| n.node.typ().union(&rtype));
1382 let rtype = Type::Array(Arc::new(rtype));
1383 Ok(self.typ.check_contains(&ctx.env, &rtype)?)
1384 }
1385}
1386
1387#[derive(Debug)]
1388pub(crate) struct Tuple<C: Ctx, E: UserEvent> {
1389 spec: Expr,
1390 typ: Type,
1391 n: Box<[Cached<C, E>]>,
1392}
1393
1394impl<C: Ctx, E: UserEvent> Tuple<C, E> {
1395 pub(crate) fn compile(
1396 ctx: &mut ExecCtx<C, E>,
1397 spec: Expr,
1398 scope: &ModPath,
1399 top_id: ExprId,
1400 args: &[Expr],
1401 ) -> Result<Node<C, E>> {
1402 let n = args
1403 .iter()
1404 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1405 .collect::<Result<Box<[_]>>>()?;
1406 let typ = Type::Tuple(Arc::from_iter(n.iter().map(|n| n.node.typ().clone())));
1407 Ok(Box::new(Self { spec, typ, n }))
1408 }
1409}
1410
1411impl<C: Ctx, E: UserEvent> Update<C, E> for Tuple<C, E> {
1412 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1413 if self.n.is_empty() && event.init {
1414 return Some(Value::Array(ValArray::from([])));
1415 }
1416 let (updated, determined) = update_args!(self.n, ctx, event);
1417 if updated && determined {
1418 let iter = self.n.iter().map(|n| n.cached.clone().unwrap());
1419 Some(Value::Array(ValArray::from_iter_exact(iter)))
1420 } else {
1421 None
1422 }
1423 }
1424
1425 fn spec(&self) -> &Expr {
1426 &self.spec
1427 }
1428
1429 fn typ(&self) -> &Type {
1430 &self.typ
1431 }
1432
1433 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1434 self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1435 }
1436
1437 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1438 self.n.iter().for_each(|n| n.node.refs(f))
1439 }
1440
1441 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1442 for n in self.n.iter_mut() {
1443 wrap!(n.node, n.node.typecheck(ctx))?
1444 }
1445 match &self.typ {
1446 Type::Tuple(typs) => {
1447 if self.n.len() != typs.len() {
1448 bail!("tuple arity mismatch {} vs {}", self.n.len(), typs.len())
1449 }
1450 for (t, n) in typs.iter().zip(self.n.iter()) {
1451 t.check_contains(&ctx.env, &n.node.typ())?
1452 }
1453 }
1454 _ => bail!("BUG: unexpected tuple rtype"),
1455 }
1456 Ok(())
1457 }
1458}
1459
1460#[derive(Debug)]
1461pub(crate) struct Variant<C: Ctx, E: UserEvent> {
1462 spec: Expr,
1463 typ: Type,
1464 tag: ArcStr,
1465 n: Box<[Cached<C, E>]>,
1466}
1467
1468impl<C: Ctx, E: UserEvent> Variant<C, E> {
1469 pub(crate) fn compile(
1470 ctx: &mut ExecCtx<C, E>,
1471 spec: Expr,
1472 scope: &ModPath,
1473 top_id: ExprId,
1474 tag: &ArcStr,
1475 args: &[Expr],
1476 ) -> Result<Node<C, E>> {
1477 let n = args
1478 .iter()
1479 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1480 .collect::<Result<Box<[_]>>>()?;
1481 let typs = Arc::from_iter(n.iter().map(|n| n.node.typ().clone()));
1482 let typ = Type::Variant(tag.clone(), typs);
1483 let tag = tag.clone();
1484 Ok(Box::new(Self { spec, typ, tag, n }))
1485 }
1486}
1487
1488impl<C: Ctx, E: UserEvent> Update<C, E> for Variant<C, E> {
1489 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1490 if self.n.len() == 0 {
1491 if event.init {
1492 Some(Value::String(self.tag.clone()))
1493 } else {
1494 None
1495 }
1496 } else {
1497 let (updated, determined) = update_args!(self.n, ctx, event);
1498 if updated && determined {
1499 let a = iter::once(Value::String(self.tag.clone()))
1500 .chain(self.n.iter().map(|n| n.cached.clone().unwrap()));
1501 Some(Value::Array(ValArray::from_iter(a)))
1502 } else {
1503 None
1504 }
1505 }
1506 }
1507
1508 fn spec(&self) -> &Expr {
1509 &self.spec
1510 }
1511
1512 fn typ(&self) -> &Type {
1513 &self.typ
1514 }
1515
1516 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1517 self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1518 }
1519
1520 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1521 self.n.iter().for_each(|n| n.node.refs(f))
1522 }
1523
1524 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1525 for n in self.n.iter_mut() {
1526 wrap!(n.node, n.node.typecheck(ctx))?
1527 }
1528 match &self.typ {
1529 Type::Variant(ttag, typs) => {
1530 if ttag != &self.tag {
1531 bail!("expected {ttag} not {}", self.tag)
1532 }
1533 if self.n.len() != typs.len() {
1534 bail!("arity mismatch {} vs {}", self.n.len(), typs.len())
1535 }
1536 for (t, n) in typs.iter().zip(self.n.iter()) {
1537 wrap!(n.node, t.check_contains(&ctx.env, &n.node.typ()))?
1538 }
1539 }
1540 _ => bail!("BUG: unexpected variant rtype"),
1541 }
1542 Ok(())
1543 }
1544}
1545
1546#[derive(Debug)]
1547pub(crate) struct Struct<C: Ctx, E: UserEvent> {
1548 spec: Expr,
1549 typ: Type,
1550 names: Box<[ArcStr]>,
1551 n: Box<[Cached<C, E>]>,
1552}
1553
1554impl<C: Ctx, E: UserEvent> Struct<C, E> {
1555 pub(crate) fn compile(
1556 ctx: &mut ExecCtx<C, E>,
1557 spec: Expr,
1558 scope: &ModPath,
1559 top_id: ExprId,
1560 args: &[(ArcStr, Expr)],
1561 ) -> Result<Node<C, E>> {
1562 let mut names: SmallVec<[ArcStr; 8]> = smallvec![];
1563 let n = args.iter().map(|(n, s)| {
1564 names.push(n.clone());
1565 s
1566 });
1567 let n = n
1568 .map(|e| Ok(Cached::new(compile(ctx, e.clone(), scope, top_id)?)))
1569 .collect::<Result<Box<[_]>>>()?;
1570 let names = Box::from_iter(names);
1571 let typs =
1572 names.iter().zip(n.iter()).map(|(n, a)| (n.clone(), a.node.typ().clone()));
1573 let typ = Type::Struct(Arc::from_iter(typs));
1574 Ok(Box::new(Self { spec, typ, names, n }))
1575 }
1576}
1577
1578impl<C: Ctx, E: UserEvent> Update<C, E> for Struct<C, E> {
1579 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1580 if self.n.is_empty() && event.init {
1581 return Some(Value::Array(ValArray::from([])));
1582 }
1583 let (updated, determined) = update_args!(self.n, ctx, event);
1584 if updated && determined {
1585 let iter = self.names.iter().zip(self.n.iter()).map(|(name, n)| {
1586 let name = Value::String(name.clone());
1587 let v = n.cached.clone().unwrap();
1588 Value::Array(ValArray::from_iter_exact([name, v].into_iter()))
1589 });
1590 Some(Value::Array(ValArray::from_iter_exact(iter)))
1591 } else {
1592 None
1593 }
1594 }
1595
1596 fn spec(&self) -> &Expr {
1597 &self.spec
1598 }
1599
1600 fn typ(&self) -> &Type {
1601 &self.typ
1602 }
1603
1604 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1605 self.n.iter_mut().for_each(|n| n.node.delete(ctx))
1606 }
1607
1608 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1609 self.n.iter().for_each(|n| n.node.refs(f))
1610 }
1611
1612 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1613 for n in self.n.iter_mut() {
1614 wrap!(n.node, n.node.typecheck(ctx))?
1615 }
1616 match &self.typ {
1617 Type::Struct(typs) => {
1618 if self.n.len() != typs.len() {
1619 bail!(
1620 "struct length mismatch {} fields expected vs {}",
1621 typs.len(),
1622 self.n.len()
1623 )
1624 }
1625 for ((_, t), n) in typs.iter().zip(self.n.iter()) {
1626 t.check_contains(&ctx.env, &n.node.typ())?
1627 }
1628 }
1629 _ => bail!("BUG: expected a struct rtype"),
1630 }
1631 Ok(())
1632 }
1633}
1634
1635#[derive(Debug)]
1636pub(crate) struct StructWith<C: Ctx, E: UserEvent> {
1637 spec: Expr,
1638 typ: Type,
1639 source: Node<C, E>,
1640 current: Option<ValArray>,
1641 replace: Box<[(usize, Cached<C, E>)]>,
1642}
1643
1644impl<C: Ctx, E: UserEvent> StructWith<C, E> {
1645 pub(crate) fn compile(
1646 ctx: &mut ExecCtx<C, E>,
1647 spec: Expr,
1648 scope: &ModPath,
1649 top_id: ExprId,
1650 source: &Expr,
1651 replace: &[(ArcStr, Expr)],
1652 ) -> Result<Node<C, E>> {
1653 let source = compile(ctx, source.clone(), scope, top_id)?;
1654 let replace = replace
1655 .iter()
1656 .map(|(_, e)| Ok((0, Cached::new(compile(ctx, e.clone(), scope, top_id)?))))
1657 .collect::<Result<Box<[_]>>>()?;
1658 let typ = source.typ().clone();
1659 Ok(Box::new(Self { spec, typ, source, current: None, replace }))
1660 }
1661}
1662
1663impl<C: Ctx, E: UserEvent> Update<C, E> for StructWith<C, E> {
1664 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1665 let mut updated = self
1666 .source
1667 .update(ctx, event)
1668 .map(|v| match v {
1669 Value::Array(a) => {
1670 self.current = Some(a.clone());
1671 true
1672 }
1673 _ => false,
1674 })
1675 .unwrap_or(false);
1676 let mut determined = self.current.is_some();
1677 for (_, n) in self.replace.iter_mut() {
1678 updated |= n.update(ctx, event);
1679 determined &= n.cached.is_some();
1680 }
1681 if updated && determined {
1682 let mut si = 0;
1683 let iter =
1684 self.current.as_ref().unwrap().iter().enumerate().map(|(i, v)| match v {
1685 Value::Array(v) if v.len() == 2 => {
1686 if si < self.replace.len() && i == self.replace[si].0 {
1687 let r = self.replace[si].1.cached.clone().unwrap();
1688 si += 1;
1689 Value::Array(ValArray::from_iter_exact(
1690 [v[0].clone(), r].into_iter(),
1691 ))
1692 } else {
1693 Value::Array(v.clone())
1694 }
1695 }
1696 _ => v.clone(),
1697 });
1698 Some(Value::Array(ValArray::from_iter_exact(iter)))
1699 } else {
1700 None
1701 }
1702 }
1703
1704 fn spec(&self) -> &Expr {
1705 &self.spec
1706 }
1707
1708 fn typ(&self) -> &Type {
1709 &self.typ
1710 }
1711
1712 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1713 self.source.delete(ctx);
1714 self.replace.iter_mut().for_each(|(_, n)| n.node.delete(ctx))
1715 }
1716
1717 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1718 self.source.refs(f);
1719 self.replace.iter().for_each(|(_, n)| n.node.refs(f))
1720 }
1721
1722 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1723 wrap!(self.source, self.source.typecheck(ctx))?;
1724 let fields = match &self.spec.kind {
1725 ExprKind::StructWith { source: _, replace } => {
1726 replace.iter().map(|(n, _)| n.clone()).collect::<SmallVec<[ArcStr; 8]>>()
1727 }
1728 _ => bail!("BUG: miscompiled structwith"),
1729 };
1730 wrap!(
1731 self,
1732 self.source.typ().with_deref(|typ| match typ {
1733 Some(Type::Struct(flds)) => {
1734 for ((i, c), n) in self.replace.iter_mut().zip(fields.iter()) {
1735 let r = flds.iter().enumerate().find_map(|(i, (field, typ))| {
1736 if field == n {
1737 Some((i, typ))
1738 } else {
1739 None
1740 }
1741 });
1742 match r {
1743 None => bail!("struct has no field named {n}"),
1744 Some((j, typ)) => {
1745 typ.check_contains(&ctx.env, &c.node.typ())?;
1746 *i = j;
1747 }
1748 }
1749 }
1750 Ok(())
1751 }
1752 None => bail!("type must be known, annotations needed"),
1753 _ => bail!("expected a struct"),
1754 })
1755 )?;
1756 wrap!(self, self.typ.check_contains(&ctx.env, self.source.typ()))
1757 }
1758}
1759
1760macro_rules! compare_op {
1761 ($name:ident, $op:tt) => {
1762 #[derive(Debug)]
1763 pub(crate) struct $name<C: Ctx, E: UserEvent> {
1764 spec: Expr,
1765 typ: Type,
1766 lhs: Cached<C, E>,
1767 rhs: Cached<C, E>,
1768 }
1769
1770 impl<C: Ctx, E: UserEvent> $name<C, E> {
1771 pub(crate) fn compile(
1772 ctx: &mut ExecCtx<C, E>,
1773 spec: Expr,
1774 scope: &ModPath,
1775 top_id: ExprId,
1776 lhs: &Expr,
1777 rhs: &Expr
1778 ) -> Result<Node<C, E>> {
1779 let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1780 let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1781 let typ = Type::Primitive(Typ::Bool.into());
1782 Ok(Box::new(Self { spec, typ, lhs, rhs }))
1783 }
1784 }
1785
1786 impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1787 fn update(
1788 &mut self,
1789 ctx: &mut ExecCtx<C, E>,
1790 event: &mut Event<E>,
1791 ) -> Option<Value> {
1792 let lhs_up = self.lhs.update(ctx, event);
1793 let rhs_up = self.rhs.update(ctx, event);
1794 if lhs_up || rhs_up {
1795 return self.lhs.cached.as_ref().and_then(|lhs| {
1796 self.rhs.cached.as_ref().map(|rhs| (lhs $op rhs).into())
1797 })
1798 }
1799 None
1800 }
1801
1802 fn spec(&self) -> &Expr {
1803 &self.spec
1804 }
1805
1806 fn typ(&self) -> &Type {
1807 &self.typ
1808 }
1809
1810 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1811 self.lhs.node.refs(f);
1812 self.rhs.node.refs(f);
1813 }
1814
1815 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1816 self.lhs.node.delete(ctx);
1817 self.rhs.node.delete(ctx)
1818 }
1819
1820 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1821 wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
1822 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
1823 wrap!(
1824 self,
1825 self.lhs.node.typ().check_contains(&ctx.env, &self.rhs.node.typ())
1826 )?;
1827 wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1828 }
1829 }
1830 };
1831}
1832
1833compare_op!(Eq, ==);
1834compare_op!(Ne, !=);
1835compare_op!(Lt, <);
1836compare_op!(Gt, >);
1837compare_op!(Lte, <=);
1838compare_op!(Gte, >=);
1839
1840macro_rules! bool_op {
1841 ($name:ident, $op:tt) => {
1842 #[derive(Debug)]
1843 pub(crate) struct $name<C: Ctx, E: UserEvent> {
1844 spec: Expr,
1845 typ: Type,
1846 lhs: Cached<C, E>,
1847 rhs: Cached<C, E>,
1848 }
1849
1850 impl<C: Ctx, E: UserEvent> $name<C, E> {
1851 pub(crate) fn compile(
1852 ctx: &mut ExecCtx<C, E>,
1853 spec: Expr,
1854 scope: &ModPath,
1855 top_id: ExprId,
1856 lhs: &Expr,
1857 rhs: &Expr
1858 ) -> Result<Node<C, E>> {
1859 let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1860 let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1861 let typ = Type::Primitive(Typ::Bool.into());
1862 Ok(Box::new(Self { spec, typ, lhs, rhs }))
1863 }
1864 }
1865
1866 impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1867 fn update(
1868 &mut self,
1869 ctx: &mut ExecCtx<C, E>,
1870 event: &mut Event<E>,
1871 ) -> Option<Value> {
1872 let lhs_up = self.lhs.update(ctx, event);
1873 let rhs_up = self.rhs.update(ctx, event);
1874 if lhs_up || rhs_up {
1875 return match (self.lhs.cached.as_ref(), self.rhs.cached.as_ref()) {
1876 (Some(Value::Bool(b0)), Some(Value::Bool(b1))) => Some(Value::Bool(*b0 $op *b1)),
1877 (_, _) => None
1878 }
1879 }
1880 None
1881 }
1882
1883 fn spec(&self) -> &Expr {
1884 &self.spec
1885 }
1886
1887 fn typ(&self) -> &Type {
1888 &self.typ
1889 }
1890
1891 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1892 self.lhs.node.refs(f);
1893 self.rhs.node.refs(f);
1894 }
1895
1896 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1897 self.lhs.node.delete(ctx);
1898 self.rhs.node.delete(ctx)
1899 }
1900
1901 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1902 wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
1903 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
1904 let bt = Type::Primitive(Typ::Bool.into());
1905 wrap!(self.lhs.node, bt.check_contains(&ctx.env, self.lhs.node.typ()))?;
1906 wrap!(self.rhs.node, bt.check_contains(&ctx.env, self.rhs.node.typ()))?;
1907 wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1908 }
1909 }
1910 };
1911}
1912
1913bool_op!(And, &&);
1914bool_op!(Or, ||);
1915
1916#[derive(Debug)]
1917pub(crate) struct Not<C: Ctx, E: UserEvent> {
1918 spec: Expr,
1919 typ: Type,
1920 n: Node<C, E>,
1921}
1922
1923impl<C: Ctx, E: UserEvent> Not<C, E> {
1924 pub(crate) fn compile(
1925 ctx: &mut ExecCtx<C, E>,
1926 spec: Expr,
1927 scope: &ModPath,
1928 top_id: ExprId,
1929 n: &Expr,
1930 ) -> Result<Node<C, E>> {
1931 let n = compile(ctx, n.clone(), scope, top_id)?;
1932 let typ = Type::Primitive(Typ::Bool.into());
1933 Ok(Box::new(Self { spec, typ, n }))
1934 }
1935}
1936
1937impl<C: Ctx, E: UserEvent> Update<C, E> for Not<C, E> {
1938 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1939 self.n.update(ctx, event).and_then(|v| match v {
1940 Value::Bool(b) => Some(Value::Bool(!b)),
1941 _ => None,
1942 })
1943 }
1944
1945 fn spec(&self) -> &Expr {
1946 &self.spec
1947 }
1948
1949 fn typ(&self) -> &Type {
1950 &self.typ
1951 }
1952
1953 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
1954 self.n.refs(f);
1955 }
1956
1957 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
1958 self.n.delete(ctx);
1959 }
1960
1961 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
1962 wrap!(self.n, self.n.typecheck(ctx))?;
1963 let bt = Type::Primitive(Typ::Bool.into());
1964 wrap!(self.n, bt.check_contains(&ctx.env, self.n.typ()))?;
1965 wrap!(self, self.typ.check_contains(&ctx.env, &Type::boolean()))
1966 }
1967}
1968
1969macro_rules! arith_op {
1970 ($name:ident, $op:tt) => {
1971 #[derive(Debug)]
1972 pub(crate) struct $name<C: Ctx, E: UserEvent> {
1973 spec: Expr,
1974 typ: Type,
1975 lhs: Cached<C, E>,
1976 rhs: Cached<C, E>
1977 }
1978
1979 impl<C: Ctx, E: UserEvent> $name<C, E> {
1980 pub(crate) fn compile(
1981 ctx: &mut ExecCtx<C, E>,
1982 spec: Expr,
1983 scope: &ModPath,
1984 top_id: ExprId,
1985 lhs: &Expr,
1986 rhs: &Expr
1987 ) -> Result<Node<C, E>> {
1988 let lhs = Cached::new(compile(ctx, lhs.clone(), scope, top_id)?);
1989 let rhs = Cached::new(compile(ctx, rhs.clone(), scope, top_id)?);
1990 let typ = Type::empty_tvar();
1991 Ok(Box::new(Self { spec, typ, lhs, rhs }))
1992 }
1993 }
1994
1995 impl<C: Ctx, E: UserEvent> Update<C, E> for $name<C, E> {
1996 fn update(&mut self, ctx: &mut ExecCtx<C, E>, event: &mut Event<E>) -> Option<Value> {
1997 let lhs_up = self.lhs.update(ctx, event);
1998 let rhs_up = self.rhs.update(ctx, event);
1999 if lhs_up || rhs_up {
2000 return self.lhs.cached.as_ref().and_then(|lhs| {
2001 self.rhs.cached.as_ref().map(|rhs| (lhs.clone() $op rhs.clone()).into())
2002 })
2003 }
2004 None
2005 }
2006
2007 fn spec(&self) -> &Expr {
2008 &self.spec
2009 }
2010
2011 fn typ(&self) -> &Type {
2012 &self.typ
2013 }
2014
2015 fn refs<'a>(&'a self, f: &'a mut (dyn FnMut(BindId) + 'a)) {
2016 self.lhs.node.refs(f);
2017 self.rhs.node.refs(f);
2018 }
2019
2020 fn delete(&mut self, ctx: &mut ExecCtx<C, E>) {
2021 self.lhs.node.delete(ctx);
2022 self.rhs.node.delete(ctx);
2023 }
2024
2025 fn typecheck(&mut self, ctx: &mut ExecCtx<C, E>) -> Result<()> {
2026 wrap!(self.lhs.node, self.lhs.node.typecheck(ctx))?;
2027 wrap!(self.rhs.node, self.rhs.node.typecheck(ctx))?;
2028 let typ = Type::Primitive(Typ::number());
2029 let lhs = self.lhs.node.typ();
2030 let rhs = self.rhs.node.typ();
2031 wrap!(self.lhs.node, typ.check_contains(&ctx.env, lhs))?;
2032 wrap!(self.rhs.node, typ.check_contains(&ctx.env, rhs))?;
2033 wrap!(self,self.typ.check_contains(&ctx.env, &lhs.union(rhs)))
2034 }
2035 }
2036 }
2037}
2038
2039arith_op!(Add, +);
2040arith_op!(Sub, -);
2041arith_op!(Mul, *);
2042arith_op!(Div, /);