use alloc::string::String;

use crate::{
    Ast, ExprId, SourceForm, SourceId,
    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,
}

#[derive(Debug, Clone)]
pub struct LoadedSource {
    pub key: String,
    pub name: String,
    pub source: String,
}

pub trait SourceLoader {
    fn load(&mut self, current_key: Option<&str>, specifier: &str) -> crate::Result<LoadedSource>;
}

#[derive(Debug, Clone, Copy, Default)]
pub struct EmptyLoader;

impl SourceLoader for EmptyLoader {
    fn load(&mut self, _current_key: Option<&str>, specifier: &str) -> crate::Result<LoadedSource> {
        Err(crate::Diagnostic::new(
            crate::DiagnosticKind::Import,
            crate::Span::default(),
            alloc::format!("no source loader is configured for import `{specifier}`"),
        ))
    }
}
