Skip to main content

neutron_engine/iris/
interpreter.rs

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}