1use crate::{
2 expr::{
3 parser, ApplyExpr, BindExpr, CouldNotResolve, Expr, ExprId, ExprKind, LambdaExpr,
4 ModPath, ModuleKind, Origin, Pattern, SelectExpr, Sig, SigItem, SigKind, Source,
5 StructExpr, StructWithExpr, StructurePattern, TryCatchExpr, TypeDefExpr,
6 },
7 format_with_flags, PrintFlag,
8};
9use anyhow::{anyhow, bail, Context, Result};
10use arcstr::ArcStr;
11use combine::stream::position::SourcePosition;
12use compact_str::format_compact;
13use futures::future::try_join_all;
14use fxhash::FxHashMap;
15use indexmap::IndexSet;
16use log::info;
17use netidx::{
18 path::Path,
19 subscriber::{Event, Subscriber},
20 utils::Either,
21};
22use netidx_value::Value;
23use poolshark::local::LPooled;
24use std::{hash::Hash, path::PathBuf, pin::Pin, str::FromStr, time::Duration};
25use tokio::{join, task, time::Instant, try_join};
26use triomphe::Arc;
27
28#[derive(Debug, Clone)]
29pub enum ModuleResolver {
30 VFS(FxHashMap<Path, ArcStr>),
31 Files(PathBuf),
32 Netidx { subscriber: Subscriber, base: Path, timeout: Option<Duration> },
33}
34
35impl ModuleResolver {
36 pub fn parse_env(
43 subscriber: Subscriber,
44 timeout: Option<Duration>,
45 s: &str,
46 ) -> Result<Vec<Self>> {
47 let mut res = vec![];
48 for l in escaping::split(s, '\\', ',') {
49 let l = l.trim();
50 if let Some(s) = l.strip_prefix("netidx:") {
51 let base = Path::from_str(s);
52 let r = Self::Netidx { subscriber: subscriber.clone(), timeout, base };
53 res.push(r);
54 } else if let Some(s) = l.strip_prefix("file:") {
55 let base = PathBuf::from_str(s)?;
56 let r = Self::Files(base);
57 res.push(r);
58 } else {
59 bail!("expected netidx: or file:")
60 }
61 }
62 Ok(res)
63 }
64}
65
66enum Resolution {
67 Resolved { interface: Option<Origin>, implementation: Origin },
68 TryNextMethod,
69}
70
71fn resolve_from_vfs(
72 scope: &ModPath,
73 parent: &Arc<Origin>,
74 name: &Path,
75 vfs: &FxHashMap<Path, ArcStr>,
76) -> Resolution {
77 macro_rules! ori {
78 ($s:expr) => {
79 Origin {
80 parent: Some(parent.clone()),
81 source: Source::Internal(name.clone().into()),
82 text: $s.clone(),
83 }
84 };
85 }
86 let scoped_intf = scope.append(&format_compact!("{name}.gxi"));
87 let scoped_impl = scope.append(&format_compact!("{name}.gx"));
88 let implementation = match vfs.get(&scoped_impl) {
89 Some(s) => ori!(s),
90 None => {
91 let mod_impl = scope.append(&format_compact!("{name}/mod.gx"));
93 match vfs.get(&mod_impl) {
94 Some(s) => ori!(s),
95 None => return Resolution::TryNextMethod,
96 }
97 }
98 };
99 let interface = vfs
100 .get(&scoped_intf)
101 .or_else(|| {
102 let mod_intf = scope.append(&format_compact!("{name}/mod.gxi"));
103 vfs.get(&mod_intf)
104 })
105 .map(|s| ori!(s));
106 Resolution::Resolved { interface, implementation }
107}
108
109async fn resolve_from_files(
110 parent: &Arc<Origin>,
111 name: &Path,
112 base: &PathBuf,
113 errors: &mut Vec<anyhow::Error>,
114) -> Resolution {
115 macro_rules! ori {
116 ($s:expr, $path:expr) => {
117 Origin {
118 parent: Some(parent.clone()),
119 source: Source::File($path),
120 text: ArcStr::from($s),
121 }
122 };
123 }
124 let mut impl_path = base.clone();
125 for part in Path::parts(&name) {
126 impl_path.push(part);
127 }
128 impl_path.set_extension("gx");
129 let mut intf_path = impl_path.with_extension("gxi");
130 let implementation = match tokio::fs::read_to_string(&impl_path).await {
131 Ok(s) => ori!(s, impl_path),
132 Err(_) => {
133 impl_path.set_extension("");
134 impl_path.push("mod.gx");
135 intf_path.set_extension("");
136 intf_path.push("mod.gxi");
137 match tokio::fs::read_to_string(&impl_path).await {
138 Ok(s) => ori!(s, impl_path.clone()),
139 Err(e) => {
140 errors.push(anyhow::Error::from(e));
141 return Resolution::TryNextMethod;
142 }
143 }
144 }
145 };
146 let interface = match tokio::fs::read_to_string(&intf_path).await {
147 Ok(s) => Some(ori!(s, intf_path)),
148 Err(_) => None,
149 };
150 Resolution::Resolved { interface, implementation }
151}
152
153async fn resolve_from_netidx(
154 parent: &Arc<Origin>,
155 name: &Path,
156 subscriber: &Subscriber,
157 base: &Path,
158 timeout: &Option<Duration>,
159 errors: &mut Vec<anyhow::Error>,
160) -> Resolution {
161 macro_rules! ori {
162 ($v:expr, $p:expr) => {
163 match $v.last() {
164 Event::Update(Value::String(text)) => Origin {
165 parent: Some(parent.clone()),
166 source: Source::Netidx($p.clone()),
167 text,
168 },
169 Event::Unsubscribed | Event::Update(_) => {
170 errors.push(anyhow!("expected string"));
171 return Resolution::TryNextMethod;
172 }
173 }
174 };
175 }
176 let impl_path = base.append(&format_compact!("{name}.gx"));
177 let intf_path = base.append(&format_compact!("{name}.gxi"));
178 let impl_sub = subscriber.subscribe_nondurable_one(impl_path.clone(), *timeout);
179 let intf_sub = subscriber.subscribe_nondurable_one(intf_path.clone(), *timeout);
180 let (impl_sub, intf_sub) = join!(impl_sub, intf_sub);
181 let implementation = match impl_sub {
182 Ok(v) => ori!(v, impl_path),
183 Err(e) => {
184 errors.push(e);
185 return Resolution::TryNextMethod;
186 }
187 };
188 let interface = match intf_sub {
189 Ok(v) => Some(ori!(v, intf_path)),
190 Err(_) => None,
191 };
192 Resolution::Resolved { interface, implementation }
193}
194
195fn add_interface_modules(exprs: Arc<[Expr]>, sig: &Sig) -> Arc<[Expr]> {
198 #[derive(Clone, Copy)]
199 enum Item<'a> {
200 Module(&'a ArcStr),
201 TypeDef(&'a TypeDefExpr),
202 Use(&'a ModPath),
203 }
204 impl<'a> PartialEq for Item<'a> {
205 fn eq(&self, other: &Self) -> bool {
206 match (self, other) {
207 (Self::Module(a), Self::Module(b)) => a == b,
208 (Self::TypeDef(a), Self::TypeDef(b)) => a.name == b.name,
209 (Self::Use(a), Self::Use(b)) => a == b,
210 (_, _) => false,
211 }
212 }
213 }
214 impl<'a> Eq for Item<'a> {}
215 impl<'a> Hash for Item<'a> {
216 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
217 match self {
218 Self::Module(m) => {
219 0u8.hash(state);
220 m.hash(state);
221 }
222 Self::TypeDef(td) => {
223 1u8.hash(state);
224 td.name.hash(state);
225 }
226 Self::Use(m) => {
227 2u8.hash(state);
228 m.hash(state);
229 }
230 }
231 }
232 }
233 impl<'a> Item<'a> {
234 fn synth(self) -> Expr {
235 match self {
236 Item::Module(name) => ExprKind::Module {
237 name: name.clone(),
238 value: ModuleKind::Unresolved { from_interface: true },
239 }
240 .to_expr_nopos(),
241 Item::TypeDef(td) => ExprKind::TypeDef(td.clone()).to_expr_nopos(),
242 Item::Use(m) => ExprKind::Use { name: m.clone() }.to_expr_nopos(),
243 }
244 }
245 }
246 let mut in_sig: LPooled<IndexSet<Item>> = LPooled::take();
247 let mut after_bind: LPooled<FxHashMap<&ArcStr, Item>> = LPooled::take();
248 let mut after_td: LPooled<FxHashMap<&ArcStr, Item>> = LPooled::take();
249 let mut after_mod: LPooled<FxHashMap<&ArcStr, Item>> = LPooled::take();
250 let mut after_use: LPooled<FxHashMap<&ModPath, Item>> = LPooled::take();
251 let mut first: Option<Item> = None;
252 let mut last: Option<&SigItem> = None;
253 macro_rules! push {
254 ($kind:ident, $name:expr) => {{
255 let name = Item::$kind($name);
256 in_sig.insert(name);
257 match last {
258 None => first = Some(name),
259 Some(si) => {
260 match &si.kind {
261 SigKind::Bind(v) => after_bind.insert(&v.name, name),
262 SigKind::Module(m) => after_mod.insert(m, name),
263 SigKind::TypeDef(td) => after_td.insert(&td.name, name),
264 SigKind::Use(n) => after_use.insert(n, name),
265 };
266 }
267 }
268 }};
269 }
270 for si in &*sig.items {
271 match &si.kind {
272 SigKind::Module(name) => push!(Module, name),
273 SigKind::TypeDef(td) => push!(TypeDef, td),
274 SigKind::Use(m) => push!(Use, m),
275 SigKind::Bind(_) => (),
276 }
277 last = Some(si);
278 }
279 for e in &*exprs {
280 if let ExprKind::Module { name, .. } = &e.kind {
281 in_sig.shift_remove(&Item::Module(name));
282 }
283 if let ExprKind::TypeDef(td) = &e.kind {
284 in_sig.shift_remove(&Item::TypeDef(td));
285 }
286 if let ExprKind::Use { name } = &e.kind {
287 in_sig.shift_remove(&Item::Use(name));
288 }
289 }
290 if in_sig.is_empty() {
291 drop(in_sig);
292 drop(after_bind);
293 drop(after_td);
294 drop(after_mod);
295 drop(after_use);
296 return exprs;
297 }
298 let mut res: LPooled<Vec<Expr>> = LPooled::take();
299 if let Some(name) = first.take() {
300 if in_sig.shift_remove(&name) {
301 res.push(name.synth());
302 }
303 }
304 let mut iter = exprs.iter();
305 loop {
306 match res.last().map(|e| &e.kind) {
307 Some(ExprKind::Bind(v)) => match &v.pattern {
308 StructurePattern::Bind(n) => {
309 if let Some(name) = after_bind.remove(n)
310 && in_sig.shift_remove(&name)
311 {
312 res.push(name.synth());
313 continue;
314 }
315 }
316 _ => (),
317 },
318 Some(ExprKind::TypeDef(td)) => {
319 if let Some(name) = after_td.remove(&td.name)
320 && in_sig.shift_remove(&name)
321 {
322 res.push(name.synth());
323 continue;
324 }
325 }
326 Some(ExprKind::Module { name, .. }) => {
327 if let Some(name) = after_mod.remove(name)
328 && in_sig.shift_remove(&name)
329 {
330 res.push(name.synth());
331 continue;
332 }
333 }
334 Some(ExprKind::Use { name }) => {
335 if let Some(name) = after_use.remove(name)
336 && in_sig.shift_remove(&name)
337 {
338 res.push(name.synth());
339 continue;
340 }
341 }
342 _ => (),
343 };
344 match iter.next() {
345 None => break,
346 Some(e) => res.push(e.clone()),
347 }
348 }
349 for name in in_sig.drain(..) {
350 res.push(name.synth());
351 }
352 Arc::from_iter(res.drain(..))
353}
354
355async fn resolve(
356 scope: ModPath,
357 prepend: Option<Arc<ModuleResolver>>,
358 resolvers: Arc<[ModuleResolver]>,
359 id: ExprId,
360 parent: Arc<Origin>,
361 pos: SourcePosition,
362 name: ArcStr,
363 from_interface: bool,
364) -> Result<Expr> {
365 macro_rules! check {
366 ($res:expr) => {
367 match $res {
368 Resolution::TryNextMethod => continue,
369 Resolution::Resolved { interface, implementation } => {
370 (interface, implementation)
371 }
372 }
373 };
374 }
375 let ts = Instant::now();
376 let name = Path::from(name);
377 let mut errors: LPooled<Vec<anyhow::Error>> = LPooled::take();
378 for r in prepend.iter().map(|r| r.as_ref()).chain(resolvers.iter()) {
379 let (interface, implementation) = match r {
380 ModuleResolver::VFS(vfs) => {
381 check!(resolve_from_vfs(&scope, &parent, &name, vfs))
382 }
383 ModuleResolver::Files(base) => {
384 check!(resolve_from_files(&parent, &name, base, &mut errors).await)
385 }
386 ModuleResolver::Netidx { subscriber, base, timeout } => {
387 let r = resolve_from_netidx(
388 &parent,
389 &name,
390 subscriber,
391 base,
392 timeout,
393 &mut errors,
394 )
395 .await;
396 check!(r)
397 }
398 };
399 let exprs = task::spawn_blocking({
400 let ori = implementation.clone();
401 move || parser::parse(ori)
402 });
403 let sig = match &interface {
404 None => None,
405 Some(ori) => {
406 let ori = ori.clone();
407 let sig = task::spawn_blocking(move || parser::parse_sig(ori))
408 .await?
409 .with_context(|| format!("parsing file {interface:?}"))?;
410 Some(sig)
411 }
412 };
413 let exprs =
414 exprs.await?.with_context(|| format!("parsing file {implementation:?}"))?;
415 let exprs = match &sig {
416 Some(sig) => add_interface_modules(exprs, &sig),
417 None => exprs,
418 };
419 let value = ModuleKind::Resolved { exprs, sig, from_interface };
420 let kind = ExprKind::Module { name: name.clone().into(), value };
421 format_with_flags(PrintFlag::NoSource | PrintFlag::NoParents, || {
422 info!(
423 "load and parse {implementation:?} and {interface:?} {:?}",
424 ts.elapsed()
425 )
426 });
427 return Ok(Expr { id, ori: Arc::new(implementation), pos, kind });
428 }
429 bail!("module {name} could not be found {errors:?}")
430}
431
432impl Expr {
433 pub fn has_unresolved_modules(&self) -> bool {
434 self.fold(false, &mut |acc, e| {
435 acc || match &e.kind {
436 ExprKind::Module { value: ModuleKind::Unresolved { .. }, .. } => true,
437 _ => false,
438 }
439 })
440 }
441
442 pub async fn resolve_modules<'a>(
447 &'a self,
448 resolvers: &'a Arc<[ModuleResolver]>,
449 ) -> Result<Expr> {
450 self.resolve_modules_int(&ModPath::root(), &None, resolvers).await
451 }
452
453 async fn resolve_modules_int<'a>(
454 &'a self,
455 scope: &ModPath,
456 prepend: &'a Option<Arc<ModuleResolver>>,
457 resolvers: &'a Arc<[ModuleResolver]>,
458 ) -> Result<Expr> {
459 if self.has_unresolved_modules() {
460 self.resolve_modules_inner(scope, prepend, resolvers).await
461 } else {
462 Ok(self.clone())
463 }
464 }
465
466 fn resolve_modules_inner<'a>(
467 &'a self,
468 scope: &'a ModPath,
469 prepend: &'a Option<Arc<ModuleResolver>>,
470 resolvers: &'a Arc<[ModuleResolver]>,
471 ) -> Pin<Box<dyn Future<Output = Result<Expr>> + Send + Sync + 'a>> {
472 macro_rules! subexprs {
473 ($args:expr) => {{
474 try_join_all($args.iter().map(|e| async {
475 e.resolve_modules_int(scope, prepend, resolvers).await
476 }))
477 .await?
478 }};
479 }
480 macro_rules! subtuples {
481 ($args:expr) => {{
482 try_join_all($args.iter().map(|(k, e)| async {
483 Ok::<_, anyhow::Error>((
484 k.clone(),
485 e.resolve_modules_int(scope, prepend, resolvers).await?,
486 ))
487 }))
488 .await?
489 }};
490 }
491 macro_rules! expr {
492 ($kind:expr) => {
493 Ok(Expr {
494 id: self.id,
495 ori: self.ori.clone(),
496 pos: self.pos,
497 kind: $kind,
498 })
499 };
500 }
501 macro_rules! only_args {
502 ($kind:ident, $args:expr) => {
503 Box::pin(async move {
504 let args = Arc::from(subexprs!($args));
505 expr!(ExprKind::$kind { args })
506 })
507 };
508 }
509 macro_rules! bin_op {
510 ($kind:ident, $lhs:expr, $rhs:expr) => {
511 Box::pin(async move {
512 let (lhs, rhs) = try_join!(
513 $lhs.resolve_modules_int(scope, prepend, resolvers),
514 $rhs.resolve_modules_int(scope, prepend, resolvers)
515 )?;
516 expr!(ExprKind::$kind { lhs: Arc::from(lhs), rhs: Arc::from(rhs) })
517 })
518 };
519 }
520 if !self.has_unresolved_modules() {
521 return Box::pin(async { Ok(self.clone()) });
522 }
523 match self.kind.clone() {
524 ExprKind::Constant(_)
525 | ExprKind::NoOp
526 | ExprKind::Use { .. }
527 | ExprKind::Ref { .. }
528 | ExprKind::StructRef { .. }
529 | ExprKind::TupleRef { .. }
530 | ExprKind::TypeDef { .. } => Box::pin(async move { Ok(self.clone()) }),
531 ExprKind::Module {
532 value: ModuleKind::Unresolved { from_interface },
533 name,
534 } => {
535 let (id, pos, prepend, resolvers) =
536 (self.id, self.pos, prepend.clone(), Arc::clone(resolvers));
537 Box::pin(async move {
538 let e = resolve(
539 scope.clone(),
540 prepend.clone(),
541 resolvers.clone(),
542 id,
543 self.ori.clone(),
544 pos,
545 name.clone(),
546 from_interface,
547 )
548 .await
549 .with_context(|| CouldNotResolve(name.clone()))?;
550 let scope = ModPath(scope.append(&*name));
551 e.resolve_modules_int(&scope, &prepend, &resolvers).await
552 })
553 }
554 ExprKind::Module {
555 value: ModuleKind::Resolved { exprs, sig, from_interface },
556 name,
557 } => Box::pin(async move {
558 let prepend = match &self.ori.source {
559 Source::Unspecified | Source::Internal(_) => None,
560 Source::File(p) => {
561 p.parent().map(|p| Arc::new(ModuleResolver::Files(p.into())))
562 }
563 Source::Netidx(p) => resolvers.iter().find_map(|m| match m {
564 ModuleResolver::Netidx { subscriber, timeout, .. } => {
565 Some(Arc::new(ModuleResolver::Netidx {
566 subscriber: subscriber.clone(),
567 base: p.clone(),
568 timeout: *timeout,
569 }))
570 }
571 ModuleResolver::Files(_) | ModuleResolver::VFS(_) => None,
572 }),
573 };
574 let exprs = try_join_all(exprs.iter().map(|e| async {
575 e.resolve_modules_int(&scope, &prepend, resolvers).await
576 }))
577 .await?;
578 expr!(ExprKind::Module {
579 value: ModuleKind::Resolved {
580 exprs: Arc::from(exprs),
581 sig,
582 from_interface
583 },
584 name,
585 })
586 }),
587 ExprKind::Module {
588 name,
589 value: ModuleKind::Dynamic { sandbox, sig, source },
590 } => Box::pin(async move {
591 let source = Arc::new(
592 source.resolve_modules_int(scope, prepend, resolvers).await?,
593 );
594 expr!(ExprKind::Module {
595 name,
596 value: ModuleKind::Dynamic { sandbox, sig, source },
597 })
598 }),
599 ExprKind::ExplicitParens(e) => Box::pin(async move {
600 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
601 expr!(ExprKind::ExplicitParens(Arc::new(e)))
602 }),
603 ExprKind::Do { exprs } => Box::pin(async move {
604 let exprs = Arc::from(subexprs!(exprs));
605 expr!(ExprKind::Do { exprs })
606 }),
607 ExprKind::Bind(b) => Box::pin(async move {
608 let BindExpr { rec, pattern, typ, value } = &*b;
609 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
610 expr!(ExprKind::Bind(Arc::new(BindExpr {
611 rec: *rec,
612 pattern: pattern.clone(),
613 typ: typ.clone(),
614 value,
615 })))
616 }),
617 ExprKind::StructWith(StructWithExpr { source, replace }) => {
618 Box::pin(async move {
619 expr!(ExprKind::StructWith(StructWithExpr {
620 source: Arc::new(
621 source.resolve_modules_int(scope, prepend, resolvers).await?,
622 ),
623 replace: Arc::from(subtuples!(replace)),
624 }))
625 })
626 }
627 ExprKind::Connect { name, value, deref } => Box::pin(async move {
628 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
629 expr!(ExprKind::Connect { name, value: Arc::new(value), deref })
630 }),
631 ExprKind::Lambda(l) => Box::pin(async move {
632 let LambdaExpr { args, vargs, rtype, constraints, throws, body } = &*l;
633 let body = match body {
634 Either::Right(s) => Either::Right(s.clone()),
635 Either::Left(e) => Either::Left(
636 e.resolve_modules_int(scope, prepend, resolvers).await?,
637 ),
638 };
639 let l = LambdaExpr {
640 args: args.clone(),
641 vargs: vargs.clone(),
642 rtype: rtype.clone(),
643 throws: throws.clone(),
644 constraints: constraints.clone(),
645 body,
646 };
647 expr!(ExprKind::Lambda(Arc::new(l)))
648 }),
649 ExprKind::TypeCast { expr, typ } => Box::pin(async move {
650 let expr = expr.resolve_modules_int(scope, prepend, resolvers).await?;
651 expr!(ExprKind::TypeCast { expr: Arc::new(expr), typ })
652 }),
653 ExprKind::Apply(ApplyExpr { args, function }) => Box::pin(async move {
654 expr!(ExprKind::Apply(ApplyExpr {
655 args: Arc::from(subtuples!(args)),
656 function
657 }))
658 }),
659 ExprKind::Any { args } => only_args!(Any, args),
660 ExprKind::Array { args } => only_args!(Array, args),
661 ExprKind::Map { args } => Box::pin(async move {
662 let args = Arc::from(subtuples!(args));
663 expr!(ExprKind::Map { args })
664 }),
665 ExprKind::MapRef { source, key } => Box::pin(async move {
666 let source = Arc::new(
667 source.resolve_modules_int(scope, prepend, resolvers).await?,
668 );
669 let key =
670 Arc::new(key.resolve_modules_inner(scope, prepend, resolvers).await?);
671 expr!(ExprKind::MapRef { source, key })
672 }),
673 ExprKind::Tuple { args } => only_args!(Tuple, args),
674 ExprKind::StringInterpolate { args } => only_args!(StringInterpolate, args),
675 ExprKind::Struct(StructExpr { args }) => Box::pin(async move {
676 let args = Arc::from(subtuples!(args));
677 expr!(ExprKind::Struct(StructExpr { args }))
678 }),
679 ExprKind::ArrayRef { source, i } => Box::pin(async move {
680 let source = Arc::new(
681 source.resolve_modules_int(scope, prepend, resolvers).await?,
682 );
683 let i = Arc::new(i.resolve_modules_int(scope, prepend, resolvers).await?);
684 expr!(ExprKind::ArrayRef { source, i })
685 }),
686 ExprKind::ArraySlice { source, start, end } => Box::pin(async move {
687 let source = Arc::new(
688 source.resolve_modules_int(scope, prepend, resolvers).await?,
689 );
690 let start = match start {
691 None => None,
692 Some(e) => Some(Arc::new(
693 e.resolve_modules_int(scope, prepend, resolvers).await?,
694 )),
695 };
696 let end = match end {
697 None => None,
698 Some(e) => Some(Arc::new(
699 e.resolve_modules_int(scope, prepend, resolvers).await?,
700 )),
701 };
702 expr!(ExprKind::ArraySlice { source, start, end })
703 }),
704 ExprKind::Variant { tag, args } => Box::pin(async move {
705 let args = Arc::from(subexprs!(args));
706 expr!(ExprKind::Variant { tag, args })
707 }),
708 ExprKind::Select(SelectExpr { arg, arms }) => Box::pin(async move {
709 let arg =
710 Arc::new(arg.resolve_modules_int(scope, prepend, resolvers).await?);
711 let arms = try_join_all(arms.iter().map(|(p, e)| async {
712 let p = match &p.guard {
713 None => p.clone(),
714 Some(e) => {
715 let e =
716 e.resolve_modules_int(scope, prepend, resolvers).await?;
717 Pattern {
718 guard: Some(e),
719 type_predicate: p.type_predicate.clone(),
720 structure_predicate: p.structure_predicate.clone(),
721 }
722 }
723 };
724 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
725 Ok::<_, anyhow::Error>((p, e))
726 }))
727 .await?;
728 expr!(ExprKind::Select(SelectExpr { arg, arms: Arc::from(arms) }))
729 }),
730 ExprKind::Qop(e) => Box::pin(async move {
731 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
732 expr!(ExprKind::Qop(Arc::new(e)))
733 }),
734 ExprKind::OrNever(e) => Box::pin(async move {
735 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
736 expr!(ExprKind::OrNever(Arc::new(e)))
737 }),
738 ExprKind::TryCatch(tc) => Box::pin(async move {
739 let exprs = try_join_all(tc.exprs.iter().map(|e| async {
740 e.resolve_modules_int(&scope, &prepend, resolvers).await
741 }))
742 .await?;
743 let handler =
744 tc.handler.resolve_modules_int(scope, prepend, resolvers).await?;
745 expr!(ExprKind::TryCatch(Arc::new(TryCatchExpr {
746 bind: tc.bind.clone(),
747 constraint: tc.constraint.clone(),
748 handler: Arc::new(handler),
749 exprs: Arc::from_iter(exprs),
750 })))
751 }),
752 ExprKind::ByRef(e) => Box::pin(async move {
753 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
754 expr!(ExprKind::ByRef(Arc::new(e)))
755 }),
756 ExprKind::Deref(e) => Box::pin(async move {
757 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
758 expr!(ExprKind::Deref(Arc::new(e)))
759 }),
760 ExprKind::Not { expr: e } => Box::pin(async move {
761 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
762 expr!(ExprKind::Not { expr: Arc::new(e) })
763 }),
764 ExprKind::Add { lhs, rhs } => bin_op!(Add, lhs, rhs),
765 ExprKind::CheckedAdd { lhs, rhs } => bin_op!(CheckedAdd, lhs, rhs),
766 ExprKind::Sub { lhs, rhs } => bin_op!(Sub, lhs, rhs),
767 ExprKind::CheckedSub { lhs, rhs } => bin_op!(CheckedSub, lhs, rhs),
768 ExprKind::Mul { lhs, rhs } => bin_op!(Mul, lhs, rhs),
769 ExprKind::CheckedMul { lhs, rhs } => bin_op!(CheckedMul, lhs, rhs),
770 ExprKind::Div { lhs, rhs } => bin_op!(Div, lhs, rhs),
771 ExprKind::CheckedDiv { lhs, rhs } => bin_op!(CheckedDiv, lhs, rhs),
772 ExprKind::Mod { lhs, rhs } => bin_op!(Mod, lhs, rhs),
773 ExprKind::CheckedMod { lhs, rhs } => bin_op!(CheckedMod, lhs, rhs),
774 ExprKind::And { lhs, rhs } => bin_op!(And, lhs, rhs),
775 ExprKind::Or { lhs, rhs } => bin_op!(Or, lhs, rhs),
776 ExprKind::Eq { lhs, rhs } => bin_op!(Eq, lhs, rhs),
777 ExprKind::Ne { lhs, rhs } => bin_op!(Ne, lhs, rhs),
778 ExprKind::Gt { lhs, rhs } => bin_op!(Gt, lhs, rhs),
779 ExprKind::Lt { lhs, rhs } => bin_op!(Lt, lhs, rhs),
780 ExprKind::Gte { lhs, rhs } => bin_op!(Gte, lhs, rhs),
781 ExprKind::Lte { lhs, rhs } => bin_op!(Lte, lhs, rhs),
782 ExprKind::Sample { lhs, rhs } => bin_op!(Sample, lhs, rhs),
783 }
784 }
785}