Implement Integers and Rationals
This commit is contained in:
		
							parent
							
								
									0d3021fb74
								
							
						
					
					
						commit
						3e03ca7e4c
					
				
					 4 changed files with 166 additions and 9 deletions
				
			
		|  | @ -1,5 +1,6 @@ | |||
| mod bool; | ||||
| mod char; | ||||
| mod number; | ||||
| mod value; | ||||
| 
 | ||||
| #[cfg(test)] | ||||
|  |  | |||
							
								
								
									
										55
									
								
								types/src/number/integer.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								types/src/number/integer.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| /* types/src/number/integer.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use value::*; | ||||
| use super::*; | ||||
| 
 | ||||
| #[derive(Debug, Eq, PartialEq)] | ||||
| pub struct Integer(pub Int); | ||||
| 
 | ||||
| impl Number for Integer { | ||||
|     fn convert_down(&self) -> Option<Box<Number>> { None } | ||||
| } | ||||
| 
 | ||||
| impl Value for Integer { | ||||
|     fn as_value(&self) -> &Value { self } | ||||
| } | ||||
| 
 | ||||
| impl IsBool for Integer { } | ||||
| impl IsChar for Integer { } | ||||
| 
 | ||||
| impl IsNumber for Integer { | ||||
|     fn is_integer(&self) -> bool { true } | ||||
| } | ||||
| 
 | ||||
| impl ValueEq for Integer { | ||||
|     fn eq(&self, other: &Value) -> bool { | ||||
|         other.as_any().downcast_ref::<Self>().map_or(false, |x| x == self) | ||||
|     } | ||||
| 
 | ||||
|     fn as_any(&self) -> &Any { self } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::Integer; | ||||
|     use value::*; | ||||
| 
 | ||||
|     #[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()); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn integers_are_integers() { | ||||
|         assert_eq!(Integer(4).is_integer(), true); | ||||
|         assert_eq!(Integer(4).is_number(), true); | ||||
|         assert_eq!(Integer(6).is_char(), false); | ||||
|         assert_eq!(Integer(6).is_bool(), false); | ||||
|     } | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| /* number.rs
 | ||||
| /* types/src/number/mod.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
|  | @ -6,19 +6,40 @@ | |||
| ///
 | ||||
| /// Scheme numbers are complex, literally.
 | ||||
| 
 | ||||
| pub mod integer; | ||||
| pub mod rational; | ||||
| 
 | ||||
| pub use self::integer::Integer; | ||||
| pub use self::rational::Rational; | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use std::fmt::Debug; | ||||
| use std::ops::Deref; | ||||
| 
 | ||||
| use super::value::*; | ||||
| 
 | ||||
| type Int = i64; | ||||
| type Flt = f64; | ||||
| 
 | ||||
| trait Number { | ||||
|     fn is_number(&self) -> bool { true } | ||||
|     fn is_complex(&self) -> bool { false } | ||||
|     fn is_real(&self) -> bool { false } | ||||
|     fn is_rational(&self) -> bool { false } | ||||
|     fn is_integer(&self) -> bool { false } | ||||
| trait Number: Debug + IsBool + IsChar + IsNumber + Value { | ||||
|     fn convert_down(&self) -> Option<Box<Number>>; | ||||
| } | ||||
| 
 | ||||
| impl Value for Box<Number> { | ||||
|     fn as_value(&self) -> &Value { self.deref().as_value() } | ||||
| } | ||||
| 
 | ||||
| impl IsBool for Box<Number> { } | ||||
| impl IsChar for Box<Number> { } | ||||
| impl IsNumber for Box<Number> { } | ||||
| 
 | ||||
| impl ValueEq for Box<Number> { | ||||
|     fn eq(&self, other: &Value) -> bool { | ||||
|         self.deref().eq(other) | ||||
|     } | ||||
|     fn as_any(&self) -> &Any { self } | ||||
| } | ||||
| 
 | ||||
| struct Integer(Int); | ||||
| struct Rational(Int, Int); | ||||
| struct Real(Flt); | ||||
| struct Complex<'a>(&'a Number, &'a Number); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										80
									
								
								types/src/number/rational.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								types/src/number/rational.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| /* types/src/number/rational.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use value::*; | ||||
| use super::*; | ||||
| 
 | ||||
| #[derive(Debug, Eq, PartialEq)] | ||||
| pub struct Rational(pub Int, pub Int); | ||||
| 
 | ||||
| impl Number for Rational { | ||||
|     fn convert_down(&self) -> Option<Box<Number>> { | ||||
|         if self.1 == 1 { | ||||
|             Some(Box::new(Integer(self.0))) | ||||
|         } | ||||
|         else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Value for Rational { | ||||
|     fn as_value(&self) -> &Value { self } | ||||
| } | ||||
| 
 | ||||
| impl IsBool for Rational { } | ||||
| impl IsChar for Rational { } | ||||
| 
 | ||||
| impl IsNumber for Rational { | ||||
|     fn is_rational(&self) -> bool { true } | ||||
| } | ||||
| 
 | ||||
| impl ValueEq for Rational { | ||||
|     fn eq(&self, other: &Value) -> bool { | ||||
|         other.as_any().downcast_ref::<Self>().map_or(false, |x| x == self) | ||||
|     } | ||||
| 
 | ||||
|     fn as_any(&self) -> &Any { self } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use std::ops::Deref; | ||||
|     use number::*; | ||||
|     use value::*; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn equal_rationals_are_equal() { | ||||
|         assert_eq!(Rational(3, 2), Rational(3, 2)); | ||||
|         assert_ne!(Rational(12, 4), Rational(9, 7)); | ||||
|         assert_eq!(Rational(4, 5).as_value(), Rational(4, 5).as_value()); | ||||
|         assert_ne!(Rational(5, 6).as_value(), Rational(7, 6).as_value()); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn rationals_are_rationals() { | ||||
|         assert_eq!(Rational(4, 3).is_rational(), true); | ||||
|         assert_eq!(Rational(4, 3).is_integer(), false); | ||||
|         assert_eq!(Rational(4, 3).is_number(), true); | ||||
|         assert_eq!(Rational(6, 8).is_char(), false); | ||||
|         assert_eq!(Rational(6, 9).is_bool(), false); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn rationals_should_reduce_to_integers_where_possible() { | ||||
|         let rational_as_integer = Rational(3, 1).convert_down(); | ||||
|         assert!(rational_as_integer.is_some()); | ||||
|         // Oh my god this line is so dumb.
 | ||||
|         let rational_as_integer = rational_as_integer.unwrap(); | ||||
|         let rational_as_integer = rational_as_integer.as_value(); | ||||
|         assert_eq!(rational_as_integer.deref(), Integer(3).as_value()); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn rationals_should_not_reduce_to_integers_where_impossible() { | ||||
|         let rational_as_integer = Rational(3, 2).convert_down(); | ||||
|         assert!(rational_as_integer.is_none()); | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue