Skip to content

Commit

Permalink
Support float(<str>) and float(<bytes>)
Browse files Browse the repository at this point in the history
  • Loading branch information
OddCoincidence committed Feb 12, 2019
1 parent 6f0ac74 commit 38c0ea0
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 5 deletions.
44 changes: 41 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions tests/snippets/floats.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
import math

def assert_raises(expr, exc_type):
"""
Helper function to assert `expr` raises an exception of type `exc_type`
Args:
expr: Callable
exec_type: Exception
Returns:
None
Raises:
Assertion error on failure
"""
try:
expr(None)
except exc_type:
assert True
else:
assert False

1 + 1.1

a = 1.2
Expand Down Expand Up @@ -39,3 +59,25 @@
assert a >= 'a'
except TypeError:
pass

assert math.isnan(float('nan'))
assert math.isnan(float('NaN'))
assert math.isnan(float('+NaN'))
assert math.isnan(float('-NaN'))

assert math.isinf(float('inf'))
assert math.isinf(float('Inf'))
assert math.isinf(float('+Inf'))
assert math.isinf(float('-Inf'))

assert float('+Inf') > 0
assert float('-Inf') < 0

assert float('3.14') == 3.14
assert float('2.99e-23') == 2.99e-23

assert float(b'3.14') == 3.14
assert float(b'2.99e-23') == 2.99e-23

assert_raises(lambda _: float('foo'), ValueError)
assert_raises(lambda _: float(2**10000), OverflowError)
1 change: 1 addition & 0 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ statrs = "0.10.0"
caseless = "0.2.1"
unicode-segmentation = "1.2.1"
lazy_static = "^1.0.1"
lexical = "2.0.0"
1 change: 1 addition & 0 deletions vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
extern crate lexical;
#[macro_use]
extern crate log;
// extern crate env_logger;
Expand Down
32 changes: 30 additions & 2 deletions vm/src/obj/objfloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use super::super::pyobject::{
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objbytes;
use super::objint;
use super::objstr;
use super::objtype;
use num_bigint::ToBigInt;
use num_traits::ToPrimitive;
Expand All @@ -23,9 +25,35 @@ fn float_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let val = if objtype::isinstance(arg, &vm.ctx.float_type()) {
get_value(arg)
} else if objtype::isinstance(arg, &vm.ctx.int_type()) {
objint::get_value(arg).to_f64().unwrap()
match objint::get_value(arg).to_f64() {
Some(f) => f,
None => {
return Err(vm.new_overflow_error("int too large to convert to float".to_string()));
}
}
} else if objtype::isinstance(arg, &vm.ctx.str_type()) {
match lexical::try_parse(objstr::get_value(arg)) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(arg)?;
return Err(
vm.new_value_error(format!("could not convert string to float: {}", arg_repr))
);
}
}
} else if objtype::isinstance(arg, &vm.ctx.bytes_type()) {
match lexical::try_parse(objbytes::get_value(arg).as_slice()) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(arg)?;
return Err(
vm.new_value_error(format!("could not convert string to float: {}", arg_repr))
);
}
}
} else {
return Err(vm.new_type_error("Cannot construct int".to_string()));
let type_name = objtype::get_type_name(&arg.typ());
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
};
set_value(zelf, val);
Ok(vm.get_none())
Expand Down

0 comments on commit 38c0ea0

Please sign in to comment.