mirror of
https://github.com/nushell/nushell
synced 2025-01-15 14:44:14 +00:00
Finish operator overflow checking (#308)
This commit is contained in:
parent
b5bade6187
commit
e0a26cd048
2 changed files with 63 additions and 29 deletions
2
TODO.md
2
TODO.md
|
@ -33,8 +33,8 @@
|
||||||
- [x] block variable captures
|
- [x] block variable captures
|
||||||
- [x] improved history and config paths
|
- [x] improved history and config paths
|
||||||
- [x] ctrl-c support
|
- [x] ctrl-c support
|
||||||
|
- [x] operator overflow
|
||||||
- [ ] Support for `$in`
|
- [ ] Support for `$in`
|
||||||
- [ ] operator overflow
|
|
||||||
- [ ] shells
|
- [ ] shells
|
||||||
- [ ] plugins
|
- [ ] plugins
|
||||||
- [ ] dataframes
|
- [ ] dataframes
|
||||||
|
|
|
@ -535,16 +535,24 @@ impl Value {
|
||||||
span,
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
||||||
Ok(Value::Duration {
|
if let Some(val) = lhs.checked_add(*rhs) {
|
||||||
val: *lhs + *rhs,
|
Ok(Value::Duration { val, span })
|
||||||
span,
|
} else {
|
||||||
})
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"add operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
||||||
Ok(Value::Filesize {
|
if let Some(val) = lhs.checked_add(*rhs) {
|
||||||
val: *lhs + *rhs,
|
Ok(Value::Filesize { val, span })
|
||||||
span,
|
} else {
|
||||||
})
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"add operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(ShellError::OperatorMismatch {
|
_ => Err(ShellError::OperatorMismatch {
|
||||||
|
@ -560,10 +568,16 @@ impl Value {
|
||||||
let span = span(&[self.span()?, rhs.span()?]);
|
let span = span(&[self.span()?, rhs.span()?]);
|
||||||
|
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||||
val: lhs - rhs,
|
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||||
span,
|
Ok(Value::Int { val, span })
|
||||||
}),
|
} else {
|
||||||
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"subtraction operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: *lhs as f64 - *rhs,
|
val: *lhs as f64 - *rhs,
|
||||||
span,
|
span,
|
||||||
|
@ -577,16 +591,24 @@ impl Value {
|
||||||
span,
|
span,
|
||||||
}),
|
}),
|
||||||
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
||||||
Ok(Value::Duration {
|
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||||
val: *lhs - *rhs,
|
Ok(Value::Duration { val, span })
|
||||||
span,
|
} else {
|
||||||
})
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"subtraction operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
||||||
Ok(Value::Filesize {
|
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||||
val: *lhs - *rhs,
|
Ok(Value::Filesize { val, span })
|
||||||
span,
|
} else {
|
||||||
})
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"add operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(ShellError::OperatorMismatch {
|
_ => Err(ShellError::OperatorMismatch {
|
||||||
|
@ -602,10 +624,16 @@ impl Value {
|
||||||
let span = span(&[self.span()?, rhs.span()?]);
|
let span = span(&[self.span()?, rhs.span()?]);
|
||||||
|
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||||
val: lhs * rhs,
|
if let Some(val) = lhs.checked_mul(*rhs) {
|
||||||
span,
|
Ok(Value::Int { val, span })
|
||||||
}),
|
} else {
|
||||||
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"multiply operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: *lhs as f64 * *rhs,
|
val: *lhs as f64 * *rhs,
|
||||||
span,
|
span,
|
||||||
|
@ -983,10 +1011,16 @@ impl Value {
|
||||||
let span = span(&[self.span()?, rhs.span()?]);
|
let span = span(&[self.span()?, rhs.span()?]);
|
||||||
|
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||||
val: lhs.pow(*rhs as u32),
|
if let Some(val) = lhs.checked_pow(*rhs as u32) {
|
||||||
span,
|
Ok(Value::Int { val, span })
|
||||||
}),
|
} else {
|
||||||
|
Err(ShellError::OperatorOverflow(
|
||||||
|
"pow operation overflowed".into(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||||
val: (*lhs as f64).powf(*rhs),
|
val: (*lhs as f64).powf(*rhs),
|
||||||
span,
|
span,
|
||||||
|
|
Loading…
Reference in a new issue