use air_parser::ast::{self, Identifier, QualifiedIdentifier, TraceColumnIndex, TraceSegmentId};
use miden_diagnostics::{SourceSpan, Spanned};
use crate::ir::{BackLink, Builder, Bus, Child, Link, Node, Op, Owner, Singleton};
#[derive(Default, Clone, PartialEq, Eq, Debug, Hash, Builder, Spanned)]
#[enum_wrapper(Op)]
pub struct Value {
pub parents: Vec<BackLink<Owner>>,
#[span]
pub value: SpannedMirValue,
pub _node: Singleton<Node>,
}
impl Value {
pub fn create(value: SpannedMirValue) -> Link<Op> {
Op::Value(Self {
value,
..Default::default()
})
.into()
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Self {
value: SpannedMirValue {
value: MirValue::Constant(ConstantValue::Felt(value as u64)),
span: Default::default(),
},
..Default::default()
}
}
}
impl Child for Value {
type Parent = Owner;
fn get_parents(&self) -> Vec<BackLink<Self::Parent>> {
self.parents.clone()
}
fn add_parent(&mut self, parent: Link<Self::Parent>) {
self.parents.push(parent.into());
}
fn remove_parent(&mut self, parent: Link<Self::Parent>) {
self.parents.retain(|p| *p != parent.clone().into());
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum MirValue {
Constant(ConstantValue),
TraceAccess(TraceAccess),
PeriodicColumn(PeriodicColumnAccess),
PublicInput(PublicInputAccess),
PublicInputTable(PublicInputTableAccess),
RandomValue(usize),
TraceAccessBinding(TraceAccessBinding),
BusAccess(BusAccess),
Null,
Unconstrained,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BusAccess {
pub bus: Link<Bus>,
pub row_offset: usize,
}
impl BusAccess {
pub const fn new(bus: Link<Bus>, row_offset: usize) -> Self {
Self { bus, row_offset }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum ConstantValue {
Felt(u64),
Vector(Vec<u64>),
Matrix(Vec<Vec<u64>>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraceAccess {
pub segment: TraceSegmentId,
pub column: TraceColumnIndex,
pub row_offset: usize,
}
impl TraceAccess {
pub const fn new(segment: TraceSegmentId, column: TraceColumnIndex, row_offset: usize) -> Self {
Self {
segment,
column,
row_offset,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct TraceAccessBinding {
pub segment: TraceSegmentId,
pub offset: usize,
pub size: usize,
}
#[derive(Debug, Eq, PartialEq, Clone, Hash, Spanned)]
pub struct SpannedMirValue {
#[span]
pub span: SourceSpan,
pub value: MirValue,
}
#[derive(Debug, Default, Eq, PartialEq, Clone, Hash)]
pub enum MirType {
#[default]
Felt,
Vector(usize),
Matrix(usize, usize),
}
impl From<ast::Type> for MirType {
fn from(value: ast::Type) -> Self {
match value {
ast::Type::Felt => MirType::Felt,
ast::Type::Vector(n) => MirType::Vector(n),
ast::Type::Matrix(cols, rows) => MirType::Matrix(cols, rows),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct PeriodicColumnAccess {
pub name: QualifiedIdentifier,
pub cycle: usize,
}
impl PeriodicColumnAccess {
pub const fn new(name: QualifiedIdentifier, cycle: usize) -> Self {
Self { name, cycle }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct PublicInputAccess {
pub name: Identifier,
pub index: usize,
}
impl PublicInputAccess {
pub const fn new(name: Identifier, index: usize) -> Self {
Self { name, index }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PublicInputTableAccess {
pub table_name: Identifier,
bus_name: Option<Identifier>,
pub num_cols: usize,
}
impl PublicInputTableAccess {
pub const fn new(table_name: Identifier, num_cols: usize) -> Self {
Self {
table_name,
bus_name: None,
num_cols,
}
}
pub fn set_bus_name(&mut self, bus_name: Identifier) {
self.bus_name = Some(bus_name);
}
pub fn bus_name(&self) -> Identifier {
self.bus_name
.expect("Bus name should have already been set")
}
}
impl Default for SpannedMirValue {
fn default() -> Self {
Self {
value: MirValue::Constant(ConstantValue::Felt(0)),
span: Default::default(),
}
}
}