netidx_bscript/expr/
mod.rs

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