use super::{InstId, MirType};
use alloy_primitives::U256;
use solar_interface::diagnostics::ErrorGuaranteed;
use std::fmt;
#[derive(Clone, Debug)]
pub enum Value {
Inst(InstId),
Arg {
index: u32,
ty: MirType,
},
Immediate(Immediate),
Undef(MirType),
Error(ErrorGuaranteed),
}
impl Value {
#[must_use]
pub fn ty(&self) -> MirType {
match self {
Self::Inst(_) | Self::Error(_) => MirType::uint256(),
Self::Arg { ty, .. } | Self::Undef(ty) => *ty,
Self::Immediate(imm) => imm.ty(),
}
}
#[must_use]
pub const fn is_immediate(&self) -> bool {
matches!(self, Self::Immediate(_))
}
#[must_use]
pub const fn as_immediate(&self) -> Option<&Immediate> {
match self {
Self::Immediate(imm) => Some(imm),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Immediate {
Bool(bool),
UInt(U256, u16),
Int(U256, u16),
Address([u8; 20]),
FixedBytes(Vec<u8>, u8),
}
impl Immediate {
#[must_use]
pub const fn ty(&self) -> MirType {
match self {
Self::Bool(_) => MirType::Bool,
Self::UInt(_, bits) => MirType::UInt(*bits),
Self::Int(_, bits) => MirType::Int(*bits),
Self::Address(_) => MirType::Address,
Self::FixedBytes(_, n) => MirType::FixedBytes(*n),
}
}
#[must_use]
pub const fn uint256(value: U256) -> Self {
Self::UInt(value, 256)
}
#[must_use]
pub const fn bool(value: bool) -> Self {
Self::Bool(value)
}
#[must_use]
pub fn zero(ty: MirType) -> Self {
match ty {
MirType::Bool => Self::Bool(false),
MirType::UInt(bits) => Self::UInt(U256::ZERO, bits),
MirType::Int(bits) => Self::Int(U256::ZERO, bits),
MirType::Address => Self::Address([0u8; 20]),
MirType::FixedBytes(n) => Self::FixedBytes(vec![0u8; n as usize], n),
_ => Self::UInt(U256::ZERO, 256),
}
}
#[must_use]
pub fn as_u256(&self) -> Option<U256> {
match self {
Self::Bool(b) => Some(U256::from(*b as u64)),
Self::UInt(v, _) | Self::Int(v, _) => Some(*v),
Self::Address(addr) => Some(U256::from_be_slice(addr)),
Self::FixedBytes(bytes, _) => {
let mut padded = [0u8; 32];
let len = bytes.len().min(32);
padded[..len].copy_from_slice(&bytes[..len]);
Some(U256::from_be_bytes(padded))
}
}
}
}
impl fmt::Display for Immediate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Bool(b) => write!(f, "{b}"),
Self::UInt(v, _) | Self::Int(v, _) => write!(f, "{v}"),
Self::Address(addr) => write!(f, "0x{}", alloy_primitives::hex::encode(addr)),
Self::FixedBytes(bytes, _) => write!(f, "0x{}", alloy_primitives::hex::encode(bytes)),
}
}
}