miden_assembly/ast/
immediate.rs

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