1use crate::IntegerType;
18
19use super::*;
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
23pub struct Literal {
24 pub span: Span,
25 pub id: NodeID,
26 pub variant: LiteralVariant,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
30pub enum LiteralVariant {
31 Address(String),
33 Boolean(bool),
35 Field(String),
38 Group(String),
40 Integer(IntegerType, String),
42 None,
44 Scalar(String),
47 Signature(String),
49 String(String),
51 Unsuffixed(String),
53}
54
55impl fmt::Display for LiteralVariant {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 match &self {
58 Self::Address(address) => write!(f, "{address}"),
59 Self::Boolean(boolean) => write!(f, "{boolean}"),
60 Self::Field(field) => write!(f, "{field}field"),
61 Self::Group(group) => write!(f, "{group}group"),
62 Self::Integer(type_, value) => write!(f, "{value}{type_}"),
63 Self::None => write!(f, "none"),
64 Self::Scalar(scalar) => write!(f, "{scalar}scalar"),
65 Self::Signature(signature) => write!(f, "{signature}"),
66 Self::String(string) => write!(f, "\"{string}\""),
67 Self::Unsuffixed(value) => write!(f, "{value}"),
68 }
69 }
70}
71
72impl fmt::Display for Literal {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 self.variant.fmt(f)
75 }
76}
77
78crate::simple_node_impl!(Literal);
79
80impl Literal {
81 pub fn address(s: String, span: Span, id: NodeID) -> Self {
82 Literal { variant: LiteralVariant::Address(s), span, id }
83 }
84
85 pub fn boolean(s: bool, span: Span, id: NodeID) -> Self {
86 Literal { variant: LiteralVariant::Boolean(s), span, id }
87 }
88
89 pub fn field(s: String, span: Span, id: NodeID) -> Self {
90 Literal { variant: LiteralVariant::Field(s), span, id }
91 }
92
93 pub fn group(s: String, span: Span, id: NodeID) -> Self {
94 Literal { variant: LiteralVariant::Group(s), span, id }
95 }
96
97 pub fn integer(integer_type: IntegerType, s: String, span: Span, id: NodeID) -> Self {
98 Literal { variant: LiteralVariant::Integer(integer_type, s), span, id }
99 }
100
101 pub fn none(span: Span, id: NodeID) -> Self {
102 Literal { variant: LiteralVariant::None, span, id }
103 }
104
105 pub fn scalar(s: String, span: Span, id: NodeID) -> Self {
106 Literal { variant: LiteralVariant::Scalar(s), span, id }
107 }
108
109 pub fn signature(s: String, span: Span, id: NodeID) -> Self {
110 Literal { variant: LiteralVariant::Signature(s), span, id }
111 }
112
113 pub fn string(s: String, span: Span, id: NodeID) -> Self {
114 Literal { variant: LiteralVariant::String(s), span, id }
115 }
116
117 pub fn unsuffixed(s: String, span: Span, id: NodeID) -> Self {
118 Literal { variant: LiteralVariant::Unsuffixed(s), span, id }
119 }
120
121 pub fn as_u32(&self) -> Option<u32> {
123 if let LiteralVariant::Integer(_, s) = &self.variant {
124 u32::from_str_by_radix(&s.replace("_", "")).ok()
125 } else {
126 None
127 }
128 }
129}
130
131impl From<Literal> for Expression {
132 fn from(value: Literal) -> Self {
133 Expression::Literal(value)
134 }
135}
136
137pub trait FromStrRadix: Sized {
141 fn from_str_by_radix(src: &str) -> Result<Self, std::num::ParseIntError>;
142}
143
144macro_rules! implement_from_str_radix {
145 ($($ty:ident)*) => {
146 $(
147 impl FromStrRadix for $ty {
148 fn from_str_by_radix(src: &str) -> Result<Self, std::num::ParseIntError> {
149 if let Some(stripped) = src.strip_prefix("0x") {
150 Self::from_str_radix(stripped, 16)
151 } else if let Some(stripped) = src.strip_prefix("0o") {
152 Self::from_str_radix(stripped, 8)
153 } else if let Some(stripped) = src.strip_prefix("0b") {
154 Self::from_str_radix(stripped, 2)
155 } else if let Some(stripped) = src.strip_prefix("-0x") {
156 let mut s = String::new();
160 s.push('-');
161 s.push_str(stripped);
162 Self::from_str_radix(&s, 16)
163 } else if let Some(stripped) = src.strip_prefix("-0o") {
164 let mut s = String::new();
166 s.push('-');
167 s.push_str(stripped);
168 Self::from_str_radix(&s, 8)
169 } else if let Some(stripped) = src.strip_prefix("-0b") {
170 let mut s = String::new();
172 s.push('-');
173 s.push_str(stripped);
174 Self::from_str_radix(&s, 2)
175 } else {
176 Self::from_str_radix(src, 10)
177 }
178 }
179 }
180 )*
181 };
182}
183
184implement_from_str_radix! { u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 }