use std::fmt;
use crate::{
eqv::{EqvRelation, SymbolicEqv},
slot::{arg::ArgNo, cell::CellRef, output::OutputId},
};
pub mod arg;
pub mod cell;
pub mod output;
#[derive(Clone, Copy, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub enum Slot {
Arg(ArgNo),
Output(OutputId),
Advice(CellRef),
Fixed(CellRef),
TableLookup(u64, usize, usize, usize, usize),
CallOutput(usize, usize),
Temp(usize),
Challenge(usize, u8, ArgNo),
}
impl Slot {
pub fn advice_abs(col: usize, row: usize) -> Self {
Self::Advice(CellRef::absolute(col, row))
}
pub fn advice_rel(col: usize, base: usize, offset: usize) -> Self {
Self::Advice(CellRef::relative(col, base, offset))
}
pub fn fixed_abs(col: usize, row: usize) -> Self {
Self::Fixed(CellRef::absolute(col, row))
}
pub fn fixed_rel(col: usize, base: usize, offset: usize) -> Self {
Self::Fixed(CellRef::relative(col, base, offset))
}
}
impl EqvRelation<Slot> for SymbolicEqv {
fn equivalent(lhs: &Slot, rhs: &Slot) -> bool {
match (lhs, rhs) {
(Slot::Arg(lhs), Slot::Arg(rhs)) => lhs == rhs,
(Slot::Output(lhs), Slot::Output(rhs)) => lhs == rhs,
(Slot::Advice(lhs), Slot::Advice(rhs)) => Self::equivalent(lhs, rhs),
(Slot::Fixed(lhs), Slot::Fixed(rhs)) => Self::equivalent(lhs, rhs),
(Slot::TableLookup(_, col0, row0, _, _), Slot::TableLookup(_, col1, row1, _, _)) => {
col0 == col1 && row0 == row1
}
(Slot::CallOutput(_, o0), Slot::CallOutput(_, o1)) => o0 == o1,
(Slot::Temp(lhs), Slot::Temp(rhs)) => lhs == rhs,
(
Slot::Challenge(lhs_index, lhs_phase, _),
Slot::Challenge(rhs_index, rhs_phase, _),
) => lhs_index == rhs_index && lhs_phase == rhs_phase,
_ => false,
}
}
}
impl std::fmt::Debug for Slot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Arg(arg) => write!(f, "{arg:?}"),
Self::Output(field) => write!(f, "{field:?}"),
Self::Advice(c) => write!(f, "adv{c:?}"),
Self::Fixed(c) => write!(f, "fix{c:?}"),
Self::TableLookup(id, col, row, idx, region_idx) => {
write!(f, "lookup{id}[{col},{row}]@({idx},{region_idx})")
}
Self::CallOutput(call, out) => write!(f, "call{call}->{out}"),
Self::Temp(id) => write!(f, "t{}", *id),
Self::Challenge(index, phase, _) => write!(f, "challenge{index}@{phase}"),
}
}
}
impl std::fmt::Display for Slot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Arg(arg) => write!(f, "{arg}"),
Self::Output(field) => write!(f, "{field}"),
Self::Advice(c) => write!(f, "adv{c}"),
Self::Fixed(c) => write!(f, "fix{c}"),
Self::TableLookup(id, col, row, idx, region_idx) => {
write!(f, "lookup{id}[{col},{row}]@({idx},{region_idx})")
}
Self::CallOutput(call, out) => write!(f, "call{call}->{out}"),
Self::Temp(id) => write!(f, "t{}", *id),
Self::Challenge(index, phase, _) => write!(f, "challenge{index}@{phase}"),
}
}
}
impl From<ArgNo> for Slot {
fn from(value: ArgNo) -> Self {
Self::Arg(value)
}
}
impl From<OutputId> for Slot {
fn from(value: OutputId) -> Self {
Self::Output(value)
}
}