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