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