miden_assembly/ast/
immediate.rs

1use core::fmt;
2
3use crate::{Felt, SourceSpan, Span, Spanned, ast::Ident};
4
5/// An 8-bit unsigned immediate
6pub type ImmU8 = Immediate<u8>;
7
8/// A 16-bit unsigned immediate
9pub type ImmU16 = Immediate<u16>;
10
11/// A 32-bit unsigned immediate
12pub type ImmU32 = Immediate<u32>;
13
14/// A field element immediate
15pub type ImmFelt = Immediate<Felt>;
16
17/// Represents the 32-bit immediate used for assertion error codes
18pub type ErrorCode = Immediate<u32>;
19
20/// Represents an instruction immediate, e.g. `add.1` or `add.CONST`
21pub enum Immediate<T> {
22    /// A literal integer value, either decimal or hex-encoded
23    Value(Span<T>),
24    /// A constant identifier
25    ///
26    /// This must refer to a constant definition in the current module.
27    ///
28    /// All immediates of this type are folded to `Value` during
29    /// semantic analysis, once all constant definitions are evaluated.
30    Constant(Ident),
31}
32
33/// All immediates
34impl<T> Immediate<T> {
35    pub fn is_literal(&self) -> bool {
36        matches!(self, Self::Value(_))
37    }
38
39    /// Override the source span of this immediate with `span`
40    pub fn with_span(self, span: SourceSpan) -> Self {
41        match self {
42            Self::Constant(id) => Self::Constant(id.with_span(span)),
43            Self::Value(value) => Self::Value(Span::new(span, value.into_inner())),
44        }
45    }
46
47    /// Transform the type of this immediate from T to U, using `map`
48    pub fn map<U, F>(self, map: F) -> Immediate<U>
49    where
50        F: FnMut(T) -> U,
51    {
52        match self {
53            Self::Constant(id) => Immediate::Constant(id),
54            Self::Value(value) => Immediate::Value(value.map(map)),
55        }
56    }
57}
58
59/// Copy-able immediates (in practice, all of them)
60impl<T: Copy> Immediate<T> {
61    pub fn expect_value(&self) -> T {
62        match self {
63            Self::Value(value) => value.into_inner(),
64            Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
65        }
66    }
67
68    pub fn expect_spanned_value(&self) -> Span<T> {
69        match self {
70            Self::Value(value) => *value,
71            Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
72        }
73    }
74}
75
76impl<T> Spanned for Immediate<T> {
77    fn span(&self) -> SourceSpan {
78        match self {
79            Self::Value(spanned) => spanned.span(),
80            Self::Constant(spanned) => spanned.span(),
81        }
82    }
83}
84
85impl<T> From<T> for Immediate<T> {
86    fn from(value: T) -> Self {
87        Self::Value(Span::unknown(value))
88    }
89}
90
91impl<T> From<Span<T>> for Immediate<T> {
92    fn from(value: Span<T>) -> Self {
93        Self::Value(value)
94    }
95}
96
97impl<T: Clone> Clone for Immediate<T> {
98    fn clone(&self) -> Self {
99        match self {
100            Self::Value(value) => Self::Value(value.clone()),
101            Self::Constant(name) => Self::Constant(name.clone()),
102        }
103    }
104}
105
106impl<T: Eq> Eq for Immediate<T> {}
107
108impl<T: PartialEq> PartialEq for Immediate<T> {
109    fn eq(&self, other: &Self) -> bool {
110        match (self, other) {
111            (Self::Value(l), Self::Value(r)) => l == r,
112            (Self::Constant(l), Self::Constant(r)) => l == r,
113            _ => false,
114        }
115    }
116}
117
118impl<T: PartialEq> PartialEq<T> for Immediate<T> {
119    fn eq(&self, other: &T) -> bool {
120        match self {
121            Self::Value(l) => l == other,
122            _ => false,
123        }
124    }
125}
126
127impl<T: fmt::Debug> fmt::Debug for Immediate<T> {
128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129        match self {
130            Self::Value(value) if f.alternate() => write!(f, "Value({value:#?})"),
131            Self::Value(value) => write!(f, "Value({value:?})"),
132            Self::Constant(name) => write!(f, "Constant({name})"),
133        }
134    }
135}
136
137impl<T: fmt::Display> fmt::Display for Immediate<T> {
138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139        match self {
140            Self::Value(value) => write!(f, "{value}"),
141            Self::Constant(name) => write!(f, "{name}"),
142        }
143    }
144}
145
146impl<T: crate::prettier::PrettyPrint> crate::prettier::PrettyPrint for Immediate<T> {
147    fn render(&self) -> crate::prettier::Document {
148        use crate::prettier::*;
149
150        match self {
151            Self::Value(value) => value.render(),
152            Self::Constant(name) => text(name),
153        }
154    }
155}