use super::*;
#[derive(Default)]
pub struct CopyAll;
impl Tactic for CopyAll {
fn cost(&self, context: &SolverContext) -> usize {
core::cmp::max(context.copies().len(), 1)
}
fn apply(&mut self, builder: &mut SolutionBuilder) -> TacticResult {
let trace_target = builder.trace_target().clone().with_topic("solver:copy-all");
let arity = builder.arity();
if builder.num_copies() != arity {
log::trace!(
target: &trace_target,
"expected all operands to require copying; but only {} out of {} operands are \
copied",
builder.num_copies(),
arity
);
return Err(TacticError::PreconditionFailed);
}
for index in (0..(arity as u8)).rev() {
let expected_value = builder.unwrap_expected(index);
let current_position =
builder.get_current_position(&expected_value.unaliased()).unwrap_or_else(|| {
panic!(
"expected {:?} on the stack, but it was not found",
expected_value.unaliased()
)
});
log::trace!(
target: &trace_target,
"copying {expected_value:?} at index {index} to top of stack, shifting {:?} down \
one",
builder.unwrap_current(0)
);
builder.dup(current_position, expected_value.unwrap_alias());
}
Ok(())
}
}