Merge branch 'port-numbers'
This commit is contained in:
commit
1dfc6823f0
3 changed files with 34 additions and 41 deletions
|
@ -3,13 +3,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::fmt;
|
||||||
use number::Number;
|
use number::Number;
|
||||||
use object::{Obj, Object};
|
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 {
|
impl Object for Int {
|
||||||
fn as_any(&self) -> &Any { self }
|
fn as_any(&self) -> &Any { self }
|
||||||
|
fn as_num(&self) -> Option<&Number> { Some(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Number for Int {
|
impl Number for Int {
|
||||||
|
@ -17,7 +26,7 @@ impl Number for Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<Obj> for Int {
|
impl PartialEq<Obj> for Int {
|
||||||
fn eq(&self, rhs: &Obj) -> bool {
|
fn eq<'a>(&self, rhs: &'a Obj) -> bool {
|
||||||
match rhs.obj().and_then(Object::as_num) {
|
match rhs.obj().and_then(Object::as_num) {
|
||||||
Some(num) => self == num,
|
Some(num) => self == num,
|
||||||
None => false
|
None => false
|
||||||
|
@ -25,8 +34,8 @@ impl PartialEq<Obj> for Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<Number> for Int {
|
impl<'a> PartialEq<Number + 'a> for Int {
|
||||||
fn eq(&self, rhs: &Number) -> bool {
|
fn eq(&self, rhs: &(Number + 'a)) -> bool {
|
||||||
match rhs.as_int() {
|
match rhs.as_int() {
|
||||||
Some(rhs) => *self == *rhs,
|
Some(rhs) => *self == *rhs,
|
||||||
None => false
|
None => false
|
||||||
|
@ -36,32 +45,23 @@ impl PartialEq<Number> for Int {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Int;
|
use super::*;
|
||||||
use number::*;
|
|
||||||
use value::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn equal_integers_are_equal() {
|
fn equal_integers_are_equal() {
|
||||||
assert_eq!(Integer(3), Integer(3));
|
assert_eq!(Int(3), Int(3));
|
||||||
assert_ne!(Integer(12), Integer(9));
|
assert_ne!(Int(12), Int(9));
|
||||||
assert_eq!(Integer(4).as_value(), Integer(4).as_value());
|
assert_eq!(Obj::new(Int(3)), Obj::new(Int(3)));
|
||||||
assert_ne!(Integer(5).as_value(), Integer(7).as_value());
|
assert_ne!(Obj::new(Int(3)), Obj::new(Int(4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn integers_are_integers() {
|
fn integers_are_integers() {
|
||||||
assert!(Integer(4).is_complex());
|
assert_eq!(Int(4).as_bool(), None);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn integers_are_exact() {
|
fn integers_are_exact() {
|
||||||
assert!(Integer(4).is_exact());
|
assert!(Int(4).is_exact());
|
||||||
assert!(!Integer(4).is_inexact());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,17 @@
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// # Numbers
|
//! # Numbers
|
||||||
///
|
//!
|
||||||
/// Scheme numbers are complex, literally.
|
//! 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;
|
mod integer;
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use object::Object;
|
use object::Object;
|
||||||
|
|
||||||
pub use self::integer::Int;
|
pub use self::integer::Int;
|
||||||
|
@ -16,19 +20,10 @@ pub use self::integer::Int;
|
||||||
pub trait Number:
|
pub trait Number:
|
||||||
Object
|
Object
|
||||||
{
|
{
|
||||||
|
/// Cast this Number to an Int if possible.
|
||||||
fn as_int(&self) -> Option<&Int> { None }
|
fn as_int(&self) -> Option<&Int> { None }
|
||||||
}
|
/// Return `true` if this Number is an exact representation of its value.
|
||||||
|
fn is_exact(&self) -> bool { true }
|
||||||
#[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.
|
// TODO: Implement PartialEq myself cause there are some weird nuances to comparing numbers.
|
||||||
|
|
|
@ -44,11 +44,11 @@ pub trait Object:
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Obj {
|
impl Obj {
|
||||||
pub fn new<T: 'static + Object>(obj: T) -> Obj {
|
pub fn new<T: Object + 'static>(obj: T) -> Obj {
|
||||||
Obj::Ptr(Box::new(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 {
|
match self {
|
||||||
Obj::Ptr(obj) => Some(obj.deref()),
|
Obj::Ptr(obj) => Some(obj.deref()),
|
||||||
Obj::Null => None
|
Obj::Null => None
|
||||||
|
@ -60,7 +60,7 @@ impl Obj {
|
||||||
mem::replace(self, Obj::Null)
|
mem::replace(self, Obj::Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unbox_as<T: 'static + Object>(&self) -> Option<&T> {
|
pub fn unbox_as<T: Object + 'static>(&self) -> Option<&T> {
|
||||||
match self {
|
match self {
|
||||||
Obj::Null => None,
|
Obj::Null => None,
|
||||||
Obj::Ptr(obj) => obj.as_any().downcast_ref::<T>()
|
Obj::Ptr(obj) => obj.as_any().downcast_ref::<T>()
|
||||||
|
@ -188,8 +188,6 @@ impl PartialEq for Obj {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Obj;
|
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn display_bools() {
|
// fn display_bools() {
|
||||||
// assert_eq!(format!("{}", Object::Bool(true)), "#t");
|
// assert_eq!(format!("{}", Object::Bool(true)), "#t");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue