Merge branch 'object-trait' into chars-lexer
This commit is contained in:
		
						commit
						7de3bfcabb
					
				
					 5 changed files with 194 additions and 100 deletions
				
			
		|  | @ -1,13 +1,10 @@ | |||
| pub mod number; | ||||
| pub mod char; | ||||
| 
 | ||||
| mod bool; | ||||
| mod object; | ||||
| mod predicates; | ||||
| mod pair; | ||||
| mod sym; | ||||
| 
 | ||||
| pub use object::Object; | ||||
| pub use object::ObjectPtr; | ||||
| pub use predicates::*; | ||||
| pub use object::Obj; | ||||
| pub use pair::Pair; | ||||
| pub use sym::Sym; | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 
 | ||||
| //! # Objects
 | ||||
| //!
 | ||||
| //! All scheme types are represented by the `Object` enum defined in this
 | ||||
| //! module. Most references to objects are going to be through an `ObjectPtr`.
 | ||||
| //! All Scheme types implement the `Object` trait defined in this module. Most
 | ||||
| //! references to objects are going to be through an `ObjectPtr`.
 | ||||
| //!
 | ||||
| //! ## Type Predicates
 | ||||
| //!
 | ||||
|  | @ -13,111 +13,133 @@ | |||
| //! available types in Scheme. These predicates are implemented as `is_*`
 | ||||
| //! methods in a bunch of `Is*` traits defined below.
 | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use std::fmt; | ||||
| use std::ops::Deref; | ||||
| use number::Number; | ||||
| use super::*; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum ObjectPtr { | ||||
|     /// Absence of a value. A null pointer.
 | ||||
| pub enum Obj { | ||||
|     Null, | ||||
|     /// A pointer to an object.
 | ||||
|     Ptr(Box<Object>), | ||||
|     Ptr(Box<Object>) | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Object { | ||||
|     Bool(bool), | ||||
|     ByteVector(Vec<u8>), | ||||
|     Char(char), | ||||
|     Number(Number), | ||||
|     Pair(ObjectPtr, ObjectPtr), | ||||
|     //Procedure/*( TODO: Something )*/,
 | ||||
|     //Record/*( TODO: Something )*/,
 | ||||
|     String(String), | ||||
|     Symbol(String), | ||||
|     Vector(Vec<ObjectPtr>), | ||||
| pub trait Object: | ||||
|     fmt::Display 
 | ||||
| { | ||||
|     fn as_any(&self) -> &Any; | ||||
|     fn as_pair(&self) -> Option<&Pair>; | ||||
|     fn as_sym(&self) -> Option<&Sym>; | ||||
| } | ||||
| 
 | ||||
| impl ObjectPtr { | ||||
|     pub fn new(obj: Object) -> ObjectPtr { | ||||
|         ObjectPtr::Ptr(Box::new(obj)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn new_pair() -> ObjectPtr { | ||||
|         ObjectPtr::new(Object::Pair(ObjectPtr::Null, ObjectPtr::Null)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for ObjectPtr { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match *self { | ||||
|             ObjectPtr::Null => write!(f, "()"), | ||||
|             ObjectPtr::Ptr(ref bx) => write!(f, "{}", bx.deref()), | ||||
| impl Obj { | ||||
|     pub fn unbox_as<T: 'static + Object>(&self) -> Option<&T> { | ||||
|         match self { | ||||
|             Obj::Null => None, | ||||
|             Obj::Ptr(obj) => obj.as_any().downcast_ref::<T>() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for Object { | ||||
| impl fmt::Display for Obj { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         match *self { | ||||
|             Object::Bool(ref v) => { | ||||
|                 let out = if *v { "#t" } else { "#f" }; | ||||
|                 write!(f, "{}", out) | ||||
|             }, | ||||
| 
 | ||||
|             Object::ByteVector(ref vec) => { | ||||
|                 // TODO: Actually write the vector values.
 | ||||
|                 write!(f, "#u8(").and_then(|_| write!(f, ")")) | ||||
|             }, | ||||
| 
 | ||||
|             Object::Char(ref c) => { | ||||
|                 // TODO: This is not correct for all cases. See section 6.6 of the spec.
 | ||||
|                 write!(f, "#\\{}", c) | ||||
|             }, | ||||
| 
 | ||||
|             Object::Number(ref n) => { | ||||
|                 // TODO: Implement Display for Number
 | ||||
|                 write!(f, "{}", n) | ||||
|             } | ||||
| 
 | ||||
|             Object::Pair(ref car, ref cdr) => { | ||||
|                 write!(f, "(").and_then(|_| Object::fmt_pair(car, cdr, f)) | ||||
|                               .and_then(|_| write!(f, ")")) | ||||
|             }, | ||||
| 
 | ||||
|             Object::String(ref st) => { | ||||
|                 write!(f, "\"{}\"", st) | ||||
|             }, | ||||
| 
 | ||||
|             Object::Symbol(ref sym) => { | ||||
|                 write!(f, "{}", sym) | ||||
|             }, | ||||
| 
 | ||||
|             Object::Vector(ref vec) => { | ||||
|                 // TODO: Actually write the vector values.
 | ||||
|                 vec.iter().enumerate().fold(write!(f, "#("), |acc, (i, obj)| { | ||||
|                     let space = if i == (vec.len() - 1) { " " } else { "" }; | ||||
|                     acc.and(write!(f, "{}{}", obj, space)) | ||||
|                 }).and(write!(f, ")")) | ||||
|             } | ||||
|         match self { | ||||
|             Obj::Null => write!(f, "null"), | ||||
|             Obj::Ptr(obj) => write!(f, "{}", obj) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Object { | ||||
|     fn fmt_pair(car: &ObjectPtr, cdr: &ObjectPtr, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         write!(f, "{}", car).and_then(|r| match cdr { | ||||
|             &ObjectPtr::Null => Ok(r),  // Don't write anything.
 | ||||
|             &ObjectPtr::Ptr(ref ptr) => match ptr.deref() { | ||||
|                 &Object::Pair(ref next_car, ref next_cdr) => { | ||||
|                     write!(f, " ").and_then(|_| Object::fmt_pair(next_car, next_cdr, f)) | ||||
|                 }, | ||||
|                 _ => write!(f, " . {}", ptr) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| //#[derive(Debug, PartialEq)]
 | ||||
| //pub enum Object {
 | ||||
| //    ByteVector(Vec<u8>),
 | ||||
| //    Char(char),
 | ||||
| //    Number(Number),
 | ||||
| //    Pair(ObjectPtr, ObjectPtr),
 | ||||
| //    //Procedure/*( TODO: Something )*/,
 | ||||
| //    //Record/*( TODO: Something )*/,
 | ||||
| //    String(String),
 | ||||
| //    Symbol(String),
 | ||||
| //    Vector(Vec<ObjectPtr>),
 | ||||
| //}
 | ||||
| //
 | ||||
| //impl ObjectPtr {
 | ||||
| //    pub fn new(obj: Object) -> ObjectPtr {
 | ||||
| //        ObjectPtr::Ptr(Box::new(obj))
 | ||||
| //    }
 | ||||
| //
 | ||||
| //    pub fn new_pair() -> ObjectPtr {
 | ||||
| //        ObjectPtr::new(Object::Pair(ObjectPtr::Null, ObjectPtr::Null))
 | ||||
| //    }
 | ||||
| //}
 | ||||
| //
 | ||||
| //impl fmt::Display for ObjectPtr {
 | ||||
| //    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | ||||
| //        match *self {
 | ||||
| //            ObjectPtr::Null => write!(f, "()"),
 | ||||
| //            ObjectPtr::Ptr(ref bx) => write!(f, "{}", bx.deref()),
 | ||||
| //        }
 | ||||
| //    }
 | ||||
| //}
 | ||||
| //
 | ||||
| //impl fmt::Display for Object {
 | ||||
| //    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | ||||
| //        match *self {
 | ||||
| //            Object::Bool(ref v) => {
 | ||||
| //                let out = if *v { "#t" } else { "#f" };
 | ||||
| //                write!(f, "{}", out)
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::ByteVector(ref vec) => {
 | ||||
| //                // TODO: Actually write the vector values.
 | ||||
| //                write!(f, "#u8(").and_then(|_| write!(f, ")"))
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::Char(ref c) => {
 | ||||
| //                // TODO: This is not correct for all cases. See section 6.6 of the spec.
 | ||||
| //                write!(f, "#\\{}", c)
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::Number(ref n) => {
 | ||||
| //                // TODO: Implement Display for Number
 | ||||
| //                write!(f, "{}", n)
 | ||||
| //            }
 | ||||
| //
 | ||||
| //            Object::Pair(ref car, ref cdr) => {
 | ||||
| //                write!(f, "(").and_then(|_| Object::fmt_pair(car, cdr, f))
 | ||||
| //                              .and_then(|_| write!(f, ")"))
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::String(ref st) => {
 | ||||
| //                write!(f, "\"{}\"", st)
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::Symbol(ref sym) => {
 | ||||
| //                write!(f, "{}", sym)
 | ||||
| //            },
 | ||||
| //
 | ||||
| //            Object::Vector(ref vec) => {
 | ||||
| //                // TODO: Actually write the vector values.
 | ||||
| //                vec.iter().enumerate().fold(write!(f, "#("), |acc, (i, obj)| {
 | ||||
| //                    let space = if i == (vec.len() - 1) { " " } else { "" };
 | ||||
| //                    acc.and(write!(f, "{}{}", obj, space))
 | ||||
| //                }).and(write!(f, ")"))
 | ||||
| //            }
 | ||||
| //        }
 | ||||
| //    }
 | ||||
| //}
 | ||||
| //
 | ||||
| //impl Object {
 | ||||
| //    fn fmt_pair(car: &ObjectPtr, cdr: &ObjectPtr, f: &mut fmt::Formatter) -> fmt::Result {
 | ||||
| //        write!(f, "{}", car).and_then(|r| match cdr {
 | ||||
| //            &ObjectPtr::Null => Ok(r),  // Don't write anything.
 | ||||
| //            &ObjectPtr::Ptr(ref ptr) => match ptr.deref() {
 | ||||
| //                &Object::Pair(ref next_car, ref next_cdr) => {
 | ||||
| //                    write!(f, " ").and_then(|_| Object::fmt_pair(next_car, next_cdr, f))
 | ||||
| //                },
 | ||||
| //                _ => write!(f, " . {}", ptr)
 | ||||
| //            }
 | ||||
| //        })
 | ||||
| //    }
 | ||||
| //}
 | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|  |  | |||
							
								
								
									
										41
									
								
								types/src/pair.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								types/src/pair.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| /* types/src/pair.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use std::fmt; | ||||
| use super::*; | ||||
| use object::Object; | ||||
| 
 | ||||
| pub struct Pair { | ||||
|     car: Obj, | ||||
|     cdr: Obj | ||||
| } | ||||
| 
 | ||||
| impl Pair { | ||||
|     fn fmt_pair(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         let r = write!(f, "{}", self.car); | ||||
|         r.and_then(|r| match self.cdr { | ||||
|             Obj::Null => Ok(r),  // Don't write anything.
 | ||||
|             Obj::Ptr(ref next) => { | ||||
|                 match next.as_pair() { | ||||
|                     Some(next_pair) => write!(f, " ").and_then(|_| next_pair.fmt_pair(f)), | ||||
|                     None => write!(f, " . {}", next) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Object for Pair { | ||||
|     fn as_any(&self) -> &Any { self } | ||||
|     fn as_pair(&self) -> Option<&Pair> { Some(self) } | ||||
|     fn as_sym(&self) -> Option<&Sym> { None } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for Pair { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         write!(f, "(").and_then(|_| self.fmt_pair(f)) | ||||
|                       .and_then(|_| write!(f, ")")) | ||||
|     } | ||||
| } | ||||
|  | @ -1,7 +1,10 @@ | |||
| /* types/src/predicates.rs
 | ||||
| /* types/src/preds.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| //! This module defines several important predicates for determing what kind of
 | ||||
| //! a thing this Object is.
 | ||||
| 
 | ||||
| pub trait IsNull { | ||||
|     /// Is this thing null?
 | ||||
|     fn is_null(&self) -> bool { false } | ||||
|  | @ -20,12 +23,21 @@ pub trait IsChar { | |||
| pub trait IsNumber { | ||||
|     /// Is this thing a number?
 | ||||
|     fn is_number(&self) -> bool { self.is_complex() || self.is_real() || self.is_rational() || self.is_integer() } | ||||
| 
 | ||||
|     /// Should return `true` if this Value is a complex number type.
 | ||||
|     fn is_complex(&self) -> bool { self.is_real() } | ||||
| 
 | ||||
|     /// Should return `true` if this Value is a real number type.
 | ||||
|     fn is_real(&self) -> bool { self.is_rational() } | ||||
| 
 | ||||
|     /// Should return `true` if this Value is a rational number type.
 | ||||
|     fn is_rational(&self) -> bool { self.is_integer() } | ||||
| 
 | ||||
|     /// Should return `true` if this Value is a integer number type.
 | ||||
|     fn is_integer(&self) -> bool { false } | ||||
| } | ||||
| 
 | ||||
| pub trait IsPair { | ||||
|     /// Should return `true` if this Value is a pair.
 | ||||
|     fn is_pair(&self) -> bool { false } | ||||
| } | ||||
							
								
								
									
										22
									
								
								types/src/sym.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								types/src/sym.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| /* types/src/symbol.rs
 | ||||
|  * Eryn Wells <eryn@erynwells.me> | ||||
|  */ | ||||
| 
 | ||||
| use std::any::Any; | ||||
| use std::fmt; | ||||
| use object::Object; | ||||
| use super::*; | ||||
| 
 | ||||
| pub struct Sym(String); | ||||
| 
 | ||||
| impl Object for Sym { | ||||
|     fn as_any(&self) -> &Any { self } | ||||
|     fn as_pair(&self) -> Option<&Pair> { None } | ||||
|     fn as_sym(&self) -> Option<&Sym> { Some(self) } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for Sym { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         write!(f, "{}", self.0) | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue