1use super::Aether;
2use crate::evaluator::ErrorReport;
3use crate::parser::Parser;
4use crate::value::Value;
5
6impl Aether {
7 pub fn eval(&mut self, code: &str) -> Result<Value, String> {
9 self.evaluator.clear_call_stack();
11 self.evaluator.reset_step_counter();
12
13 let program = if let Some(cached_program) = self.cache.get(code) {
15 cached_program
16 } else {
17 let mut parser = Parser::new(code);
19 let program = parser
20 .parse_program()
21 .map_err(|e| format!("Parse error: {}", e))?;
22
23 let optimized = self.optimizer.optimize_program(&program);
25
26 self.cache.insert(code, optimized.clone());
28 optimized
29 };
30
31 self.evaluator
33 .eval_program(&program)
34 .map_err(|e| format!("Runtime error: {}", e))
35 }
36
37 pub fn eval_report(&mut self, code: &str) -> Result<Value, ErrorReport> {
41 self.evaluator.clear_call_stack();
43 self.evaluator.reset_step_counter();
44
45 let program = if let Some(cached_program) = self.cache.get(code) {
47 cached_program
48 } else {
49 let mut parser = Parser::new(code);
50 let program = parser
51 .parse_program()
52 .map_err(|e| ErrorReport::parse_error(e.to_string()))?;
53
54 let optimized = self.optimizer.optimize_program(&program);
55 self.cache.insert(code, optimized.clone());
56 optimized
57 };
58
59 self.evaluator
60 .eval_program(&program)
61 .map_err(|e| e.to_error_report())
62 }
63
64 pub fn set_module_resolver(&mut self, resolver: Box<dyn crate::module_system::ModuleResolver>) {
68 self.evaluator.set_module_resolver(resolver);
69 }
70
71 pub fn push_import_base(&mut self, module_id: String, base_dir: Option<std::path::PathBuf>) {
75 self.evaluator.push_import_base(module_id, base_dir);
76 }
77
78 pub fn pop_import_base(&mut self) {
80 self.evaluator.pop_import_base();
81 }
82
83 pub fn eval_file(&mut self, path: impl AsRef<std::path::Path>) -> Result<Value, String> {
93 let path = path.as_ref();
94
95 let code = std::fs::read_to_string(path).map_err(|e| format!("IO error: {}", e))?;
96
97 let canon = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
98 let base_dir = canon.parent().map(|p| p.to_path_buf());
99
100 self.push_import_base(canon.display().to_string(), base_dir);
101 let res = self.eval(&code);
102 self.pop_import_base();
103 res
104 }
105
106 pub fn eval_file_report(
108 &mut self,
109 path: impl AsRef<std::path::Path>,
110 ) -> Result<Value, ErrorReport> {
111 let path = path.as_ref();
112
113 let code = std::fs::read_to_string(path)
114 .map_err(|e| ErrorReport::io_error(format!("IO error: {e}")))?;
115
116 let canon = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
117 let base_dir = canon.parent().map(|p| p.to_path_buf());
118
119 self.push_import_base(canon.display().to_string(), base_dir);
120 let res = self.eval_report(&code);
121 self.pop_import_base();
122 res
123 }
124
125 pub fn set_global(&mut self, name: &str, value: Value) {
129 self.evaluator.set_global(name.to_string(), value);
130 }
131
132 pub fn reset_env(&mut self) {
136 self.evaluator.reset_env();
137 }
138
139 pub fn with_isolated_scope<R>(
146 &mut self,
147 f: impl FnOnce(&mut Aether) -> Result<R, String>,
148 ) -> Result<R, String> {
149 let prev_env = self.evaluator.enter_child_scope();
150 let result = f(self);
151 self.evaluator.restore_env(prev_env);
152 result
153 }
154
155 #[cfg(feature = "async")]
160 pub async fn eval_async(&mut self, code: &str) -> Result<Value, String> {
161 tokio::task::yield_now().await;
164 self.eval(code)
165 }
166}