2017-04-22 09:29:11 -07:00
|
|
|
/* types/src/object.rs
|
2017-04-03 14:51:39 -04:00
|
|
|
* Eryn Wells <eryn@erynwells.me>
|
|
|
|
*/
|
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
//! # 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`.
|
|
|
|
//!
|
|
|
|
//! ## Type Predicates
|
|
|
|
//!
|
|
|
|
//! Objects satisfy one (and only one) of several predicates which define the
|
|
|
|
//! available types in Scheme. These predicates are implemented as `is_*`
|
|
|
|
//! methods in a bunch of `Is*` traits defined below.
|
2017-04-03 14:51:39 -04:00
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
use std::fmt;
|
|
|
|
use std::ops::Deref;
|
|
|
|
use number::Number;
|
2017-04-21 19:28:39 -07:00
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
#[derive(Debug)]
|
2017-04-21 19:28:39 -07:00
|
|
|
pub enum ObjectPtr {
|
|
|
|
/// Absence of a value. A null pointer.
|
|
|
|
Null,
|
|
|
|
/// A pointer to an object.
|
|
|
|
Ptr(Box<Object>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Object {
|
|
|
|
Bool(bool),
|
|
|
|
ByteVector(Vec<u8>),
|
|
|
|
Char(char),
|
2017-04-22 09:29:11 -07:00
|
|
|
Number(Number),
|
2017-04-21 19:28:39 -07:00
|
|
|
Pair(ObjectPtr, ObjectPtr),
|
|
|
|
//Procedure/*( TODO: Something )*/,
|
|
|
|
//Record/*( TODO: Something )*/,
|
|
|
|
String(String),
|
|
|
|
Symbol(String),
|
|
|
|
Vector(Vec<ObjectPtr>),
|
|
|
|
}
|
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
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()),
|
|
|
|
}
|
|
|
|
}
|
2017-04-09 14:08:54 -07:00
|
|
|
}
|
2017-04-08 16:35:11 -07:00
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
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)
|
|
|
|
},
|
2017-04-09 14:08:54 -07:00
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
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) => {
|
|
|
|
write!(f, "{}", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
Object::Pair(ref car, ref cdr) => {
|
|
|
|
// TODO: There are rules for printing pairs...
|
|
|
|
// Print a dot before the cdr iff it's anything but Null or another Pair.
|
2017-04-22 09:32:47 -07:00
|
|
|
// Going to need a recursive helper to avoid printing ( and ) for every pair.
|
2017-04-22 09:29:11 -07:00
|
|
|
write!(f, "({}", car).and_then(|_| match cdr {
|
|
|
|
&ObjectPtr::Null => write!(f, ")"),
|
|
|
|
&ObjectPtr::Ptr(ref ptr) => match ptr.deref() {
|
|
|
|
&Object::Pair(_, _) => write!(f, "{}", ptr),
|
|
|
|
_ => write!(f, " . {})", ptr)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
Object::String(ref st) => {
|
|
|
|
write!(f, "\"{}\"", st)
|
|
|
|
},
|
|
|
|
|
|
|
|
Object::Symbol(ref sym) => {
|
|
|
|
write!(f, "{}", sym)
|
|
|
|
},
|
2017-04-03 14:51:39 -04:00
|
|
|
|
2017-04-22 09:29:11 -07:00
|
|
|
Object::Vector(ref vec) => {
|
|
|
|
// TODO: Actually write the vector values.
|
|
|
|
write!(f, "#(").and_then(|_| write!(f, ")"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-09 14:08:54 -07:00
|
|
|
}
|