rustpython_ast/
builtin.rs1use crate::bigint::BigInt;
4
5pub type String = std::string::String;
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
8pub struct Identifier(String);
9
10impl Identifier {
11 #[inline]
12 pub fn new(s: impl Into<String>) -> Self {
13 Self(s.into())
14 }
15}
16
17impl Identifier {
18 #[inline]
19 pub fn as_str(&self) -> &str {
20 self.0.as_str()
21 }
22}
23
24impl std::cmp::PartialEq<str> for Identifier {
25 #[inline]
26 fn eq(&self, other: &str) -> bool {
27 self.0 == other
28 }
29}
30
31impl std::cmp::PartialEq<String> for Identifier {
32 #[inline]
33 fn eq(&self, other: &String) -> bool {
34 &self.0 == other
35 }
36}
37
38impl std::ops::Deref for Identifier {
39 type Target = str;
40 #[inline]
41 fn deref(&self) -> &Self::Target {
42 self.0.as_str()
43 }
44}
45
46impl AsRef<str> for Identifier {
47 #[inline]
48 fn as_ref(&self) -> &str {
49 self.0.as_str()
50 }
51}
52
53impl AsRef<String> for Identifier {
54 #[inline]
55 fn as_ref(&self) -> &String {
56 &self.0
57 }
58}
59
60impl std::fmt::Display for Identifier {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 self.0.fmt(f)
63 }
64}
65
66impl From<Identifier> for String {
67 #[inline]
68 fn from(id: Identifier) -> String {
69 id.0
70 }
71}
72
73impl From<String> for Identifier {
74 #[inline]
75 fn from(id: String) -> Self {
76 Self(id)
77 }
78}
79
80impl<'a> From<&'a str> for Identifier {
81 #[inline]
82 fn from(id: &'a str) -> Identifier {
83 id.to_owned().into()
84 }
85}
86
87#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
88pub struct Int(u32);
89
90impl Int {
91 pub fn new(i: u32) -> Self {
92 Self(i)
93 }
94 pub fn to_u32(&self) -> u32 {
95 self.0
96 }
97 pub fn to_usize(&self) -> usize {
98 self.0 as _
99 }
100}
101
102impl std::cmp::PartialEq<u32> for Int {
103 #[inline]
104 fn eq(&self, other: &u32) -> bool {
105 self.0 == *other
106 }
107}
108
109impl std::cmp::PartialEq<usize> for Int {
110 #[inline]
111 fn eq(&self, other: &usize) -> bool {
112 self.0 as usize == *other
113 }
114}
115
116#[derive(Clone, Debug, PartialEq, is_macro::Is)]
117pub enum Constant {
118 None,
119 Bool(bool),
120 Str(String),
121 Bytes(Vec<u8>),
122 Int(BigInt),
123 Tuple(Vec<Constant>),
124 Float(f64),
125 Complex { real: f64, imag: f64 },
126 Ellipsis,
127}
128
129impl Constant {
130 pub fn is_true(self) -> bool {
131 self.bool().map_or(false, |b| b)
132 }
133 pub fn is_false(self) -> bool {
134 self.bool().map_or(false, |b| !b)
135 }
136 pub fn complex(self) -> Option<(f64, f64)> {
137 match self {
138 Constant::Complex { real, imag } => Some((real, imag)),
139 _ => None,
140 }
141 }
142}
143
144impl From<String> for Constant {
145 fn from(s: String) -> Constant {
146 Self::Str(s)
147 }
148}
149impl From<Vec<u8>> for Constant {
150 fn from(b: Vec<u8>) -> Constant {
151 Self::Bytes(b)
152 }
153}
154impl From<bool> for Constant {
155 fn from(b: bool) -> Constant {
156 Self::Bool(b)
157 }
158}
159impl From<BigInt> for Constant {
160 fn from(i: BigInt) -> Constant {
161 Self::Int(i)
162 }
163}
164
165#[cfg(feature = "rustpython-literal")]
166impl std::fmt::Display for Constant {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 match self {
169 Constant::None => f.pad("None"),
170 Constant::Bool(b) => f.pad(if *b { "True" } else { "False" }),
171 Constant::Str(s) => rustpython_literal::escape::UnicodeEscape::new_repr(s.as_str())
172 .str_repr()
173 .write(f),
174 Constant::Bytes(b) => {
175 let escape = rustpython_literal::escape::AsciiEscape::new_repr(b);
176 let repr = escape.bytes_repr().to_string().unwrap();
177 f.pad(&repr)
178 }
179 Constant::Int(i) => i.fmt(f),
180 Constant::Tuple(tup) => {
181 if let [elt] = &**tup {
182 write!(f, "({elt},)")
183 } else {
184 f.write_str("(")?;
185 for (i, elt) in tup.iter().enumerate() {
186 if i != 0 {
187 f.write_str(", ")?;
188 }
189 elt.fmt(f)?;
190 }
191 f.write_str(")")
192 }
193 }
194 Constant::Float(fp) => f.pad(&rustpython_literal::float::to_string(*fp)),
195 Constant::Complex { real, imag } => {
196 if *real == 0.0 {
197 write!(f, "{imag}j")
198 } else {
199 write!(f, "({real}{imag:+}j)")
200 }
201 }
202 Constant::Ellipsis => f.pad("..."),
203 }
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210 #[test]
211 fn test_is_macro() {
212 let none = Constant::None;
213 assert!(none.is_none());
214 assert!(!none.is_bool());
215 }
216}