miden_assembly_syntax/ast/constants/
value.rs1use core::fmt;
2
3use miden_core::utils::{
4 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
5};
6use miden_debug_types::{SourceSpan, Span, Spanned};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::{
11 ast::{HashKind, Ident},
12 parser::{IntValue, WordValue},
13};
14
15#[derive(Clone)]
20#[repr(u8)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub enum ConstantValue {
23 Int(Span<IntValue>) = 1,
25 String(Ident),
27 Word(Span<WordValue>),
29 Hash(HashKind, Ident),
32}
33
34impl Eq for ConstantValue {}
35
36impl PartialEq for ConstantValue {
37 fn eq(&self, other: &Self) -> bool {
38 match (self, other) {
39 (Self::Int(l), Self::Int(y)) => l == y,
40 (Self::Int(_), _) => false,
41 (Self::Word(l), Self::Word(y)) => l == y,
42 (Self::Word(_), _) => false,
43 (Self::String(l), Self::String(y)) => l == y,
44 (Self::String(_), _) => false,
45 (Self::Hash(x_hk, x_i), Self::Hash(y_hk, y_i)) => x_i == y_i && x_hk == y_hk,
46 (Self::Hash(..), _) => false,
47 }
48 }
49}
50
51impl core::hash::Hash for ConstantValue {
52 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
53 core::mem::discriminant(self).hash(state);
54 match self {
55 Self::Int(value) => value.hash(state),
56 Self::Word(value) => value.hash(state),
57 Self::String(value) => value.hash(state),
58 Self::Hash(kind, value) => {
59 kind.hash(state);
60 value.hash(state);
61 },
62 }
63 }
64}
65
66impl fmt::Debug for ConstantValue {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match self {
69 Self::Int(lit) => fmt::Debug::fmt(&**lit, f),
70 Self::Word(lit) => fmt::Debug::fmt(&**lit, f),
71 Self::String(name) => fmt::Debug::fmt(&**name, f),
72 Self::Hash(hash_kind, str) => fmt::Debug::fmt(&(str, hash_kind), f),
73 }
74 }
75}
76
77impl crate::prettier::PrettyPrint for ConstantValue {
78 fn render(&self) -> crate::prettier::Document {
79 use crate::prettier::*;
80
81 match self {
82 Self::Int(literal) => literal.render(),
83 Self::Word(literal) => literal.render(),
84 Self::String(ident) => text(format!("\"{}\"", ident.as_str().escape_debug())),
85 Self::Hash(hash_kind, str) => flatten(
86 display(hash_kind)
87 + const_text("(")
88 + text(format!("\"{}\"", str.as_str().escape_debug()))
89 + const_text(")"),
90 ),
91 }
92 }
93}
94
95impl Spanned for ConstantValue {
96 fn span(&self) -> SourceSpan {
97 match self {
98 Self::Int(spanned) => spanned.span(),
99 Self::Word(spanned) => spanned.span(),
100 Self::String(spanned) => spanned.span(),
101 Self::Hash(_, spanned) => spanned.span(),
102 }
103 }
104}
105
106impl ConstantValue {
107 const fn tag(&self) -> u8 {
108 unsafe { *(self as *const Self).cast::<u8>() }
115 }
116}
117
118impl Serializable for ConstantValue {
119 fn write_into<W: ByteWriter>(&self, target: &mut W) {
120 target.write_u8(self.tag());
121 match self {
122 Self::Int(value) => value.inner().write_into(target),
123 Self::String(id) => id.write_into(target),
124 Self::Word(value) => value.inner().write_into(target),
125 Self::Hash(kind, id) => {
126 kind.write_into(target);
127 id.write_into(target);
128 },
129 }
130 }
131}
132
133impl Deserializable for ConstantValue {
134 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
135 match source.read_u8()? {
136 1 => IntValue::read_from(source).map(Span::unknown).map(Self::Int),
137 2 => Ident::read_from(source).map(Self::String),
138 3 => WordValue::read_from(source).map(Span::unknown).map(Self::Word),
139 4 => {
140 let kind = HashKind::read_from(source)?;
141 let id = Ident::read_from(source)?;
142 Ok(Self::Hash(kind, id))
143 },
144 invalid => Err(DeserializationError::InvalidValue(format!(
145 "unexpected ConstantValue tag: '{invalid}'"
146 ))),
147 }
148 }
149}
150
151#[cfg(feature = "arbitrary")]
152impl proptest::arbitrary::Arbitrary for ConstantValue {
153 type Parameters = ();
154
155 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
156 use proptest::{arbitrary::any, prop_oneof, strategy::Strategy};
157
158 prop_oneof![
159 any::<IntValue>().prop_map(|n| Self::Int(Span::unknown(n))),
160 any::<Ident>().prop_map(Self::String),
161 any::<WordValue>().prop_map(|word| Self::Word(Span::unknown(word))),
162 any::<(HashKind, Ident)>().prop_map(|(kind, s)| Self::Hash(kind, s)),
163 ]
164 .boxed()
165 }
166
167 type Strategy = proptest::prelude::BoxedStrategy<Self>;
168}