Resolve `source`'s module imports. Each `alias := import("path")` adds its exported interface to the prelude and yields an export set for qualified access.
(&self, source: &str)
| 453 | fn resolve_modules(&self, source: &str) -> Result<ResolvedModules, Vec<Diagnostic>> { |
| 454 | let mut prelude = String::new(); |
| 455 | let mut aliases: std::collections::HashMap<String, hll_to_ir::imports::ModuleAlias> = |
| 456 | std::collections::HashMap::new(); |
| 457 | // Import aliases are namespace handles, not symbol definitions, so they never |
| 458 | // conflict with a same-named export such as `klog := import("klog")`. |
| 459 | |
| 460 | // An unparseable root skips resolution; the compiler reports it with a span. |
| 461 | let Ok(mut local_names) = hll_to_ir::imports::collect_declaration_names(source) else { |
| 462 | return Ok(ResolvedModules { |
| 463 | prelude: None, |
| 464 | aliases: std::collections::HashMap::new(), |
| 465 | }); |
| 466 | }; |
| 467 | for (alias, _) in hll_to_ir::imports::collect_module_imports(source) |
| 468 | .map_err(|msg| vec![Diagnostic::new(DiagnosticLevel::Error, msg)])? |
| 469 | { |
| 470 | local_names.remove(&alias); |
| 471 | } |
| 472 | let mut imported_exports: std::collections::HashMap<String, String> = |
| 473 | std::collections::HashMap::new(); |
| 474 | |
| 475 | if self.module_resolver.is_some() || self.current_source_path.is_some() { |
| 476 | let module_imports = hll_to_ir::imports::collect_module_imports(source) |
| 477 | .map_err(|msg| vec![Diagnostic::new(DiagnosticLevel::Error, msg)])?; |
| 478 | for (alias, path) in module_imports { |
| 479 | if aliases.contains_key(&alias) { |
| 480 | return Err(vec![Diagnostic::new( |
| 481 | DiagnosticLevel::Error, |
| 482 | format!("duplicate module import alias `{alias}`"), |
| 483 | )]); |
| 484 | } |
| 485 | let resolved = self |
| 486 | .resolve_module_source(&path, self.current_source_path.as_deref()) |
| 487 | .map_err(|msg| vec![Diagnostic::new(DiagnosticLevel::Error, msg)])? |
| 488 | .ok_or_else(|| { |
| 489 | let key = Self::module_key(&path); |
| 490 | vec![Diagnostic::new( |
| 491 | DiagnosticLevel::Error, |
| 492 | format!("cannot resolve import(\"{path}\"): no module named `{key}`"), |
| 493 | )] |
| 494 | })?; |
| 495 | let exports = |
| 496 | hll_to_ir::imports::collect_exports(&resolved.source).map_err(|msg| { |
| 497 | vec![Diagnostic::new( |
| 498 | DiagnosticLevel::Error, |
| 499 | format!("failed to read exports of \"{path}\": {msg}"), |
| 500 | )] |
| 501 | })?; |
| 502 | // Interfaces and generic templates: prefixed like exports, but not link symbols. |
| 503 | let namespaced = hll_to_ir::imports::collect_exported_interfaces(&resolved.source) |
| 504 | .map_err(|msg| { |
| 505 | vec![Diagnostic::new( |
| 506 | DiagnosticLevel::Error, |
| 507 | format!("failed to read interfaces of \"{path}\": {msg}"), |
| 508 | )] |
| 509 | })?; |
| 510 | // Only modules the closure itself compiles are mangled. Stdlib modules are |
| 511 | // precompiled flat and skipped by the closure, so importing one resolves flat. |
| 512 | let mangle_this = self.mangle_modules && !resolved.is_stdlib; |
no test coverage detected