use std::sync::Arc;
use beamr::atom::{Atom, AtomTable};
use beamr::module::{ModuleRegistry, ResolvedImportTarget};
use beamr::namespace::NamespaceId;
use beamr::native::{BifRegistryImpl, NativeRegistrationError};
use beamr::scheduler::{Scheduler, SchedulerConfig, SchedulerServices};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum SchedulerCompositionError {
#[error("BIF registry population failed: {source}")]
BifRegistration {
#[source]
source: NativeRegistrationError,
},
#[error("scheduler construction failed: {detail}")]
Construction {
detail: String,
},
}
pub fn compose_scheduler(
config: SchedulerConfig,
services: SchedulerServices,
module_registry: Arc<ModuleRegistry>,
) -> Result<Scheduler, SchedulerCompositionError> {
let atom_table = Arc::new(AtomTable::with_common_atoms());
let bif_registry = Arc::new(BifRegistryImpl::new());
beamr::native::bifs::register_gate1_bifs(&bif_registry, &atom_table)
.map_err(|source| SchedulerCompositionError::BifRegistration { source })?;
Scheduler::with_services_and_code_server(
config,
services,
module_registry,
atom_table,
bif_registry,
)
.map_err(|detail| SchedulerCompositionError::Construction { detail })
}
pub(crate) fn resolve_atom(scheduler: &Scheduler, atom: Atom) -> String {
scheduler
.atom_table()
.resolve(atom)
.map_or_else(|| format!("{atom:?}"), str::to_owned)
}
pub(crate) fn deferred_erlang_imports(scheduler: &Scheduler, module: Atom) -> Option<Vec<String>> {
let committed = scheduler.lookup_module_in(NamespaceId::DEFAULT, module)?;
let erlang = scheduler.atom_table().intern("erlang");
Some(
committed
.resolved_imports
.iter()
.filter(|import| {
import.module == erlang
&& matches!(import.target, ResolvedImportTarget::Deferred { .. })
})
.map(|import| {
format!(
"erlang:{}/{}",
resolve_atom(scheduler, import.function),
import.arity
)
})
.collect(),
)
}