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 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 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#[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 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 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}