Skip to main content

neutron_engine/iris/
interpreter.rs

1 use std::collections::{HashMap, HashSet};
2use std::fs;
3use std::path::PathBuf;
4use std::rc::Rc;
5use std::cell::RefCell;
6
7use super::parser::{Expr, BinaryOp, UnaryOp, Stmt};
8
9
10use super::value::Value;
11use std::process::Command;
12use std::fs::{read_to_string, write};
13use std::env;
14use std::thread::sleep;
15use std::time::Duration;
16// use TokenType::Bang; - unused
17
18pub struct Interpreter {
19
20    globals: Rc<RefCell<HashMap<String, Value>>>,
21    env: Rc<RefCell<HashMap<String, Value>>>,
22    imported: Rc<RefCell<HashSet<PathBuf>>>,
23    base_path: PathBuf,
24}
25
26#[derive(Debug, Clone)]
27enum ControlFlow {
28    Return(Value),
29    Break,
30    Continue,
31}
32
33impl Interpreter {
34    pub fn new() -> Self {
35        let globals = Rc::new(RefCell::new(HashMap::new()));
36        Self::register_builtins(&mut globals.borrow_mut());
37        Interpreter {
38            globals: globals.clone(),
39            env: globals,
40            imported: Rc::new(RefCell::new(HashSet::new())),
41            base_path: PathBuf::from("."),
42        }
43    }
44
45    pub fn with_base_path(mut self, path: &str) -> Self {
46        self.base_path = PathBuf::from(path);
47        self
48    }
49
50    pub fn mark_imported(&mut self, path: &str) {
51        let file_path = self.base_path.join(path);
52        if let Ok(canonical) = fs::canonicalize(&file_path) {
53            self.imported.borrow_mut().insert(canonical);
54        } else {
55            self.imported.borrow_mut().insert(file_path);
56        }
57    }
58
59    fn register_builtins(env: &mut HashMap<String, Value>) {
60        let builtins = [
61            ("print", Value::Builtin(builtin_print)),
62            ("println", Value::Builtin(builtin_println)),
63            ("input", Value::Builtin(builtin_input)),
64            ("len", Value::Builtin(builtin_len)),
65            ("typeof", Value::Builtin(builtin_typeof)),
66            ("push", Value::Builtin(builtin_push)),
67            ("pop", Value::Builtin(builtin_pop)),
68            ("keys", Value::Builtin(builtin_keys)),
69            ("values", Value::Builtin(builtin_values)),
70            ("range", Value::Builtin(builtin_range)),
71            ("str", Value::Builtin(builtin_str)),
72            ("num", Value::Builtin(builtin_num)),
73            ("system", Value::Builtin(builtin_system)),
74            ("fs_read", Value::Builtin(builtin_fs_read)),
75            ("fs_write", Value::Builtin(builtin_fs_write)),
76            ("env_get", Value::Builtin(builtin_env_get)),
77            ("sleep", Value::Builtin(builtin_sleep)),
78            ("proc_list", Value::Builtin(builtin_proc_list)),
79            // ("room_scan", Value::Builtin(builtin_room_scan)),
80
81        ];
82
83        for (name, value) in builtins.iter() {
84            env.insert((*name).to_string(), value.clone());
85        }
86
87        let iris_namespace = builtins
88            .iter()
89            .map(|(name, value)| ((*name).to_string(), value.clone()))
90            .collect::<HashMap<_, _>>();
91        env.insert(
92            "iris".to_string(),
93            Value::Object(Rc::new(RefCell::new(iris_namespace.clone()))),
94        );
95        env.insert(
96            "std".to_string(),
97            Value::Object(Rc::new(RefCell::new(iris_namespace))),
98        );
99    }
100
101    pub fn execute(&mut self, stmts: &[Stmt]) -> Result<Value, String> {
102        let last = Value::Null;
103        for stmt in stmts {
104            match self.execute_stmt(stmt)? {
105                Some(ControlFlow::Return(v)) => return Ok(v),
106                Some(ControlFlow::Break) => return Err("break outside loop".to_string()),
107                Some(ControlFlow::Continue) => return Err("continue outside loop".to_string()),
108                None => {}
109            }
110        }
111        Ok(last)
112    }
113
114    pub fn invoke_main_if_present(&mut self) -> Result<(), String> {
115        let maybe_main = self
116            .env
117            .borrow()
118            .get("main")
119            .cloned()
120            .or_else(|| self.globals.borrow().get("main").cloned());
121
122        if let Some(func) = maybe_main {
123            match func {
124                Value::Function { .. } | Value::Builtin(_) => {
125                    self.invoke_callable(func, vec![])?;
126                }
127                _ => {}
128            }
129        }
130
131        Ok(())
132    }
133
134    fn execute_stmt(&mut self, stmt: &Stmt) -> Result<Option<ControlFlow>, String> {
135        match stmt {
136            Stmt::Expr(expr) => {
137                self.evaluate(expr)?;
138                Ok(None)
139            }
140            Stmt::Let { name, value } => {
141                let val = self.evaluate(value)?;
142                self.env.borrow_mut().insert(name.clone(), val);
143                Ok(None)
144            }
145            Stmt::Const { name, value } => {
146                let val = self.evaluate(value)?;
147                self.env.borrow_mut().insert(name.clone(), val);
148                Ok(None)
149            }
150            Stmt::Fn { name, params, body } => {
151                let func = Value::Function {
152                    params: params.clone(),
153                    body: body.clone(),
154                    closure: self.env.clone(),
155                };
156                self.env.borrow_mut().insert(name.clone(), func);
157                Ok(None)
158            }
159            Stmt::Block(stmts) => {
160                for stmt in stmts {
161                    match self.execute_stmt(stmt)? {
162                        Some(cf) => return Ok(Some(cf)),
163                        None => {}
164                    }
165                }
166                Ok(None)
167            }
168            Stmt::If { condition, then_branch, else_branch } => {
169                if self.evaluate(condition)?.is_truthy() {
170                    for stmt in then_branch {
171                        match self.execute_stmt(stmt)? {
172                            Some(cf) => return Ok(Some(cf)),
173                            None => {}
174                        }
175                    }
176                } else if let Some(else_stmts) = else_branch {
177                    for stmt in else_stmts {
178                        match self.execute_stmt(stmt)? {
179                            Some(cf) => return Ok(Some(cf)),
180                            None => {}
181                        }
182                    }
183                }
184                Ok(None)
185            }
186            Stmt::While { condition, body } => {
187                loop {
188                    if !self.evaluate(condition)?.is_truthy() {
189                        break;
190                    }
191                    for stmt in body {
192                        match self.execute_stmt(stmt)? {
193                            Some(ControlFlow::Return(v)) => return Ok(Some(ControlFlow::Return(v))),
194                            Some(ControlFlow::Break) => return Ok(None),
195                            Some(ControlFlow::Continue) => break,
196                            None => {}
197                        }
198                    }
199                }
200                Ok(None)
201            }
202            Stmt::For { var, iterable, body } => {
203                let iter_val = self.evaluate(iterable)?;
204                let items = match iter_val {
205                    Value::Array(arr) => arr.borrow().clone(),
206                    Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(),
207                    _ => return Err("Cannot iterate over this type".to_string()),
208                };
209                for item in items {
210                    self.env.borrow_mut().insert(var.clone(), item);
211                    for stmt in body {
212                        match self.execute_stmt(stmt)? {
213                            Some(ControlFlow::Return(v)) => return Ok(Some(ControlFlow::Return(v))),
214                            Some(ControlFlow::Break) => return Ok(None),
215                            Some(ControlFlow::Continue) => break,
216                            None => {}
217                        }
218                    }
219                }
220                Ok(None)
221            }
222            Stmt::Return(expr) => {
223                let val = match expr {
224                    Some(e) => self.evaluate(e)?,
225                    None => Value::Null,
226                };
227                Ok(Some(ControlFlow::Return(val)))
228            }
229            Stmt::Break => Ok(Some(ControlFlow::Break)),
230            Stmt::Continue => Ok(Some(ControlFlow::Continue)),
231            Stmt::SystemIris { traits } => {
232                // Minimal implementation: store requested traits in globals so user code can read them.
233                let mut existing = self.globals.borrow_mut();
234                existing.insert(
235                    "system_iris_traits".to_string(),
236                    Value::Array(Rc::new(RefCell::new(traits.iter().map(|t| Value::String(t.clone())).collect()))),
237                );
238                existing.insert(
239                    "system_iris_foundation".to_string(),
240                    Value::Bool(traits.iter().any(|t| t.eq_ignore_ascii_case("foundation"))),
241                );
242                existing.insert(
243                    "system_iris_compiler_speed_target".to_string(),
244                    Value::String("faster-than-rust-cpp-ocaml".to_string()),
245                );
246                Ok(None)
247            }
248            Stmt::Import { path } => {
249                let file_path = self.base_path.join(path);
250                let canonical = fs::canonicalize(&file_path).unwrap_or(file_path.clone());
251                if self.imported.borrow().contains(&canonical) {
252                    return Ok(None);
253                }
254
255                let source = read_to_string(&file_path)
256                    .map_err(|e| format!("Failed to import '{}': {}", path, e))?;
257                let tokens = super::lexer::tokenize(&source)?;
258                let ast = super::parser::parse(&tokens)?;
259
260                self.imported.borrow_mut().insert(canonical);
261                let previous_base = self.base_path.clone();
262                if let Some(parent) = file_path.parent() {
263                    self.base_path = parent.to_path_buf();
264                }
265                let result = self.execute(&ast);
266                self.base_path = previous_base;
267                result.map(|_| None)
268            }
269        }
270    }
271
272
273    fn evaluate(&mut self, expr: &Expr) -> Result<Value, String> {
274        match expr {
275            Expr::Null => Ok(Value::Null),
276            Expr::Bool(b) => Ok(Value::Bool(*b)),
277            Expr::Number(n) => Ok(Value::Number(*n)),
278            Expr::String(s) => Ok(Value::String(s.clone())),
279            Expr::Identifier(name) => {
280                if let Some(val) = self.env.borrow().get(name) {
281                    return Ok(val.clone());
282                }
283                if let Some(val) = self.globals.borrow().get(name) {
284                    return Ok(val.clone());
285                }
286                Err(format!("Undefined variable: '{}'", name))
287            }
288            Expr::Array(elements) => {
289                let mut vals = Vec::new();
290                for elem in elements {
291                    vals.push(self.evaluate(elem)?);
292                }
293                Ok(Value::Array(Rc::new(RefCell::new(vals))))
294            }
295            Expr::Object(pairs) => {
296                let mut map = HashMap::new();
297                for (k, v) in pairs {
298                    map.insert(k.clone(), self.evaluate(v)?);
299                }
300                Ok(Value::Object(Rc::new(RefCell::new(map))))
301            }
302            Expr::Binary { left, op, right } => {
303                let l = self.evaluate(left)?;
304                let r = self.evaluate(right)?;
305                match op {
306                    BinaryOp::Add => {
307                        match (&l, &r) {
308                            (Value::String(a), _) => Ok(Value::String(format!("{}{}", a, r))),
309                            (_, Value::String(b)) => Ok(Value::String(format!("{}{}", l, b))),
310                            (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a + b)),
311                            _ => Err("Invalid operands for +".to_string()),
312                        }
313                    }
314                    BinaryOp::Sub => numeric_op(l, r, |a, b| a - b),
315                    BinaryOp::Mul => numeric_op(l, r, |a, b| a * b),
316                    BinaryOp::Div => numeric_op(l, r, |a, b| a / b),
317                    BinaryOp::Mod => numeric_op(l, r, |a, b| a % b),
318                    BinaryOp::Eq => Ok(Value::Bool(l == r)),
319                    BinaryOp::Neq => Ok(Value::Bool(l != r)),
320                    BinaryOp::Lt => compare_op(l, r, |a, b| a < b),
321                    BinaryOp::Gt => compare_op(l, r, |a, b| a > b),
322                    BinaryOp::Lte => compare_op(l, r, |a, b| a <= b),
323                    BinaryOp::Gte => compare_op(l, r, |a, b| a >= b),
324                    BinaryOp::And => Ok(Value::Bool(l.is_truthy() && r.is_truthy())),
325                    BinaryOp::Or => Ok(Value::Bool(l.is_truthy() || r.is_truthy())),
326                }
327            }
328            Expr::Unary { op, expr } => {
329                let val = self.evaluate(expr)?;
330                match op {
331                    UnaryOp::Neg => match val {
332                        Value::Number(n) => Ok(Value::Number(-n)),
333                        _ => Err("Cannot negate non-number".to_string()),
334                    },
335                    UnaryOp::Not => Ok(Value::Bool(!val.is_truthy())),
336                }
337            }
338            Expr::Call { callee, args } => {
339                let func = self.evaluate(callee)?;
340                let arg_vals: Result<Vec<Value>, String> = args.iter().map(|a| self.evaluate(a)).collect();
341                let arg_vals = arg_vals?;
342                self.invoke_callable(func, arg_vals)
343            }
344            Expr::Index { object, index } => {
345                let obj = self.evaluate(object)?;
346                let idx = self.evaluate(index)?;
347                match (obj, idx) {
348                    (Value::Array(arr), Value::Number(n)) => {
349                        let i = n as usize;
350                        let arr = arr.borrow();
351                        if i >= arr.len() {
352                            return Err("Index out of bounds".to_string());
353                        }
354                        Ok(arr[i].clone())
355                    }
356                    (Value::String(s), Value::Number(n)) => {
357                        let i = n as usize;
358                        if i >= s.len() {
359                            return Err("Index out of bounds".to_string());
360                        }
361                        Ok(Value::String(s.chars().nth(i).unwrap().to_string()))
362                    }
363                    (Value::Object(map), Value::String(key)) => {
364                        let map = map.borrow();
365                        match map.get(&key) {
366                            Some(v) => Ok(v.clone()),
367                            None => Ok(Value::Null),
368                        }
369                    }
370                    _ => Err("Cannot index this type".to_string()),
371                }
372            }
373            Expr::Member { object, property } => {
374                let obj = self.evaluate(object)?;
375                match obj {
376                    Value::Object(map) => {
377                        let map = map.borrow();
378                        match map.get(property) {
379                            Some(v) => Ok(v.clone()),
380                            None => Ok(Value::Null),
381                        }
382                    }
383                    _ => Err("Cannot access property".to_string()),
384                }
385            }
386            Expr::Assign { target, value } => {
387                let val = self.evaluate(value)?;
388                match target.as_ref() {
389                    Expr::Identifier(name) => {
390                        self.env.borrow_mut().insert(name.clone(), val.clone());
391                        Ok(val)
392                    }
393                    Expr::Member { object, property } => {
394                        let obj = self.evaluate(object)?;
395                        match obj {
396                            Value::Object(map) => {
397                                map.borrow_mut().insert(property.clone(), val.clone());
398                                Ok(val)
399                            }
400                            _ => Err("Cannot set property".to_string()),
401                        }
402                    }
403                    Expr::Index { object, index } => {
404                        let obj = self.evaluate(object)?;
405                        let idx = self.evaluate(index)?;
406                        match (obj, idx) {
407                            (Value::Array(arr), Value::Number(n)) => {
408                                let i = n as usize;
409                                arr.borrow_mut()[i] = val.clone();
410                                Ok(val)
411                            }
412                            (Value::Object(map), Value::String(key)) => {
413                                map.borrow_mut().insert(key, val.clone());
414                                Ok(val)
415                            }
416                            _ => Err("Cannot set index".to_string()),
417                        }
418                    }
419                    _ => Err("Invalid assignment target".to_string()),
420                }
421            }
422            Expr::Lambda { params, body } => {
423                Ok(Value::Function {
424                    params: params.clone(),
425                    body: body.clone(),
426                    closure: self.env.clone(),
427                })
428            }
429        }
430    }
431
432    fn invoke_callable(&mut self, func: Value, arg_vals: Vec<Value>) -> Result<Value, String> {
433        match func {
434            Value::Builtin(f) => f(&arg_vals),
435            Value::Function { params, body, closure } => {
436                let mut new_env = HashMap::new();
437                for (k, v) in closure.borrow().iter() {
438                    new_env.insert(k.clone(), v.clone());
439                }
440                for (i, param) in params.iter().enumerate() {
441                    new_env.insert(param.clone(), arg_vals.get(i).cloned().unwrap_or(Value::Null));
442                }
443                let old_env = self.env.clone();
444                self.env = Rc::new(RefCell::new(new_env));
445                let mut result = Value::Null;
446                for stmt in &body {
447                    match self.execute_stmt(stmt)? {
448                        Some(ControlFlow::Return(v)) => { result = v; break; }
449                        Some(ControlFlow::Break) => { result = Value::Null; break; }
450                        Some(ControlFlow::Continue) => { result = Value::Null; break; }
451                        None => {}
452                    }
453                }
454                self.env = old_env;
455                Ok(result)
456            }
457            _ => Err("Not a function".to_string()),
458        }
459    }
460}
461
462fn numeric_op<F>(left: Value, right: Value, op: F) -> Result<Value, String>
463where F: Fn(f64, f64) -> f64 {
464    match (left, right) {
465        (Value::Number(a), Value::Number(b)) => Ok(Value::Number(op(a, b))),
466        _ => Err("Invalid operands for numeric operation".to_string()),
467    }
468}
469
470fn compare_op<F>(left: Value, right: Value, op: F) -> Result<Value, String>
471where 
472    F: Fn(f64, f64) -> bool 
473{
474    match (left, right) {
475        (Value::Number(a), Value::Number(b)) => Ok(Value::Bool(op(a, b))),
476        _ => Err("Invalid operands for comparison".to_string()),
477    }
478}
479
480fn builtin_print(args: &[Value]) -> Result<Value, String> {
481    let mut msg = String::new();
482    for (i, arg) in args.iter().enumerate() {
483        if i > 0 {
484            msg.push(' ');
485        }
486        msg.push_str(&arg.to_string());
487    }
488    print!("{}", msg);
489    Ok(Value::Null)
490}
491
492fn builtin_println(args: &[Value]) -> Result<Value, String> {
493    let mut msg = String::new();
494    for (i, arg) in args.iter().enumerate() {
495        if i > 0 {
496            msg.push(' ');
497        }
498        msg.push_str(&arg.to_string());
499    }
500    println!("{}", msg);
501    Ok(Value::Null)
502}
503
504fn builtin_input(args: &[Value]) -> Result<Value, String> {
505    use std::io::{self, Write};
506    if let Some(arg) = args.first() {
507        print!("{}", arg);
508        io::stdout().flush().unwrap();
509    }
510    let mut buf = String::new();
511    io::stdin().read_line(&mut buf).map_err(|e| e.to_string())?;
512    Ok(Value::String(buf.trim().to_string()))
513}
514
515fn builtin_len(args: &[Value]) -> Result<Value, String> {
516    match args.first() {
517        Some(Value::Array(arr)) => Ok(Value::Number(arr.borrow().len() as f64)),
518        Some(Value::String(s)) => Ok(Value::Number(s.len() as f64)),
519        _ => Ok(Value::Number(0.0)),
520    }
521}
522
523fn builtin_typeof(args: &[Value]) -> Result<Value, String> {
524    match args.first() {
525        Some(v) => Ok(Value::String(v.type_name().to_string())),
526        None => Ok(Value::String("null".to_string())),
527    }
528}
529
530fn builtin_push(args: &[Value]) -> Result<Value, String> {
531    if args.len() < 2 {
532        return Err("push requires 2 arguments".to_string());
533    }
534    match &args[0] {
535        Value::Array(arr) => {
536            arr.borrow_mut().push(args[1].clone());
537            Ok(args[0].clone())
538        }
539        _ => Err("First argument must be an array".to_string()),
540    }
541}
542
543fn builtin_pop(args: &[Value]) -> Result<Value, String> {
544    match args.first() {
545        Some(Value::Array(arr)) => {
546            match arr.borrow_mut().pop() {
547                Some(v) => Ok(v),
548                None => Ok(Value::Null),
549            }
550        }
551        _ => Err("pop requires an array".to_string()),
552    }
553}
554
555fn builtin_keys(args: &[Value]) -> Result<Value, String> {
556    match args.first() {
557        Some(Value::Object(map)) => {
558            let keys: Vec<Value> = map.borrow().keys().cloned().map(Value::String).collect();
559            Ok(Value::Array(Rc::new(RefCell::new(keys))))
560        }
561        _ => Err("keys requires an object".to_string()),
562    }
563}
564
565fn builtin_values(args: &[Value]) -> Result<Value, String> {
566    match args.first() {
567        Some(Value::Object(map)) => {
568            let vals: Vec<Value> = map.borrow().values().cloned().collect();
569            Ok(Value::Array(Rc::new(RefCell::new(vals))))
570        }
571        _ => Err("values requires an object".to_string()),
572    }
573}
574
575fn builtin_range(args: &[Value]) -> Result<Value, String> {
576    if args.len() < 2 {
577        return Err("range requires 2 arguments".to_string());
578    }
579    match (&args[0], &args[1]) {
580        (Value::Number(start), Value::Number(end)) => {
581            let mut vals = Vec::new();
582            let s = *start as i64;
583            let e = *end as i64;
584            for i in s..=e {
585                vals.push(Value::Number(i as f64));
586            }
587            Ok(Value::Array(Rc::new(RefCell::new(vals))))
588        }
589        _ => Err("range requires numeric arguments".to_string()),
590    }
591}
592
593fn builtin_str(args: &[Value]) -> Result<Value, String> {
594    match args.first() {
595        Some(v) => Ok(Value::String(v.to_string())),
596        None => Ok(Value::String("".to_string())),
597    }
598}
599
600fn builtin_num(args: &[Value]) -> Result<Value, String> {
601    match args.first() {
602        Some(Value::String(s)) => match s.parse::<f64>() {
603            Ok(n) => Ok(Value::Number(n)),
604            Err(_) => Ok(Value::Number(0.0)),
605        },
606        Some(Value::Number(n)) => Ok(Value::Number(*n)),
607        Some(Value::Bool(b)) => Ok(Value::Number(if *b { 1.0 } else { 0.0 })),
608        _ => Ok(Value::Number(0.0)),
609    }
610}
611
612fn builtin_system(args: &[Value]) -> Result<Value, String> {
613    if let Some(Value::String(cmd)) = args.first() {
614        let output = Command::new("cmd").args(["/c", &cmd]).output().map_err(|e| format!("system failed: {}", e))?;
615        Ok(Value::Number(if output.status.success() { 0.0 } else { 1.0 }))
616    } else {
617        Err("system requires string command".to_string())
618    }
619}
620
621fn builtin_fs_read(args: &[Value]) -> Result<Value, String> {
622    if let Some(Value::String(path)) = args.first() {
623        read_to_string(&path).map(Value::String).map_err(|e| format!("fs_read failed: {}", e))
624    } else {
625        Err("fs_read requires string path".to_string())
626    }
627}
628
629fn builtin_fs_write(args: &[Value]) -> Result<Value, String> {
630    if args.len() < 2 {
631        return Err("fs_write requires path and content".to_string());
632    }
633    if let (Some(Value::String(path)), Some(content)) = (args.first(), args.get(1)) {
634        let content_str = content.to_string();
635        write(&path, content_str.as_bytes()).map(|_| Value::Null).map_err(|e| format!("fs_write failed: {}", e))
636    } else {
637        Err("fs_write requires string path and content".to_string())
638    }
639}
640
641fn builtin_env_get(args: &[Value]) -> Result<Value, String> {
642    if let Some(Value::String(key)) = args.first() {
643        Ok(Value::String(env::var(&key).unwrap_or_else(|_| String::new())))
644    } else {
645        Err("env_get requires string key".to_string())
646    }
647}
648
649fn builtin_sleep(args: &[Value]) -> Result<Value, String> {
650    if let Some(Value::Number(ms)) = args.first() {
651        sleep(Duration::from_millis(*ms as u64));
652
653        Ok(Value::Null)
654    } else {
655        Err("sleep requires number (ms)".to_string())
656    }
657}
658
659fn builtin_proc_list(_args: &[Value]) -> Result<Value, String> {
660    let output = Command::new("tasklist").args(["/FO", "CSV", "/NH"]).output().map_err(|e| format!("proc_list failed: {}", e))?;
661    let stdout = String::from_utf8_lossy(&output.stdout);
662    Ok(Value::String(stdout.to_string()))
663}