diff --git a/tests/snippets/strings.py b/tests/snippets/strings.py index 7b219ba8a..cd7d9f262 100644 --- a/tests/snippets/strings.py +++ b/tests/snippets/strings.py @@ -225,6 +225,18 @@ assert_raises(TypeError, lambda: "My name is %(name)s" % "Foo", msg="format requ assert_raises(ValueError, lambda: "This %(food}s is great!" % {"food": "cookie"}, msg="incomplete format key") assert_raises(ValueError, lambda: "My name is %" % "Foo", msg="incomplete format") +# Erase if features are implemented +assert_raises(NotImplementedError, lambda: "%e" % 1.2345, + msg="Not yet implemented for %e and %E") +assert_raises(NotImplementedError, lambda: "%E" % 1.2345, + msg="Not yet implemented for %e and %E") +assert_raises(NotImplementedError, lambda: "%g" % 1.2345, + msg="Not yet implemented for %g and %G") +assert_raises(NotImplementedError, lambda: "%G" % 1.2345, + msg="Not yet implemented for %g and %G") +assert_raises(NotImplementedError, lambda: "%3.9f" % 1.2345, + msg="Not yet implemented for %#.#f types") + assert 'a' < 'b' assert 'a' <= 'b' assert 'a' <= 'a' diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index cac22a3a5..e67fd0715 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -210,7 +210,7 @@ impl CFormatSpec { } } - pub fn format_float(&self, num: f64) -> String { + pub fn format_float(&self, num: f64) -> Result { let magnitude = num.abs(); let sign_string = if num.is_sign_positive() { @@ -226,7 +226,22 @@ impl CFormatSpec { }; // TODO: Support precision - let magnitude_string = format!("{:.6}", magnitude); + let magnitude_string = match self.format_type { + CFormatType::Float(CFloatType::PointDecimal) => { + if Some(CFormatQuantity::Amount(6)) != self.precision { + return Err("Not yet implemented for %#.#f types".to_string()); + } else { + format!("{:.6}", magnitude) + } + } + CFormatType::Float(CFloatType::Exponent(_)) => { + return Err("Not yet implemented for %e and %E".to_string()) + } + CFormatType::Float(CFloatType::General(_)) => { + return Err("Not yet implemented for %g and %G".to_string()) + } + _ => unreachable!(), + }; if self.flags.contains(CConversionFlags::ZERO_PAD) { let fill_char = if !self.flags.contains(CConversionFlags::LEFT_ADJUST) { @@ -234,7 +249,7 @@ impl CFormatSpec { } else { ' ' }; - format!( + Ok(format!( "{}{}", sign_string, self.fill_string( @@ -242,9 +257,9 @@ impl CFormatSpec { fill_char, Some(sign_string.chars().count()) ) - ) + )) } else { - self.fill_string(format!("{}{}", sign_string, magnitude_string), ' ', None) + Ok(self.fill_string(format!("{}{}", sign_string, magnitude_string), ' ', None)) } } } @@ -806,34 +821,39 @@ mod tests { assert_eq!( "%f".parse::() .unwrap() - .format_float(f64::from(1.2345)), - "1.234500".to_string() + .format_float(f64::from(1.2345)) + .ok(), + Some("1.234500".to_string()) ); assert_eq!( "%+f" .parse::() .unwrap() - .format_float(f64::from(1.2345)), - "+1.234500".to_string() + .format_float(f64::from(1.2345)) + .ok(), + Some("+1.234500".to_string()) ); assert_eq!( "% f" .parse::() .unwrap() - .format_float(f64::from(1.2345)), - " 1.234500".to_string() + .format_float(f64::from(1.2345)) + .ok(), + Some(" 1.234500".to_string()) ); assert_eq!( "%f".parse::() .unwrap() - .format_float(f64::from(-1.2345)), - "-1.234500".to_string() + .format_float(f64::from(-1.2345)) + .ok(), + Some("-1.234500".to_string()) ); assert_eq!( "%f".parse::() .unwrap() - .format_float(f64::from(1.2345678901)), - "1.234568".to_string() + .format_float(f64::from(1.2345678901)) + .ok(), + Some("1.234568".to_string()) ); } diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index e7c572aef..8a1e83380 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1231,18 +1231,22 @@ fn do_cformat_specifier( Ok(format_spec.format_number(objint::get_value(&obj))) } CFormatType::Float(_) => { - if objtype::isinstance(&obj, &vm.ctx.float_type()) { - Ok(format_spec.format_float(objfloat::get_value(&obj))) + let result = if objtype::isinstance(&obj, &vm.ctx.float_type()) { + format_spec.format_float(objfloat::get_value(&obj)) } else if objtype::isinstance(&obj, &vm.ctx.int_type()) { - Ok(format_spec.format_float(objint::get_value(&obj).to_f64().unwrap())) + format_spec.format_float(objint::get_value(&obj).to_f64().unwrap()) } else { let required_type_string = "an floating point or integer"; - Err(vm.new_type_error(format!( + return Err(vm.new_type_error(format!( "%{} format: {} is required, not {}", format_spec.format_char, required_type_string, obj.class() - ))) + ))); + }; + match result { + Ok(transformed) => Ok(transformed), + Err(error) => Err(vm.new_not_implemented_error(error)), } } CFormatType::Character => {