use std::collections::{HashMap, HashSet};
use crate::parser::Type;
use super::OwnershipMode;
#[derive(Debug, Clone)]
pub struct FunctionSignature {
pub name: String,
pub param_types: Vec<Type>, pub param_ownership: Vec<OwnershipMode>,
pub return_type: Option<Type>, pub return_ownership: OwnershipMode,
pub has_self_receiver: bool, pub is_extern: bool, }
#[derive(Debug, Clone)]
pub struct SignatureRegistry {
pub signatures: HashMap<String, FunctionSignature>,
collision_keys: HashSet<String>,
}
impl Default for SignatureRegistry {
fn default() -> Self {
Self::new()
}
}
impl SignatureRegistry {
pub fn new() -> Self {
let mut registry = SignatureRegistry {
signatures: HashMap::new(),
collision_keys: HashSet::new(),
};
if let Err(e) = crate::stdlib_scanner::populate_runtime_signatures(&mut registry) {
eprintln!("Warning: Failed to scan runtime signatures: {}", e);
eprintln!("Continuing with empty registry - may generate incorrect borrows");
}
registry
}
pub fn add_function(&mut self, name: String, sig: FunctionSignature) {
if let Some(existing) = self.signatures.get(&name) {
if existing.param_types != sig.param_types
|| existing.param_ownership != sig.param_ownership
{
self.collision_keys.insert(name.clone());
}
}
self.signatures.insert(name, sig);
}
pub fn get_signature(&self, name: &str) -> Option<&FunctionSignature> {
self.signatures.get(name)
}
pub fn has_collision(&self, name: &str) -> bool {
self.collision_keys.contains(name)
}
pub fn find_signature_ending_with(&self, suffix: &str) -> Option<&FunctionSignature> {
let pattern = format!("::{}", suffix);
self.signatures
.iter()
.find(|(key, _)| key.ends_with(&pattern))
.map(|(_, sig)| sig)
}
pub fn find_signature_by_name_and_arg_count(
&self,
name: &str,
arg_count: usize,
) -> Option<&FunctionSignature> {
if let Some(sig) = self.signatures.get(name) {
let sig_args = if sig.has_self_receiver {
sig.param_ownership.len().saturating_sub(1)
} else {
sig.param_ownership.len()
};
if sig_args == arg_count {
return Some(sig);
}
}
let pattern = format!("::{}", name);
for (key, sig) in &self.signatures {
if key.ends_with(&pattern) || key == name {
let sig_args = if sig.has_self_receiver {
sig.param_ownership.len().saturating_sub(1)
} else {
sig.param_ownership.len()
};
if sig_args == arg_count {
return Some(sig);
}
}
}
None
}
pub fn merge(&mut self, other: &SignatureRegistry) {
for (name, sig) in &other.signatures {
if let Some(existing) = self.signatures.get(name) {
if existing.param_types != sig.param_types
|| existing.param_ownership != sig.param_ownership
{
self.collision_keys.insert(name.clone());
}
}
self.signatures.insert(name.clone(), sig.clone());
}
self.collision_keys
.extend(other.collision_keys.iter().cloned());
}
}