1use crate::{
2 expr::{
3 parser, Bind, CouldNotResolve, Expr, ExprId, ExprKind, Lambda, ModPath,
4 ModuleKind, Origin, Pattern, Source, TryCatch,
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
62async fn resolve(
63 scope: ModPath,
64 prepend: Option<Arc<ModuleResolver>>,
65 resolvers: Arc<[ModuleResolver]>,
66 id: ExprId,
67 parent: Arc<Origin>,
68 pos: SourcePosition,
69 export: bool,
70 name: ArcStr,
71) -> Result<Expr> {
72 let jh = task::spawn(async move {
73 let ts = Instant::now();
74 let name = Path::from(name);
75 let mut errors = vec![];
76 for r in prepend.iter().map(|r| r.as_ref()).chain(resolvers.iter()) {
77 let ori = match r {
78 ModuleResolver::VFS(vfs) => {
79 let scoped = scope.append(&name);
80 match vfs.get(&scoped) {
81 Some(s) => Origin {
82 parent: Some(parent.clone()),
83 source: Source::Internal(name.clone().into()),
84 text: s.clone(),
85 },
86 None => continue,
87 }
88 }
89 ModuleResolver::Files(base) => {
90 let mut full_path = base.clone();
91 for part in Path::parts(&name) {
92 full_path.push(part);
93 }
94 full_path.set_extension("gx");
95 match tokio::fs::read_to_string(&full_path).await {
96 Ok(s) => Origin {
97 parent: Some(parent.clone()),
98 source: Source::File(full_path),
99 text: ArcStr::from(s),
100 },
101 Err(_) => {
102 full_path.set_extension("");
103 full_path.push("mod.gx");
104 match tokio::fs::read_to_string(&full_path).await {
105 Ok(s) => Origin {
106 parent: Some(parent.clone()),
107 source: Source::File(full_path),
108 text: ArcStr::from(s),
109 },
110 Err(e) => {
111 errors.push(anyhow::Error::from(e));
112 continue;
113 }
114 }
115 }
116 }
117 }
118 ModuleResolver::Netidx { subscriber, base, timeout } => {
119 let full_path = base.append(&name);
120 let source = Source::Netidx(full_path.clone());
121 let sub =
122 subscriber.subscribe_nondurable_one(full_path, *timeout).await;
123 match sub {
124 Err(e) => {
125 errors.push(e);
126 continue;
127 }
128 Ok(v) => match v.last() {
129 Event::Update(Value::String(text)) => {
130 Origin { parent: Some(parent.clone()), source, text }
131 }
132 Event::Unsubscribed | Event::Update(_) => {
133 errors.push(anyhow!("expected string"));
134 continue;
135 }
136 },
137 }
138 }
139 };
140 let value = ModuleKind::Resolved(
141 parser::parse(ori.clone())
142 .with_context(|| format!("parsing file {ori:?}"))?,
143 );
144 let kind = ExprKind::Module { name: name.clone().into(), export, value };
145 format_with_flags(PrintFlag::NoSource | PrintFlag::NoParents, || {
146 info!("load and parse {ori} {:?}", ts.elapsed())
147 });
148 return Ok(Expr { id, ori: Arc::new(ori), pos, kind });
149 }
150 bail!("module {name} could not be found {errors:?}")
151 });
152 jh.await?
153}
154
155impl Expr {
156 pub fn has_unresolved_modules(&self) -> bool {
157 self.fold(false, &mut |acc, e| {
158 acc || match &e.kind {
159 ExprKind::Module { value: ModuleKind::Unresolved, .. } => true,
160 _ => false,
161 }
162 })
163 }
164
165 pub async fn resolve_modules<'a>(
170 &'a self,
171 resolvers: &'a Arc<[ModuleResolver]>,
172 ) -> Result<Expr> {
173 self.resolve_modules_int(&ModPath::root(), &None, resolvers).await
174 }
175
176 async fn resolve_modules_int<'a>(
177 &'a self,
178 scope: &ModPath,
179 prepend: &'a Option<Arc<ModuleResolver>>,
180 resolvers: &'a Arc<[ModuleResolver]>,
181 ) -> Result<Expr> {
182 if self.has_unresolved_modules() {
183 self.resolve_modules_inner(scope, prepend, resolvers).await
184 } else {
185 Ok(self.clone())
186 }
187 }
188
189 fn resolve_modules_inner<'a>(
190 &'a self,
191 scope: &'a ModPath,
192 prepend: &'a Option<Arc<ModuleResolver>>,
193 resolvers: &'a Arc<[ModuleResolver]>,
194 ) -> Pin<Box<dyn Future<Output = Result<Expr>> + Send + Sync + 'a>> {
195 macro_rules! subexprs {
196 ($args:expr) => {{
197 try_join_all($args.iter().map(|e| async {
198 e.resolve_modules_int(scope, prepend, resolvers).await
199 }))
200 .await?
201 }};
202 }
203 macro_rules! subtuples {
204 ($args:expr) => {{
205 try_join_all($args.iter().map(|(k, e)| async {
206 Ok::<_, anyhow::Error>((
207 k.clone(),
208 e.resolve_modules_int(scope, prepend, resolvers).await?,
209 ))
210 }))
211 .await?
212 }};
213 }
214 macro_rules! expr {
215 ($kind:expr) => {
216 Ok(Expr {
217 id: self.id,
218 ori: self.ori.clone(),
219 pos: self.pos,
220 kind: $kind,
221 })
222 };
223 }
224 macro_rules! only_args {
225 ($kind:ident, $args:expr) => {
226 Box::pin(async move {
227 let args = Arc::from(subexprs!($args));
228 expr!(ExprKind::$kind { args })
229 })
230 };
231 }
232 macro_rules! bin_op {
233 ($kind:ident, $lhs:expr, $rhs:expr) => {
234 Box::pin(async move {
235 let (lhs, rhs) = try_join!(
236 $lhs.resolve_modules_int(scope, prepend, resolvers),
237 $rhs.resolve_modules_int(scope, prepend, resolvers)
238 )?;
239 expr!(ExprKind::$kind { lhs: Arc::from(lhs), rhs: Arc::from(rhs) })
240 })
241 };
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 .with_context(|| CouldNotResolve(name.clone()))?;
263 let scope = ModPath(scope.append(&*name));
264 e.resolve_modules_int(&scope, &prepend, &resolvers).await
265 })
266 }
267 ExprKind::Constant(_)
268 | ExprKind::Use { .. }
269 | ExprKind::Ref { .. }
270 | ExprKind::StructRef { .. }
271 | ExprKind::TupleRef { .. }
272 | ExprKind::TypeDef { .. } => Box::pin(async move { Ok(self.clone()) }),
273 ExprKind::Module { value: ModuleKind::Inline(exprs), export, name } => {
274 Box::pin(async move {
275 let scope = ModPath(scope.append(&*name));
276 let exprs = try_join_all(exprs.iter().map(|e| async {
277 e.resolve_modules_int(&scope, prepend, resolvers).await
278 }))
279 .await?;
280 expr!(ExprKind::Module {
281 value: ModuleKind::Inline(Arc::from(exprs)),
282 name,
283 export,
284 })
285 })
286 }
287 ExprKind::Module { value: ModuleKind::Resolved(exprs), export, name } => {
288 Box::pin(async move {
289 let prepend = match &self.ori.source {
290 Source::Unspecified | Source::Internal(_) => None,
291 Source::File(p) => {
292 p.parent().map(|p| Arc::new(ModuleResolver::Files(p.into())))
293 }
294 Source::Netidx(p) => resolvers.iter().find_map(|m| match m {
295 ModuleResolver::Netidx { subscriber, timeout, .. } => {
296 Some(Arc::new(ModuleResolver::Netidx {
297 subscriber: subscriber.clone(),
298 base: p.clone(),
299 timeout: *timeout,
300 }))
301 }
302 ModuleResolver::Files(_) | ModuleResolver::VFS(_) => None,
303 }),
304 };
305 let exprs = try_join_all(exprs.iter().map(|e| async {
306 e.resolve_modules_int(&scope, &prepend, resolvers).await
307 }))
308 .await?;
309 expr!(ExprKind::Module {
310 value: ModuleKind::Resolved(Arc::from(exprs)),
311 name,
312 export,
313 })
314 })
315 }
316 ExprKind::Module {
317 name,
318 export,
319 value: ModuleKind::Dynamic { sandbox, sig, source },
320 } => Box::pin(async move {
321 let source = Arc::new(
322 source.resolve_modules_int(scope, prepend, resolvers).await?,
323 );
324 expr!(ExprKind::Module {
325 name,
326 export,
327 value: ModuleKind::Dynamic { sandbox, sig, source },
328 })
329 }),
330 ExprKind::Do { exprs } => Box::pin(async move {
331 let exprs = Arc::from(subexprs!(exprs));
332 expr!(ExprKind::Do { exprs })
333 }),
334 ExprKind::Bind(b) => Box::pin(async move {
335 let Bind { rec, doc, pattern, typ, export, value } = &*b;
336 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
337 expr!(ExprKind::Bind(Arc::new(Bind {
338 rec: *rec,
339 doc: doc.clone(),
340 pattern: pattern.clone(),
341 typ: typ.clone(),
342 export: *export,
343 value,
344 })))
345 }),
346 ExprKind::StructWith { source, replace } => Box::pin(async move {
347 expr!(ExprKind::StructWith {
348 source: Arc::new(
349 source.resolve_modules_int(scope, prepend, resolvers).await?,
350 ),
351 replace: Arc::from(subtuples!(replace)),
352 })
353 }),
354 ExprKind::Connect { name, value, deref } => Box::pin(async move {
355 let value = value.resolve_modules_int(scope, prepend, resolvers).await?;
356 expr!(ExprKind::Connect { name, value: Arc::new(value), deref })
357 }),
358 ExprKind::Lambda(l) => Box::pin(async move {
359 let Lambda { args, vargs, rtype, constraints, throws, body } = &*l;
360 let body = match body {
361 Either::Right(s) => Either::Right(s.clone()),
362 Either::Left(e) => Either::Left(
363 e.resolve_modules_int(scope, prepend, resolvers).await?,
364 ),
365 };
366 let l = Lambda {
367 args: args.clone(),
368 vargs: vargs.clone(),
369 rtype: rtype.clone(),
370 throws: throws.clone(),
371 constraints: constraints.clone(),
372 body,
373 };
374 expr!(ExprKind::Lambda(Arc::new(l)))
375 }),
376 ExprKind::TypeCast { expr, typ } => Box::pin(async move {
377 let expr = expr.resolve_modules_int(scope, prepend, resolvers).await?;
378 expr!(ExprKind::TypeCast { expr: Arc::new(expr), typ })
379 }),
380 ExprKind::Apply { args, function } => Box::pin(async move {
381 expr!(ExprKind::Apply { args: Arc::from(subtuples!(args)), function })
382 }),
383 ExprKind::Any { args } => only_args!(Any, args),
384 ExprKind::Array { args } => only_args!(Array, args),
385 ExprKind::Map { args } => Box::pin(async move {
386 let args = Arc::from(subtuples!(args));
387 expr!(ExprKind::Map { args })
388 }),
389 ExprKind::MapRef { source, key } => Box::pin(async move {
390 let source = Arc::new(
391 source.resolve_modules_int(scope, prepend, resolvers).await?,
392 );
393 let key =
394 Arc::new(key.resolve_modules_inner(scope, prepend, resolvers).await?);
395 expr!(ExprKind::MapRef { source, key })
396 }),
397 ExprKind::Tuple { args } => only_args!(Tuple, args),
398 ExprKind::StringInterpolate { args } => only_args!(StringInterpolate, args),
399 ExprKind::Struct { args } => Box::pin(async move {
400 let args = Arc::from(subtuples!(args));
401 expr!(ExprKind::Struct { args })
402 }),
403 ExprKind::ArrayRef { source, i } => Box::pin(async move {
404 let source = Arc::new(
405 source.resolve_modules_int(scope, prepend, resolvers).await?,
406 );
407 let i = Arc::new(i.resolve_modules_int(scope, prepend, resolvers).await?);
408 expr!(ExprKind::ArrayRef { source, i })
409 }),
410 ExprKind::ArraySlice { source, start, end } => Box::pin(async move {
411 let source = Arc::new(
412 source.resolve_modules_int(scope, prepend, resolvers).await?,
413 );
414 let start = match start {
415 None => None,
416 Some(e) => Some(Arc::new(
417 e.resolve_modules_int(scope, prepend, resolvers).await?,
418 )),
419 };
420 let end = match end {
421 None => None,
422 Some(e) => Some(Arc::new(
423 e.resolve_modules_int(scope, prepend, resolvers).await?,
424 )),
425 };
426 expr!(ExprKind::ArraySlice { source, start, end })
427 }),
428 ExprKind::Variant { tag, args } => Box::pin(async move {
429 let args = Arc::from(subexprs!(args));
430 expr!(ExprKind::Variant { tag, args })
431 }),
432 ExprKind::Select { arg, arms } => Box::pin(async move {
433 let arg =
434 Arc::new(arg.resolve_modules_int(scope, prepend, resolvers).await?);
435 let arms = try_join_all(arms.iter().map(|(p, e)| async {
436 let p = match &p.guard {
437 None => p.clone(),
438 Some(e) => {
439 let e =
440 e.resolve_modules_int(scope, prepend, resolvers).await?;
441 Pattern {
442 guard: Some(e),
443 type_predicate: p.type_predicate.clone(),
444 structure_predicate: p.structure_predicate.clone(),
445 }
446 }
447 };
448 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
449 Ok::<_, anyhow::Error>((p, e))
450 }))
451 .await?;
452 expr!(ExprKind::Select { arg, arms: Arc::from(arms) })
453 }),
454 ExprKind::Qop(e) => Box::pin(async move {
455 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
456 expr!(ExprKind::Qop(Arc::new(e)))
457 }),
458 ExprKind::OrNever(e) => Box::pin(async move {
459 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
460 expr!(ExprKind::OrNever(Arc::new(e)))
461 }),
462 ExprKind::TryCatch(tc) => Box::pin(async move {
463 let exprs = try_join_all(tc.exprs.iter().map(|e| async {
464 e.resolve_modules_int(&scope, &prepend, resolvers).await
465 }))
466 .await?;
467 let handler =
468 tc.handler.resolve_modules_int(scope, prepend, resolvers).await?;
469 expr!(ExprKind::TryCatch(Arc::new(TryCatch {
470 bind: tc.bind.clone(),
471 constraint: tc.constraint.clone(),
472 handler: Arc::new(handler),
473 exprs: Arc::from_iter(exprs),
474 })))
475 }),
476 ExprKind::ByRef(e) => Box::pin(async move {
477 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
478 expr!(ExprKind::ByRef(Arc::new(e)))
479 }),
480 ExprKind::Deref(e) => Box::pin(async move {
481 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
482 expr!(ExprKind::Deref(Arc::new(e)))
483 }),
484 ExprKind::Not { expr: e } => Box::pin(async move {
485 let e = e.resolve_modules_int(scope, prepend, resolvers).await?;
486 expr!(ExprKind::Not { expr: Arc::new(e) })
487 }),
488 ExprKind::Add { lhs, rhs } => bin_op!(Add, lhs, rhs),
489 ExprKind::Sub { lhs, rhs } => bin_op!(Sub, lhs, rhs),
490 ExprKind::Mul { lhs, rhs } => bin_op!(Mul, lhs, rhs),
491 ExprKind::Div { lhs, rhs } => bin_op!(Div, lhs, rhs),
492 ExprKind::Mod { lhs, rhs } => bin_op!(Mul, lhs, rhs),
493 ExprKind::And { lhs, rhs } => bin_op!(And, lhs, rhs),
494 ExprKind::Or { lhs, rhs } => bin_op!(Or, lhs, rhs),
495 ExprKind::Eq { lhs, rhs } => bin_op!(Eq, lhs, rhs),
496 ExprKind::Ne { lhs, rhs } => bin_op!(Ne, lhs, rhs),
497 ExprKind::Gt { lhs, rhs } => bin_op!(Gt, lhs, rhs),
498 ExprKind::Lt { lhs, rhs } => bin_op!(Lt, lhs, rhs),
499 ExprKind::Gte { lhs, rhs } => bin_op!(Gte, lhs, rhs),
500 ExprKind::Lte { lhs, rhs } => bin_op!(Lte, lhs, rhs),
501 ExprKind::Sample { lhs, rhs } => bin_op!(Sample, lhs, rhs),
502 }
503 }
504}