Improve float.fromhex module of objfloat (#1552)

* Improve  float.fromhex module of objfloat

- Python float.fromhex can handle string of float and hex without `.`
  - For example '0.0', '-0.0', '0x0p0', '-0x0p0'
- Add test case mantioned

* Change unwrap to expect for error handling

* Improve error handling with pattern matching

- `expect` that can't express python vm error message changed to pattern match
- Erase duplicated test case

* Refactoring with or_else and map_err

- Use `or_else` instead of value condition and `match` statement
  - For floating-point input
- Use `map_err` instead of `match ` statement
  - For hexadecimal floating-point input without dot

* Add else condition
This commit is contained in:
Johan
2019-11-01 03:54:28 +09:00
committed by Windel Bouwman
parent 0b50c21eff
commit 40a22f217d
2 changed files with 33 additions and 6 deletions

View File

@@ -240,12 +240,21 @@ a = 3.1__4
with assert_raises(SyntaxError):
exec(src)
assert float.fromhex('0.0') == 0.0
assert float.fromhex('-0.0') == 0.0
assert float.fromhex('0x0p0') == 0.0
assert float.fromhex('0x010p0') == 16.0
assert float.fromhex('0x0.10p3') == 0.5
assert float.fromhex('-0x0p0') == 0.0
assert float.fromhex('0x0.p0') == 0.0
assert float.fromhex('-0x0.p0') == 0.0
assert float.fromhex('0x0.0p+0') == 0.0
assert float.fromhex('-0x0.0p+0') == -0.0
assert float.fromhex('0x1.000000p+0') == 1.0
assert float.fromhex('-0x1.800000p+0') == -1.5
assert float.fromhex('inf') == float('inf')
assert math.isnan(float.fromhex('nan'))
assert_raises(ValueError, lambda: float.fromhex('error'))
assert (0.0).hex() == '0x0.0p+0'
assert (-0.0).hex() == '-0x0.0p+0'

View File

@@ -583,12 +583,30 @@ impl PyFloat {
#[pymethod]
fn fromhex(repr: PyStringRef, vm: &VirtualMachine) -> PyResult<f64> {
hexf_parse::parse_hexf64(repr.as_str(), false).or_else(|_| match repr.as_str() {
"nan" => Ok(std::f64::NAN),
"inf" => Ok(std::f64::INFINITY),
"-inf" => Ok(std::f64::NEG_INFINITY),
_ => Err(vm.new_value_error("invalid hexadecimal floating-point string".to_string())),
})
hexf_parse::parse_hexf64(repr.as_str(), false)
.or_else(|_| repr.as_str().parse::<f64>())
.or_else(|_| match repr.as_str() {
"nan" => Ok(std::f64::NAN),
"inf" => Ok(std::f64::INFINITY),
"-inf" => Ok(std::f64::NEG_INFINITY),
value => {
let mut hex = String::new();
if value.contains("0x") {
for ch in value.chars() {
if ch == 'p' {
hex.push_str(".p");
} else {
hex.push(ch);
}
}
} else {
hex = value.to_string();
}
hexf_parse::parse_hexf64(hex.as_str(), false).map_err(|_| {
vm.new_value_error("invalid hexadecimal floating-point string".to_string())
})
}
})
}
#[pymethod]