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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Value data structures more complicated than the basics are defined
//! here.

use {
    crate::{Args, Env, OMap, Result, Scope, Stmt, Symbol, Value},
    std::{cell::RefCell, ops::Deref, rc::Rc},
};

#[derive(Clone)]
pub struct List(Rc<RefCell<Vec<Value>>>);
impl List {
    pub fn new(s: Vec<Value>) -> Self {
        Self(rcell!(s))
    }
}
impl Deref for List {
    type Target = Rc<RefCell<Vec<Value>>>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl PartialEq for List {
    fn eq(&self, other: &List) -> bool {
        let me = self.borrow();
        let you = other.borrow();
        me.len() == you.len() && me.iter().enumerate().all(|(i, v)| v == &you[i])
    }
}
impl From<Vec<Value>> for List {
    fn from(v: Vec<Value>) -> Self {
        Self::new(v)
    }
}

#[derive(Clone)]
pub struct Map(Rc<RefCell<OMap>>);
impl Map {
    pub fn new(m: OMap) -> Self {
        Self(rcell!(m))
    }
}
impl Deref for Map {
    type Target = Rc<RefCell<OMap>>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl PartialEq for Map {
    fn eq(&self, other: &Map) -> bool {
        let me = self.borrow();
        let you = other.borrow();
        me.len() == you.len() && me.iter().all(|(i, v)| Some(v) == you.get(i))
    }
}
impl From<OMap> for Map {
    fn from(m: OMap) -> Self {
        Self::new(m)
    }
}

/// Three types of functions in Hatter:
/// Fn: Function defined in Hatter.
/// Native: Function defined in Rust.
/// Special: Function defined in Rust whose arguments aren't evaluated,
/// like a macro.
#[derive(Clone)]
pub enum Fn {
    Fn(Vec<Symbol>, Vec<Stmt>, Scope),
    Native(Rc<Native>),
    Special(Rc<Special>),
}

/// Hatter function defined in Rust.
pub type Native = dyn std::ops::Fn(Args) -> Result<Value>;

/// Hatter function defined in Rust whose arguments aren't evaluated,
/// like a macro.
pub type Special = dyn std::ops::Fn(&mut Env, &[Stmt]) -> Result<Value>;

/// If you want to expose your own structs to Hatter code, this is the
/// trait for you.
#[allow(unused_variables)]
pub trait Object {
    /// String name of this type, like "string" or "Person".
    fn typename(&self) -> &str;

    /// obj.KEY
    fn get(&self, key: &str) -> Option<Value> {
        None
    }

    /// obj.KEY = VAL
    fn set(&self, key: &str, val: Value) {}
}