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 if self.loaded_modules.contains(path) {
156 return Ok(());
157 }
158
159 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 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 (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 (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 (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 (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}