use alloc::vec::Vec;
use miden_air::logup::StackOverflowMsg;
use miden_core::{
Felt,
operations::{Operation, opcodes},
};
use super::{
build_trace_from_ops,
lookup_harness::{Expectations, InteractionLog},
};
use crate::RowIndex;
#[test]
fn stack_overflow_bus_emits_per_interaction_row() {
let ops = vec![
Operation::U32add, Operation::Pad, Operation::Pad, Operation::U32add, Operation::Drop, Operation::Pad, Operation::Drop, Operation::Drop, Operation::Drop, Operation::Pad, Operation::Drop, ];
let init_stack = (1..17).rev().collect::<Vec<u64>>();
let trace = build_trace_from_ops(ops, &init_stack);
let log = InteractionLog::new(&trace);
let main = trace.main_trace();
let mut exp = Expectations::new(&log);
for row in 0..main.num_rows() {
let idx = RowIndex::from(row);
let next = RowIndex::from(row + 1);
let op = main.get_op_code(idx);
if op == Felt::from_u8(opcodes::PAD) {
exp.add(
row,
&StackOverflowMsg {
clk: main.clk(idx),
val: main.stack_element(15, idx),
prev: main.parent_overflow_address(idx),
},
);
} else if op == Felt::from_u8(opcodes::DROP) && main.is_non_empty_overflow(idx) {
exp.remove(
row,
&StackOverflowMsg {
clk: main.parent_overflow_address(idx),
val: main.stack_element(15, next),
prev: main.parent_overflow_address(next),
},
);
}
}
assert_eq!(exp.count_adds(), 4, "expected one add per PAD");
assert_eq!(exp.count_removes(), 4, "expected one remove per DROP with non-empty overflow");
log.assert_contains(&exp);
}