cl-interpret: Enforce wrapping behavior

This commit is contained in:
John 2024-07-09 06:13:55 -05:00
parent 0beb121f32
commit b446677eda
2 changed files with 13 additions and 9 deletions

View File

@ -1,9 +1,9 @@
//! Implementations of built-in functions //! Implementations of built-in functions
use super::{ use super::{
convalue::ConValue,
env::Environment, env::Environment,
error::{Error, IResult}, error::{Error, IResult},
convalue::ConValue,
BuiltIn, Callable, BuiltIn, Callable,
}; };
use cl_ast::Sym; use cl_ast::Sym;
@ -183,7 +183,7 @@ builtins! {
pub fn neg(tail) -> IResult<ConValue> { pub fn neg(tail) -> IResult<ConValue> {
Ok(match tail { Ok(match tail {
ConValue::Empty => ConValue::Empty, ConValue::Empty => ConValue::Empty,
ConValue::Int(v) => ConValue::Int(-v), ConValue::Int(v) => ConValue::Int(v.wrapping_neg()),
_ => Err(Error::TypeError)?, _ => Err(Error::TypeError)?,
}) })
} }

View File

@ -207,7 +207,7 @@ pub mod convalue {
ops! { ops! {
Add: add = [ Add: add = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a + b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_add(b)),
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(), (ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
@ -231,32 +231,36 @@ pub mod convalue {
] ]
Div: div = [ Div: div = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a / b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_div(b).unwrap_or_else(|| {
eprintln!("Warning: Divide by zero in {a} / {b}"); a
})),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Mul: mul = [ Mul: mul = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a * b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_mul(b)),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Rem: rem = [ Rem: rem = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a % b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.checked_rem(b).unwrap_or_else(|| {
eprintln!("Warning: Divide by zero in {a} % {b}"); a
})),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Shl: shl = [ Shl: shl = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a << b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_shl(b as _)),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Shr: shr = [ Shr: shr = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a >> b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_shr(b as _)),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
Sub: sub = [ Sub: sub = [
(ConValue::Empty, ConValue::Empty) => ConValue::Empty, (ConValue::Empty, ConValue::Empty) => ConValue::Empty,
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a - b), (ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_sub(b)),
_ => Err(Error::TypeError)? _ => Err(Error::TypeError)?
] ]
} }