diff --git a/lexer/src/number.rs b/lexer/src/number.rs index 2b98585..7bab968 100644 --- a/lexer/src/number.rs +++ b/lexer/src/number.rs @@ -2,7 +2,7 @@ * Eryn Wells */ -use sibiltypes::Number; +use sibiltypes::number::{Number, Exact}; #[derive(Debug)] pub enum Radix { Bin, Oct, Dec, Hex } @@ -10,12 +10,9 @@ pub enum Radix { Bin, Oct, Dec, Hex } #[derive(PartialEq, Debug)] pub enum Sign { Pos, Neg } -#[derive(PartialEq, Debug)] -pub enum Exactness { Exact, Inexact } - #[derive(Debug)] pub struct NumberBuilder { - exact: Option, + exact: Exact, radix: Radix, sign: Sign, value: f64, @@ -25,7 +22,7 @@ pub struct NumberBuilder { impl NumberBuilder { pub fn new() -> NumberBuilder { NumberBuilder { - exact: None, + exact: Exact::Yes, radix: Radix::Dec, sign: Sign::Pos, value: 0.0, @@ -33,8 +30,8 @@ impl NumberBuilder { } } - pub fn exact<'a>(&'a mut self, ex: Exactness) -> &'a mut NumberBuilder { - self.exact = Some(ex); + pub fn exact<'a>(&'a mut self, ex: Exact) -> &'a mut NumberBuilder { + self.exact = ex; self } @@ -79,8 +76,7 @@ impl NumberBuilder { value }; // TODO: Use an integer if we can. - let exact = self.point == 0 || self.exact == Some(Exactness::Exact); - Number::from_float(value, exact) + Number::from_float(value, self.exact) } pub fn radix_value(&self) -> u32 { diff --git a/types/src/number/mod.rs b/types/src/number/mod.rs index 4f9a467..8b90c3b 100644 --- a/types/src/number/mod.rs +++ b/types/src/number/mod.rs @@ -17,16 +17,28 @@ pub use self::real::Real; type Int = i64; type Flt = f64; +#[derive(Debug, Eq, PartialEq)] +pub enum Exact { Yes, No } + +impl fmt::Display for Exact { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", match *self { + Exact::Yes => "#e", + Exact::No => "#i", + }) + } +} + // TODO: Implement PartialEq myself cause there are some weird nuances to comparing numbers. #[derive(Debug, PartialEq)] pub struct Number { real: Real, imag: Option, - exact: bool, + exact: Exact, } impl Number { - fn new(real: Real, imag: Option, exact: bool) -> Number { + fn new(real: Real, imag: Option, exact: Exact) -> Number { Number { real: real.reduce(), imag: imag.map(|n| n.reduce()), @@ -34,12 +46,12 @@ impl Number { } } - pub fn from_int(value: Int, exact: bool) -> Number { + pub fn from_int(value: Int, exact: Exact) -> Number { Number::new(Real::Integer(value), None, exact) } - pub fn from_quotient(p: Int, q: Int, exact: bool) -> Number { - let real = if exact { + pub fn from_quotient(p: Int, q: Int, exact: Exact) -> Number { + let real = if exact == Exact::Yes { // Make an exact rational an integer if possible. Real::Rational(p, q).demote() } @@ -50,8 +62,8 @@ impl Number { Number::new(real, None, exact) } - pub fn from_float(value: Flt, exact: bool) -> Number { - let real = if exact { + pub fn from_float(value: Flt, exact: Exact) -> Number { + let real = if exact == Exact::Yes { // Attempt to demote irrationals. Real::Irrational(value).demote() } @@ -61,7 +73,12 @@ impl Number { Number::new(real, None, exact) } - pub fn is_exact(&self) -> bool { self.exact } + pub fn is_exact(&self) -> bool { + match self.exact { + Exact::Yes => true, + Exact::No => false, + } + } } impl fmt::Display for Number { @@ -85,6 +102,6 @@ mod tests { #[test] fn exact_irrationals_are_reduced() { let real = Real::Rational(3, 2); - assert_eq!(Number::from_float(1.5, true), Number::new(real, None, true)); + assert_eq!(Number::from_float(1.5, Exact::Yes), Number::new(real, None, Exact::Yes)); } }