Skip to main content

miden_assembly_syntax/ast/
immediate.rs

1use alloc::sync::Arc;
2use core::fmt;
3
4use miden_debug_types::{SourceSpan, Span, Spanned};
5
6use crate::{Felt, ast::Ident};
7
8/// An 8-bit unsigned immediate
9pub type ImmU8 = Immediate<u8>;
10
11/// A 16-bit unsigned immediate
12pub type ImmU16 = Immediate<u16>;
13
14/// A 32-bit unsigned immediate
15pub type ImmU32 = Immediate<u32>;
16
17/// A field element immediate
18pub type ImmFelt = Immediate<Felt>;
19
20/// An event identifier given as a constant reference, a felt value, or an inline event name.
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub enum EventImmediate {
23    /// A constant reference or literal felt value.
24    Immediate(ImmFelt),
25    /// An inline `event("...")` expression.
26    Name(Span<Arc<str>>),
27}
28
29impl EventImmediate {
30    /// Unwrap the resolved event identifier or panic.
31    pub fn expect_value(&self) -> Felt {
32        match self {
33            Self::Immediate(imm) => imm.expect_value(),
34            Self::Name(name) => {
35                panic!("tried to unwrap unresolved event name: '{}'", name.inner())
36            },
37        }
38    }
39}
40
41impl Spanned for EventImmediate {
42    fn span(&self) -> SourceSpan {
43        match self {
44            Self::Immediate(imm) => imm.span(),
45            Self::Name(name) => name.span(),
46        }
47    }
48}
49
50impl From<ImmFelt> for EventImmediate {
51    fn from(imm: ImmFelt) -> Self {
52        Self::Immediate(imm)
53    }
54}
55
56/// The type of error messages used in MASM assertions.
57pub type ErrorMsg = Immediate<Arc<str>>;
58
59/// Represents an instruction immediate, e.g. `add.1` or `add.CONST`
60pub enum Immediate<T> {
61    /// A literal integer value, either decimal or hex-encoded
62    Value(Span<T>),
63    /// A constant identifier
64    ///
65    /// This must refer to a constant definition in the current module.
66    ///
67    /// All immediates of this type are folded to `Value` during linking.
68    Constant(Ident),
69}
70
71/// All immediates
72impl<T> Immediate<T> {
73    pub fn is_literal(&self) -> bool {
74        matches!(self, Self::Value(_))
75    }
76
77    /// Override the source span of this immediate with `span`
78    pub fn with_span(self, span: SourceSpan) -> Self {
79        match self {
80            Self::Constant(id) => Self::Constant(id.with_span(span)),
81            Self::Value(value) => Self::Value(Span::new(span, value.into_inner())),
82        }
83    }
84
85    /// Transform the type of this immediate from T to U, using `map`
86    pub fn map<U, F>(self, map: F) -> Immediate<U>
87    where
88        F: FnMut(T) -> U,
89    {
90        match self {
91            Self::Constant(id) => Immediate::Constant(id),
92            Self::Value(value) => Immediate::Value(value.map(map)),
93        }
94    }
95}
96
97/// Copy-able immediates (in practice, all of them)
98impl<T: Copy> Immediate<T> {
99    pub fn expect_value(&self) -> T {
100        match self {
101            Self::Value(value) => value.into_inner(),
102            Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
103        }
104    }
105
106    pub fn expect_spanned_value(&self) -> Span<T> {
107        match self {
108            Self::Value(value) => *value,
109            Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
110        }
111    }
112}
113
114impl Immediate<Arc<str>> {
115    pub fn expect_string(&self) -> Arc<str> {
116        match self {
117            Self::Value(value) => value.clone().into_inner(),
118            Self::Constant(name) => panic!("tried to unwrap unresolved constant: '{name}'"),
119        }
120    }
121}
122
123impl<T> Spanned for Immediate<T> {
124    fn span(&self) -> SourceSpan {
125        match self {
126            Self::Value(spanned) => spanned.span(),
127            Self::Constant(spanned) => spanned.span(),
128        }
129    }
130}
131
132impl<T> From<T> for Immediate<T> {
133    fn from(value: T) -> Self {
134        Self::Value(Span::unknown(value))
135    }
136}
137
138impl<T> From<Span<T>> for Immediate<T> {
139    fn from(value: Span<T>) -> Self {
140        Self::Value(value)
141    }
142}
143
144impl<T: Clone> Clone for Immediate<T> {
145    fn clone(&self) -> Self {
146        match self {
147            Self::Value(value) => Self::Value(value.clone()),
148            Self::Constant(name) => Self::Constant(name.clone()),
149        }
150    }
151}
152
153impl<T: Eq> Eq for Immediate<T> {}
154
155impl<T: PartialEq> PartialEq for Immediate<T> {
156    fn eq(&self, other: &Self) -> bool {
157        match (self, other) {
158            (Self::Value(l), Self::Value(r)) => l == r,
159            (Self::Constant(l), Self::Constant(r)) => l == r,
160            _ => false,
161        }
162    }
163}
164
165impl<T: PartialEq> PartialEq<T> for Immediate<T> {
166    fn eq(&self, other: &T) -> bool {
167        match self {
168            Self::Value(l) => l == other,
169            _ => false,
170        }
171    }
172}
173
174impl<T: core::hash::Hash> core::hash::Hash for Immediate<T> {
175    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
176        core::mem::discriminant(self).hash(state);
177        match self {
178            Self::Value(v) => v.hash(state),
179            Self::Constant(name) => name.hash(state),
180        }
181    }
182}
183
184impl<T: fmt::Debug> fmt::Debug for Immediate<T> {
185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186        match self {
187            Self::Value(value) if f.alternate() => write!(f, "Value({value:#?})"),
188            Self::Value(value) => write!(f, "Value({value:?})"),
189            Self::Constant(name) => write!(f, "Constant({name})"),
190        }
191    }
192}
193
194impl<T: fmt::Display> fmt::Display for Immediate<T> {
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        match self {
197            Self::Value(value) => write!(f, "{value}"),
198            Self::Constant(name) => write!(f, "{name}"),
199        }
200    }
201}
202
203impl<T: crate::prettier::PrettyPrint> crate::prettier::PrettyPrint for Immediate<T> {
204    fn render(&self) -> crate::prettier::Document {
205        use crate::prettier::*;
206
207        match self {
208            Self::Value(value) => value.render(),
209            Self::Constant(name) => text(name),
210        }
211    }
212}