use crate::lang::FunctionId;
use crate::lang::plugin::{TrampolineEntry, TrampolineKind};
use crate::pass::Outcome::Unchanged;
use crate::pass::{ModelResult, PassInfo, model};
use std::collections::HashMap;
enum ServiceFnRole {
Ctor,
Method,
Destructor,
}
#[derive(Default)]
pub struct Config {}
pub struct Pass {
info: PassInfo,
entries: Vec<TrampolineEntry>,
done: bool,
}
impl Pass {
#[must_use]
pub fn new(_: Config) -> Self {
Self { info: PassInfo { name: file!() }, entries: Vec::new(), done: false }
}
pub fn process(
&mut self,
_pass_meta: &mut crate::pass::PassMeta,
fns_all: &model::common::fns::all::Pass,
service_all: &model::common::service::all::Pass,
) -> ModelResult {
if self.done {
return Ok(Unchanged);
}
let mut service_fn_roles: HashMap<FunctionId, (crate::lang::ServiceId, ServiceFnRole)> = HashMap::new();
for (&svc_id, svc) in service_all.iter() {
service_fn_roles.insert(svc.destructor, (svc_id, ServiceFnRole::Destructor));
for &fn_id in &svc.ctors {
service_fn_roles.insert(fn_id, (svc_id, ServiceFnRole::Ctor));
}
for &fn_id in &svc.methods {
service_fn_roles.insert(fn_id, (svc_id, ServiceFnRole::Method));
}
}
if fns_all.originals().next().is_none() {
return Ok(Unchanged);
}
let mut entries = Vec::new();
let mut originals: Vec<_> = fns_all.originals().collect();
originals.sort_by(|(_, a), (_, b)| a.name.cmp(&b.name));
for (&fn_id, _func) in originals {
let kind = match service_fn_roles.get(&fn_id) {
Some((svc_id, ServiceFnRole::Ctor)) => TrampolineKind::ServiceCtor { service_id: *svc_id },
Some((svc_id, ServiceFnRole::Method)) => TrampolineKind::ServiceMethod { service_id: *svc_id },
Some((svc_id, ServiceFnRole::Destructor)) => TrampolineKind::ServiceDestructor { service_id: *svc_id },
None => TrampolineKind::Raw,
};
entries.push(TrampolineEntry { fn_id, kind });
}
self.entries = entries;
self.done = true;
let mut outcome = Unchanged;
outcome.changed();
Ok(outcome)
}
#[must_use]
pub fn entries(&self) -> &[TrampolineEntry] {
&self.entries
}
}