Skip to main content

relon_eval_api/
module.rs

1//! Module resolution protocol.
2//!
3//! `@import("path")` does not look up files itself. Instead, the evaluator
4//! asks each registered [`ModuleResolver`] in order until one returns
5//! `Some(ModuleSource)`. The evaluator then parses and evaluates that
6//! source once, caching the result by its [`ModuleSource::canonical_id`].
7//!
8//! Concrete resolver implementations (`StdModuleResolver`,
9//! `FilesystemModuleResolver`, host-supplied resolvers) live in the
10//! backend crate (`relon-evaluator`); the trait + payload type live here
11//! so any backend implementing [`crate::Evaluator`] can share them.
12
13use crate::error::RuntimeError;
14use crate::scope::Scope;
15use relon_parser::TokenRange;
16use std::sync::Arc;
17
18/// The source text plus identity of a module produced by a [`ModuleResolver`].
19#[derive(Debug, Clone)]
20pub struct ModuleSource {
21    /// Stable identity for this module — used as the key for the module cache
22    /// and the cycle-detection stack. For filesystem modules this is the
23    /// canonical absolute path; for `std/...` modules it is the virtual path
24    /// itself; for host-provided modules it can be any unique string.
25    pub canonical_id: String,
26    /// The Relon source text to parse and evaluate.
27    pub source: String,
28    /// Working directory used when nested `@import("./relative.relon")` calls
29    /// fire from inside this module. Filesystem resolvers normally set this to
30    /// the parent of `canonical_id`; in-memory modules can leave it empty.
31    pub current_dir: String,
32}
33
34/// A pluggable resolver that answers `@import("path")` requests.
35///
36/// Resolvers are polled in order; the first non-`None` return value is used.
37/// Returning `Ok(None)` defers to the next resolver. Returning `Err(_)` aborts
38/// the import without consulting later resolvers.
39pub trait ModuleResolver: Send + Sync {
40    fn resolve(
41        &self,
42        path: &str,
43        scope: &Arc<Scope>,
44        range: TokenRange,
45    ) -> Result<Option<ModuleSource>, RuntimeError>;
46}