Files
Decodal/crates/decodal-core/src/module.rs
T

105 lines
2.5 KiB
Rust

use alloc::{string::String, vec::Vec};
use crate::{
Ast, ExprId, SourceForm, SourceId, Value,
runtime::{EnvId, ThunkId},
};
#[derive(Debug, Clone)]
pub struct Module {
pub key: String,
pub name: String,
pub source: SourceId,
pub ast: Ast,
pub root: ExprId,
pub source_form: SourceForm,
pub root_env: EnvId,
pub root_thunk: ThunkId,
}
/// Content resolved by an [`ImportLoader`].
#[derive(Debug, Clone)]
pub enum LoadedImport {
Source {
key: String,
name: String,
source: String,
},
Value {
key: String,
value: Value,
},
}
/// An import specifier offered by host-owned language tooling.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImportCandidate {
pub specifier: String,
pub detail: Option<String>,
}
impl ImportCandidate {
pub fn new(specifier: impl Into<String>) -> Self {
Self {
specifier: specifier.into(),
detail: None,
}
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
}
impl LoadedImport {
pub fn source(
key: impl Into<String>,
name: impl Into<String>,
source: impl Into<String>,
) -> Self {
Self::Source {
key: key.into(),
name: name.into(),
source: source.into(),
}
}
pub fn value(key: impl Into<String>, value: Value) -> Self {
Self::Value {
key: key.into(),
value,
}
}
}
pub trait ImportLoader {
fn load(&mut self, current_key: Option<&str>, specifier: &str) -> crate::Result<LoadedImport>;
/// Returns host-resolvable import specifiers matching an unfinished prefix.
///
/// Runtime-only loaders may keep the default implementation. Hosts that
/// provide an editor should implement this from the same namespace used by
/// [`ImportLoader::load`].
fn complete_import(
&mut self,
_current_key: Option<&str>,
_prefix: &str,
) -> crate::Result<Vec<ImportCandidate>> {
Ok(Vec::new())
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct EmptyLoader;
impl ImportLoader for EmptyLoader {
fn load(&mut self, _current_key: Option<&str>, specifier: &str) -> crate::Result<LoadedImport> {
Err(crate::Diagnostic::new(
crate::DiagnosticKind::Import,
crate::Span::default(),
alloc::format!("no source loader is configured for import `{specifier}`"),
))
}
}