use llmcc_rust::{bind_symbols, build_llmcc_ir, collect_symbols, CompileCtxt, LangRust};
use llmcc_core::symbol::SymbolKind;
fn compile(sources: &[&str]) -> (&'static CompileCtxt<'static>, Vec<&'static CompileCtxt<'static>>) {
let byte_sources: Vec<Vec<u8>> = sources
.iter()
.map(|s| s.as_bytes().to_vec())
.collect();
let cc = Box::leak(Box::new(CompileCtxt::from_sources::<LangRust>(&byte_sources)));
build_llmcc_ir::<LangRust>(cc).unwrap();
let globals = cc.create_globals();
let mut units = Vec::new();
for i in 0..sources.len() {
let unit = cc.compile_unit(i);
units.push(unit);
}
for unit in &units {
let _ = collect_symbols(*unit, globals);
}
for unit in &units {
let _ = bind_symbols(*unit, globals);
}
(cc, units)
}
#[test]
fn cross_unit_struct_function_call() {
let impl_source = r#"
pub struct MyStruct;
impl MyStruct {
pub fn new() -> Self {
Self
}
}
"#;
let caller_source = r#"
fn caller() {
let _x = MyStruct::new();
}
"#;
let (cc, units) = compile(&[impl_source, caller_source]);
assert!(
cc.global_symbols()
.find_global_suffix(&[cc.interner().intern("caller")])
.is_some(),
"caller function should be in global symbols"
);
let my_struct_sym = cc
.global_symbols()
.find_global_suffix(&[cc.interner().intern("MyStruct")]);
assert!(my_struct_sym.is_some(), "MyStruct should be in global symbols");
let new_func = cc
.global_symbols()
.find_global_suffix_vec(&[
cc.interner().intern("new"),
cc.interner().intern("MyStruct"),
]);
assert!(
!new_func.is_empty(),
"MyStruct::new function should exist in symbol table"
);
let caller_sym = cc
.global_symbols()
.find_global_suffix(&[cc.interner().intern("caller")])
.expect("caller should exist");
let depends = caller_sym.depends.borrow();
println!("Caller dependencies: {:?}", *depends);
assert!(
!depends.is_empty(),
"caller should have dependencies (at least MyStruct or MyStruct::new)"
);
let new_sym = new_func.first().expect("new should exist");
let my_struct_sym = my_struct_sym.expect("MyStruct should exist");
let has_new_dep = depends.iter().any(|&id| id == new_sym.id);
let has_struct_dep = depends.iter().any(|&id| id == my_struct_sym.id);
println!("has_new_dep: {}", has_new_dep);
println!("has_struct_dep: {}", has_struct_dep);
println!("new_sym.id: {:?}", new_sym.id);
println!("my_struct_sym.id: {:?}", my_struct_sym.id);
assert!(
has_new_dep || has_struct_dep,
"caller should depend on either new function or MyStruct struct"
);
}