lithia/
lisp.rs

1use std::{collections::HashMap, rc::Rc};
2
3use crate::{errors::*, object::Object};
4
5pub struct Lisp<'a> {
6    scope: Vec<HashMap<String, Rc<Object>>>,
7    pub globals: &'a mut HashMap<String, Rc<Object>>,
8}
9
10impl<'a> Lisp<'a> {
11    pub fn new(globals: &'a mut HashMap<String, Rc<Object>>) -> Self {
12        Self {
13            scope: vec![HashMap::new()],
14            globals,
15        }
16    }
17
18    // New scope
19    pub fn scope_create(&mut self) {
20        self.scope.push(HashMap::new());
21    }
22
23    // End scope
24    pub fn scope_end(&mut self) {
25        self.scope.pop();
26    }
27
28    pub fn add_var(
29        &mut self,
30        global: bool,
31        name: &str,
32        object: Rc<Object>,
33    ) -> Result<&mut Self, LispError> {
34        if global {
35            match self.globals.get(name) {
36                Some(_) => {
37                    return Err(LispError::new(
38                        LispErrorKind::Eval,
39                        EvalError::GlobalExists(name.to_string()),
40                    ))
41                }
42                None => self.globals.insert(name.to_string(), object),
43            }
44        } else {
45            let len = self.scope.len();
46            self.scope[len - 1].insert(name.to_string(), object)
47        };
48
49        Ok(self)
50    }
51
52    pub fn add_func(
53        &mut self,
54        global: bool,
55        name: &str,
56        func: fn(&mut Lisp, Rc<Object>) -> RustFuncResult,
57    ) -> Result<&mut Self, LispError> {
58        self.add_var(global, name, Rc::new(Object::RustFunc(func)))
59    }
60
61    fn eval_symbol(&self, symbol: &str) -> LispResult {
62        if !symbol.is_empty() {
63            for s in self.scope.iter().rev() {
64                if let Some(o) = s.get(symbol) {
65                    return Ok(o.clone());
66                }
67            }
68
69            // Check globals
70            match self.globals.get(symbol) {
71                Some(o) => Ok(o.clone()),
72                None => Err(LispError::new(
73                    LispErrorKind::Eval,
74                    EvalError::UnknownSymbol(symbol.to_string()),
75                )),
76            }
77        } else {
78            Ok(Rc::new(Object::Nil))
79        }
80    }
81
82    pub fn set_var(&mut self, symbol: &str, data: Rc<Object>) -> Result<(), LispError> {
83        // Check for variable, going up scope if it can't find it
84        for v in self.scope.iter_mut().rev() {
85            if let Some(s) = v.get_mut(symbol) {
86                *s = data;
87                return Ok(());
88            }
89        }
90
91        // If variable not found, create it
92        self.add_var(false, symbol, data)?;
93
94        Ok(())
95    }
96
97    pub fn eval_object(&mut self, object: Rc<Object>) -> LispResult {
98        //let object_unwrapped = Rc::get_mut(&mut object).unwrap();
99
100        match &*object {
101            Object::Pair(ref f, ref a) => {
102                // Execute expression
103                match &*self.eval_object(f.clone())? {
104                    Object::RustFunc(f) => match f(self, Rc::clone(a)) {
105                        Ok(x) => Ok(x),
106                        Err(e) => Err(LispError::new(LispErrorKind::RustFunc, e)),
107                    },
108                    Object::LispFunc(p, b) => {
109                        let mut args = Vec::new();
110                        let objects = b.iter().map(Rc::clone).collect(); // Store objects on the heap
111
112                        // Create args
113                        let mut cur_object = a;
114
115                        loop {
116                            match &**cur_object {
117                                Object::Pair(a, b) => {
118                                    args.push(self.eval_object(a.clone())?);
119
120                                    cur_object = b
121                                }
122                                Object::Nil => break,
123                                _ => {
124                                    return Err(LispError::new(
125                                        LispErrorKind::RustFunc,
126                                        RustFuncError::new_args_error(ArgumentsError::DottedPair),
127                                    ))
128                                }
129                            }
130                        }
131
132                        let mut scope = Lisp::new(self.globals);
133
134                        for (i, p) in p.iter().enumerate() {
135                            match args.get(i) {
136                                Some(a) => scope.add_var(false, p, a.clone())?,
137                                None => {
138                                    return Err(LispError::new(
139                                        LispErrorKind::RustFunc,
140                                        RustFuncError::new_args_error(ArgumentsError::NotEnough),
141                                    ))
142                                }
143                            };
144                        }
145
146                        // Call function
147                        scope.eval_objects(objects)
148                    }
149                    Object::Character(_) => Ok(Rc::clone(&object)),
150                    _ => Err(LispError::new(
151                        LispErrorKind::Eval,
152                        EvalError::NonFunction(Rc::clone(&object)),
153                    )),
154                }
155            }
156            Object::Symbol(s) => Ok(self.eval_symbol(s)?),
157            Object::Quoted(o) => Ok(Rc::clone(o)),
158            _ => Ok(object),
159        }
160    }
161
162    pub fn eval_objects(&mut self, objects: Vec<Rc<Object>>) -> LispResult {
163        let mut ret = Rc::new(Object::Nil);
164
165        for o in objects {
166            ret = self.eval_object(o)?
167        }
168
169        Ok(ret)
170    }
171
172    pub fn eval(&mut self, input: &str) -> LispResult {
173        let objects = Object::eval(input)?; // Evaluate tokens into objects
174        let objects = objects.into_iter().map(Rc::new).collect(); // Store objects on the heap
175
176        self.eval_objects(objects)
177    }
178}