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::{self, 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 utils::split_escaped(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::Do { exprs } => Box::pin(async move {
331 let exprs = Arc::from(subexprs!(exprs));
332 Ok(Expr {
333 id: self.id,
334 ori: self.ori.clone(),
335 pos: self.pos,
336 kind: ExprKind::Do { exprs },
337 })
338 }),
339 ExprKind::Bind(b) => Box::pin(async move {
340 let Bind { doc, pattern, typ, export, value } = &*b;
341 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
342 Ok(Expr {
343 id: self.id,
344 ori: self.ori.clone(),
345 pos: self.pos,
346 kind: ExprKind::Bind(Arc::new(Bind {
347 doc: doc.clone(),
348 pattern: pattern.clone(),
349 typ: typ.clone(),
350 export: *export,
351 value,
352 })),
353 })
354 }),
355 ExprKind::StructWith { source, replace } => Box::pin(async move {
356 Ok(Expr {
357 id: self.id,
358 ori: self.ori.clone(),
359 pos: self.pos,
360 kind: ExprKind::StructWith {
361 source: Arc::new(
362 source.resolve_modules_int(scope, prepend, resolvers).await?,
363 ),
364 replace: Arc::from(subtuples!(replace)),
365 },
366 })
367 }),
368 ExprKind::Connect { name, value, deref } => Box::pin(async move {
369 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
370 Ok(Expr {
371 id: self.id,
372 ori: self.ori.clone(),
373 pos: self.pos,
374 kind: ExprKind::Connect { name, value: Arc::new(value), deref },
375 })
376 }),
377 ExprKind::Lambda(l) => Box::pin(async move {
378 let Lambda { args, vargs, rtype, constraints, body } = &*l;
379 let body = match body {
380 Either::Right(s) => Either::Right(s.clone()),
381 Either::Left(e) => Either::Left(
382 e.resolve_modules_int(scope, prepend, resolvers).await?,
383 ),
384 };
385 let l = Lambda {
386 args: args.clone(),
387 vargs: vargs.clone(),
388 rtype: rtype.clone(),
389 constraints: constraints.clone(),
390 body,
391 };
392 let kind = ExprKind::Lambda(Arc::new(l));
393 Ok(Expr { id: self.id, ori: self.ori.clone(), pos: self.pos, kind })
394 }),
395 ExprKind::TypeCast { expr, typ } => Box::pin(async move {
396 let expr = expr.resolve_modules_int(scope, prepend, resolvers).await?;
397 Ok(Expr {
398 id: self.id,
399 ori: self.ori.clone(),
400 pos: self.pos,
401 kind: ExprKind::TypeCast { expr: Arc::new(expr), typ },
402 })
403 }),
404 ExprKind::Apply { args, function } => Box::pin(async move {
405 Ok(Expr {
406 id: self.id,
407 ori: self.ori.clone(),
408 pos: self.pos,
409 kind: ExprKind::Apply { args: Arc::from(subtuples!(args)), function },
410 })
411 }),
412 ExprKind::Any { args } => only_args!(Any, args),
413 ExprKind::Array { args } => only_args!(Array, args),
414 ExprKind::Tuple { args } => only_args!(Tuple, args),
415 ExprKind::StringInterpolate { args } => only_args!(StringInterpolate, args),
416 ExprKind::Struct { args } => Box::pin(async move {
417 let args = Arc::from(subtuples!(args));
418 Ok(Expr {
419 id: self.id,
420 ori: self.ori.clone(),
421 pos: self.pos,
422 kind: ExprKind::Struct { args },
423 })
424 }),
425 ExprKind::ArrayRef { source, i } => Box::pin(async move {
426 let source = Arc::new(
427 source.resolve_modules_int(scope, prepend, resolvers).await?,
428 );
429 let i = Arc::new(i.resolve_modules_int(scope, prepend, resolvers).await?);
430 Ok(Expr {
431 id: self.id,
432 ori: self.ori.clone(),
433 pos: self.pos,
434 kind: ExprKind::ArrayRef { source, i },
435 })
436 }),
437 ExprKind::ArraySlice { source, start, end } => Box::pin(async move {
438 let source = Arc::new(
439 source.resolve_modules_int(scope, prepend, resolvers).await?,
440 );
441 let start = match start {
442 None => None,
443 Some(e) => Some(Arc::new(
444 e.resolve_modules_int(scope, prepend, resolvers).await?,
445 )),
446 };
447 let end = match end {
448 None => None,
449 Some(e) => Some(Arc::new(
450 e.resolve_modules_int(scope, prepend, resolvers).await?,
451 )),
452 };
453 Ok(Expr {
454 id: self.id,
455 ori: self.ori.clone(),
456 pos: self.pos,
457 kind: ExprKind::ArraySlice { source, start, end },
458 })
459 }),
460 ExprKind::Variant { tag, args } => Box::pin(async move {
461 let args = Arc::from(subexprs!(args));
462 Ok(Expr {
463 id: self.id,
464 ori: self.ori.clone(),
465 pos: self.pos,
466 kind: ExprKind::Variant { tag, args },
467 })
468 }),
469 ExprKind::Select { arg, arms } => Box::pin(async move {
470 let arg =
471 Arc::new(arg.resolve_modules_int(scope, prepend, resolvers).await?);
472 let arms = try_join_all(arms.iter().map(|(p, e)| async {
473 let p = match &p.guard {
474 None => p.clone(),
475 Some(e) => {
476 let e =
477 e.resolve_modules_int(scope, prepend, resolvers).await?;
478 Pattern {
479 guard: Some(e),
480 type_predicate: p.type_predicate.clone(),
481 structure_predicate: p.structure_predicate.clone(),
482 }
483 }
484 };
485 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
486 Ok::<_, anyhow::Error>((p, e))
487 }))
488 .await?;
489 Ok(Expr {
490 id: self.id,
491 ori: self.ori.clone(),
492 pos: self.pos,
493 kind: ExprKind::Select { arg, arms: Arc::from(arms) },
494 })
495 }),
496 ExprKind::Qop(e) => Box::pin(async move {
497 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
498 Ok(Expr {
499 id: self.id,
500 ori: self.ori.clone(),
501 pos: self.pos,
502 kind: ExprKind::Qop(Arc::new(e)),
503 })
504 }),
505 ExprKind::ByRef(e) => Box::pin(async move {
506 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
507 Ok(Expr {
508 id: self.id,
509 ori: self.ori.clone(),
510 pos: self.pos,
511 kind: ExprKind::ByRef(Arc::new(e)),
512 })
513 }),
514 ExprKind::Deref(e) => Box::pin(async move {
515 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
516 Ok(Expr {
517 id: self.id,
518 ori: self.ori.clone(),
519 pos: self.pos,
520 kind: ExprKind::Deref(Arc::new(e)),
521 })
522 }),
523 ExprKind::Not { expr: e } => Box::pin(async move {
524 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
525 Ok(Expr {
526 id: self.id,
527 ori: self.ori.clone(),
528 pos: self.pos,
529 kind: ExprKind::Not { expr: Arc::new(e) },
530 })
531 }),
532 ExprKind::Add { lhs, rhs } => bin_op!(Add, lhs, rhs),
533 ExprKind::Sub { lhs, rhs } => bin_op!(Sub, lhs, rhs),
534 ExprKind::Mul { lhs, rhs } => bin_op!(Mul, lhs, rhs),
535 ExprKind::Div { lhs, rhs } => bin_op!(Div, lhs, rhs),
536 ExprKind::Mod { lhs, rhs } => bin_op!(Mul, lhs, rhs),
537 ExprKind::And { lhs, rhs } => bin_op!(And, lhs, rhs),
538 ExprKind::Or { lhs, rhs } => bin_op!(Or, lhs, rhs),
539 ExprKind::Eq { lhs, rhs } => bin_op!(Eq, lhs, rhs),
540 ExprKind::Ne { lhs, rhs } => bin_op!(Ne, lhs, rhs),
541 ExprKind::Gt { lhs, rhs } => bin_op!(Gt, lhs, rhs),
542 ExprKind::Lt { lhs, rhs } => bin_op!(Lt, lhs, rhs),
543 ExprKind::Gte { lhs, rhs } => bin_op!(Gte, lhs, rhs),
544 ExprKind::Lte { lhs, rhs } => bin_op!(Lte, lhs, rhs),
545 ExprKind::Sample { lhs, rhs } => bin_op!(Sample, lhs, rhs),
546 }
547 }
548}