use core::fmt;
use crate::{ast::Ident, Felt, SourceSpan, Span, Spanned};
pub type ImmU8 = Immediate<u8>;
pub type ImmU16 = Immediate<u16>;
pub type ImmU32 = Immediate<u32>;
pub type ImmFelt = Immediate<Felt>;
pub type ErrorCode = Immediate<u32>;
pub enum Immediate<T> {
Value(Span<T>),
Constant(Ident),
}
impl<T> Immediate<T> {
pub fn is_literal(&self) -> bool {
matches!(self, Self::Value(_))
}
pub fn map<U, F>(self, map: F) -> Immediate<U>
where
F: FnMut(T) -> U,
{
match self {
Self::Constant(id) => Immediate::Constant(id),
Self::Value(value) => Immediate::Value(value.map(map)),
}
}
}
impl<T: Copy> Immediate<T> {
pub fn expect_value(&self) -> T {
match self {
Self::Value(value) => value.into_inner(),
Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
}
}
pub fn expect_spanned_value(&self) -> Span<T> {
match self {
Self::Value(value) => *value,
Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
}
}
}
impl<T> Spanned for Immediate<T> {
fn span(&self) -> SourceSpan {
match self {
Self::Value(spanned) => spanned.span(),
Self::Constant(spanned) => spanned.span(),
}
}
}
impl<T> From<T> for Immediate<T> {
fn from(value: T) -> Self {
Self::Value(Span::unknown(value))
}
}
impl<T> From<Span<T>> for Immediate<T> {
fn from(value: Span<T>) -> Self {
Self::Value(value)
}
}
impl<T: Clone> Clone for Immediate<T> {
fn clone(&self) -> Self {
match self {
Self::Value(ref value) => Self::Value(value.clone()),
Self::Constant(ref name) => Self::Constant(name.clone()),
}
}
}
impl<T: Eq> Eq for Immediate<T> {}
impl<T: PartialEq> PartialEq for Immediate<T> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Value(l), Self::Value(r)) => l == r,
(Self::Constant(l), Self::Constant(r)) => l == r,
_ => false,
}
}
}
impl<T: PartialEq> PartialEq<T> for Immediate<T> {
fn eq(&self, other: &T) -> bool {
match self {
Self::Value(l) => l == other,
_ => false,
}
}
}
impl<T: fmt::Debug> fmt::Debug for Immediate<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Value(value) if f.alternate() => write!(f, "Value({value:#?})"),
Self::Value(value) => write!(f, "Value({value:?})"),
Self::Constant(name) => write!(f, "Constant({name})"),
}
}
}
impl<T: fmt::Display> fmt::Display for Immediate<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Value(value) => write!(f, "{value}"),
Self::Constant(name) => write!(f, "{name}"),
}
}
}
impl<T: crate::prettier::PrettyPrint> crate::prettier::PrettyPrint for Immediate<T> {
fn render(&self) -> crate::prettier::Document {
use crate::prettier::*;
match self {
Self::Value(ref value) => value.render(),
Self::Constant(ref name) => text(name),
}
}
}