protospec_build/asg/expression/
const_int.rs

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}