use std::collections::HashMap;
use std::path::PathBuf;
use crate::ast::{SourceLocation, UnionDef, WordDef};
pub fn check_collisions(words: &[WordDef]) -> Result<(), String> {
let mut definitions: HashMap<&str, Vec<&SourceLocation>> = HashMap::new();
for word in words {
if let Some(ref source) = word.source {
definitions.entry(&word.name).or_default().push(source);
}
}
let mut errors = Vec::new();
for (name, locations) in definitions {
if locations.len() > 1 {
let mut msg = format!("Word '{}' is defined multiple times:\n", name);
for loc in &locations {
msg.push_str(&format!(" - {}\n", loc));
}
msg.push_str("\nHint: Rename one of the definitions to avoid collision.");
errors.push(msg);
}
}
if errors.is_empty() {
Ok(())
} else {
Err(errors.join("\n\n"))
}
}
pub fn check_union_collisions(unions: &[UnionDef]) -> Result<(), String> {
let mut definitions: HashMap<&str, Vec<&SourceLocation>> = HashMap::new();
for union_def in unions {
if let Some(ref source) = union_def.source {
definitions.entry(&union_def.name).or_default().push(source);
}
}
let mut errors = Vec::new();
for (name, locations) in definitions {
if locations.len() > 1 {
let mut msg = format!("Union '{}' is defined multiple times:\n", name);
for loc in &locations {
msg.push_str(&format!(" - {}\n", loc));
}
msg.push_str("\nHint: Rename one of the definitions to avoid collision.");
errors.push(msg);
}
}
if errors.is_empty() {
Ok(())
} else {
Err(errors.join("\n\n"))
}
}
pub fn find_stdlib() -> Option<PathBuf> {
if let Ok(path) = std::env::var("SEQ_STDLIB") {
let path = PathBuf::from(path);
if path.is_dir() {
return Some(path);
}
eprintln!(
"Warning: SEQ_STDLIB is set to '{}' but that directory doesn't exist",
path.display()
);
}
if let Ok(exe_path) = std::env::current_exe()
&& let Some(exe_dir) = exe_path.parent()
{
let stdlib_path = exe_dir.join("stdlib");
if stdlib_path.is_dir() {
return Some(stdlib_path);
}
if let Some(parent) = exe_dir.parent() {
let stdlib_path = parent.join("stdlib");
if stdlib_path.is_dir() {
return Some(stdlib_path);
}
}
}
let local_stdlib = PathBuf::from("stdlib");
if local_stdlib.is_dir() {
return Some(local_stdlib.canonicalize().unwrap_or(local_stdlib));
}
None
}