use std::collections::HashMap;
use acir::circuit::{AcirOpcodeLocation, AssertionPayload, OpcodeLocation};
pub use optimizers::optimize;
mod optimizers;
mod simulator;
pub mod validator;
pub use simulator::CircuitSimulator;
#[derive(Debug)]
pub struct AcirTransformationMap {
old_indices_to_new_indices: HashMap<usize, Vec<usize>>,
}
impl AcirTransformationMap {
fn new(acir_opcode_positions: &[usize]) -> Self {
let mut old_indices_to_new_indices = HashMap::with_capacity(acir_opcode_positions.len());
for (new_index, old_index) in acir_opcode_positions.iter().copied().enumerate() {
old_indices_to_new_indices.entry(old_index).or_insert_with(Vec::new).push(new_index);
}
AcirTransformationMap { old_indices_to_new_indices }
}
pub fn new_locations(
&self,
old_location: OpcodeLocation,
) -> impl Iterator<Item = OpcodeLocation> + '_ {
let old_acir_index = match old_location {
OpcodeLocation::Acir(index) => index,
OpcodeLocation::Brillig { acir_index, .. } => acir_index,
};
self.old_indices_to_new_indices.get(&old_acir_index).into_iter().flat_map(
move |new_indices| {
new_indices.iter().map(move |new_index| match old_location {
OpcodeLocation::Acir(_) => OpcodeLocation::Acir(*new_index),
OpcodeLocation::Brillig { brillig_index, .. } => {
OpcodeLocation::Brillig { acir_index: *new_index, brillig_index }
}
})
},
)
}
pub fn new_acir_locations(
&self,
old_location: AcirOpcodeLocation,
) -> impl Iterator<Item = AcirOpcodeLocation> + '_ {
let old_acir_index = old_location.index();
self.old_indices_to_new_indices.get(&old_acir_index).into_iter().flat_map(
move |new_indices| {
new_indices.iter().map(move |new_index| AcirOpcodeLocation::new(*new_index))
},
)
}
}
fn transform_assert_messages<F: Clone>(
assert_messages: Vec<(OpcodeLocation, AssertionPayload<F>)>,
map: &AcirTransformationMap,
) -> Vec<(OpcodeLocation, AssertionPayload<F>)> {
assert_messages
.into_iter()
.flat_map(|(location, message)| {
let new_locations = map.new_locations(location);
new_locations.map(move |new_location| (new_location, message.clone()))
})
.collect()
}
#[macro_export]
macro_rules! assert_circuit_snapshot {
($acir:expr, $($arg:tt)*) => {
#[allow(unused_mut)]
let acir_string = $acir.to_string();
insta::assert_snapshot!(acir_string, $($arg)*)
};
}