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