1use std::collections::HashMap;
2use std::sync::Arc;
3
4use crate::error::IonError;
5use crate::host_types::{HostEnumDef, HostStructDef, IonType, IonTypeDef};
6use crate::interpreter::{Interpreter, Limits};
7use crate::lexer::Lexer;
8use crate::module::Module;
9use crate::parser::Parser;
10use crate::stdlib::OutputHandler;
11use crate::value::Value;
12
13pub struct Engine {
15 interpreter: Interpreter,
16 output: Arc<dyn OutputHandler>,
17}
18
19impl Engine {
20 pub fn new() -> Self {
21 let output = crate::stdlib::missing_output_handler();
22 Self {
23 interpreter: Interpreter::with_output(Arc::clone(&output)),
24 output,
25 }
26 }
27
28 pub fn with_output<H>(output: H) -> Self
30 where
31 H: OutputHandler + 'static,
32 {
33 Self::with_output_handler(Arc::new(output))
34 }
35
36 pub fn with_output_handler(output: Arc<dyn OutputHandler>) -> Self {
38 Self {
39 interpreter: Interpreter::with_output(Arc::clone(&output)),
40 output,
41 }
42 }
43
44 pub fn eval(&mut self, source: &str) -> Result<Value, IonError> {
46 let mut lexer = Lexer::new(source);
47 let tokens = lexer.tokenize()?;
48 let mut parser = Parser::new(tokens);
49 let program = parser.parse_program()?;
50 self.interpreter.eval_program(&program)
51 }
52
53 pub fn set(&mut self, name: &str, value: Value) {
55 self.interpreter.env.define(name.to_string(), value, false);
56 }
57
58 pub fn get(&self, name: &str) -> Option<Value> {
60 self.interpreter.env.get(name).cloned()
61 }
62
63 pub fn get_all(&self) -> HashMap<String, Value> {
65 self.interpreter.env.top_level()
66 }
67
68 pub fn set_limits(&mut self, limits: Limits) {
70 self.interpreter.limits = limits;
71 }
72
73 pub fn set_output<H>(&mut self, output: H)
76 where
77 H: OutputHandler + 'static,
78 {
79 self.set_output_handler(Arc::new(output));
80 }
81
82 pub fn set_output_handler(&mut self, output: Arc<dyn OutputHandler>) {
84 self.output = Arc::clone(&output);
85 let io = crate::stdlib::io_module_with_output(output);
86 self.interpreter
87 .env
88 .define(io.name.clone(), io.to_value(), false);
89 }
90
91 pub fn register_fn(&mut self, name: &str, func: fn(&[Value]) -> Result<Value, String>) {
93 self.interpreter.env.define(
94 name.to_string(),
95 Value::BuiltinFn(name.to_string(), func),
96 false,
97 );
98 }
99
100 pub fn register_closure<F>(&mut self, name: &str, func: F)
106 where
107 F: Fn(&[Value]) -> Result<Value, String> + Send + Sync + 'static,
108 {
109 self.interpreter.env.define(
110 name.to_string(),
111 Value::BuiltinClosure(name.to_string(), crate::value::BuiltinClosureFn::new(func)),
112 false,
113 );
114 }
115
116 pub fn register_struct(&mut self, def: HostStructDef) {
118 self.interpreter.types.register_struct(def);
119 }
120
121 pub fn register_enum(&mut self, def: HostEnumDef) {
123 self.interpreter.types.register_enum(def);
124 }
125
126 pub fn register_module(&mut self, module: Module) {
128 let name = module.name.clone();
129 let value = module.to_value();
130 self.interpreter.env.define(name, value, false);
131 }
132
133 pub fn register_type<T: IonType>(&mut self) {
135 match T::ion_type_def() {
136 IonTypeDef::Struct(def) => self.interpreter.types.register_struct(def),
137 IonTypeDef::Enum(def) => self.interpreter.types.register_enum(def),
138 }
139 }
140
141 pub fn set_typed<T: IonType>(&mut self, name: &str, value: &T) {
143 self.interpreter
144 .env
145 .define(name.to_string(), value.to_ion(), false);
146 }
147
148 pub fn get_typed<T: IonType>(&self, name: &str) -> Result<T, String> {
150 let val = self.interpreter.env.get(name).ok_or_else(|| {
151 format!(
152 "{}{}{}",
153 ion_str!("variable '"),
154 name,
155 ion_str!("' not found")
156 )
157 })?;
158 T::from_ion(val)
159 }
160
161 #[cfg(feature = "vm")]
164 pub fn vm_eval(&mut self, source: &str) -> Result<Value, IonError> {
165 let mut lexer = Lexer::new(source);
166 let tokens = lexer.tokenize()?;
167 let mut parser = Parser::new(tokens);
168 let program = parser.parse_program()?;
169
170 let compiler = crate::compiler::Compiler::new();
172 match compiler.compile_program(&program) {
173 Ok((chunk, fn_chunks)) => {
174 let mut vm = crate::vm::Vm::with_env_and_output(
175 std::mem::take(&mut self.interpreter.env),
176 Arc::clone(&self.output),
177 );
178 vm.preload_fn_chunks(fn_chunks);
180 vm.set_types(self.interpreter.types.clone());
182 let result = vm.execute(&chunk);
183 self.interpreter.env = std::mem::take(vm.env_mut());
185 result
186 }
187 Err(_) => {
188 self.interpreter.eval_program(&program)
190 }
191 }
192 }
193}
194
195impl Default for Engine {
196 fn default() -> Self {
197 Self::new()
198 }
199}