diff --git a/types/src/number/integer.rs b/types/src/number/integer.rs index a11024b..f842c6b 100644 --- a/types/src/number/integer.rs +++ b/types/src/number/integer.rs @@ -3,13 +3,22 @@ */ use std::any::Any; +use std::fmt; use number::Number; use object::{Obj, Object}; -pub type Int = i64; +#[derive(Debug, Eq, PartialEq)] +pub struct Int(i64); + +impl fmt::Display for Int { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} impl Object for Int { fn as_any(&self) -> &Any { self } + fn as_num(&self) -> Option<&Number> { Some(self) } } impl Number for Int { @@ -17,7 +26,7 @@ impl Number for Int { } impl PartialEq for Int { - fn eq(&self, rhs: &Obj) -> bool { + fn eq<'a>(&self, rhs: &'a Obj) -> bool { match rhs.obj().and_then(Object::as_num) { Some(num) => self == num, None => false @@ -25,8 +34,8 @@ impl PartialEq for Int { } } -impl PartialEq for Int { - fn eq(&self, rhs: &Number) -> bool { +impl<'a> PartialEq for Int { + fn eq(&self, rhs: &(Number + 'a)) -> bool { match rhs.as_int() { Some(rhs) => *self == *rhs, None => false @@ -36,32 +45,23 @@ impl PartialEq for Int { #[cfg(test)] mod tests { - use super::Int; - use number::*; - use value::*; + use super::*; #[test] fn equal_integers_are_equal() { - assert_eq!(Integer(3), Integer(3)); - assert_ne!(Integer(12), Integer(9)); - assert_eq!(Integer(4).as_value(), Integer(4).as_value()); - assert_ne!(Integer(5).as_value(), Integer(7).as_value()); + assert_eq!(Int(3), Int(3)); + assert_ne!(Int(12), Int(9)); + assert_eq!(Obj::new(Int(3)), Obj::new(Int(3))); + assert_ne!(Obj::new(Int(3)), Obj::new(Int(4))); } #[test] fn integers_are_integers() { - assert!(Integer(4).is_complex()); - assert!(Integer(4).is_real()); - assert!(Integer(4).is_rational()); - assert!(Integer(4).is_integer()); - assert!(Integer(4).is_number()); - assert!(!Integer(6).is_char()); - assert!(!Integer(6).is_bool()); + assert_eq!(Int(4).as_bool(), None); } #[test] fn integers_are_exact() { - assert!(Integer(4).is_exact()); - assert!(!Integer(4).is_inexact()); + assert!(Int(4).is_exact()); } } diff --git a/types/src/number/mod.rs b/types/src/number/mod.rs index 122214e..65fac0a 100644 --- a/types/src/number/mod.rs +++ b/types/src/number/mod.rs @@ -2,13 +2,17 @@ * Eryn Wells */ -/// # Numbers -/// -/// Scheme numbers are complex, literally. +//! # Numbers +//! +//! Scheme numbers are complex, literally. The model it uses is a hierarchy of types called the +//! Number Tower. It consists of four types, in order: Integers, Rationals (or Fractionals), +//! Irrationals (or Reals), and Complex Numbers. Each type going down the tower can be +//! unequivocally cast to the type below it, but the reverse is not necessarily true. So, an +//! Integer can be cast as a Rational (by putting its value over 1), but a Rational like 1/2 cannot +//! be represented as an Integer. mod integer; -use std::fmt; use object::Object; pub use self::integer::Int; @@ -16,19 +20,10 @@ pub use self::integer::Int; pub trait Number: Object { + /// Cast this Number to an Int if possible. fn as_int(&self) -> Option<&Int> { None } -} - -#[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", - }) - } + /// Return `true` if this Number is an exact representation of its value. + fn is_exact(&self) -> bool { true } } // TODO: Implement PartialEq myself cause there are some weird nuances to comparing numbers. diff --git a/types/src/object.rs b/types/src/object.rs index 3eb2201..3680ef7 100644 --- a/types/src/object.rs +++ b/types/src/object.rs @@ -44,11 +44,11 @@ pub trait Object: } impl Obj { - pub fn new(obj: T) -> Obj { + pub fn new(obj: T) -> Obj { Obj::Ptr(Box::new(obj)) } - pub fn obj<'a>(&'a self) -> Option<&'a Object> { + pub fn obj<'s, 'r: 's>(&'s self) -> Option<&'r (Object + 's)> { match self { Obj::Ptr(obj) => Some(obj.deref()), Obj::Null => None @@ -60,7 +60,7 @@ impl Obj { mem::replace(self, Obj::Null) } - pub fn unbox_as(&self) -> Option<&T> { + pub fn unbox_as(&self) -> Option<&T> { match self { Obj::Null => None, Obj::Ptr(obj) => obj.as_any().downcast_ref::() @@ -188,8 +188,6 @@ impl PartialEq for Obj { #[cfg(test)] mod tests { - use super::Obj; - // #[test] // fn display_bools() { // assert_eq!(format!("{}", Object::Bool(true)), "#t");