1use crate::{
2 expr::{
3 parser, Bind, Expr, ExprId, ExprKind, Lambda, ModPath, ModuleKind, Origin,
4 Pattern, Source,
5 },
6 format_with_flags, PrintFlag,
7};
8use anyhow::{anyhow, bail, Context, Result};
9use arcstr::ArcStr;
10use combine::stream::position::SourcePosition;
11use futures::future::try_join_all;
12use fxhash::FxHashMap;
13use log::info;
14use netidx::{
15 path::Path,
16 subscriber::{Event, Subscriber},
17 utils::Either,
18};
19use netidx_value::Value;
20use std::{path::PathBuf, pin::Pin, str::FromStr, time::Duration};
21use tokio::{task, time::Instant, try_join};
22use triomphe::Arc;
23
24#[derive(Debug, Clone)]
25pub enum ModuleResolver {
26 VFS(FxHashMap<Path, ArcStr>),
27 Files(PathBuf),
28 Netidx { subscriber: Subscriber, base: Path, timeout: Option<Duration> },
29}
30
31impl ModuleResolver {
32 pub fn parse_env(
39 subscriber: Subscriber,
40 timeout: Option<Duration>,
41 s: &str,
42 ) -> Result<Vec<Self>> {
43 let mut res = vec![];
44 for l in escaping::split(s, '\\', ',') {
45 let l = l.trim();
46 if let Some(s) = l.strip_prefix("netidx:") {
47 let base = Path::from_str(s);
48 let r = Self::Netidx { subscriber: subscriber.clone(), timeout, base };
49 res.push(r);
50 } else if let Some(s) = l.strip_prefix("file:") {
51 let base = PathBuf::from_str(s)?;
52 let r = Self::Files(base);
53 res.push(r);
54 } else {
55 bail!("expected netidx: or file:")
56 }
57 }
58 Ok(res)
59 }
60}
61
62impl Expr {
63 pub fn has_unresolved_modules(&self) -> bool {
64 self.fold(false, &mut |acc, e| {
65 acc || match &e.kind {
66 ExprKind::Module { value: ModuleKind::Unresolved, .. } => true,
67 _ => false,
68 }
69 })
70 }
71
72 pub async fn resolve_modules<'a>(
77 &'a self,
78 resolvers: &'a Arc<[ModuleResolver]>,
79 ) -> Result<Expr> {
80 self.resolve_modules_int(&ModPath::root(), &None, resolvers).await
81 }
82
83 async fn resolve_modules_int<'a>(
84 &'a self,
85 scope: &ModPath,
86 prepend: &'a Option<Arc<ModuleResolver>>,
87 resolvers: &'a Arc<[ModuleResolver]>,
88 ) -> Result<Expr> {
89 if self.has_unresolved_modules() {
90 self.resolve_modules_inner(scope, prepend, resolvers).await
91 } else {
92 Ok(self.clone())
93 }
94 }
95
96 fn resolve_modules_inner<'a>(
97 &'a self,
98 scope: &'a ModPath,
99 prepend: &'a Option<Arc<ModuleResolver>>,
100 resolvers: &'a Arc<[ModuleResolver]>,
101 ) -> Pin<Box<dyn Future<Output = Result<Expr>> + Send + Sync + 'a>> {
102 macro_rules! subexprs {
103 ($args:expr) => {{
104 try_join_all($args.iter().map(|e| async {
105 e.resolve_modules_int(scope, prepend, resolvers).await
106 }))
107 .await?
108 }};
109 }
110 macro_rules! subtuples {
111 ($args:expr) => {{
112 try_join_all($args.iter().map(|(k, e)| async {
113 Ok::<_, anyhow::Error>((
114 k.clone(),
115 e.resolve_modules_int(scope, prepend, resolvers).await?,
116 ))
117 }))
118 .await?
119 }};
120 }
121 macro_rules! only_args {
122 ($kind:ident, $args:expr) => {
123 Box::pin(async move {
124 let args = Arc::from(subexprs!($args));
125 Ok(Expr {
126 id: self.id,
127 ori: self.ori.clone(),
128 pos: self.pos,
129 kind: ExprKind::$kind { args },
130 })
131 })
132 };
133 }
134 macro_rules! bin_op {
135 ($kind:ident, $lhs:expr, $rhs:expr) => {
136 Box::pin(async move {
137 let (lhs, rhs) = try_join!(
138 $lhs.resolve_modules_int(scope, prepend, resolvers),
139 $rhs.resolve_modules_int(scope, prepend, resolvers)
140 )?;
141 Ok(Expr {
142 id: self.id,
143 ori: self.ori.clone(),
144 pos: self.pos,
145 kind: ExprKind::$kind {
146 lhs: Arc::from(lhs),
147 rhs: Arc::from(rhs),
148 },
149 })
150 })
151 };
152 }
153 async fn resolve(
154 scope: ModPath,
155 prepend: Option<Arc<ModuleResolver>>,
156 resolvers: Arc<[ModuleResolver]>,
157 id: ExprId,
158 parent: Arc<Origin>,
159 pos: SourcePosition,
160 export: bool,
161 name: ArcStr,
162 ) -> Result<Expr> {
163 let jh = task::spawn(async move {
164 let ts = Instant::now();
165 let name_rel = name.trim_start_matches(Path::SEP);
166 let name_mod = Path::from(name.clone()).append("mod.gx");
167 let name_mod = name_mod.trim_start_matches(Path::SEP);
168 let mut errors = vec![];
169 for r in prepend.iter().map(|r| r.as_ref()).chain(resolvers.iter()) {
170 let ori = match r {
171 ModuleResolver::VFS(vfs) => {
172 let scoped = scope.append(&*name);
173 match vfs.get(&scoped) {
174 Some(s) => Origin {
175 parent: Some(parent.clone()),
176 source: Source::Internal(name.clone()),
177 text: s.clone(),
178 },
179 None => continue,
180 }
181 }
182 ModuleResolver::Files(base) => {
183 let full_path = base
184 .join(name_rel)
185 .with_extension("gx")
186 .canonicalize()?;
187 match tokio::fs::read_to_string(&full_path).await {
188 Ok(s) => Origin {
189 parent: Some(parent.clone()),
190 source: Source::File(full_path),
191 text: ArcStr::from(s),
192 },
193 Err(_) => {
194 let full_path = base.join(name_mod).canonicalize()?;
195 match tokio::fs::read_to_string(&full_path).await {
196 Ok(s) => Origin {
197 parent: Some(parent.clone()),
198 source: Source::File(full_path),
199 text: ArcStr::from(s),
200 },
201 Err(e) => {
202 errors.push(anyhow::Error::from(e));
203 continue;
204 }
205 }
206 }
207 }
208 }
209 ModuleResolver::Netidx { subscriber, base, timeout } => {
210 let full_path = base.append(name_rel);
211 let source = Source::Netidx(full_path.clone());
212 let sub = subscriber
213 .subscribe_nondurable_one(full_path, *timeout)
214 .await;
215 match sub {
216 Err(e) => {
217 errors.push(e);
218 continue;
219 }
220 Ok(v) => match v.last() {
221 Event::Update(Value::String(text)) => Origin {
222 parent: Some(parent.clone()),
223 source,
224 text,
225 },
226 Event::Unsubscribed | Event::Update(_) => {
227 errors.push(anyhow!("expected string"));
228 continue;
229 }
230 },
231 }
232 }
233 };
234 let value = ModuleKind::Resolved(
235 parser::parse(ori.clone())
236 .with_context(|| format!("parsing file {ori:?}"))?,
237 );
238 let kind = ExprKind::Module { name, export, value };
239 format_with_flags(PrintFlag::NoSource | PrintFlag::NoParents, || {
240 info!("load and parse {ori} {:?}", ts.elapsed())
241 });
242 return Ok(Expr { id, ori: Arc::new(ori), pos, kind });
243 }
244 bail!("module {name} could not be found {errors:?}")
245 });
246 jh.await?
247 }
248 if !self.has_unresolved_modules() {
249 return Box::pin(async { Ok(self.clone()) });
250 }
251 match self.kind.clone() {
252 ExprKind::Module { value: ModuleKind::Unresolved, export, name } => {
253 let (id, pos, prepend, resolvers) =
254 (self.id, self.pos, prepend.clone(), Arc::clone(resolvers));
255 Box::pin(async move {
256 let e = resolve(
257 scope.clone(),
258 prepend.clone(),
259 resolvers.clone(),
260 id,
261 self.ori.clone(),
262 pos,
263 export,
264 name.clone(),
265 )
266 .await?;
267 let scope = ModPath(scope.append(&*name));
268 e.resolve_modules_int(&scope, &prepend, &resolvers).await
269 })
270 }
271 ExprKind::Constant(_)
272 | ExprKind::Use { .. }
273 | ExprKind::Ref { .. }
274 | ExprKind::StructRef { .. }
275 | ExprKind::TupleRef { .. }
276 | ExprKind::TypeDef { .. } => Box::pin(async move { Ok(self.clone()) }),
277 ExprKind::Module { value: ModuleKind::Inline(exprs), export, name } => {
278 Box::pin(async move {
279 let scope = ModPath(scope.append(&*name));
280 let exprs = try_join_all(exprs.iter().map(|e| async {
281 e.resolve_modules_int(&scope, prepend, resolvers).await
282 }))
283 .await?;
284 Ok(Expr {
285 id: self.id,
286 ori: self.ori.clone(),
287 pos: self.pos,
288 kind: ExprKind::Module {
289 value: ModuleKind::Inline(Arc::from(exprs)),
290 name,
291 export,
292 },
293 })
294 })
295 }
296 ExprKind::Module { value: ModuleKind::Resolved(exprs), export, name } => {
297 Box::pin(async move {
298 let prepend = match &self.ori.source {
299 Source::Unspecified | Source::Internal(_) => None,
300 Source::File(p) => {
301 p.parent().map(|p| Arc::new(ModuleResolver::Files(p.into())))
302 }
303 Source::Netidx(p) => resolvers.iter().find_map(|m| match m {
304 ModuleResolver::Netidx { subscriber, timeout, .. } => {
305 Some(Arc::new(ModuleResolver::Netidx {
306 subscriber: subscriber.clone(),
307 base: p.clone(),
308 timeout: *timeout,
309 }))
310 }
311 ModuleResolver::Files(_) | ModuleResolver::VFS(_) => None,
312 }),
313 };
314 let exprs = try_join_all(exprs.iter().map(|e| async {
315 e.resolve_modules_int(&scope, &prepend, resolvers).await
316 }))
317 .await?;
318 Ok(Expr {
319 id: self.id,
320 ori: self.ori.clone(),
321 pos: self.pos,
322 kind: ExprKind::Module {
323 value: ModuleKind::Resolved(Arc::from(exprs)),
324 name,
325 export,
326 },
327 })
328 })
329 }
330 ExprKind::Module {
331 name,
332 export,
333 value: ModuleKind::Dynamic { sandbox, sig, source },
334 } => Box::pin(async move {
335 let source = Arc::new(
336 source.resolve_modules_int(scope, prepend, resolvers).await?,
337 );
338 Ok(Expr {
339 id: self.id,
340 ori: self.ori.clone(),
341 pos: self.pos,
342 kind: ExprKind::Module {
343 name,
344 export,
345 value: ModuleKind::Dynamic { sandbox, sig, source },
346 },
347 })
348 }),
349 ExprKind::Do { exprs } => Box::pin(async move {
350 let exprs = Arc::from(subexprs!(exprs));
351 Ok(Expr {
352 id: self.id,
353 ori: self.ori.clone(),
354 pos: self.pos,
355 kind: ExprKind::Do { exprs },
356 })
357 }),
358 ExprKind::Bind(b) => Box::pin(async move {
359 let Bind { rec, doc, pattern, typ, export, value } = &*b;
360 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
361 Ok(Expr {
362 id: self.id,
363 ori: self.ori.clone(),
364 pos: self.pos,
365 kind: ExprKind::Bind(Arc::new(Bind {
366 rec: *rec,
367 doc: doc.clone(),
368 pattern: pattern.clone(),
369 typ: typ.clone(),
370 export: *export,
371 value,
372 })),
373 })
374 }),
375 ExprKind::StructWith { source, replace } => Box::pin(async move {
376 Ok(Expr {
377 id: self.id,
378 ori: self.ori.clone(),
379 pos: self.pos,
380 kind: ExprKind::StructWith {
381 source: Arc::new(
382 source.resolve_modules_int(scope, prepend, resolvers).await?,
383 ),
384 replace: Arc::from(subtuples!(replace)),
385 },
386 })
387 }),
388 ExprKind::Connect { name, value, deref } => Box::pin(async move {
389 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
390 Ok(Expr {
391 id: self.id,
392 ori: self.ori.clone(),
393 pos: self.pos,
394 kind: ExprKind::Connect { name, value: Arc::new(value), deref },
395 })
396 }),
397 ExprKind::Lambda(l) => Box::pin(async move {
398 let Lambda { args, vargs, rtype, constraints, body } = &*l;
399 let body = match body {
400 Either::Right(s) => Either::Right(s.clone()),
401 Either::Left(e) => Either::Left(
402 e.resolve_modules_int(scope, prepend, resolvers).await?,
403 ),
404 };
405 let l = Lambda {
406 args: args.clone(),
407 vargs: vargs.clone(),
408 rtype: rtype.clone(),
409 constraints: constraints.clone(),
410 body,
411 };
412 let kind = ExprKind::Lambda(Arc::new(l));
413 Ok(Expr { id: self.id, ori: self.ori.clone(), pos: self.pos, kind })
414 }),
415 ExprKind::TypeCast { expr, typ } => Box::pin(async move {
416 let expr = expr.resolve_modules_int(scope, prepend, resolvers).await?;
417 Ok(Expr {
418 id: self.id,
419 ori: self.ori.clone(),
420 pos: self.pos,
421 kind: ExprKind::TypeCast { expr: Arc::new(expr), typ },
422 })
423 }),
424 ExprKind::Apply { args, function } => Box::pin(async move {
425 Ok(Expr {
426 id: self.id,
427 ori: self.ori.clone(),
428 pos: self.pos,
429 kind: ExprKind::Apply { args: Arc::from(subtuples!(args)), function },
430 })
431 }),
432 ExprKind::Any { args } => only_args!(Any, args),
433 ExprKind::Array { args } => only_args!(Array, args),
434 ExprKind::Tuple { args } => only_args!(Tuple, args),
435 ExprKind::StringInterpolate { args } => only_args!(StringInterpolate, args),
436 ExprKind::Struct { args } => Box::pin(async move {
437 let args = Arc::from(subtuples!(args));
438 Ok(Expr {
439 id: self.id,
440 ori: self.ori.clone(),
441 pos: self.pos,
442 kind: ExprKind::Struct { args },
443 })
444 }),
445 ExprKind::ArrayRef { source, i } => Box::pin(async move {
446 let source = Arc::new(
447 source.resolve_modules_int(scope, prepend, resolvers).await?,
448 );
449 let i = Arc::new(i.resolve_modules_int(scope, prepend, resolvers).await?);
450 Ok(Expr {
451 id: self.id,
452 ori: self.ori.clone(),
453 pos: self.pos,
454 kind: ExprKind::ArrayRef { source, i },
455 })
456 }),
457 ExprKind::ArraySlice { source, start, end } => Box::pin(async move {
458 let source = Arc::new(
459 source.resolve_modules_int(scope, prepend, resolvers).await?,
460 );
461 let start = match start {
462 None => None,
463 Some(e) => Some(Arc::new(
464 e.resolve_modules_int(scope, prepend, resolvers).await?,
465 )),
466 };
467 let end = match end {
468 None => None,
469 Some(e) => Some(Arc::new(
470 e.resolve_modules_int(scope, prepend, resolvers).await?,
471 )),
472 };
473 Ok(Expr {
474 id: self.id,
475 ori: self.ori.clone(),
476 pos: self.pos,
477 kind: ExprKind::ArraySlice { source, start, end },
478 })
479 }),
480 ExprKind::Variant { tag, args } => Box::pin(async move {
481 let args = Arc::from(subexprs!(args));
482 Ok(Expr {
483 id: self.id,
484 ori: self.ori.clone(),
485 pos: self.pos,
486 kind: ExprKind::Variant { tag, args },
487 })
488 }),
489 ExprKind::Select { arg, arms } => Box::pin(async move {
490 let arg =
491 Arc::new(arg.resolve_modules_int(scope, prepend, resolvers).await?);
492 let arms = try_join_all(arms.iter().map(|(p, e)| async {
493 let p = match &p.guard {
494 None => p.clone(),
495 Some(e) => {
496 let e =
497 e.resolve_modules_int(scope, prepend, resolvers).await?;
498 Pattern {
499 guard: Some(e),
500 type_predicate: p.type_predicate.clone(),
501 structure_predicate: p.structure_predicate.clone(),
502 }
503 }
504 };
505 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
506 Ok::<_, anyhow::Error>((p, e))
507 }))
508 .await?;
509 Ok(Expr {
510 id: self.id,
511 ori: self.ori.clone(),
512 pos: self.pos,
513 kind: ExprKind::Select { arg, arms: Arc::from(arms) },
514 })
515 }),
516 ExprKind::Qop(e) => Box::pin(async move {
517 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
518 Ok(Expr {
519 id: self.id,
520 ori: self.ori.clone(),
521 pos: self.pos,
522 kind: ExprKind::Qop(Arc::new(e)),
523 })
524 }),
525 ExprKind::ByRef(e) => Box::pin(async move {
526 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
527 Ok(Expr {
528 id: self.id,
529 ori: self.ori.clone(),
530 pos: self.pos,
531 kind: ExprKind::ByRef(Arc::new(e)),
532 })
533 }),
534 ExprKind::Deref(e) => Box::pin(async move {
535 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
536 Ok(Expr {
537 id: self.id,
538 ori: self.ori.clone(),
539 pos: self.pos,
540 kind: ExprKind::Deref(Arc::new(e)),
541 })
542 }),
543 ExprKind::Not { expr: e } => Box::pin(async move {
544 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
545 Ok(Expr {
546 id: self.id,
547 ori: self.ori.clone(),
548 pos: self.pos,
549 kind: ExprKind::Not { expr: Arc::new(e) },
550 })
551 }),
552 ExprKind::Add { lhs, rhs } => bin_op!(Add, lhs, rhs),
553 ExprKind::Sub { lhs, rhs } => bin_op!(Sub, lhs, rhs),
554 ExprKind::Mul { lhs, rhs } => bin_op!(Mul, lhs, rhs),
555 ExprKind::Div { lhs, rhs } => bin_op!(Div, lhs, rhs),
556 ExprKind::Mod { lhs, rhs } => bin_op!(Mul, lhs, rhs),
557 ExprKind::And { lhs, rhs } => bin_op!(And, lhs, rhs),
558 ExprKind::Or { lhs, rhs } => bin_op!(Or, lhs, rhs),
559 ExprKind::Eq { lhs, rhs } => bin_op!(Eq, lhs, rhs),
560 ExprKind::Ne { lhs, rhs } => bin_op!(Ne, lhs, rhs),
561 ExprKind::Gt { lhs, rhs } => bin_op!(Gt, lhs, rhs),
562 ExprKind::Lt { lhs, rhs } => bin_op!(Lt, lhs, rhs),
563 ExprKind::Gte { lhs, rhs } => bin_op!(Gte, lhs, rhs),
564 ExprKind::Lte { lhs, rhs } => bin_op!(Lte, lhs, rhs),
565 ExprKind::Sample { lhs, rhs } => bin_op!(Sample, lhs, rhs),
566 }
567 }
568}