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;
16pub 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 ];
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 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}