use miden_core::{
mast::{MastForest, MastForestRootMap, MastNodeExt},
utils::Idx,
};
use crate::{
Assembler,
diagnostics::{IntoDiagnostic, Report},
testing::TestContext,
};
fn merge_programs(
program_a: &str,
program_b: &str,
) -> Result<(MastForest, MastForest, MastForest, MastForestRootMap), Report> {
let context = TestContext::new();
let module = context.parse_module_with_path("lib::mod", program_a)?;
let lib_a = Assembler::new(context.source_manager()).assemble_library([module])?;
let mut assembler = Assembler::new(context.source_manager());
assembler.link_dynamic_library(lib_a.clone())?;
let lib_b = assembler.assemble_library([program_b])?.mast_forest().as_ref().clone();
let lib_a = lib_a.mast_forest().as_ref().clone();
let (merged, root_maps) = MastForest::merge([&lib_a, &lib_b]).into_diagnostic()?;
Ok((lib_a, lib_b, merged, root_maps))
}
#[test]
fn mast_forest_merge_assembler() {
let lib_a = r#"
pub proc foo
push.19
end
pub proc qux
swap drop
end
"#;
let lib_b = r#"
use lib::mod
pub proc qux_duplicate
swap drop
end
pub proc bar
push.2
if.true
push.3
else
while.true
add
push.23
end
end
exec.mod::foo
end"#;
let (forest_a, forest_b, merged, root_maps) = merge_programs(lib_a, lib_b).unwrap();
for (forest_idx, forest) in [forest_a, forest_b].into_iter().enumerate() {
for root in forest.procedure_roots() {
let original_digest = forest.nodes()[root.to_usize()].digest();
let new_root = root_maps.map_root(forest_idx, root).unwrap();
let new_digest = merged.nodes()[new_root.to_usize()].digest();
assert_eq!(original_digest, new_digest);
}
}
merged.nodes().iter().for_each(|node| assert!(!node.is_external()));
}