netidx_bscript/expr/
mod.rs

1use crate::typ::{TVar, Type};
2use anyhow::{anyhow, bail, Result};
3use arcstr::ArcStr;
4use combine::stream::position::SourcePosition;
5use compact_str::{format_compact, CompactString};
6use netidx::{
7    path::Path,
8    publisher::Typ,
9    subscriber::{Event, Subscriber, Value},
10    utils::{self, Either},
11};
12use regex::Regex;
13use serde::{
14    de::{self, Visitor},
15    Deserialize, Deserializer, Serialize, Serializer,
16};
17use smallvec::{smallvec, SmallVec};
18use std::{
19    borrow::Borrow,
20    cmp::{Ordering, PartialEq, PartialOrd},
21    fmt::{self, Display, Write},
22    future::Future,
23    ops::Deref,
24    path::PathBuf,
25    pin::Pin,
26    result,
27    str::FromStr,
28    sync::LazyLock,
29    time::Duration,
30};
31use triomphe::Arc;
32
33pub mod parser;
34#[cfg(test)]
35mod test;
36
37pub static VNAME: LazyLock<Regex> =
38    LazyLock::new(|| Regex::new("^[a-z][a-z0-9_]*$").unwrap());
39
40atomic_id!(ExprId);
41
42#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
43pub struct ModPath(pub Path);
44
45impl FromStr for ModPath {
46    type Err = anyhow::Error;
47
48    fn from_str(s: &str) -> result::Result<Self, Self::Err> {
49        parser::parse_modpath(s)
50    }
51}
52
53impl ModPath {
54    pub fn root() -> ModPath {
55        ModPath(Path::root())
56    }
57}
58
59impl Borrow<str> for ModPath {
60    fn borrow(&self) -> &str {
61        self.0.borrow()
62    }
63}
64
65impl Deref for ModPath {
66    type Target = Path;
67
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}
72
73impl Display for ModPath {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        let len = Path::levels(&self.0);
76        for (i, part) in Path::parts(&self.0).enumerate() {
77            write!(f, "{part}")?;
78            if i < len - 1 {
79                write!(f, "::")?
80            }
81        }
82        Ok(())
83    }
84}
85
86impl<A> FromIterator<A> for ModPath
87where
88    A: Borrow<str>,
89{
90    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
91        ModPath(Path::from_iter(iter))
92    }
93}
94
95impl<I, A> From<I> for ModPath
96where
97    A: Borrow<str>,
98    I: IntoIterator<Item = A>,
99{
100    fn from(value: I) -> Self {
101        ModPath::from_iter(value)
102    }
103}
104
105impl PartialEq<[&str]> for ModPath {
106    fn eq(&self, other: &[&str]) -> bool {
107        Path::levels(&self.0) == other.len()
108            && Path::parts(&self.0).zip(other.iter()).all(|(s0, s1)| s0 == *s1)
109    }
110}
111
112impl<const L: usize> PartialEq<[&str; L]> for ModPath {
113    fn eq(&self, other: &[&str; L]) -> bool {
114        Path::levels(&self.0) == L
115            && Path::parts(&self.0).zip(other.iter()).all(|(s0, s1)| s0 == *s1)
116    }
117}
118
119#[derive(Debug, Clone)]
120pub enum ModuleResolver {
121    Files(PathBuf),
122    Netidx { subscriber: Subscriber, base: Path, timeout: Option<Duration> },
123}
124
125impl ModuleResolver {
126    /// Parse a comma separated list of module resolvers. Netidx
127    /// resolvers are of the form, netidx:/path/in/netidx, and
128    /// filesystem resolvers are of the form file:/path/in/fs
129    ///
130    /// This format is intended to be used in an environment variable,
131    /// for example.
132    pub fn parse_env(
133        subscriber: Subscriber,
134        timeout: Option<Duration>,
135        s: &str,
136    ) -> Result<Vec<ModuleResolver>> {
137        let mut res = vec![];
138        for l in utils::split_escaped(s, '\\', ',') {
139            let l = l.trim();
140            if let Some(s) = l.strip_prefix("netidx:") {
141                let base = Path::from_str(s);
142                let r = Self::Netidx { subscriber: subscriber.clone(), timeout, base };
143                res.push(r);
144            } else if let Some(s) = l.strip_prefix("file:") {
145                let base = PathBuf::from_str(s)?;
146                let r = Self::Files(base);
147                res.push(r);
148            } else {
149                bail!("expected netidx: or file:")
150            }
151        }
152        Ok(res)
153    }
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
157pub enum StructurePattern {
158    Ignore,
159    Literal(Value),
160    Bind(ArcStr),
161    Slice {
162        all: Option<ArcStr>,
163        binds: Arc<[StructurePattern]>,
164    },
165    SlicePrefix {
166        all: Option<ArcStr>,
167        prefix: Arc<[StructurePattern]>,
168        tail: Option<ArcStr>,
169    },
170    SliceSuffix {
171        all: Option<ArcStr>,
172        head: Option<ArcStr>,
173        suffix: Arc<[StructurePattern]>,
174    },
175    Tuple {
176        all: Option<ArcStr>,
177        binds: Arc<[StructurePattern]>,
178    },
179    Variant {
180        all: Option<ArcStr>,
181        tag: ArcStr,
182        binds: Arc<[StructurePattern]>,
183    },
184    Struct {
185        exhaustive: bool,
186        all: Option<ArcStr>,
187        binds: Arc<[(ArcStr, StructurePattern)]>,
188    },
189}
190
191impl StructurePattern {
192    pub fn single_bind(&self) -> Option<&ArcStr> {
193        match self {
194            Self::Bind(s) => Some(s),
195            Self::Ignore
196            | Self::Literal(_)
197            | Self::Slice { .. }
198            | Self::SlicePrefix { .. }
199            | Self::SliceSuffix { .. }
200            | Self::Tuple { .. }
201            | Self::Struct { .. }
202            | Self::Variant { .. } => None,
203        }
204    }
205
206    pub fn with_names<'a>(&'a self, f: &mut impl FnMut(&'a ArcStr)) {
207        match self {
208            Self::Bind(n) => f(n),
209            Self::Ignore | Self::Literal(_) => (),
210            Self::Slice { all, binds } => {
211                if let Some(n) = all {
212                    f(n)
213                }
214                for t in binds.iter() {
215                    t.with_names(f)
216                }
217            }
218            Self::SlicePrefix { all, prefix, tail } => {
219                if let Some(n) = all {
220                    f(n)
221                }
222                if let Some(n) = tail {
223                    f(n)
224                }
225                for t in prefix.iter() {
226                    t.with_names(f)
227                }
228            }
229            Self::SliceSuffix { all, head, suffix } => {
230                if let Some(n) = all {
231                    f(n)
232                }
233                if let Some(n) = head {
234                    f(n)
235                }
236                for t in suffix.iter() {
237                    t.with_names(f)
238                }
239            }
240            Self::Tuple { all, binds } => {
241                if let Some(n) = all {
242                    f(n)
243                }
244                for t in binds.iter() {
245                    t.with_names(f)
246                }
247            }
248            Self::Variant { all, tag: _, binds } => {
249                if let Some(n) = all {
250                    f(n)
251                }
252                for t in binds.iter() {
253                    t.with_names(f)
254                }
255            }
256            Self::Struct { exhaustive: _, all, binds } => {
257                if let Some(n) = all {
258                    f(n)
259                }
260                for (_, t) in binds.iter() {
261                    t.with_names(f)
262                }
263            }
264        }
265    }
266
267    pub fn binds_uniq(&self) -> bool {
268        let mut names: SmallVec<[&ArcStr; 16]> = smallvec![];
269        self.with_names(&mut |s| names.push(s));
270        names.sort();
271        let len = names.len();
272        names.dedup();
273        names.len() == len
274    }
275
276    pub fn infer_type_predicate(&self) -> Type {
277        match self {
278            Self::Bind(_) | Self::Ignore => Type::empty_tvar(),
279            Self::Literal(v) => Type::Primitive(Typ::get(v).into()),
280            Self::Tuple { all: _, binds } => {
281                let a = binds.iter().map(|p| p.infer_type_predicate());
282                Type::Tuple(Arc::from_iter(a))
283            }
284            Self::Variant { all: _, tag, binds } => {
285                let a = binds.iter().map(|p| p.infer_type_predicate());
286                Type::Variant(tag.clone(), Arc::from_iter(a))
287            }
288            Self::Slice { all: _, binds }
289            | Self::SlicePrefix { all: _, prefix: binds, tail: _ }
290            | Self::SliceSuffix { all: _, head: _, suffix: binds } => {
291                let t = binds
292                    .iter()
293                    .fold(Type::Bottom, |t, p| t.union(&p.infer_type_predicate()));
294                Type::Array(Arc::new(t))
295            }
296            Self::Struct { all: _, exhaustive: _, binds } => {
297                let mut typs = binds
298                    .iter()
299                    .map(|(n, p)| (n.clone(), p.infer_type_predicate()))
300                    .collect::<SmallVec<[(ArcStr, Type); 8]>>();
301                typs.sort_by_key(|(n, _)| n.clone());
302                Type::Struct(Arc::from_iter(typs.into_iter()))
303            }
304        }
305    }
306}
307
308impl fmt::Display for StructurePattern {
309    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310        macro_rules! with_sep {
311            ($binds:expr) => {
312                for (i, b) in $binds.iter().enumerate() {
313                    write!(f, "{b}")?;
314                    if i < $binds.len() - 1 {
315                        write!(f, ", ")?
316                    }
317                }
318            };
319        }
320        match self {
321            StructurePattern::Ignore => write!(f, "_"),
322            StructurePattern::Literal(v) => write!(f, "{v}"),
323            StructurePattern::Bind(n) => write!(f, "{n}"),
324            StructurePattern::Slice { all, binds } => {
325                if let Some(all) = all {
326                    write!(f, "{all}@ ")?
327                }
328                write!(f, "[")?;
329                with_sep!(binds);
330                write!(f, "]")
331            }
332            StructurePattern::SlicePrefix { all, prefix, tail } => {
333                if let Some(all) = all {
334                    write!(f, "{all}@ ")?
335                }
336                write!(f, "[")?;
337                for b in prefix.iter() {
338                    write!(f, "{b}, ")?
339                }
340                match tail {
341                    None => write!(f, "..]"),
342                    Some(name) => write!(f, "{name}..]"),
343                }
344            }
345            StructurePattern::SliceSuffix { all, head, suffix } => {
346                if let Some(all) = all {
347                    write!(f, "{all}@ ")?
348                }
349                write!(f, "[")?;
350                match head {
351                    None => write!(f, ".., ")?,
352                    Some(name) => write!(f, "{name}.., ")?,
353                }
354                with_sep!(suffix);
355                write!(f, "]")
356            }
357            StructurePattern::Tuple { all, binds } => {
358                if let Some(all) = all {
359                    write!(f, "{all}@ ")?
360                }
361                write!(f, "(")?;
362                with_sep!(binds);
363                write!(f, ")")
364            }
365            StructurePattern::Variant { all, tag, binds } if binds.len() == 0 => {
366                if let Some(all) = all {
367                    write!(f, "{all}@")?
368                }
369                write!(f, "`{tag}")
370            }
371            StructurePattern::Variant { all, tag, binds } => {
372                if let Some(all) = all {
373                    write!(f, "{all}@")?
374                }
375                write!(f, "`{tag}(")?;
376                with_sep!(binds);
377                write!(f, ")")
378            }
379            StructurePattern::Struct { exhaustive, all, binds } => {
380                if let Some(all) = all {
381                    write!(f, "{all}@ ")?
382                }
383                write!(f, "{{")?;
384                for (i, (name, pat)) in binds.iter().enumerate() {
385                    write!(f, "{name}: {pat}")?;
386                    if !exhaustive || i < binds.len() - 1 {
387                        write!(f, ", ")?
388                    }
389                }
390                if !exhaustive {
391                    write!(f, "..")?
392                }
393                write!(f, "}}")
394            }
395        }
396    }
397}
398
399#[derive(Debug, Clone, PartialEq, PartialOrd)]
400pub struct Pattern {
401    pub type_predicate: Option<Type>,
402    pub structure_predicate: StructurePattern,
403    pub guard: Option<Expr>,
404}
405
406#[derive(Debug, Clone, PartialEq, PartialOrd)]
407pub struct Arg {
408    pub labeled: Option<Option<Expr>>,
409    pub pattern: StructurePattern,
410    pub constraint: Option<Type>,
411}
412
413#[derive(Debug, Clone, PartialEq, PartialOrd)]
414pub enum ModuleKind {
415    Inline(Arc<[Expr]>),
416    Resolved(Origin),
417    Unresolved,
418}
419
420#[derive(Debug, Clone, PartialEq, PartialOrd)]
421pub struct Bind {
422    pub doc: Option<ArcStr>,
423    pub pattern: StructurePattern,
424    pub typ: Option<Type>,
425    pub export: bool,
426    pub value: Expr,
427}
428
429#[derive(Debug, Clone, PartialEq, PartialOrd)]
430pub struct Lambda {
431    pub args: Arc<[Arg]>,
432    pub vargs: Option<Option<Type>>,
433    pub rtype: Option<Type>,
434    pub constraints: Arc<[(TVar, Type)]>,
435    pub body: Either<Expr, ArcStr>,
436}
437
438#[derive(Debug, Clone, PartialEq, PartialOrd)]
439pub enum ExprKind {
440    Constant(Value),
441    Module { name: ArcStr, export: bool, value: ModuleKind },
442    Do { exprs: Arc<[Expr]> },
443    Use { name: ModPath },
444    Bind(Arc<Bind>),
445    Ref { name: ModPath },
446    Connect { name: ModPath, value: Arc<Expr> },
447    StringInterpolate { args: Arc<[Expr]> },
448    StructRef { source: Arc<Expr>, field: ArcStr },
449    TupleRef { source: Arc<Expr>, field: usize },
450    ArrayRef { source: Arc<Expr>, i: Arc<Expr> },
451    ArraySlice { source: Arc<Expr>, start: Option<Arc<Expr>>, end: Option<Arc<Expr>> },
452    StructWith { source: Arc<Expr>, replace: Arc<[(ArcStr, Expr)]> },
453    Lambda(Arc<Lambda>),
454    TypeDef { name: ArcStr, params: Arc<[(TVar, Option<Type>)]>, typ: Type },
455    TypeCast { expr: Arc<Expr>, typ: Type },
456    Apply { args: Arc<[(Option<ArcStr>, Expr)]>, function: Arc<Expr> },
457    Any { args: Arc<[Expr]> },
458    Array { args: Arc<[Expr]> },
459    Tuple { args: Arc<[Expr]> },
460    Variant { tag: ArcStr, args: Arc<[Expr]> },
461    Struct { args: Arc<[(ArcStr, Expr)]> },
462    Select { arg: Arc<Expr>, arms: Arc<[(Pattern, Expr)]> },
463    Qop(Arc<Expr>),
464    ByRef(Arc<Expr>),
465    Deref(Arc<Expr>),
466    Eq { lhs: Arc<Expr>, rhs: Arc<Expr> },
467    Ne { lhs: Arc<Expr>, rhs: Arc<Expr> },
468    Lt { lhs: Arc<Expr>, rhs: Arc<Expr> },
469    Gt { lhs: Arc<Expr>, rhs: Arc<Expr> },
470    Lte { lhs: Arc<Expr>, rhs: Arc<Expr> },
471    Gte { lhs: Arc<Expr>, rhs: Arc<Expr> },
472    And { lhs: Arc<Expr>, rhs: Arc<Expr> },
473    Or { lhs: Arc<Expr>, rhs: Arc<Expr> },
474    Not { expr: Arc<Expr> },
475    Add { lhs: Arc<Expr>, rhs: Arc<Expr> },
476    Sub { lhs: Arc<Expr>, rhs: Arc<Expr> },
477    Mul { lhs: Arc<Expr>, rhs: Arc<Expr> },
478    Div { lhs: Arc<Expr>, rhs: Arc<Expr> },
479}
480
481impl ExprKind {
482    pub fn to_expr(self, pos: SourcePosition) -> Expr {
483        Expr { id: ExprId::new(), pos, kind: self }
484    }
485
486    /// does not provide any position information or comment
487    pub fn to_expr_nopos(self) -> Expr {
488        Expr { id: ExprId::new(), pos: Default::default(), kind: self }
489    }
490
491    pub fn to_string_pretty(&self, col_limit: usize) -> String {
492        let mut buf = String::new();
493        self.pretty_print(0, col_limit, true, &mut buf).unwrap();
494        buf
495    }
496
497    fn pretty_print(
498        &self,
499        indent: usize,
500        limit: usize,
501        newline: bool,
502        buf: &mut String,
503    ) -> fmt::Result {
504        macro_rules! kill_newline {
505            ($buf:expr) => {
506                if let Some('\n') = $buf.chars().next_back() {
507                    $buf.pop();
508                }
509            };
510        }
511        macro_rules! try_single_line {
512            ($trunc:ident) => {{
513                let len = buf.len();
514                let (start, indent) = if newline {
515                    push_indent(indent, buf);
516                    (len, indent)
517                } else {
518                    (buf.rfind('\n').unwrap_or(0), 0)
519                };
520                writeln!(buf, "{}", self)?;
521                if buf.len() - start <= limit {
522                    return Ok(());
523                } else {
524                    if $trunc {
525                        buf.truncate(len + indent)
526                    }
527                    len + indent
528                }
529            }};
530        }
531        macro_rules! binop {
532            ($sep:literal, $lhs:expr, $rhs:expr) => {{
533                try_single_line!(true);
534                write!(buf, "(")?;
535                writeln!(buf, "{} {}", $lhs, $sep)?;
536                $rhs.kind.pretty_print(indent, limit, true, buf)?;
537                write!(buf, ")")
538            }};
539        }
540        let mut tbuf = CompactString::new("");
541        macro_rules! typ {
542            ($typ:expr) => {{
543                match $typ {
544                    None => "",
545                    Some(typ) => {
546                        tbuf.clear();
547                        write!(tbuf, ": {typ}")?;
548                        tbuf.as_str()
549                    }
550                }
551            }};
552        }
553        fn push_indent(indent: usize, buf: &mut String) {
554            buf.extend((0..indent).into_iter().map(|_| ' '));
555        }
556        fn pretty_print_exprs_int<'a, A, F: Fn(&'a A) -> &'a Expr>(
557            indent: usize,
558            limit: usize,
559            buf: &mut String,
560            exprs: &'a [A],
561            open: &str,
562            close: &str,
563            sep: &str,
564            f: F,
565        ) -> fmt::Result {
566            writeln!(buf, "{}", open)?;
567            for i in 0..exprs.len() {
568                f(&exprs[i]).kind.pretty_print(indent + 2, limit, true, buf)?;
569                if i < exprs.len() - 1 {
570                    kill_newline!(buf);
571                    writeln!(buf, "{}", sep)?
572                }
573            }
574            push_indent(indent, buf);
575            writeln!(buf, "{}", close)
576        }
577        fn pretty_print_exprs(
578            indent: usize,
579            limit: usize,
580            buf: &mut String,
581            exprs: &[Expr],
582            open: &str,
583            close: &str,
584            sep: &str,
585        ) -> fmt::Result {
586            pretty_print_exprs_int(indent, limit, buf, exprs, open, close, sep, |a| a)
587        }
588        let exp = |export| if export { "pub " } else { "" };
589        match self {
590            ExprKind::Constant(_)
591            | ExprKind::Use { .. }
592            | ExprKind::Ref { .. }
593            | ExprKind::StructRef { .. }
594            | ExprKind::TupleRef { .. }
595            | ExprKind::TypeDef { .. }
596            | ExprKind::ArrayRef { .. }
597            | ExprKind::ArraySlice { .. }
598            | ExprKind::StringInterpolate { .. }
599            | ExprKind::Module {
600                name: _,
601                export: _,
602                value: ModuleKind::Unresolved | ModuleKind::Resolved(_),
603            } => {
604                if newline {
605                    push_indent(indent, buf);
606                }
607                writeln!(buf, "{self}")
608            }
609            ExprKind::Bind(b) => {
610                let Bind { doc, pattern, typ, export, value } = &**b;
611                try_single_line!(true);
612                if let Some(doc) = doc {
613                    if doc == "" {
614                        writeln!(buf, "///")?;
615                    } else {
616                        for line in doc.lines() {
617                            writeln!(buf, "///{line}")?;
618                        }
619                    }
620                }
621                writeln!(buf, "{}let {pattern}{} = ", exp(*export), typ!(typ))?;
622                value.kind.pretty_print(indent + 2, limit, false, buf)
623            }
624            ExprKind::StructWith { source, replace } => {
625                try_single_line!(true);
626                match &source.kind {
627                    ExprKind::Ref { .. }
628                    | ExprKind::Do { .. }
629                    | ExprKind::Apply { .. } => writeln!(buf, "{{ {source} with")?,
630                    _ => writeln!(buf, "{{ ({source}) with")?,
631                }
632                let indent = indent + 2;
633                for (i, (name, e)) in replace.iter().enumerate() {
634                    push_indent(indent, buf);
635                    write!(buf, "{name}: ")?;
636                    e.kind.pretty_print(indent + 2, limit, false, buf)?;
637                    if i < replace.len() - 1 {
638                        kill_newline!(buf);
639                        writeln!(buf, ",")?
640                    }
641                }
642                writeln!(buf, "}}")
643            }
644            ExprKind::Module { name, export, value: ModuleKind::Inline(exprs) } => {
645                try_single_line!(true);
646                write!(buf, "{}mod {name} ", exp(*export))?;
647                pretty_print_exprs(indent, limit, buf, exprs, "{", "}", ";")
648            }
649            ExprKind::Do { exprs } => {
650                try_single_line!(true);
651                pretty_print_exprs(indent, limit, buf, exprs, "{", "}", ";")
652            }
653            ExprKind::Connect { name, value } => {
654                try_single_line!(true);
655                writeln!(buf, "{name} <- ")?;
656                value.kind.pretty_print(indent + 2, limit, false, buf)
657            }
658            ExprKind::TypeCast { expr, typ } => {
659                try_single_line!(true);
660                writeln!(buf, "cast<{typ}>(")?;
661                expr.kind.pretty_print(indent + 2, limit, true, buf)?;
662                writeln!(buf, ")")
663            }
664            ExprKind::Array { args } => {
665                try_single_line!(true);
666                pretty_print_exprs(indent, limit, buf, args, "[", "]", ",")
667            }
668            ExprKind::Any { args } => {
669                try_single_line!(true);
670                write!(buf, "any")?;
671                pretty_print_exprs(indent, limit, buf, args, "(", ")", ",")
672            }
673            ExprKind::Tuple { args } => {
674                try_single_line!(true);
675                pretty_print_exprs(indent, limit, buf, args, "(", ")", ",")
676            }
677            ExprKind::Variant { tag: _, args } if args.len() == 0 => {
678                if newline {
679                    push_indent(indent, buf)
680                }
681                write!(buf, "{self}")
682            }
683            ExprKind::Variant { tag, args } => {
684                try_single_line!(true);
685                write!(buf, "`{tag}")?;
686                pretty_print_exprs(indent, limit, buf, args, "(", ")", ",")
687            }
688            ExprKind::Struct { args } => {
689                try_single_line!(true);
690                writeln!(buf, "{{")?;
691                for (i, (n, e)) in args.iter().enumerate() {
692                    push_indent(indent + 2, buf);
693                    write!(buf, "{n}: ")?;
694                    e.kind.pretty_print(indent + 2, limit, false, buf)?;
695                    if i < args.len() - 1 {
696                        kill_newline!(buf);
697                        writeln!(buf, ", ")?
698                    }
699                }
700                push_indent(indent, buf);
701                writeln!(buf, "}}")
702            }
703            ExprKind::Qop(e) => {
704                try_single_line!(true);
705                e.kind.pretty_print(indent, limit, true, buf)?;
706                kill_newline!(buf);
707                writeln!(buf, "?")
708            }
709            ExprKind::Apply { function, args } => {
710                try_single_line!(true);
711                match &function.kind {
712                    ExprKind::Ref { .. } | ExprKind::Do { .. } => {
713                        function.kind.pretty_print(indent, limit, true, buf)?
714                    }
715                    e => {
716                        write!(buf, "(")?;
717                        e.pretty_print(indent, limit, true, buf)?;
718                        kill_newline!(buf);
719                        write!(buf, ")")?;
720                    }
721                }
722                kill_newline!(buf);
723                writeln!(buf, "(")?;
724                for i in 0..args.len() {
725                    match &args[i].0 {
726                        None => {
727                            args[i].1.kind.pretty_print(indent + 2, limit, true, buf)?
728                        }
729                        Some(name) => match &args[i].1.kind {
730                            ExprKind::Ref { name: n }
731                                if Path::dirname(&n.0).is_none()
732                                    && Path::basename(&n.0) == Some(name.as_str()) =>
733                            {
734                                writeln!(buf, "#{name}")?
735                            }
736                            _ => {
737                                write!(buf, "#{name}: ")?;
738                                args[i].1.kind.pretty_print(
739                                    indent + 2,
740                                    limit,
741                                    false,
742                                    buf,
743                                )?
744                            }
745                        },
746                    }
747                    if i < args.len() - 1 {
748                        kill_newline!(buf);
749                        writeln!(buf, ",")?
750                    }
751                }
752                writeln!(buf, ")")
753            }
754            ExprKind::Lambda(l) => {
755                let Lambda { args, vargs, rtype, constraints, body } = &**l;
756                try_single_line!(true);
757                for (i, (tvar, typ)) in constraints.iter().enumerate() {
758                    write!(buf, "{tvar}: {typ}")?;
759                    if i < constraints.len() - 1 {
760                        write!(buf, ", ")?;
761                    }
762                }
763                write!(buf, "|")?;
764                for (i, a) in args.iter().enumerate() {
765                    match &a.labeled {
766                        None => {
767                            write!(buf, "{}", a.pattern)?;
768                            buf.push_str(typ!(&a.constraint));
769                        }
770                        Some(def) => {
771                            write!(buf, "#{}", a.pattern)?;
772                            buf.push_str(typ!(&a.constraint));
773                            if let Some(def) = def {
774                                write!(buf, " = {def}")?;
775                            }
776                        }
777                    }
778                    if vargs.is_some() || i < args.len() - 1 {
779                        write!(buf, ", ")?
780                    }
781                }
782                if let Some(typ) = vargs {
783                    write!(buf, "@args{}", typ!(typ))?;
784                }
785                write!(buf, "| ")?;
786                if let Some(t) = rtype {
787                    write!(buf, "-> {t} ")?
788                }
789                match body {
790                    Either::Right(builtin) => {
791                        writeln!(buf, "'{builtin}")
792                    }
793                    Either::Left(body) => match &body.kind {
794                        ExprKind::Do { exprs } => {
795                            pretty_print_exprs(indent, limit, buf, exprs, "{", "}", ";")
796                        }
797                        _ => body.kind.pretty_print(indent, limit, false, buf),
798                    },
799                }
800            }
801            ExprKind::Eq { lhs, rhs } => binop!("==", lhs, rhs),
802            ExprKind::Ne { lhs, rhs } => binop!("!=", lhs, rhs),
803            ExprKind::Lt { lhs, rhs } => binop!("<", lhs, rhs),
804            ExprKind::Gt { lhs, rhs } => binop!(">", lhs, rhs),
805            ExprKind::Lte { lhs, rhs } => binop!("<=", lhs, rhs),
806            ExprKind::Gte { lhs, rhs } => binop!(">=", lhs, rhs),
807            ExprKind::And { lhs, rhs } => binop!("&&", lhs, rhs),
808            ExprKind::Or { lhs, rhs } => binop!("||", lhs, rhs),
809            ExprKind::Add { lhs, rhs } => binop!("+", lhs, rhs),
810            ExprKind::Sub { lhs, rhs } => binop!("-", lhs, rhs),
811            ExprKind::Mul { lhs, rhs } => binop!("*", lhs, rhs),
812            ExprKind::Div { lhs, rhs } => binop!("/", lhs, rhs),
813            ExprKind::Not { expr } => {
814                try_single_line!(true);
815                match &expr.kind {
816                    ExprKind::Do { exprs } => {
817                        pretty_print_exprs(indent, limit, buf, exprs, "!{", "}", ";")
818                    }
819                    _ => {
820                        writeln!(buf, "!(")?;
821                        expr.kind.pretty_print(indent + 2, limit, true, buf)?;
822                        push_indent(indent, buf);
823                        writeln!(buf, ")")
824                    }
825                }
826            }
827            ExprKind::ByRef(e) => {
828                try_single_line!(true);
829                write!(buf, "&")?;
830                e.kind.pretty_print(indent + 2, limit, false, buf)
831            }
832            ExprKind::Deref(e) => {
833                try_single_line!(true);
834                write!(buf, "*")?;
835                e.kind.pretty_print(indent + 2, limit, false, buf)
836            }
837            ExprKind::Select { arg, arms } => {
838                try_single_line!(true);
839                write!(buf, "select ")?;
840                arg.kind.pretty_print(indent, limit, false, buf)?;
841                kill_newline!(buf);
842                writeln!(buf, " {{")?;
843                for (i, (pat, expr)) in arms.iter().enumerate() {
844                    if let Some(tp) = &pat.type_predicate {
845                        write!(buf, "{tp} as ")?;
846                    }
847                    write!(buf, "{} ", pat.structure_predicate)?;
848                    if let Some(guard) = &pat.guard {
849                        write!(buf, "if ")?;
850                        guard.kind.pretty_print(indent + 2, limit, false, buf)?;
851                        kill_newline!(buf);
852                        write!(buf, " ")?;
853                    }
854                    write!(buf, "=> ")?;
855                    if let ExprKind::Do { exprs } = &expr.kind {
856                        let term = if i < arms.len() - 1 { "}," } else { "}" };
857                        pretty_print_exprs(
858                            indent + 2,
859                            limit,
860                            buf,
861                            exprs,
862                            "{",
863                            term,
864                            ";",
865                        )?;
866                    } else if i < arms.len() - 1 {
867                        expr.kind.pretty_print(indent + 2, limit, false, buf)?;
868                        kill_newline!(buf);
869                        writeln!(buf, ",")?
870                    } else {
871                        expr.kind.pretty_print(indent, limit, false, buf)?;
872                    }
873                }
874                push_indent(indent, buf);
875                writeln!(buf, "}}")
876            }
877        }
878    }
879}
880
881impl fmt::Display for ExprKind {
882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
883        fn write_binop(
884            f: &mut fmt::Formatter,
885            op: &str,
886            lhs: &Expr,
887            rhs: &Expr,
888        ) -> fmt::Result {
889            write!(f, "(")?;
890            write!(f, "{lhs} {op} {rhs}")?;
891            write!(f, ")")
892        }
893        fn print_exprs(
894            f: &mut fmt::Formatter,
895            exprs: &[Expr],
896            open: &str,
897            close: &str,
898            sep: &str,
899        ) -> fmt::Result {
900            write!(f, "{open}")?;
901            for i in 0..exprs.len() {
902                write!(f, "{}", &exprs[i])?;
903                if i < exprs.len() - 1 {
904                    write!(f, "{sep}")?
905                }
906            }
907            write!(f, "{close}")
908        }
909        let mut tbuf = CompactString::new("");
910        macro_rules! typ {
911            ($typ:expr) => {{
912                match $typ {
913                    None => "",
914                    Some(typ) => {
915                        tbuf.clear();
916                        write!(tbuf, ": {typ}")?;
917                        tbuf.as_str()
918                    }
919                }
920            }};
921        }
922        let exp = |export| if export { "pub " } else { "" };
923        match self {
924            ExprKind::Constant(v) => v.fmt_ext(f, &parser::BSCRIPT_ESC, true),
925            ExprKind::Bind(b) => {
926                let Bind { doc, pattern, typ, export, value } = &**b;
927                if let Some(doc) = doc {
928                    if doc == "" {
929                        writeln!(f, "///")?
930                    } else {
931                        for line in doc.lines() {
932                            writeln!(f, "///{line}")?
933                        }
934                    }
935                }
936                write!(f, "{}let {pattern}{} = {value}", exp(*export), typ!(typ))
937            }
938            ExprKind::StructWith { source, replace } => {
939                match &source.kind {
940                    ExprKind::Ref { .. }
941                    | ExprKind::Do { .. }
942                    | ExprKind::Apply { .. } => write!(f, "{{ {source} with ")?,
943                    _ => write!(f, "{{ ({source}) with ")?,
944                }
945                for (i, (name, e)) in replace.iter().enumerate() {
946                    write!(f, "{name}: {e}")?;
947                    if i < replace.len() - 1 {
948                        write!(f, ", ")?
949                    }
950                }
951                write!(f, " }}")
952            }
953            ExprKind::Connect { name, value } => write!(f, "{name} <- {value}"),
954            ExprKind::Use { name } => {
955                write!(f, "use {name}")
956            }
957            ExprKind::Ref { name } => {
958                write!(f, "{name}")
959            }
960            ExprKind::StructRef { source, field } => match &source.kind {
961                ExprKind::Do { .. } | ExprKind::Ref { .. } | ExprKind::Apply { .. } => {
962                    write!(f, "{source}.{field}")
963                }
964                source => write!(f, "({source}).{field}"),
965            },
966            ExprKind::TupleRef { source, field } => match &source.kind {
967                ExprKind::Do { .. } | ExprKind::Ref { .. } | ExprKind::Apply { .. } => {
968                    write!(f, "{source}.{field}")
969                }
970                source => write!(f, "({source}).{field}"),
971            },
972            ExprKind::Module { name, export, value } => {
973                write!(f, "{}mod {name}", exp(*export))?;
974                match value {
975                    ModuleKind::Resolved(_) | ModuleKind::Unresolved => write!(f, ";"),
976                    ModuleKind::Inline(exprs) => print_exprs(f, &**exprs, "{", "}", "; "),
977                }
978            }
979            ExprKind::TypeCast { expr, typ } => write!(f, "cast<{typ}>({expr})"),
980            ExprKind::TypeDef { name, params, typ } => {
981                write!(f, "type {name}")?;
982                if !params.is_empty() {
983                    write!(f, "<")?;
984                    for (i, (tv, ct)) in params.iter().enumerate() {
985                        write!(f, "{tv}")?;
986                        if let Some(ct) = ct {
987                            write!(f, ": {ct}")?;
988                        }
989                        if i < params.len() - 1 {
990                            write!(f, ", ")?;
991                        }
992                    }
993                    write!(f, ">")?;
994                }
995                write!(f, " = {typ}")
996            }
997            ExprKind::Do { exprs } => print_exprs(f, &**exprs, "{", "}", "; "),
998            ExprKind::Lambda(l) => {
999                let Lambda { args, vargs, rtype, constraints, body } = &**l;
1000                for (i, (tvar, typ)) in constraints.iter().enumerate() {
1001                    write!(f, "{tvar}: {typ}")?;
1002                    if i < constraints.len() - 1 {
1003                        write!(f, ", ")?;
1004                    }
1005                }
1006                write!(f, "|")?;
1007                for (i, a) in args.iter().enumerate() {
1008                    match &a.labeled {
1009                        None => {
1010                            write!(f, "{}", a.pattern)?;
1011                            write!(f, "{}", typ!(&a.constraint))?;
1012                        }
1013                        Some(def) => {
1014                            write!(f, "#{}", a.pattern)?;
1015                            write!(f, "{}", typ!(&a.constraint))?;
1016                            if let Some(def) = def {
1017                                write!(f, " = {def}")?;
1018                            }
1019                        }
1020                    }
1021                    if vargs.is_some() || i < args.len() - 1 {
1022                        write!(f, ", ")?
1023                    }
1024                }
1025                if let Some(typ) = vargs {
1026                    write!(f, "@args{}", typ!(typ))?;
1027                }
1028                write!(f, "| ")?;
1029                if let Some(t) = rtype {
1030                    write!(f, "-> {t} ")?
1031                }
1032                match body {
1033                    Either::Right(builtin) => write!(f, "'{builtin}"),
1034                    Either::Left(body) => write!(f, "{body}"),
1035                }
1036            }
1037            ExprKind::Array { args } => print_exprs(f, args, "[", "]", ", "),
1038            ExprKind::Any { args } => {
1039                write!(f, "any")?;
1040                print_exprs(f, args, "(", ")", ", ")
1041            }
1042            ExprKind::Tuple { args } => print_exprs(f, args, "(", ")", ", "),
1043            ExprKind::Variant { tag, args } if args.len() == 0 => {
1044                write!(f, "`{tag}")
1045            }
1046            ExprKind::Variant { tag, args } => {
1047                write!(f, "`{tag}")?;
1048                print_exprs(f, args, "(", ")", ", ")
1049            }
1050            ExprKind::Struct { args } => {
1051                write!(f, "{{ ")?;
1052                for (i, (n, e)) in args.iter().enumerate() {
1053                    write!(f, "{n}: {e}")?;
1054                    if i < args.len() - 1 {
1055                        write!(f, ", ")?
1056                    }
1057                }
1058                write!(f, " }}")
1059            }
1060            ExprKind::Qop(e) => write!(f, "{}?", e),
1061            ExprKind::StringInterpolate { args } => {
1062                write!(f, "\"")?;
1063                for s in args.iter() {
1064                    match &s.kind {
1065                        ExprKind::Constant(Value::String(s)) if s.len() > 0 => {
1066                            let es = utils::escape(&*s, '\\', &parser::BSCRIPT_ESC);
1067                            write!(f, "{es}",)?;
1068                        }
1069                        s => {
1070                            write!(f, "[{s}]")?;
1071                        }
1072                    }
1073                }
1074                write!(f, "\"")
1075            }
1076            ExprKind::ArrayRef { source, i } => match &source.kind {
1077                ExprKind::Ref { .. } | ExprKind::Do { .. } | ExprKind::Apply { .. } => {
1078                    write!(f, "{}[{}]", source, i)
1079                }
1080                _ => write!(f, "({})[{}]", &source, &i),
1081            },
1082            ExprKind::ArraySlice { source, start, end } => {
1083                let s = match start.as_ref() {
1084                    None => "",
1085                    Some(e) => &format_compact!("{e}"),
1086                };
1087                let e = match &end.as_ref() {
1088                    None => "",
1089                    Some(e) => &format_compact!("{e}"),
1090                };
1091                match &source.kind {
1092                    ExprKind::Ref { .. }
1093                    | ExprKind::Do { .. }
1094                    | ExprKind::Apply { .. } => {
1095                        write!(f, "{}[{}..{}]", source, s, e)
1096                    }
1097                    _ => write!(f, "({})[{}..{}]", source, s, e),
1098                }
1099            }
1100            ExprKind::Apply { args, function } => {
1101                match &function.kind {
1102                    ExprKind::Ref { name: _ } | ExprKind::Do { exprs: _ } => {
1103                        write!(f, "{function}")?
1104                    }
1105                    function => write!(f, "({function})")?,
1106                }
1107                write!(f, "(")?;
1108                for i in 0..args.len() {
1109                    match &args[i].0 {
1110                        None => write!(f, "{}", &args[i].1)?,
1111                        Some(name) => match &args[i].1.kind {
1112                            ExprKind::Ref { name: n }
1113                                if Path::dirname(&n.0).is_none()
1114                                    && Path::basename(&n.0) == Some(name.as_str()) =>
1115                            {
1116                                write!(f, "#{name}")?
1117                            }
1118                            _ => write!(f, "#{name}: {}", &args[i].1)?,
1119                        },
1120                    }
1121                    if i < args.len() - 1 {
1122                        write!(f, ", ")?
1123                    }
1124                }
1125                write!(f, ")")
1126            }
1127            ExprKind::Select { arg, arms } => {
1128                write!(f, "select {arg} {{")?;
1129                for (i, (pat, rhs)) in arms.iter().enumerate() {
1130                    if let Some(tp) = &pat.type_predicate {
1131                        write!(f, "{tp} as ")?;
1132                    }
1133                    write!(f, "{} ", pat.structure_predicate)?;
1134                    if let Some(guard) = &pat.guard {
1135                        write!(f, "if {guard} ")?;
1136                    }
1137                    write!(f, "=> {rhs}")?;
1138                    if i < arms.len() - 1 {
1139                        write!(f, ", ")?
1140                    }
1141                }
1142                write!(f, "}}")
1143            }
1144            ExprKind::Eq { lhs, rhs } => write_binop(f, "==", lhs, rhs),
1145            ExprKind::Ne { lhs, rhs } => write_binop(f, "!=", lhs, rhs),
1146            ExprKind::Gt { lhs, rhs } => write_binop(f, ">", lhs, rhs),
1147            ExprKind::Lt { lhs, rhs } => write_binop(f, "<", lhs, rhs),
1148            ExprKind::Gte { lhs, rhs } => write_binop(f, ">=", lhs, rhs),
1149            ExprKind::Lte { lhs, rhs } => write_binop(f, "<=", lhs, rhs),
1150            ExprKind::And { lhs, rhs } => write_binop(f, "&&", lhs, rhs),
1151            ExprKind::Or { lhs, rhs } => write_binop(f, "||", lhs, rhs),
1152            ExprKind::Add { lhs, rhs } => write_binop(f, "+", lhs, rhs),
1153            ExprKind::Sub { lhs, rhs } => write_binop(f, "-", lhs, rhs),
1154            ExprKind::Mul { lhs, rhs } => write_binop(f, "*", lhs, rhs),
1155            ExprKind::Div { lhs, rhs } => write_binop(f, "/", lhs, rhs),
1156            ExprKind::ByRef(e) => write!(f, "&{e}"),
1157            ExprKind::Deref(e) => write!(f, "*{e}"),
1158            ExprKind::Not { expr } => {
1159                write!(f, "(!{expr})")
1160            }
1161        }
1162    }
1163}
1164
1165#[derive(Debug, Clone)]
1166pub struct Expr {
1167    pub id: ExprId,
1168    pub pos: SourcePosition,
1169    pub kind: ExprKind,
1170}
1171
1172impl PartialOrd for Expr {
1173    fn partial_cmp(&self, rhs: &Expr) -> Option<Ordering> {
1174        self.kind.partial_cmp(&rhs.kind)
1175    }
1176}
1177
1178impl PartialEq for Expr {
1179    fn eq(&self, rhs: &Expr) -> bool {
1180        self.kind.eq(&rhs.kind)
1181    }
1182}
1183
1184impl Eq for Expr {}
1185
1186impl Serialize for Expr {
1187    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1188    where
1189        S: Serializer,
1190    {
1191        serializer.serialize_str(&self.to_string())
1192    }
1193}
1194
1195impl Default for Expr {
1196    fn default() -> Self {
1197        ExprKind::Constant(Value::Null).to_expr(Default::default())
1198    }
1199}
1200
1201impl FromStr for Expr {
1202    type Err = anyhow::Error;
1203
1204    fn from_str(s: &str) -> result::Result<Self, Self::Err> {
1205        parser::parse_one(s)
1206    }
1207}
1208
1209// hallowed are the ori
1210#[derive(Debug, Clone, PartialEq, PartialOrd)]
1211pub struct Origin {
1212    pub name: Option<ArcStr>,
1213    pub source: ArcStr,
1214    pub exprs: Arc<[Expr]>,
1215}
1216
1217impl fmt::Display for Origin {
1218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1219        match &self.name {
1220            None => write!(f, "in expr {}", self.source),
1221            Some(n) => {
1222                if n.ends_with(".bs") {
1223                    write!(f, "in file {n}")
1224                } else {
1225                    write!(f, "in module {n}")
1226                }
1227            }
1228        }
1229    }
1230}
1231
1232#[derive(Clone, Copy)]
1233struct ExprVisitor;
1234
1235impl<'de> Visitor<'de> for ExprVisitor {
1236    type Value = Expr;
1237
1238    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1239        write!(formatter, "expected expression")
1240    }
1241
1242    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
1243    where
1244        E: de::Error,
1245    {
1246        Expr::from_str(s).map_err(de::Error::custom)
1247    }
1248
1249    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
1250    where
1251        E: de::Error,
1252    {
1253        Expr::from_str(s).map_err(de::Error::custom)
1254    }
1255
1256    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
1257    where
1258        E: de::Error,
1259    {
1260        Expr::from_str(&s).map_err(de::Error::custom)
1261    }
1262}
1263
1264impl<'de> Deserialize<'de> for Expr {
1265    fn deserialize<D>(de: D) -> Result<Self, D::Error>
1266    where
1267        D: Deserializer<'de>,
1268    {
1269        de.deserialize_str(ExprVisitor)
1270    }
1271}
1272
1273impl Expr {
1274    pub fn new(kind: ExprKind, pos: SourcePosition) -> Self {
1275        Expr { id: ExprId::new(), pos, kind }
1276    }
1277
1278    pub fn to_string_pretty(&self, col_limit: usize) -> String {
1279        self.kind.to_string_pretty(col_limit)
1280    }
1281
1282    /// fold over self and all of self's sub expressions
1283    pub fn fold<T, F: FnMut(T, &Self) -> T>(&self, init: T, f: &mut F) -> T {
1284        let init = f(init, self);
1285        match &self.kind {
1286            ExprKind::Constant(_)
1287            | ExprKind::Use { .. }
1288            | ExprKind::Ref { .. }
1289            | ExprKind::StructRef { .. }
1290            | ExprKind::TupleRef { .. }
1291            | ExprKind::TypeDef { .. } => init,
1292            ExprKind::Module { value: ModuleKind::Inline(e), .. } => {
1293                e.iter().fold(init, |init, e| e.fold(init, f))
1294            }
1295            ExprKind::Module { value: ModuleKind::Resolved(o), .. } => {
1296                o.exprs.iter().fold(init, |init, e| e.fold(init, f))
1297            }
1298            ExprKind::Module { value: ModuleKind::Unresolved, .. } => init,
1299            ExprKind::Do { exprs } => exprs.iter().fold(init, |init, e| e.fold(init, f)),
1300            ExprKind::Bind(b) => b.value.fold(init, f),
1301            ExprKind::StructWith { replace, .. } => {
1302                replace.iter().fold(init, |init, (_, e)| e.fold(init, f))
1303            }
1304            ExprKind::Connect { value, .. } => value.fold(init, f),
1305            ExprKind::Lambda(l) => match &l.body {
1306                Either::Left(e) => e.fold(init, f),
1307                Either::Right(_) => init,
1308            },
1309            ExprKind::TypeCast { expr, .. } => expr.fold(init, f),
1310            ExprKind::Apply { args, function: _ } => {
1311                args.iter().fold(init, |init, (_, e)| e.fold(init, f))
1312            }
1313            ExprKind::Any { args }
1314            | ExprKind::Array { args }
1315            | ExprKind::Tuple { args }
1316            | ExprKind::Variant { args, .. }
1317            | ExprKind::StringInterpolate { args } => {
1318                args.iter().fold(init, |init, e| e.fold(init, f))
1319            }
1320            ExprKind::ArrayRef { source, i } => {
1321                let init = source.fold(init, f);
1322                i.fold(init, f)
1323            }
1324            ExprKind::ArraySlice { source, start, end } => {
1325                let init = source.fold(init, f);
1326                let init = match start {
1327                    None => init,
1328                    Some(e) => e.fold(init, f),
1329                };
1330                match end {
1331                    None => init,
1332                    Some(e) => e.fold(init, f),
1333                }
1334            }
1335            ExprKind::Struct { args } => {
1336                args.iter().fold(init, |init, (_, e)| e.fold(init, f))
1337            }
1338            ExprKind::Select { arg, arms } => {
1339                let init = arg.fold(init, f);
1340                arms.iter().fold(init, |init, (p, e)| {
1341                    let init = match p.guard.as_ref() {
1342                        None => init,
1343                        Some(g) => g.fold(init, f),
1344                    };
1345                    e.fold(init, f)
1346                })
1347            }
1348            ExprKind::Qop(e)
1349            | ExprKind::ByRef(e)
1350            | ExprKind::Deref(e)
1351            | ExprKind::Not { expr: e } => e.fold(init, f),
1352            ExprKind::Add { lhs, rhs }
1353            | ExprKind::Sub { lhs, rhs }
1354            | ExprKind::Mul { lhs, rhs }
1355            | ExprKind::Div { lhs, rhs }
1356            | ExprKind::And { lhs, rhs }
1357            | ExprKind::Or { lhs, rhs }
1358            | ExprKind::Eq { lhs, rhs }
1359            | ExprKind::Ne { lhs, rhs }
1360            | ExprKind::Gt { lhs, rhs }
1361            | ExprKind::Lt { lhs, rhs }
1362            | ExprKind::Gte { lhs, rhs }
1363            | ExprKind::Lte { lhs, rhs } => {
1364                let init = lhs.fold(init, f);
1365                rhs.fold(init, f)
1366            }
1367        }
1368    }
1369
1370    pub fn has_unresolved_modules(&self) -> bool {
1371        self.fold(false, &mut |acc, e| {
1372            acc || match &e.kind {
1373                ExprKind::Module { value: ModuleKind::Unresolved, .. } => true,
1374                _ => false,
1375            }
1376        })
1377    }
1378
1379    /// Resolve external modules referenced in the expression using
1380    /// the resolvers list. Each resolver will be tried in order,
1381    /// until one succeeds. If no resolver succeeds then an error will
1382    /// be returned.
1383    pub async fn resolve_modules<'a>(
1384        &'a self,
1385        scope: &'a ModPath,
1386        resolvers: &'a [ModuleResolver],
1387    ) -> Result<Expr> {
1388        if self.has_unresolved_modules() {
1389            self.resolve_modules_inner(scope, resolvers).await
1390        } else {
1391            Ok(self.clone())
1392        }
1393    }
1394
1395    fn resolve_modules_inner<'a>(
1396        &'a self,
1397        scope: &'a ModPath,
1398        resolvers: &'a [ModuleResolver],
1399    ) -> Pin<Box<dyn Future<Output = Result<Expr>> + Send + Sync + 'a>> {
1400        macro_rules! subexprs {
1401            ($args:expr) => {{
1402                let mut tmp = vec![];
1403                for e in $args.iter() {
1404                    tmp.push(e.resolve_modules(scope, resolvers).await?);
1405                }
1406                tmp
1407            }};
1408        }
1409        macro_rules! subtuples {
1410            ($args:expr) => {{
1411                let mut tmp = vec![];
1412                for (k, e) in $args.iter() {
1413                    let e = e.resolve_modules(scope, resolvers).await?;
1414                    tmp.push((k.clone(), e));
1415                }
1416                tmp
1417            }};
1418        }
1419        macro_rules! only_args {
1420            ($kind:ident, $args:expr) => {
1421                Box::pin(async move {
1422                    let args = Arc::from(subexprs!($args));
1423                    Ok(Expr {
1424                        id: self.id,
1425                        pos: self.pos,
1426                        kind: ExprKind::$kind { args },
1427                    })
1428                })
1429            };
1430        }
1431        macro_rules! bin_op {
1432            ($kind:ident, $lhs:expr, $rhs:expr) => {
1433                Box::pin(async move {
1434                    let lhs = Arc::from($lhs.resolve_modules(scope, resolvers).await?);
1435                    let rhs = Arc::from($rhs.resolve_modules(scope, resolvers).await?);
1436                    Ok(Expr {
1437                        id: self.id,
1438                        pos: self.pos,
1439                        kind: ExprKind::$kind { lhs, rhs },
1440                    })
1441                })
1442            };
1443        }
1444        if !self.has_unresolved_modules() {
1445            return Box::pin(async { Ok(self.clone()) });
1446        }
1447        match self.kind.clone() {
1448            ExprKind::Module { value: ModuleKind::Unresolved, export, name } => {
1449                Box::pin(async move {
1450                    let full_name = scope.append(&name);
1451                    let full_name = full_name.trim_start_matches(Path::SEP);
1452                    let mut errors = vec![];
1453                    for r in resolvers {
1454                        let (filename, s) = match r {
1455                            ModuleResolver::Files(base) => {
1456                                let full_path = base.join(full_name).with_extension("bs");
1457                                match tokio::fs::read_to_string(&full_path).await {
1458                                    Ok(s) => (
1459                                        ArcStr::from(full_path.to_string_lossy()),
1460                                        ArcStr::from(s),
1461                                    ),
1462                                    Err(e) => {
1463                                        errors.push(anyhow::Error::from(e));
1464                                        continue;
1465                                    }
1466                                }
1467                            }
1468                            ModuleResolver::Netidx { subscriber, base, timeout } => {
1469                                let full_path = base.append(full_name);
1470                                let name: ArcStr = full_path.clone().into();
1471                                let sub = subscriber
1472                                    .subscribe_nondurable_one(full_path, *timeout)
1473                                    .await;
1474                                match sub {
1475                                    Err(e) => {
1476                                        errors.push(e);
1477                                        continue;
1478                                    }
1479                                    Ok(v) => match v.last() {
1480                                        Event::Update(Value::String(s)) => (name, s),
1481                                        Event::Unsubscribed | Event::Update(_) => {
1482                                            errors.push(anyhow!("expected string"));
1483                                            continue;
1484                                        }
1485                                    },
1486                                }
1487                            }
1488                        };
1489                        let value =
1490                            ModuleKind::Resolved(parser::parse(Some(filename), s)?);
1491                        return Ok(Expr {
1492                            id: self.id,
1493                            pos: self.pos,
1494                            kind: ExprKind::Module { name, export, value },
1495                        });
1496                    }
1497                    bail!("module {name} could not be found {errors:?}")
1498                })
1499            }
1500            ExprKind::Constant(_)
1501            | ExprKind::Use { .. }
1502            | ExprKind::Ref { .. }
1503            | ExprKind::StructRef { .. }
1504            | ExprKind::TupleRef { .. }
1505            | ExprKind::TypeDef { .. } => Box::pin(async move { Ok(self.clone()) }),
1506            ExprKind::Module { value: ModuleKind::Inline(exprs), export, name } => {
1507                Box::pin(async move {
1508                    let scope = ModPath(scope.append(&name));
1509                    let mut tmp = vec![];
1510                    for e in exprs.iter() {
1511                        tmp.push(e.resolve_modules(&scope, resolvers).await?);
1512                    }
1513                    Ok(Expr {
1514                        id: self.id,
1515                        pos: self.pos,
1516                        kind: ExprKind::Module {
1517                            value: ModuleKind::Inline(Arc::from(tmp)),
1518                            name,
1519                            export,
1520                        },
1521                    })
1522                })
1523            }
1524            ExprKind::Module { value: ModuleKind::Resolved(o), export, name } => {
1525                Box::pin(async move {
1526                    let scope = ModPath(scope.append(&name));
1527                    let mut tmp = vec![];
1528                    for e in o.exprs.iter() {
1529                        tmp.push(e.resolve_modules(&scope, resolvers).await?);
1530                    }
1531                    Ok(Expr {
1532                        id: self.id,
1533                        pos: self.pos,
1534                        kind: ExprKind::Module {
1535                            value: ModuleKind::Resolved(Origin {
1536                                exprs: Arc::from(tmp),
1537                                ..o.clone()
1538                            }),
1539                            name,
1540                            export,
1541                        },
1542                    })
1543                })
1544            }
1545            ExprKind::Do { exprs } => Box::pin(async move {
1546                let exprs = Arc::from(subexprs!(exprs));
1547                Ok(Expr { id: self.id, pos: self.pos, kind: ExprKind::Do { exprs } })
1548            }),
1549            ExprKind::Bind(b) => Box::pin(async move {
1550                let Bind { doc, pattern, typ, export, value } = &*b;
1551                let value = value.resolve_modules(scope, resolvers).await?;
1552                Ok(Expr {
1553                    id: self.id,
1554                    pos: self.pos,
1555                    kind: ExprKind::Bind(Arc::new(Bind {
1556                        doc: doc.clone(),
1557                        pattern: pattern.clone(),
1558                        typ: typ.clone(),
1559                        export: *export,
1560                        value,
1561                    })),
1562                })
1563            }),
1564            ExprKind::StructWith { source, replace } => Box::pin(async move {
1565                Ok(Expr {
1566                    id: self.id,
1567                    pos: self.pos,
1568                    kind: ExprKind::StructWith {
1569                        source: Arc::new(source.resolve_modules(scope, resolvers).await?),
1570                        replace: Arc::from(subtuples!(replace)),
1571                    },
1572                })
1573            }),
1574            ExprKind::Connect { name, value } => Box::pin(async move {
1575                let value = value.resolve_modules(scope, resolvers).await?;
1576                Ok(Expr {
1577                    id: self.id,
1578                    pos: self.pos,
1579                    kind: ExprKind::Connect { name, value: Arc::new(value) },
1580                })
1581            }),
1582            ExprKind::Lambda(l) => Box::pin(async move {
1583                let Lambda { args, vargs, rtype, constraints, body } = &*l;
1584                let body = match body {
1585                    Either::Right(s) => Either::Right(s.clone()),
1586                    Either::Left(e) => {
1587                        Either::Left(e.resolve_modules(scope, resolvers).await?)
1588                    }
1589                };
1590                let l = Lambda {
1591                    args: args.clone(),
1592                    vargs: vargs.clone(),
1593                    rtype: rtype.clone(),
1594                    constraints: constraints.clone(),
1595                    body,
1596                };
1597                let kind = ExprKind::Lambda(Arc::new(l));
1598                Ok(Expr { id: self.id, pos: self.pos, kind })
1599            }),
1600            ExprKind::TypeCast { expr, typ } => Box::pin(async move {
1601                let expr = expr.resolve_modules(scope, resolvers).await?;
1602                Ok(Expr {
1603                    id: self.id,
1604                    pos: self.pos,
1605                    kind: ExprKind::TypeCast { expr: Arc::new(expr), typ },
1606                })
1607            }),
1608            ExprKind::Apply { args, function } => Box::pin(async move {
1609                Ok(Expr {
1610                    id: self.id,
1611                    pos: self.pos,
1612                    kind: ExprKind::Apply { args: Arc::from(subtuples!(args)), function },
1613                })
1614            }),
1615            ExprKind::Any { args } => only_args!(Any, args),
1616            ExprKind::Array { args } => only_args!(Array, args),
1617            ExprKind::Tuple { args } => only_args!(Tuple, args),
1618            ExprKind::StringInterpolate { args } => only_args!(StringInterpolate, args),
1619            ExprKind::Struct { args } => Box::pin(async move {
1620                let args = Arc::from(subtuples!(args));
1621                Ok(Expr { id: self.id, pos: self.pos, kind: ExprKind::Struct { args } })
1622            }),
1623            ExprKind::ArrayRef { source, i } => Box::pin(async move {
1624                let source = Arc::new(source.resolve_modules(scope, resolvers).await?);
1625                let i = Arc::new(i.resolve_modules(scope, resolvers).await?);
1626                Ok(Expr {
1627                    id: self.id,
1628                    pos: self.pos,
1629                    kind: ExprKind::ArrayRef { source, i },
1630                })
1631            }),
1632            ExprKind::ArraySlice { source, start, end } => Box::pin(async move {
1633                let source = Arc::new(source.resolve_modules(scope, resolvers).await?);
1634                let start = match start {
1635                    None => None,
1636                    Some(e) => Some(Arc::new(e.resolve_modules(scope, resolvers).await?)),
1637                };
1638                let end = match end {
1639                    None => None,
1640                    Some(e) => Some(Arc::new(e.resolve_modules(scope, resolvers).await?)),
1641                };
1642                Ok(Expr {
1643                    id: self.id,
1644                    pos: self.pos,
1645                    kind: ExprKind::ArraySlice { source, start, end },
1646                })
1647            }),
1648            ExprKind::Variant { tag, args } => Box::pin(async move {
1649                let args = Arc::from(subexprs!(args));
1650                Ok(Expr {
1651                    id: self.id,
1652                    pos: self.pos,
1653                    kind: ExprKind::Variant { tag, args },
1654                })
1655            }),
1656            ExprKind::Select { arg, arms } => Box::pin(async move {
1657                let arg = Arc::new(arg.resolve_modules(scope, resolvers).await?);
1658                let mut tmp = vec![];
1659                for (p, e) in arms.iter() {
1660                    let p = match &p.guard {
1661                        None => p.clone(),
1662                        Some(e) => {
1663                            let e = e.resolve_modules(scope, resolvers).await?;
1664                            Pattern {
1665                                guard: Some(e),
1666                                type_predicate: p.type_predicate.clone(),
1667                                structure_predicate: p.structure_predicate.clone(),
1668                            }
1669                        }
1670                    };
1671                    let e = e.resolve_modules(scope, resolvers).await?;
1672                    tmp.push((p, e));
1673                }
1674                Ok(Expr {
1675                    id: self.id,
1676                    pos: self.pos,
1677                    kind: ExprKind::Select { arg, arms: Arc::from(tmp) },
1678                })
1679            }),
1680            ExprKind::Qop(e) => Box::pin(async move {
1681                let e = e.resolve_modules(scope, resolvers).await?;
1682                Ok(Expr { id: self.id, pos: self.pos, kind: ExprKind::Qop(Arc::new(e)) })
1683            }),
1684            ExprKind::ByRef(e) => Box::pin(async move {
1685                let e = e.resolve_modules(scope, resolvers).await?;
1686                Ok(Expr {
1687                    id: self.id,
1688                    pos: self.pos,
1689                    kind: ExprKind::ByRef(Arc::new(e)),
1690                })
1691            }),
1692            ExprKind::Deref(e) => Box::pin(async move {
1693                let e = e.resolve_modules(scope, resolvers).await?;
1694                Ok(Expr {
1695                    id: self.id,
1696                    pos: self.pos,
1697                    kind: ExprKind::Deref(Arc::new(e)),
1698                })
1699            }),
1700            ExprKind::Not { expr: e } => Box::pin(async move {
1701                let e = e.resolve_modules(scope, resolvers).await?;
1702                Ok(Expr {
1703                    id: self.id,
1704                    pos: self.pos,
1705                    kind: ExprKind::Not { expr: Arc::new(e) },
1706                })
1707            }),
1708            ExprKind::Add { lhs, rhs } => bin_op!(Add, lhs, rhs),
1709            ExprKind::Sub { lhs, rhs } => bin_op!(Sub, lhs, rhs),
1710            ExprKind::Mul { lhs, rhs } => bin_op!(Mul, lhs, rhs),
1711            ExprKind::Div { lhs, rhs } => bin_op!(Div, lhs, rhs),
1712            ExprKind::And { lhs, rhs } => bin_op!(And, lhs, rhs),
1713            ExprKind::Or { lhs, rhs } => bin_op!(Or, lhs, rhs),
1714            ExprKind::Eq { lhs, rhs } => bin_op!(Eq, lhs, rhs),
1715            ExprKind::Ne { lhs, rhs } => bin_op!(Ne, lhs, rhs),
1716            ExprKind::Gt { lhs, rhs } => bin_op!(Gt, lhs, rhs),
1717            ExprKind::Lt { lhs, rhs } => bin_op!(Lt, lhs, rhs),
1718            ExprKind::Gte { lhs, rhs } => bin_op!(Gte, lhs, rhs),
1719            ExprKind::Lte { lhs, rhs } => bin_op!(Lte, lhs, rhs),
1720        }
1721    }
1722}
1723
1724impl fmt::Display for Expr {
1725    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1726        write!(f, "{}", self.kind)
1727    }
1728}