use super::*;
#[test]
fn test_basic_push_pop() {
let mut sm = StackManager::new();
sm.push_named("a", 1);
sm.push_named("b", 1);
assert_eq!(sm.stack_depth(), 2);
assert_eq!(sm.stack_len(), 2);
assert_eq!(sm.access_var("b"), 0);
assert_eq!(sm.access_var("a"), 1);
sm.pop();
assert_eq!(sm.stack_depth(), 1);
}
#[test]
fn test_no_spill_under_16() {
let mut sm = StackManager::new();
for i in 0..16 {
sm.push_named(&format!("v{}", i), 1);
}
assert_eq!(sm.stack_depth(), 16);
assert!(sm.drain_side_effects().is_empty());
}
#[test]
fn test_spill_at_17() {
let mut sm = StackManager::new();
for i in 0..16 {
sm.push_named(&format!("v{}", i), 1);
}
sm.access_var("v15");
sm.push_named("v16", 1);
let effects = sm.drain_side_effects();
assert!(!effects.is_empty(), "expected spill instructions");
assert!(sm.spilled.iter().any(|v| v.name.as_deref() == Some("v0")));
}
#[test]
fn test_reload_spilled_var() {
let mut sm = StackManager::new();
for i in 0..16 {
sm.push_named(&format!("v{}", i), 1);
}
sm.push_named("v16", 1);
sm.drain_side_effects();
let depth = sm.access_var("v0");
let effects = sm.drain_side_effects();
assert!(!effects.is_empty(), "expected reload instructions");
assert_eq!(depth, 0); }
#[test]
fn test_temp_push() {
let mut sm = StackManager::new();
sm.push_temp(1);
assert_eq!(sm.stack_depth(), 1);
assert!(sm.last().unwrap().name.is_none());
}
#[test]
fn test_multi_width_spill() {
let mut sm = StackManager::new();
sm.push_named("digest", 5);
for i in 0..11 {
sm.push_named(&format!("v{}", i), 1);
}
assert_eq!(sm.stack_depth(), 16);
sm.push_named("extra", 1);
let effects = sm.drain_side_effects();
assert!(!effects.is_empty());
let write_count = effects.iter().filter(|l| l.contains("write_mem")).count();
assert_eq!(write_count, 5, "expected 5 write_mem for Digest spill");
}
#[test]
fn test_spill_all_named() {
let mut sm = StackManager::new();
sm.push_named("a", 1);
sm.push_named("b", 1);
sm.push_named("c", 1);
sm.push_temp(1); assert_eq!(sm.stack_depth(), 4);
sm.spill_all_named();
let effects = sm.drain_side_effects();
let write_count = effects.iter().filter(|l| l.contains("write_mem")).count();
assert_eq!(write_count, 3, "expected 3 write_mem for 3 named vars");
assert_eq!(sm.stack_len(), 1, "only anonymous temp should remain");
assert!(
sm.last().unwrap().name.is_none(),
"remaining entry should be anonymous"
);
}
#[test]
fn test_spill_all_named_empty() {
let mut sm = StackManager::new();
sm.push_temp(1);
sm.push_temp(1);
sm.spill_all_named();
let effects = sm.drain_side_effects();
assert!(effects.is_empty(), "no named vars โ no spill");
assert_eq!(sm.stack_len(), 2);
}