1use super::*;
2
3#[derive(Clone, Copy, Debug, PartialEq)]
4pub enum ConstInt {
5 I8(i8),
6 I16(i16),
7 I32(i32),
8 I64(i64),
9 I128(i128),
10 U8(u8),
11 U16(u16),
12 U32(u32),
13 U64(u64),
14 U128(u128),
15}
16
17macro_rules! const_int_biop {
18 ($e1: expr, $e2: expr, $i1: ident, $i2: ident, $op: expr) => {
19 match ($e1, $e2) {
20 (ConstInt::I8($i1), ConstInt::I8($i2)) => $op,
21 (ConstInt::I16($i1), ConstInt::I16($i2)) => $op,
22 (ConstInt::I32($i1), ConstInt::I32($i2)) => $op,
23 (ConstInt::I64($i1), ConstInt::I64($i2)) => $op,
24 (ConstInt::I128($i1), ConstInt::I128($i2)) => $op,
25 (ConstInt::U8($i1), ConstInt::U8($i2)) => $op,
26 (ConstInt::U16($i1), ConstInt::U16($i2)) => $op,
27 (ConstInt::U32($i1), ConstInt::U32($i2)) => $op,
28 (ConstInt::U64($i1), ConstInt::U64($i2)) => $op,
29 (ConstInt::U128($i1), ConstInt::U128($i2)) => $op,
30 _ => None,
31 }
32 };
33}
34
35macro_rules! const_int_biop_map {
36 ($e1: expr, $e2: expr, $i1: ident, $i2: ident, $op: expr) => {
37 match ($e1, $e2) {
38 (ConstInt::I8($i1), ConstInt::I8($i2)) => Some(ConstInt::I8($op)),
39 (ConstInt::I16($i1), ConstInt::I16($i2)) => Some(ConstInt::I16($op)),
40 (ConstInt::I32($i1), ConstInt::I32($i2)) => Some(ConstInt::I32($op)),
41 (ConstInt::I64($i1), ConstInt::I64($i2)) => Some(ConstInt::I64($op)),
42 (ConstInt::I128($i1), ConstInt::I128($i2)) => Some(ConstInt::I128($op)),
43 (ConstInt::U8($i1), ConstInt::U8($i2)) => Some(ConstInt::U8($op)),
44 (ConstInt::U16($i1), ConstInt::U16($i2)) => Some(ConstInt::U16($op)),
45 (ConstInt::U32($i1), ConstInt::U32($i2)) => Some(ConstInt::U32($op)),
46 (ConstInt::U64($i1), ConstInt::U64($i2)) => Some(ConstInt::U64($op)),
47 (ConstInt::U128($i1), ConstInt::U128($i2)) => Some(ConstInt::U128($op)),
48 _ => None,
49 }
50 };
51}
52
53macro_rules! const_int_map {
54 ($e1: expr, $i1: ident, $sop: expr, $usop: expr) => {
55 match $e1 {
56 ConstInt::I8($i1) => Some(ConstInt::I8($sop)),
57 ConstInt::I16($i1) => Some(ConstInt::I16($sop)),
58 ConstInt::I32($i1) => Some(ConstInt::I32($sop)),
59 ConstInt::I64($i1) => Some(ConstInt::I64($sop)),
60 ConstInt::I128($i1) => Some(ConstInt::I128($sop)),
61 ConstInt::U8($i1) => Some(ConstInt::U8($usop)),
62 ConstInt::U16($i1) => Some(ConstInt::U16($usop)),
63 ConstInt::U32($i1) => Some(ConstInt::U32($usop)),
64 ConstInt::U64($i1) => Some(ConstInt::U64($usop)),
65 ConstInt::U128($i1) => Some(ConstInt::U128($usop)),
66 }
67 };
68}
69
70macro_rules! const_int_op {
71 ($e1: expr, $i1: ident, $op: expr) => {
72 match $e1 {
73 ConstInt::I8($i1) => $op,
74 ConstInt::I16($i1) => $op,
75 ConstInt::I32($i1) => $op,
76 ConstInt::I64($i1) => $op,
77 ConstInt::I128($i1) => $op,
78 ConstInt::U8($i1) => $op,
79 ConstInt::U16($i1) => $op,
80 ConstInt::U32($i1) => $op,
81 ConstInt::U64($i1) => $op,
82 ConstInt::U128($i1) => $op,
83 }
84 };
85}
86
87impl PartialOrd for ConstInt {
88 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
89 const_int_biop!(self, other, i1, i2, i1.partial_cmp(i2))
90 }
91}
92
93impl BitOr for ConstInt {
94 type Output = Option<Self>;
95
96 fn bitor(self, other: Self) -> Self::Output {
97 const_int_biop_map!(self, other, i1, i2, i1 | i2)
98 }
99}
100
101impl BitAnd for ConstInt {
102 type Output = Option<Self>;
103
104 fn bitand(self, other: Self) -> Self::Output {
105 const_int_biop_map!(self, other, i1, i2, i1 & i2)
106 }
107}
108
109impl BitXor for ConstInt {
110 type Output = Option<Self>;
111
112 fn bitxor(self, other: Self) -> Self::Output {
113 const_int_biop_map!(self, other, i1, i2, i1 ^ i2)
114 }
115}
116
117impl Shr for ConstInt {
118 type Output = Option<Self>;
119
120 fn shr(self, other: Self) -> Self::Output {
121 const_int_biop_map!(self, other, i1, i2, i1 >> i2)
122 }
123}
124
125impl Shl for ConstInt {
126 type Output = Option<Self>;
127
128 fn shl(self, other: Self) -> Self::Output {
129 const_int_biop_map!(self, other, i1, i2, i1 << i2)
130 }
131}
132
133impl Add for ConstInt {
134 type Output = Option<Self>;
135
136 fn add(self, other: Self) -> Self::Output {
137 const_int_biop_map!(self, other, i1, i2, i1 + i2)
138 }
139}
140
141impl Sub for ConstInt {
142 type Output = Option<Self>;
143
144 fn sub(self, other: Self) -> Self::Output {
145 const_int_biop_map!(self, other, i1, i2, i1 - i2)
146 }
147}
148
149impl Mul for ConstInt {
150 type Output = Option<Self>;
151
152 fn mul(self, other: Self) -> Self::Output {
153 const_int_biop_map!(self, other, i1, i2, i1 * i2)
154 }
155}
156
157impl Div for ConstInt {
158 type Output = Option<Self>;
159
160 fn div(self, other: Self) -> Self::Output {
161 const_int_biop_map!(self, other, i1, i2, i1 / i2)
162 }
163}
164
165impl Rem for ConstInt {
166 type Output = Option<Self>;
167
168 fn rem(self, other: Self) -> Self::Output {
169 const_int_biop_map!(self, other, i1, i2, i1 % i2)
170 }
171}
172
173impl Neg for ConstInt {
174 type Output = Option<Self>;
175
176 #[allow(unreachable_code, unused_variables)]
177 fn neg(self) -> Self::Output {
178 const_int_map!(self, i1, -i1, unimplemented!("cannot neg unsigned value"))
179 }
180}
181
182impl Not for ConstInt {
183 type Output = Option<Self>;
184
185 fn not(self) -> Self::Output {
186 const_int_map!(self, i1, i1.not(), i1.not())
187 }
188}
189
190impl ConstInt {
191 pub fn cast_to(&self, target: ScalarType) -> Self {
192 const_int_op!(
193 self,
194 i1,
195 match target {
196 ScalarType::I8 => ConstInt::I8(*i1 as i8),
197 ScalarType::I16 => ConstInt::I16(*i1 as i16),
198 ScalarType::I32 => ConstInt::I32(*i1 as i32),
199 ScalarType::I64 => ConstInt::I64(*i1 as i64),
200 ScalarType::I128 => ConstInt::I128(*i1 as i128),
201 ScalarType::U8 => ConstInt::U8(*i1 as u8),
202 ScalarType::U16 => ConstInt::U16(*i1 as u16),
203 ScalarType::U32 => ConstInt::U32(*i1 as u32),
204 ScalarType::U64 => ConstInt::U64(*i1 as u64),
205 ScalarType::U128 => ConstInt::U128(*i1 as u128),
206 }
207 )
208 }
209
210 pub fn parse(scalar_type: ScalarType, value: &str, span: Span) -> AsgResult<ConstInt> {
211 if value.starts_with("0x") {
212 let value = &value[2..];
213 return Ok(match scalar_type {
214 ScalarType::I8 => ConstInt::I8(
215 i8::from_str_radix(value, 16)
216 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
217 ),
218 ScalarType::I16 => ConstInt::I16(
219 i16::from_str_radix(value, 16)
220 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
221 ),
222 ScalarType::I32 => ConstInt::I32(
223 i32::from_str_radix(value, 16)
224 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
225 ),
226 ScalarType::I64 => ConstInt::I64(
227 i64::from_str_radix(value, 16)
228 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
229 ),
230 ScalarType::I128 => ConstInt::I128(
231 i128::from_str_radix(value, 16)
232 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
233 ),
234 ScalarType::U8 => ConstInt::U8(
235 u8::from_str_radix(value, 16)
236 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
237 ),
238 ScalarType::U16 => ConstInt::U16(
239 u16::from_str_radix(value, 16)
240 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
241 ),
242 ScalarType::U32 => ConstInt::U32(
243 u32::from_str_radix(value, 16)
244 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
245 ),
246 ScalarType::U64 => ConstInt::U64(
247 u64::from_str_radix(value, 16)
248 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
249 ),
250 ScalarType::U128 => ConstInt::U128(
251 u128::from_str_radix(value, 16)
252 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
253 ),
254 });
255 }
256 Ok(match scalar_type {
257 ScalarType::I8 => ConstInt::I8(
258 value
259 .parse()
260 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
261 ),
262 ScalarType::I16 => ConstInt::I16(
263 value
264 .parse()
265 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
266 ),
267 ScalarType::I32 => ConstInt::I32(
268 value
269 .parse()
270 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
271 ),
272 ScalarType::I64 => ConstInt::I64(
273 value
274 .parse()
275 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
276 ),
277 ScalarType::I128 => ConstInt::I128(
278 value
279 .parse()
280 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
281 ),
282 ScalarType::U8 => ConstInt::U8(
283 value
284 .parse()
285 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
286 ),
287 ScalarType::U16 => ConstInt::U16(
288 value
289 .parse()
290 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
291 ),
292 ScalarType::U32 => ConstInt::U32(
293 value
294 .parse()
295 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
296 ),
297 ScalarType::U64 => ConstInt::U64(
298 value
299 .parse()
300 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
301 ),
302 ScalarType::U128 => ConstInt::U128(
303 value
304 .parse()
305 .map_err(|_| AsgError::InvalidInt(value.to_string(), span))?,
306 ),
307 })
308 }
309}