use crate::instruction::{Instruction, OpCode};
use effects::stack_effect_for_arg_inference;
use indexed::{apply_pick, apply_reversen, apply_roll, apply_xdrop};
use state::EntryStack;
mod effects;
mod indexed;
mod state;
pub(super) fn estimate_required_entry_stack_depth(instructions: &[Instruction]) -> Option<usize> {
let mut state = EntryStack::default();
let mut saw_supported_opcode = false;
for instruction in instructions {
if instruction.opcode == OpCode::Ret {
break;
}
apply_instruction_for_arg_inference(instruction, &mut state)?;
saw_supported_opcode = true;
}
saw_supported_opcode.then_some(state.required_entry_depth())
}
fn apply_instruction_for_arg_inference(
instruction: &Instruction,
state: &mut EntryStack,
) -> Option<()> {
match instruction.opcode {
OpCode::Pick => apply_pick(state),
OpCode::Roll => apply_roll(state),
OpCode::Xdrop => apply_xdrop(state),
OpCode::Reversen => apply_reversen(state),
_ => {
let effect = stack_effect_for_arg_inference(instruction, state.stack())?;
state.pop_count(effect.pops);
state.push_all(effect.pushes);
Some(())
}
}
}