neutron_engine/iris/
mod.rs1pub mod lexer;
9pub mod parser;
10pub mod interpreter;
11pub mod value;
12
13use std::fs;
14use std::path::Path;
15
16pub fn run_file(path: &str) -> Result<(), String> {
18 let source = fs::read_to_string(path)
19 .map_err(|e| format!("Failed to read '{}': {}", path, e))?;
20 let base = Path::new(path).parent().unwrap_or(Path::new("."));
21 let file_name = Path::new(path).file_name().unwrap_or_default().to_str().unwrap_or("");
22 run_with_base(&source, base.to_str().unwrap_or("."), Some(file_name))
23}
24
25pub fn run(source: &str) -> Result<(), String> {
27 run_with_base(source, ".", None)
28}
29
30pub fn run_with_base(source: &str, base_path: &str, entry_file: Option<&str>) -> Result<(), String> {
32 let tokens = lexer::tokenize(source)?;
33 let ast = parser::parse(&tokens)?;
34 let mut interp = interpreter::Interpreter::new().with_base_path(base_path);
35 if let Some(file) = entry_file {
36 interp.mark_imported(file);
37 }
38 interp.execute(&ast)?;
39 Ok(())
40}
41
42pub fn repl() {
44 use std::io::{self, Write};
45
46 println!("Iris REPL v0.1.0");
47 println!("Type 'exit' or press Ctrl+C to quit.\n");
48
49 let mut interp = interpreter::Interpreter::new();
50
51 loop {
52 print!("iris> ");
53 io::stdout().flush().unwrap();
54
55 let mut input = String::new();
56 if io::stdin().read_line(&mut input).is_err() {
57 break;
58 }
59
60 let input = input.trim();
61 if input == "exit" || input == "quit" {
62 break;
63 }
64 if input.is_empty() {
65 continue;
66 }
67
68 match lexer::tokenize(input) {
69 Ok(tokens) => {
70 match parser::parse(&tokens) {
71 Ok(ast) => {
72 match interp.execute(&ast) {
73 Ok(result) => {
74 if !matches!(result, value::Value::Null) {
75 println!("{}", result);
76 }
77 }
78 Err(e) => eprintln!("Runtime error: {}", e),
79 }
80 }
81 Err(e) => eprintln!("Parse error: {}", e),
82 }
83 }
84 Err(e) => eprintln!("Lex error: {}", e),
85 }
86 }
87}
88