use crate::core::ir::FunctionDef;
use ahash::AHashMap;
pub(in crate::backends::rustler::gen_bindings) fn regate_ungated_same_name_functions(
functions: &[FunctionDef],
) -> Vec<FunctionDef> {
let groups = collect_function_groups(functions);
let mut gated_cfg_by_name: AHashMap<&str, Option<String>> = AHashMap::new();
for (name, indices) in &groups {
if !is_mixed_gated_group(indices, functions) {
continue;
}
let gated = merge_gated_cfgs(indices.iter().map(|&i| functions[i].cfg.as_deref()));
gated_cfg_by_name.insert(name.as_str(), gated);
}
if gated_cfg_by_name.is_empty() {
return functions.to_vec();
}
functions
.iter()
.cloned()
.map(|mut function| {
if function.cfg.is_none() {
if let Some(Some(gated)) = gated_cfg_by_name.get(function.name.as_str()) {
function.cfg = Some(format!("not({gated})"));
}
}
function
})
.collect()
}
fn collect_function_groups(functions: &[FunctionDef]) -> AHashMap<String, Vec<usize>> {
let mut name_to_indices: AHashMap<String, Vec<usize>> = AHashMap::new();
for (idx, func) in functions.iter().enumerate() {
name_to_indices.entry(func.name.clone()).or_default().push(idx);
}
name_to_indices
}
fn is_mixed_gated_group(indices: &[usize], functions: &[FunctionDef]) -> bool {
if indices.len() <= 1 {
return false;
}
let has_ungated = indices.iter().any(|&i| functions[i].cfg.is_none());
let has_gated = indices.iter().any(|&i| functions[i].cfg.is_some());
has_ungated && has_gated
}
fn merge_gated_cfgs<'a>(cfgs: impl Iterator<Item = Option<&'a str>>) -> Option<String> {
let mut distinct: Vec<&str> = Vec::new();
for cfg in cfgs.flatten() {
if !distinct.contains(&cfg) {
distinct.push(cfg);
}
}
match distinct.len() {
0 => None,
1 => Some(distinct[0].to_string()),
_ => Some(format!("any({})", distinct.join(", "))),
}
}
#[cfg(test)]
mod tests;