1use crate::ast::*;
19use std::convert::TryFrom;
20
21#[derive(Debug, thiserror::Error)]
23#[error("{message}")]
24pub struct Error {
25 pub(crate) message: String,
26}
27
28impl Error {
29 pub(crate) fn new<S: Into<String>>(message: S) -> Self {
31 Self { message: message.into() }
32 }
33}
34
35pub type Result<T> = std::result::Result<T, Error>;
37
38impl Value {
39 pub(crate) fn maybe_cast(self, target: Option<ExprType>) -> Result<Value> {
45 match (target, self) {
46 (Some(ExprType::Integer), Value::Double(d)) => {
47 Ok(Value::Integer(double_to_integer(d)?))
48 }
49 (Some(ExprType::Double), Value::Integer(i)) => Ok(Value::Double(integer_to_double(i))),
50 (_, v) => Ok(v),
51 }
52 }
53}
54
55pub fn double_to_integer(d: f64) -> Result<i32> {
57 let d = d.round();
58 if d.is_finite() && d >= (i32::MIN as f64) && (d <= i32::MAX as f64) {
59 Ok(d as i32)
60 } else {
61 Err(Error::new(format!("Cannot cast {} to integer due to overflow", d)))
62 }
63}
64
65pub(crate) fn integer_to_double(i: i32) -> f64 {
67 i as f64
68}
69
70pub(crate) fn bitwise_shl(lhs: i32, rhs: i32) -> Result<i32> {
72 let bits = match u32::try_from(rhs) {
73 Ok(n) => n,
74 Err(_) => {
75 return Err(Error::new(format!("Number of bits to << ({}) must be positive", rhs)))
76 }
77 };
78
79 match lhs.checked_shl(bits) {
80 Some(i) => Ok(i),
81 None => Ok(0),
82 }
83}
84
85pub(crate) fn bitwise_shr(lhs: i32, rhs: i32) -> Result<i32> {
87 let bits = match u32::try_from(rhs) {
88 Ok(n) => n,
89 Err(_) => {
90 return Err(Error::new(format!("Number of bits to >> ({}) must be positive", rhs)))
91 }
92 };
93
94 match lhs.checked_shr(bits) {
95 Some(i) => Ok(i),
96 None if lhs < 0 => Ok(-1),
97 None => Ok(0),
98 }
99}
100
101pub fn add_integer(lhs: i32, rhs: i32) -> Result<i32> {
103 match lhs.checked_add(rhs) {
104 Some(i) => Ok(i),
105 None => Err(Error::new("Integer overflow".to_owned())),
106 }
107}
108
109pub fn sub_integer(lhs: i32, rhs: i32) -> Result<i32> {
111 match lhs.checked_sub(rhs) {
112 Some(i) => Ok(i),
113 None => Err(Error::new("Integer underflow".to_owned())),
114 }
115}
116
117pub fn mul_integer(lhs: i32, rhs: i32) -> Result<i32> {
119 match lhs.checked_mul(rhs) {
120 Some(i) => Ok(i),
121 None => Err(Error::new("Integer overflow".to_owned())),
122 }
123}
124
125pub fn div_integer(lhs: i32, rhs: i32) -> Result<i32> {
127 if rhs == 0 {
128 return Err(Error::new("Division by zero"));
129 }
130 match lhs.checked_div(rhs) {
131 Some(i) => Ok(i),
132 None => Err(Error::new("Integer underflow".to_owned())),
133 }
134}
135
136pub fn modulo_integer(lhs: i32, rhs: i32) -> Result<i32> {
138 if rhs == 0 {
139 return Err(Error::new("Modulo by zero"));
140 }
141 match lhs.checked_rem(rhs) {
142 Some(i) => Ok(i),
143 None => Err(Error::new("Integer underflow".to_owned())),
144 }
145}
146
147pub fn pow_integer(lhs: i32, rhs: i32) -> Result<i32> {
149 let exp = match u32::try_from(rhs) {
150 Ok(exp) => exp,
151 Err(_) => {
152 return Err(Error::new(format!("Exponent {} cannot be negative", rhs)));
153 }
154 };
155 match lhs.checked_pow(exp) {
156 Some(i) => Ok(i),
157 None => Err(Error::new("Integer overflow".to_owned())),
158 }
159}
160
161pub fn neg_integer(i: i32) -> Result<i32> {
163 match i.checked_neg() {
164 Some(i) => Ok(i),
165 None => Err(Error::new("Integer underflow".to_owned())),
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::Value::*;
172 use super::*;
173
174 #[test]
175 fn test_double_to_integer() {
176 assert_eq!(8, double_to_integer(8.4).unwrap());
177 assert_eq!(9, double_to_integer(8.5).unwrap());
178 assert_eq!(9, double_to_integer(8.6).unwrap());
179
180 double_to_integer(f64::NAN).unwrap_err();
181 double_to_integer(i32::MAX as f64 + 1.0).unwrap_err();
182 double_to_integer(i32::MIN as f64 - 1.0).unwrap_err();
183 }
184
185 #[test]
186 fn test_integer_to_double() {
187 assert_eq!(7.0, integer_to_double(7));
188 }
189
190 #[test]
191 fn test_value_maybe_cast() {
192 let all_types = [ExprType::Boolean, ExprType::Double, ExprType::Integer, ExprType::Text];
193 for target in all_types {
194 assert_eq!(Boolean(true), Boolean(true).maybe_cast(Some(target)).unwrap());
195 if target != ExprType::Integer {
196 assert_eq!(Double(3.8), Double(3.8).maybe_cast(Some(target)).unwrap());
197 match Double(f64::NAN).maybe_cast(Some(target)).unwrap() {
198 Double(d) => assert!(d.is_nan()),
199 _ => panic!(),
200 }
201 }
202 if target != ExprType::Double {
203 assert_eq!(Integer(3), Integer(3).maybe_cast(Some(target)).unwrap());
204 }
205 assert_eq!(
206 Text("a".to_owned()),
207 Text("a".to_owned()).maybe_cast(Some(target)).unwrap()
208 );
209 }
210
211 assert_eq!(Integer(8), Double(8.4).maybe_cast(Some(ExprType::Integer)).unwrap());
212 assert_eq!(Integer(9), Double(8.5).maybe_cast(Some(ExprType::Integer)).unwrap());
213 assert_eq!(Integer(9), Double(8.6).maybe_cast(Some(ExprType::Integer)).unwrap());
214 assert_eq!(Double(7.0), Integer(7).maybe_cast(Some(ExprType::Double)).unwrap());
215
216 Double(f64::NAN).maybe_cast(Some(ExprType::Integer)).unwrap_err();
217 assert_eq!(
218 Double(i32::MAX as f64),
219 Integer(i32::MAX).maybe_cast(Some(ExprType::Double)).unwrap()
220 );
221 Double(i32::MAX as f64 + 1.0).maybe_cast(Some(ExprType::Integer)).unwrap_err();
222 assert_eq!(
223 Double(i32::MIN as f64),
224 Integer(i32::MIN).maybe_cast(Some(ExprType::Double)).unwrap()
225 );
226 Double(i32::MIN as f64 - 1.0).maybe_cast(Some(ExprType::Integer)).unwrap_err();
227 }
228
229 #[test]
230 fn test_value_shl() {
231 assert_eq!(12, bitwise_shl(3, 2).unwrap());
232 assert_eq!(0xf0000000u32 as i32, bitwise_shl(0xf0000000u32 as i32, 0).unwrap());
233 assert_eq!(0x80000000u32 as i32, bitwise_shl(1, 31).unwrap());
234 assert_eq!(0, bitwise_shl(0xf0000000u32 as i32, 31).unwrap());
235
236 assert_eq!(0xe0000000u32 as i32, bitwise_shl(0xf0000000u32 as i32, 1).unwrap());
237 assert_eq!(0, bitwise_shl(0x80000000u32 as i32, 1).unwrap());
238 assert_eq!(0, bitwise_shl(1, 32).unwrap());
239 assert_eq!(0, bitwise_shl(1, 64).unwrap());
240
241 assert_eq!(
242 "Number of bits to << (-1) must be positive",
243 format!("{}", bitwise_shl(3, -1).unwrap_err())
244 );
245 }
246
247 #[test]
248 fn test_value_shr() {
249 assert_eq!(3, bitwise_shr(12, 2).unwrap());
250 assert_eq!(0xf0000000u32 as i32, bitwise_shr(0xf0000000u32 as i32, 0).unwrap());
251 assert_eq!(-1, bitwise_shr(0xf0000000u32 as i32, 31).unwrap());
252 assert_eq!(1, bitwise_shr(0x70000000u32 as i32, 30).unwrap());
253 assert_eq!(-2, bitwise_shr(-8, 2).unwrap());
254
255 assert_eq!(0xf0000000u32 as i32, bitwise_shr(0xe0000000u32 as i32, 1).unwrap());
256 assert_eq!(0xc0000000u32 as i32, bitwise_shr(0x80000000u32 as i32, 1).unwrap());
257 assert_eq!(0x38000000, bitwise_shr(0x70000000, 1).unwrap());
258 assert_eq!(0, bitwise_shr(0x70000000u32 as i32, 32).unwrap());
259 assert_eq!(0, bitwise_shr(0x70000000u32 as i32, 32).unwrap());
260 assert_eq!(-1, bitwise_shr(0x80000000u32 as i32, 32).unwrap());
261 assert_eq!(-1, bitwise_shr(0x80000000u32 as i32, 64).unwrap());
262
263 assert_eq!(
264 "Number of bits to >> (-1) must be positive",
265 format!("{}", bitwise_shr(3, -1).unwrap_err())
266 );
267 }
268
269 #[test]
270 fn test_value_add_integer() {
271 assert_eq!(5, add_integer(2, 3).unwrap());
272 assert_eq!(i32::MAX, add_integer(i32::MAX, 0).unwrap());
273 assert_eq!("Integer overflow", format!("{}", add_integer(i32::MAX, 1).unwrap_err()));
274 }
275
276 #[test]
277 fn test_value_sub_integer() {
278 assert_eq!(-1, sub_integer(2, 3).unwrap());
279 assert_eq!(i32::MIN, sub_integer(i32::MIN, 0).unwrap());
280 assert_eq!("Integer underflow", format!("{}", sub_integer(i32::MIN, 1).unwrap_err()));
281 }
282
283 #[test]
284 fn test_value_mul_integer() {
285 assert_eq!(6, mul_integer(2, 3).unwrap());
286 assert_eq!(i32::MAX, mul_integer(i32::MAX, 1).unwrap());
287 assert_eq!("Integer overflow", format!("{}", mul_integer(i32::MAX, 2).unwrap_err()));
288 }
289
290 #[test]
291 fn test_value_div_integer() {
292 assert_eq!(2, div_integer(10, 5).unwrap());
293 assert_eq!(6, div_integer(20, 3).unwrap());
294 assert_eq!(i32::MIN, div_integer(i32::MIN, 1).unwrap());
295 assert_eq!("Division by zero", format!("{}", div_integer(4, 0).unwrap_err()));
296 assert_eq!("Integer underflow", format!("{}", div_integer(i32::MIN, -1).unwrap_err()));
297 }
298
299 #[test]
300 fn test_value_modulo_integer() {
301 assert_eq!(0, modulo_integer(10, 5).unwrap());
302 assert_eq!(2, modulo_integer(20, 3).unwrap());
303 assert_eq!("Modulo by zero", format!("{}", modulo_integer(4, 0).unwrap_err()));
304 assert_eq!("Integer underflow", format!("{}", modulo_integer(i32::MIN, -1).unwrap_err()));
305 }
306
307 #[test]
308 fn test_value_pow_integer() {
309 assert_eq!(1, pow_integer(0, 0).unwrap());
310 assert_eq!(9, pow_integer(3, 2).unwrap());
311 assert_eq!(i32::MAX, pow_integer(i32::MAX, 1).unwrap());
312 assert_eq!("Integer overflow", format!("{}", pow_integer(i32::MAX, 2).unwrap_err()));
313 assert_eq!(
314 "Exponent -3 cannot be negative",
315 format!("{}", pow_integer(1, -3).unwrap_err())
316 );
317 }
318
319 #[test]
320 fn test_value_neg_integer() {
321 assert_eq!(-6, neg_integer(6).unwrap());
322 assert_eq!(5, neg_integer(-5).unwrap());
323 }
324}