Skip to main content

coda_runtime/runtime/
interpreter.rs

1use crate::{
2    frontend::token::TokenKind,
3    runtime::{ast::*, value::*},
4    env::Env,
5};
6use std::{cell::RefCell, collections::{HashMap, HashSet}, fmt::Write, rc::Rc};
7
8pub type ModuleLoader = fn(&str, &mut Env) -> Result<bool, Box<dyn std::error::Error>>;
9
10pub struct Module {
11    pub exports: HashMap<String, Value>,
12}
13
14pub struct Interpreter {
15    pub env: Rc<RefCell<Env>>,
16    pub base_path: std::path::PathBuf,
17    pub module_loader: Option<ModuleLoader>,
18    pub loaded_modules: HashSet<String>,
19}
20
21pub enum RuntimeControl {
22    Return(Value),
23}
24
25impl Interpreter {
26    pub fn new(
27        env: Env,
28        base_path: std::path::PathBuf,
29        module_loader: Option<ModuleLoader>,
30    ) -> Self {
31        Self {
32            env: Rc::new(RefCell::new(env)),
33            base_path,
34            module_loader,
35            loaded_modules: HashSet::new(),
36        }
37    }
38
39    pub fn interpret(
40        &mut self,
41        statements: Vec<Stmt>,
42    ) -> Result<(), Box<dyn std::error::Error>> {
43        for stmt in statements {
44            self.execute(stmt)?;
45        }
46
47        Ok(())
48    }
49
50    pub fn execute(&mut self, stmt: Stmt) -> Result<Option<RuntimeControl>, Box<dyn std::error::Error>> {
51        match stmt {
52            Stmt::Let { name, value, is_exported, .. } => {
53                let val = self.evaluate(value)?;
54
55                if is_exported {
56                    self.env.borrow_mut().define_export(name, val);
57                } else {
58                    self.env.borrow_mut().define(name, val);
59                }
60
61                Ok(None)
62            }
63
64            Stmt::Expr(expr) => {
65                let _ = self.evaluate(expr)?;
66                Ok(None)
67            }
68
69            Stmt::Block(statements) => {
70                self.execute_block(statements, None)?;
71
72                Ok(None)
73            }
74
75            Stmt::Function { name, params, body, is_exported, .. } => {
76                let function = Value::Function(Function {
77                    name: name.clone(),
78                    params,
79                    body,
80                    closure: self.env.clone(),
81                });
82
83                if is_exported {
84                    self.env.borrow_mut().define_export(name, function);
85                } else {
86                    self.env.borrow_mut().define(name, function);
87                }
88
89                Ok(None)
90            }
91
92            Stmt::Return(expr) => {
93                let value = match expr {
94                    Some(e) => self.evaluate(e)?,
95                    None => Value::Null,
96                };
97
98                Ok(Some(RuntimeControl::Return(value)))
99            }
100
101            Stmt::If { condition, then_branch, else_branch } => {
102                let cond = self.evaluate(condition)?;
103                let cond_bool = cond.as_bool();
104
105                if cond_bool {
106                    self.execute_block(then_branch, None)?;
107                } else if let Some(else_branch) = else_branch {
108                    self.execute_block(else_branch, None)?;
109                }
110
111                Ok(None)
112            }
113
114            Stmt::While { condition, body } => {
115                while self.evaluate(condition.clone())?.as_bool() {
116                    if let Some(ctrl) = self.execute_block(body.clone(), None)? {
117                        if let RuntimeControl::Return(_) = ctrl {
118                            return Ok(Some(ctrl));
119                        }
120                    }
121                }
122
123                Ok(None)
124            }
125
126            Stmt::Import(module_path) => {
127                self.execute_import(&module_path)?;
128
129                Ok(None)
130            }
131        }
132    }
133
134    fn execute_block(&mut self, statements: Vec<Stmt>, env: Option<Rc<RefCell<Env>>>) -> Result<Option<RuntimeControl>, Box<dyn std::error::Error>> {
135        let previous = self.env.clone();
136        let env_to_use = env.unwrap_or_else(|| previous.clone());
137
138        self.env = env_to_use;
139
140        for stmt in statements {
141            if let Some(RuntimeControl::Return(val)) = self.execute(stmt)? {
142                self.env = previous;
143
144                return Ok(Some(RuntimeControl::Return(val)));
145            }
146        }
147
148        self.env = previous;
149
150        Ok(None)
151    }
152
153    fn execute_import(&mut self, path: &str) -> Result<(), Box<dyn std::error::Error>> {
154        // Prevent duplicate imports
155        if self.loaded_modules.contains(path) {
156            return Ok(());
157        }
158
159        // Try external module loader (std etc.)
160        if let Some(loader) = self.module_loader {
161            let handled = loader(path, &mut self.env.borrow_mut())?;
162            if handled {
163                self.loaded_modules.insert(path.to_string());
164                return Ok(());
165            }
166        }
167
168        // Fallback: user file import
169        let full_path = if path.starts_with("./") || path.starts_with("../") {
170            self.base_path.join(path)
171        } else {
172            std::path::PathBuf::from(path)
173        };
174
175        let src = std::fs::read_to_string(&full_path)?;
176
177        let tokens = crate::frontend::lexer::scan(&src)?;
178        let stmts = crate::frontend::parser::parse(tokens)?;
179
180        let module_env = Rc::new(RefCell::new(Env::new_with_parent(None)));
181
182        for stmt in stmts {
183            if let Some(ctrl) =
184                self.execute_block(vec![stmt], Some(module_env.clone()))?
185            {
186                if let RuntimeControl::Return(_) = ctrl {
187                    break;
188                }
189            }
190        }
191
192        let values = module_env.borrow().values.clone();
193
194        for (name, val) in values {
195            self.env.borrow_mut().define(name, val);
196        }
197
198        self.loaded_modules.insert(path.to_string());
199
200        Ok(())
201    }
202
203    pub fn evaluate(&mut self, expr: Expr) -> Result<Value, Box<dyn std::error::Error>> {
204        match expr {
205            Expr::Literal(lit) => Ok(match lit {
206                ValueLiteral::Number(n) => Value::Number(n),
207                ValueLiteral::String(s) => Value::String(s),
208                ValueLiteral::Bool(b) => Value::Bool(b),
209                ValueLiteral::Null => Value::Null,
210            }),
211
212            Expr::Variable(name) => Ok(self.env.borrow().get(&name).ok_or_else(|| format!("undefined variable `{name}`"))?),
213
214            Expr::Binary { left, operator, right } => {
215                let l = self.evaluate(*left)?;
216                let r = self.evaluate(*right)?;
217
218                match (&l, &r, operator.clone()) {
219                    // numbers
220                    (Value::Number(a), Value::Number(b), TokenKind::Plus) => Ok(Value::Number(a + b)),
221                    (Value::Number(a), Value::Number(b), TokenKind::Minus) => Ok(Value::Number(a - b)),
222                    (Value::Number(a), Value::Number(b), TokenKind::Star) => Ok(Value::Number(a * b)),
223                    (Value::Number(a), Value::Number(b), TokenKind::Slash) => Ok(Value::Number(a / b)),
224
225                    // compound assignment
226                    (Value::Number(a), Value::Number(b), TokenKind::PlusEqual) => Ok(Value::Number(a + b)),
227                    (Value::Number(a), Value::Number(b), TokenKind::MinusEqual) => Ok(Value::Number(a - b)),
228                    (Value::Number(a), Value::Number(b), TokenKind::StarEqual) => Ok(Value::Number(a * b)),
229                    (Value::Number(a), Value::Number(b), TokenKind::SlashEqual) => Ok(Value::Number(a / b)),
230
231                    // strings
232                    (Value::String(a), Value::String(b), TokenKind::Plus) => {
233                        let mut s = String::with_capacity(a.len() + b.len());
234
235                        s.push_str(a);
236                        s.push_str(b);
237
238                        Ok(Value::String(s))
239                    }
240
241                    (Value::String(a), Value::Number(b), TokenKind::Plus) => {
242                        let mut s = String::with_capacity(a.len() + 16);
243
244                        s.push_str(a);
245                        write!(&mut s, "{}", b).unwrap();
246
247                        Ok(Value::String(s))
248                    }
249
250                    (Value::Number(a), Value::String(b), TokenKind::Plus) => {
251                        let mut s = String::with_capacity(a.to_string().len() + b.len());
252
253                        s.push_str(a.to_string().as_str());
254                        s.push_str(b);
255
256                        Ok(Value::String(s))
257                    }
258
259                    // comparison operators
260                    (Value::Number(a), Value::Number(b), TokenKind::Greater) => Ok(Value::Bool(a > b)),
261                    (Value::Number(a), Value::Number(b), TokenKind::GreaterEqual) => Ok(Value::Bool(a >= b)),
262                    (Value::Number(a), Value::Number(b), TokenKind::Less) => Ok(Value::Bool(a < b)),
263                    (Value::Number(a), Value::Number(b), TokenKind::LessEqual) => Ok(Value::Bool(a <= b)),
264                    (Value::Number(a), Value::Number(b), TokenKind::EqualEqual) => Ok(Value::Bool(a == b)),
265                    (Value::Number(a), Value::Number(b), TokenKind::BangEqual) => Ok(Value::Bool(a != b)),
266                    (Value::String(a), Value::String(b), TokenKind::EqualEqual) => Ok(Value::Bool(a == b)),
267
268                    _ => Err(format!("unsupported operation: {l:?} {operator:?} {r:?}").into()),
269                }
270            }
271
272            Expr::Call { callee, args } => {
273                let callee_val = self.evaluate(*callee)?;
274                let mut evaluated_args = Vec::with_capacity(args.len());
275
276                for arg in args {
277                    evaluated_args.push(self.evaluate(arg)?);
278                }
279
280                match callee_val {
281                    Value::NativeFunction(f) => Ok(f(evaluated_args)),
282                    Value::Function(func) => {
283                        let call_env = Rc::new(RefCell::new(Env::new_with_parent(Some(func.closure.clone()))));
284
285                        for (param, arg) in func.params.iter().zip(evaluated_args.into_iter()) {
286                            call_env.borrow_mut().define(param.clone(), arg);
287                        }
288
289                        let result = match self.execute_block(func.body.clone(), Some(call_env))? {
290                            Some(RuntimeControl::Return(val)) => val,
291                            None => Value::Null,
292                        };
293
294                        Ok(result)
295                    }
296
297                    _ => panic!("can only call functions"),
298                }
299            }
300
301            Expr::Assign { name, value } => {
302                let val = self.evaluate(*value)?;
303
304                self.env.borrow_mut().assign(&name, val)?;
305
306                Ok(Value::Null)
307            }
308
309            Expr::Array(elements) => {
310                let mut values = Vec::with_capacity(elements.len());
311
312                for el in elements {
313                    values.push(self.evaluate(el)?);
314                }
315
316                Ok(Value::Array(values))
317            }
318
319            Expr::Function { name, params, body } => {
320                let func = Value::Function(Function {
321                    name: name.clone(),
322                    params,
323                    body,
324                    closure: self.env.clone(),
325                });
326
327                Ok(func)
328            }
329
330            expr => panic!("unimplemented expr {expr:?}"),
331        }
332    }
333
334    pub fn run(
335        &mut self,
336        statements: Vec<Stmt>,
337    ) -> Result<(), Box<dyn std::error::Error>> {
338        self.interpret(statements)
339    }
340}