1use std::collections::HashMap;
2
3use crate::error::IonError;
4use crate::host_types::{HostEnumDef, HostStructDef, IonType, IonTypeDef};
5use crate::interpreter::{Interpreter, Limits};
6use crate::lexer::Lexer;
7use crate::module::Module;
8use crate::parser::Parser;
9use crate::value::Value;
10
11pub struct Engine {
13 interpreter: Interpreter,
14}
15
16impl Engine {
17 pub fn new() -> Self {
18 Self {
19 interpreter: Interpreter::new(),
20 }
21 }
22
23 pub fn eval(&mut self, source: &str) -> Result<Value, IonError> {
25 let mut lexer = Lexer::new(source);
26 let tokens = lexer.tokenize()?;
27 let mut parser = Parser::new(tokens);
28 let program = parser.parse_program()?;
29 self.interpreter.eval_program(&program)
30 }
31
32 pub fn set(&mut self, name: &str, value: Value) {
34 self.interpreter.env.define(name.to_string(), value, false);
35 }
36
37 pub fn get(&self, name: &str) -> Option<Value> {
39 self.interpreter.env.get(name).cloned()
40 }
41
42
43 pub fn get_all(&self) -> HashMap<String, Value> {
45 self.interpreter.env.top_level()
46 }
47
48 pub fn set_limits(&mut self, limits: Limits) {
50 self.interpreter.limits = limits;
51 }
52
53 pub fn register_fn(&mut self, name: &str, func: fn(&[Value]) -> Result<Value, String>) {
55 self.interpreter.env.define(
56 name.to_string(),
57 Value::BuiltinFn(name.to_string(), func),
58 false,
59 );
60 }
61
62 pub fn register_closure<F>(&mut self, name: &str, func: F)
68 where
69 F: Fn(&[Value]) -> Result<Value, String> + Send + Sync + 'static,
70 {
71 self.interpreter.env.define(
72 name.to_string(),
73 Value::BuiltinClosure(
74 name.to_string(),
75 crate::value::BuiltinClosureFn::new(func),
76 ),
77 false,
78 );
79 }
80
81 pub fn register_struct(&mut self, def: HostStructDef) {
83 self.interpreter.types.register_struct(def);
84 }
85
86 pub fn register_enum(&mut self, def: HostEnumDef) {
88 self.interpreter.types.register_enum(def);
89 }
90
91 pub fn register_module(&mut self, module: Module) {
93 let name = module.name.clone();
94 let value = module.to_value();
95 self.interpreter.env.define(name, value, false);
96 }
97
98 pub fn register_type<T: IonType>(&mut self) {
100 match T::ion_type_def() {
101 IonTypeDef::Struct(def) => self.interpreter.types.register_struct(def),
102 IonTypeDef::Enum(def) => self.interpreter.types.register_enum(def),
103 }
104 }
105
106 pub fn set_typed<T: IonType>(&mut self, name: &str, value: &T) {
108 self.interpreter
109 .env
110 .define(name.to_string(), value.to_ion(), false);
111 }
112
113 pub fn get_typed<T: IonType>(&self, name: &str) -> Result<T, String> {
115 let val = self
116 .interpreter
117 .env
118 .get(name)
119 .ok_or_else(|| format!("{}{}{}", ion_str!("variable '"), name, ion_str!("' not found")))?;
120 T::from_ion(val)
121 }
122
123 #[cfg(feature = "vm")]
126 pub fn vm_eval(&mut self, source: &str) -> Result<Value, IonError> {
127 let mut lexer = Lexer::new(source);
128 let tokens = lexer.tokenize()?;
129 let mut parser = Parser::new(tokens);
130 let program = parser.parse_program()?;
131
132 let compiler = crate::compiler::Compiler::new();
134 match compiler.compile_program(&program) {
135 Ok((chunk, fn_chunks)) => {
136 let mut vm = crate::vm::Vm::with_env(std::mem::take(&mut self.interpreter.env));
137 vm.preload_fn_chunks(fn_chunks);
139 vm.set_types(self.interpreter.types.clone());
141 crate::interpreter::register_builtins(vm.env_mut());
143 let result = vm.execute(&chunk);
144 self.interpreter.env = std::mem::take(vm.env_mut());
146 result
147 }
148 Err(_) => {
149 self.interpreter.eval_program(&program)
151 }
152 }
153 }
154}
155
156impl Default for Engine {
157 fn default() -> Self {
158 Self::new()
159 }
160}