1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::rc::Rc;

mod tokenizer;
mod eval;
pub mod stdlib;

pub use tokenizer::parse;
pub use eval::{Procedure, Environment, eval, ForeignFunction};

#[derive(Debug, Clone)]
pub enum Value {
    List(Rc<Vec<Value>>),
    String(Rc<String>),
    Float(f64),
    Int(i64),
    Bool(bool),

    Ident(Rc<String>),
    ForeignFn(ForeignFunction),
    Lambda(Procedure)
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        use ::Value::*;
        fn rc_to_usize<T: ?Sized>(rc: &Rc<T>) -> usize {
            use std::mem::transmute;
            unsafe {transmute(&*rc)}
        }

        match (self, other) {
            (&List(ref rc1), &List(ref rc2)) =>
                rc_to_usize(rc1) == rc_to_usize(rc2),
            (&String(ref rc1), &String(ref rc2)) =>
                rc_to_usize(rc1) == rc_to_usize(rc2) || rc1 == rc2,
            (&Float(f1), &Float(f2)) => f1 == f2,
            (&Int(i1), &Int(i2)) => i1 == i2,
            (&Bool(b1), &Bool(b2)) => b1 == b2,
            (&Ident(ref id1), &Ident(ref id2)) =>
                rc_to_usize(id1) == rc_to_usize(id2) || id1 == id2,
            (&ForeignFn(ref ff1), &ForeignFn(ref ff2)) => ff1 == ff2,
            (&Lambda(ref l1), &Lambda(ref l2)) => l1 == l2,
            _ => false
        }
    }
}

impl Eq for Value {}

// TODO: Ty, work on implementing Hash for this!


#[derive(Debug)]
pub enum Error {
    UnexpectedType{expected: String, found: String},
    UnexpectedArity{expected: u16, found: u16}
}