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