1use std::collections::{HashMap, HashSet};
2use std::fs;
3use std::path::PathBuf;
4use std::rc::Rc;
5use std::cell::RefCell;
6
7use super::lexer;
8use super::parser::{self, Expr, Stmt, BinaryOp, UnaryOp};
9use super::value::Value;
10
11pub struct Interpreter {
12 globals: Rc<RefCell<HashMap<String, Value>>>,
13 env: Rc<RefCell<HashMap<String, Value>>>,
14 imported: Rc<RefCell<HashSet<PathBuf>>>,
15 base_path: PathBuf,
16}
17
18#[derive(Debug, Clone)]
19enum ControlFlow {
20 Return(Value),
21 Break,
22 Continue,
23}
24
25impl Interpreter {
26 pub fn new() -> Self {
27 let globals = Rc::new(RefCell::new(HashMap::new()));
28 Self::register_builtins(&mut globals.borrow_mut());
29 Interpreter {
30 globals: globals.clone(),
31 env: globals,
32 imported: Rc::new(RefCell::new(HashSet::new())),
33 base_path: PathBuf::from("."),
34 }
35 }
36
37 pub fn with_base_path(mut self, path: &str) -> Self {
38 self.base_path = PathBuf::from(path);
39 self
40 }
41
42 pub fn mark_imported(&mut self, path: &str) {
43 let file_path = self.base_path.join(path);
44 if let Ok(canonical) = fs::canonicalize(&file_path) {
45 self.imported.borrow_mut().insert(canonical);
46 } else {
47 self.imported.borrow_mut().insert(file_path);
48 }
49 }
50
51 fn register_builtins(env: &mut HashMap<String, Value>) {
52 env.insert("print".to_string(), Value::Builtin(builtin_print));
53 env.insert("input".to_string(), Value::Builtin(builtin_input));
54 env.insert("len".to_string(), Value::Builtin(builtin_len));
55 env.insert("typeof".to_string(), Value::Builtin(builtin_typeof));
56 env.insert("push".to_string(), Value::Builtin(builtin_push));
57 env.insert("pop".to_string(), Value::Builtin(builtin_pop));
58 env.insert("keys".to_string(), Value::Builtin(builtin_keys));
59 env.insert("values".to_string(), Value::Builtin(builtin_values));
60 env.insert("range".to_string(), Value::Builtin(builtin_range));
61 env.insert("str".to_string(), Value::Builtin(builtin_str));
62 env.insert("num".to_string(), Value::Builtin(builtin_num));
63 }
64
65 pub fn execute(&mut self, stmts: &[Stmt]) -> Result<Value, String> {
66 let mut last = Value::Null;
67 for stmt in stmts {
68 match self.execute_stmt(stmt)? {
69 Some(ControlFlow::Return(v)) => return Ok(v),
70 Some(ControlFlow::Break) => return Err("break outside loop".to_string()),
71 Some(ControlFlow::Continue) => return Err("continue outside loop".to_string()),
72 None => {}
73 }
74 }
75 Ok(last)
76 }
77
78 fn execute_stmt(&mut self, stmt: &Stmt) -> Result<Option<ControlFlow>, String> {
79 match stmt {
80 Stmt::Import { path } => {
81 let file_path = self.base_path.join(path);
82 let canonical = fs::canonicalize(&file_path).unwrap_or(file_path.clone());
83
84 if self.imported.borrow().contains(&canonical) {
85 return Ok(None);
86 }
87
88 self.imported.borrow_mut().insert(canonical.clone());
89
90 let source = fs::read_to_string(&file_path)
91 .map_err(|e| format!("Failed to import '{}': {}", path, e))?;
92
93 let tokens = lexer::tokenize(&source)?;
94 let ast = parser::parse(&tokens)?;
95
96 let new_base = canonical.parent().unwrap_or(&self.base_path).to_path_buf();
97 let mut sub_interp = Interpreter {
98 globals: self.globals.clone(),
99 env: self.env.clone(),
100 imported: self.imported.clone(),
101 base_path: new_base,
102 };
103 sub_interp.execute(&ast)?;
104
105 Ok(None)
106 }
107 Stmt::Expr(expr) => {
108 self.evaluate(expr)?;
109 Ok(None)
110 }
111 Stmt::Let { name, value } => {
112 let val = self.evaluate(value)?;
113 self.env.borrow_mut().insert(name.clone(), val);
114 Ok(None)
115 }
116 Stmt::Const { name, value } => {
117 let val = self.evaluate(value)?;
118 self.env.borrow_mut().insert(name.clone(), val);
119 Ok(None)
120 }
121 Stmt::Fn { name, params, body } => {
122 let func = Value::Function {
123 params: params.clone(),
124 body: body.clone(),
125 closure: self.env.clone(),
126 };
127 self.env.borrow_mut().insert(name.clone(), func);
128 Ok(None)
129 }
130 Stmt::Block(stmts) => {
131 for stmt in stmts {
132 match self.execute_stmt(stmt)? {
133 Some(cf) => return Ok(Some(cf)),
134 None => {}
135 }
136 }
137 Ok(None)
138 }
139 Stmt::If { condition, then_branch, else_branch } => {
140 if self.evaluate(condition)?.is_truthy() {
141 for stmt in then_branch {
142 match self.execute_stmt(stmt)? {
143 Some(cf) => return Ok(Some(cf)),
144 None => {}
145 }
146 }
147 } else if let Some(else_stmts) = else_branch {
148 for stmt in else_stmts {
149 match self.execute_stmt(stmt)? {
150 Some(cf) => return Ok(Some(cf)),
151 None => {}
152 }
153 }
154 }
155 Ok(None)
156 }
157 Stmt::While { condition, body } => {
158 loop {
159 if !self.evaluate(condition)?.is_truthy() {
160 break;
161 }
162 for stmt in body {
163 match self.execute_stmt(stmt)? {
164 Some(ControlFlow::Return(v)) => return Ok(Some(ControlFlow::Return(v))),
165 Some(ControlFlow::Break) => return Ok(None),
166 Some(ControlFlow::Continue) => break,
167 None => {}
168 }
169 }
170 }
171 Ok(None)
172 }
173 Stmt::For { var, iterable, body } => {
174 let iter_val = self.evaluate(iterable)?;
175 let items = match iter_val {
176 Value::Array(arr) => arr.borrow().clone(),
177 Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(),
178 _ => return Err("Cannot iterate over this type".to_string()),
179 };
180 for item in items {
181 self.env.borrow_mut().insert(var.clone(), item);
182 for stmt in body {
183 match self.execute_stmt(stmt)? {
184 Some(ControlFlow::Return(v)) => return Ok(Some(ControlFlow::Return(v))),
185 Some(ControlFlow::Break) => return Ok(None),
186 Some(ControlFlow::Continue) => break,
187 None => {}
188 }
189 }
190 }
191 Ok(None)
192 }
193 Stmt::Return(expr) => {
194 let val = match expr {
195 Some(e) => self.evaluate(e)?,
196 None => Value::Null,
197 };
198 Ok(Some(ControlFlow::Return(val)))
199 }
200 Stmt::Break => Ok(Some(ControlFlow::Break)),
201 Stmt::Continue => Ok(Some(ControlFlow::Continue)),
202 }
203 }
204
205 fn evaluate(&mut self, expr: &Expr) -> Result<Value, String> {
206 match expr {
207 Expr::Null => Ok(Value::Null),
208 Expr::Bool(b) => Ok(Value::Bool(*b)),
209 Expr::Number(n) => Ok(Value::Number(*n)),
210 Expr::String(s) => Ok(Value::String(s.clone())),
211 Expr::Identifier(name) => {
212 if let Some(val) = self.env.borrow().get(name) {
213 return Ok(val.clone());
214 }
215 if let Some(val) = self.globals.borrow().get(name) {
216 return Ok(val.clone());
217 }
218 Err(format!("Undefined variable: '{}'", name))
219 }
220 Expr::Array(elements) => {
221 let mut vals = Vec::new();
222 for elem in elements {
223 vals.push(self.evaluate(elem)?);
224 }
225 Ok(Value::Array(Rc::new(RefCell::new(vals))))
226 }
227 Expr::Object(pairs) => {
228 let mut map = HashMap::new();
229 for (k, v) in pairs {
230 map.insert(k.clone(), self.evaluate(v)?);
231 }
232 Ok(Value::Object(Rc::new(RefCell::new(map))))
233 }
234 Expr::Binary { left, op, right } => {
235 let l = self.evaluate(left)?;
236 let r = self.evaluate(right)?;
237 match op {
238 BinaryOp::Add => {
239 match (&l, &r) {
240 (Value::String(a), _) => Ok(Value::String(format!("{}{}", a, r))),
241 (_, Value::String(b)) => Ok(Value::String(format!("{}{}", l, b))),
242 (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a + b)),
243 _ => Err("Invalid operands for +".to_string()),
244 }
245 }
246 BinaryOp::Sub => numeric_op(l, r, |a, b| a - b),
247 BinaryOp::Mul => numeric_op(l, r, |a, b| a * b),
248 BinaryOp::Div => numeric_op(l, r, |a, b| a / b),
249 BinaryOp::Mod => numeric_op(l, r, |a, b| a % b),
250 BinaryOp::Eq => Ok(Value::Bool(l == r)),
251 BinaryOp::Neq => Ok(Value::Bool(l != r)),
252 BinaryOp::Lt => compare_op(l, r, |a, b| a < b),
253 BinaryOp::Gt => compare_op(l, r, |a, b| a > b),
254 BinaryOp::Lte => compare_op(l, r, |a, b| a <= b),
255 BinaryOp::Gte => compare_op(l, r, |a, b| a >= b),
256 BinaryOp::And => Ok(Value::Bool(l.is_truthy() && r.is_truthy())),
257 BinaryOp::Or => Ok(Value::Bool(l.is_truthy() || r.is_truthy())),
258 }
259 }
260 Expr::Unary { op, expr } => {
261 let val = self.evaluate(expr)?;
262 match op {
263 UnaryOp::Neg => match val {
264 Value::Number(n) => Ok(Value::Number(-n)),
265 _ => Err("Cannot negate non-number".to_string()),
266 },
267 UnaryOp::Not => Ok(Value::Bool(!val.is_truthy())),
268 }
269 }
270 Expr::Call { callee, args } => {
271 let func = self.evaluate(callee)?;
272 let arg_vals: Result<Vec<Value>, String> = args.iter().map(|a| self.evaluate(a)).collect();
273 let arg_vals = arg_vals?;
274
275 match func {
276 Value::Builtin(f) => f(&arg_vals),
277 Value::Function { params, body, closure } => {
278 let mut new_env = HashMap::new();
279 for (k, v) in closure.borrow().iter() {
280 new_env.insert(k.clone(), v.clone());
281 }
282 for (i, param) in params.iter().enumerate() {
283 new_env.insert(param.clone(), arg_vals.get(i).cloned().unwrap_or(Value::Null));
284 }
285 let old_env = self.env.clone();
286 self.env = Rc::new(RefCell::new(new_env));
287 let mut result = Value::Null;
288 for stmt in &body {
289 match self.execute_stmt(stmt)? {
290 Some(ControlFlow::Return(v)) => { result = v; break; }
291 Some(ControlFlow::Break) => { result = Value::Null; break; }
292 Some(ControlFlow::Continue) => { result = Value::Null; break; }
293 None => {}
294 }
295 }
296 self.env = old_env;
297 Ok(result)
298 }
299 _ => Err("Not a function".to_string()),
300 }
301 }
302 Expr::Index { object, index } => {
303 let obj = self.evaluate(object)?;
304 let idx = self.evaluate(index)?;
305 match (obj, idx) {
306 (Value::Array(arr), Value::Number(n)) => {
307 let i = n as usize;
308 let arr = arr.borrow();
309 if i >= arr.len() {
310 return Err("Index out of bounds".to_string());
311 }
312 Ok(arr[i].clone())
313 }
314 (Value::String(s), Value::Number(n)) => {
315 let i = n as usize;
316 if i >= s.len() {
317 return Err("Index out of bounds".to_string());
318 }
319 Ok(Value::String(s.chars().nth(i).unwrap().to_string()))
320 }
321 (Value::Object(map), Value::String(key)) => {
322 let map = map.borrow();
323 match map.get(&key) {
324 Some(v) => Ok(v.clone()),
325 None => Ok(Value::Null),
326 }
327 }
328 _ => Err("Cannot index this type".to_string()),
329 }
330 }
331 Expr::Member { object, property } => {
332 let obj = self.evaluate(object)?;
333 match obj {
334 Value::Object(map) => {
335 let map = map.borrow();
336 match map.get(property) {
337 Some(v) => Ok(v.clone()),
338 None => Ok(Value::Null),
339 }
340 }
341 _ => Err("Cannot access property".to_string()),
342 }
343 }
344 Expr::Assign { target, value } => {
345 let val = self.evaluate(value)?;
346 match target.as_ref() {
347 Expr::Identifier(name) => {
348 self.env.borrow_mut().insert(name.clone(), val.clone());
349 Ok(val)
350 }
351 Expr::Member { object, property } => {
352 let obj = self.evaluate(object)?;
353 match obj {
354 Value::Object(map) => {
355 map.borrow_mut().insert(property.clone(), val.clone());
356 Ok(val)
357 }
358 _ => Err("Cannot set property".to_string()),
359 }
360 }
361 Expr::Index { object, index } => {
362 let obj = self.evaluate(object)?;
363 let idx = self.evaluate(index)?;
364 match (obj, idx) {
365 (Value::Array(arr), Value::Number(n)) => {
366 let i = n as usize;
367 arr.borrow_mut()[i] = val.clone();
368 Ok(val)
369 }
370 (Value::Object(map), Value::String(key)) => {
371 map.borrow_mut().insert(key, val.clone());
372 Ok(val)
373 }
374 _ => Err("Cannot set index".to_string()),
375 }
376 }
377 _ => Err("Invalid assignment target".to_string()),
378 }
379 }
380 Expr::Lambda { params, body } => {
381 Ok(Value::Function {
382 params: params.clone(),
383 body: body.clone(),
384 closure: self.env.clone(),
385 })
386 }
387 }
388 }
389}
390
391fn numeric_op<F>(left: Value, right: Value, op: F) -> Result<Value, String>
392where F: Fn(f64, f64) -> f64 {
393 match (left, right) {
394 (Value::Number(a), Value::Number(b)) => Ok(Value::Number(op(a, b))),
395 _ => Err("Invalid operands for numeric operation".to_string()),
396 }
397}
398
399fn compare_op<F>(left: Value, right: Value, op: F) -> Result<Value, String>
400where F: Fn(f64, f64) -> bool {
401 match (left, right) {
402 (Value::Number(a), Value::Number(b)) => Ok(Value::Bool(op(a, b))),
403 _ => Err("Invalid operands for comparison".to_string()),
404 }
405}
406
407fn builtin_print(args: &[Value]) -> Result<Value, String> {
408 let msg = args.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(" ");
409 println!("{}", msg);
410 Ok(Value::Null)
411}
412
413fn builtin_input(args: &[Value]) -> Result<Value, String> {
414 use std::io::{self, Write};
415 if let Some(arg) = args.first() {
416 print!("{}", arg);
417 io::stdout().flush().unwrap();
418 }
419 let mut buf = String::new();
420 io::stdin().read_line(&mut buf).map_err(|e| e.to_string())?;
421 Ok(Value::String(buf.trim().to_string()))
422}
423
424fn builtin_len(args: &[Value]) -> Result<Value, String> {
425 match args.first() {
426 Some(Value::Array(arr)) => Ok(Value::Number(arr.borrow().len() as f64)),
427 Some(Value::String(s)) => Ok(Value::Number(s.len() as f64)),
428 _ => Ok(Value::Number(0.0)),
429 }
430}
431
432fn builtin_typeof(args: &[Value]) -> Result<Value, String> {
433 match args.first() {
434 Some(v) => Ok(Value::String(v.type_name().to_string())),
435 None => Ok(Value::String("null".to_string())),
436 }
437}
438
439fn builtin_push(args: &[Value]) -> Result<Value, String> {
440 if args.len() < 2 {
441 return Err("push requires 2 arguments".to_string());
442 }
443 match &args[0] {
444 Value::Array(arr) => {
445 arr.borrow_mut().push(args[1].clone());
446 Ok(args[0].clone())
447 }
448 _ => Err("First argument must be an array".to_string()),
449 }
450}
451
452fn builtin_pop(args: &[Value]) -> Result<Value, String> {
453 match args.first() {
454 Some(Value::Array(arr)) => {
455 match arr.borrow_mut().pop() {
456 Some(v) => Ok(v),
457 None => Ok(Value::Null),
458 }
459 }
460 _ => Err("pop requires an array".to_string()),
461 }
462}
463
464fn builtin_keys(args: &[Value]) -> Result<Value, String> {
465 match args.first() {
466 Some(Value::Object(map)) => {
467 let keys: Vec<Value> = map.borrow().keys().cloned().map(Value::String).collect();
468 Ok(Value::Array(Rc::new(RefCell::new(keys))))
469 }
470 _ => Err("keys requires an object".to_string()),
471 }
472}
473
474fn builtin_values(args: &[Value]) -> Result<Value, String> {
475 match args.first() {
476 Some(Value::Object(map)) => {
477 let vals: Vec<Value> = map.borrow().values().cloned().collect();
478 Ok(Value::Array(Rc::new(RefCell::new(vals))))
479 }
480 _ => Err("values requires an object".to_string()),
481 }
482}
483
484fn builtin_range(args: &[Value]) -> Result<Value, String> {
485 if args.len() < 2 {
486 return Err("range requires 2 arguments".to_string());
487 }
488 match (&args[0], &args[1]) {
489 (Value::Number(start), Value::Number(end)) => {
490 let mut vals = Vec::new();
491 let s = *start as i64;
492 let e = *end as i64;
493 for i in s..=e {
494 vals.push(Value::Number(i as f64));
495 }
496 Ok(Value::Array(Rc::new(RefCell::new(vals))))
497 }
498 _ => Err("range requires numeric arguments".to_string()),
499 }
500}
501
502fn builtin_str(args: &[Value]) -> Result<Value, String> {
503 match args.first() {
504 Some(v) => Ok(Value::String(v.to_string())),
505 None => Ok(Value::String("".to_string())),
506 }
507}
508
509fn builtin_num(args: &[Value]) -> Result<Value, String> {
510 match args.first() {
511 Some(Value::String(s)) => match s.parse::<f64>() {
512 Ok(n) => Ok(Value::Number(n)),
513 Err(_) => Ok(Value::Number(0.0)),
514 },
515 Some(Value::Number(n)) => Ok(Value::Number(*n)),
516 Some(Value::Bool(b)) => Ok(Value::Number(if *b { 1.0 } else { 0.0 })),
517 _ => Ok(Value::Number(0.0)),
518 }
519}