1pub mod ast;
4pub mod interner;
5pub mod interpreter;
6pub mod mir;
7pub mod pattern;
8pub mod types;
9pub mod utils;
10
11pub mod compiler;
12pub mod runtime;
13
14pub mod plugin;
15
16use std::path::PathBuf;
17
18use crate::plugin::{MachineFunction, MacroFunction};
19use compiler::IoChannelInfo;
20pub use log;
21use plugin::{DynSystemPlugin, ExtFunTypeInfo, Plugin, SystemPlugin};
22use runtime::vm::{self, Program, ReturnCode};
23use utils::error::ReportableError;
24
25#[derive(Debug, Clone, Copy, Default)]
34pub struct Config {
35 pub compiler: compiler::Config,
36 }
38
39pub struct ExecContext {
46 compiler: Option<compiler::Context>,
47 vm: Option<runtime::vm::Machine>,
48 plugins: Vec<Box<dyn Plugin>>,
49 sys_plugins: Vec<DynSystemPlugin>,
50 path: Option<PathBuf>,
51 config: Config,
52}
53
54impl ExecContext {
55 pub fn new(
58 plugins: impl Iterator<Item = Box<dyn Plugin>>,
59 path: Option<PathBuf>,
60 config: Config,
61 ) -> Self {
62 let plugins = plugins
63 .chain([plugin::get_builtin_fns_as_plugins()])
64 .collect::<Vec<_>>();
65
66 let sys_plugins = vec![];
67 Self {
68 compiler: None,
69 vm: None,
70 plugins,
71 sys_plugins,
72 path,
73 config,
74 }
75 }
76 pub fn add_plugin<T: Plugin + 'static>(&mut self, plug: T) {
77 self.plugins.push(Box::new(plug))
78 }
79 pub fn get_plugins(&self) -> impl ExactSizeIterator<Item = &Box<dyn Plugin>> {
80 self.plugins.iter()
81 }
82 pub fn get_system_plugins(&self) -> impl ExactSizeIterator<Item = &DynSystemPlugin> {
83 self.sys_plugins.iter()
84 }
85 pub fn add_system_plugin<T: SystemPlugin + 'static>(&mut self, plug: T) {
87 let plugin_dyn = DynSystemPlugin::from(plug);
88
89 self.sys_plugins.push(plugin_dyn)
90 }
91 pub fn get_compiler(&self) -> Option<&compiler::Context> {
92 self.compiler.as_ref()
93 }
94 pub fn take_compiler(&mut self) -> Option<compiler::Context> {
95 self.compiler.take()
96 }
97 pub fn take_vm(&mut self) -> Option<runtime::vm::Machine> {
98 self.vm.take()
99 }
100 pub fn get_vm(&self) -> Option<&runtime::vm::Machine> {
101 self.vm.as_ref()
102 }
103 pub fn get_compiler_mut(&mut self) -> Option<&mut compiler::Context> {
104 self.compiler.as_mut()
105 }
106 pub fn get_vm_mut(&mut self) -> Option<&mut runtime::vm::Machine> {
107 self.vm.as_mut()
108 }
109 fn get_extfun_types(&self) -> Vec<ExtFunTypeInfo> {
110 plugin::get_extfun_types(&self.plugins)
111 .chain(
112 self.sys_plugins
113 .iter()
114 .flat_map(|p| p.clsinfos.clone().into_iter().map(ExtFunTypeInfo::from)),
115 )
116 .collect()
117 }
118 fn get_macro_types(&self) -> Vec<Box<dyn MacroFunction>> {
119 plugin::get_macro_functions(&self.plugins)
120 .chain(self.sys_plugins.iter().flat_map(|p| {
121 p.macroinfos
122 .iter()
123 .map(|i| Box::new(i.clone()) as Box<dyn MacroFunction>)
124 }))
125 .collect()
126 }
127 pub fn prepare_compiler(&mut self) {
128 let macroinfos = plugin::get_macro_functions(&self.plugins).chain(
129 self.sys_plugins.iter().flat_map(|p| {
130 p.macroinfos
131 .iter()
132 .map(|i| Box::new(i.clone()) as Box<dyn MacroFunction>)
133 }),
134 );
135 self.compiler = Some(compiler::Context::new(
136 self.get_extfun_types(),
137 macroinfos,
138 self.path.clone(),
139 self.config.compiler,
140 ));
141 }
142 pub fn prepare_machine(&mut self, src: &str) -> Result<(), Vec<Box<dyn ReportableError>>> {
144 if self.compiler.is_none() {
145 self.prepare_compiler();
146 }
147
148 let prog = self.compiler.as_ref().unwrap().emit_bytecode(src)?;
149 self.prepare_machine_with_bytecode(prog);
150 Ok(())
151 }
152
153 pub fn prepare_machine_with_bytecode(&mut self, prog: Program) {
155 let cls =
156 plugin::get_ext_closures(&self.plugins).chain(self.sys_plugins.iter().flat_map(|p| {
157 p.clsinfos
158 .clone()
159 .into_iter()
160 .map(|c| Box::new(c) as Box<dyn MachineFunction>)
161 }));
162 let vm = vm::Machine::new(prog, [].into_iter(), cls);
163 self.vm = Some(vm);
164 }
165
166 pub fn get_iochannel_count(&self) -> Option<IoChannelInfo> {
167 self.vm.as_ref().and_then(|vm| vm.prog.iochannels)
168 }
169 pub fn run_main(&mut self) -> ReturnCode {
171 if let Some(vm) = self.vm.as_mut() {
172 self.sys_plugins.iter().for_each(|plug: &DynSystemPlugin| {
173 let p = unsafe { plug.inner.get().as_mut().unwrap_unchecked() };
175 let _ = p.on_init(vm);
176 });
177 let res = vm.execute_main();
178 self.sys_plugins.iter().for_each(|plug: &DynSystemPlugin| {
179 let p = unsafe { plug.inner.get().as_mut().unwrap_unchecked() };
181 let _ = p.after_main(vm);
182 });
183 res
184 } else {
185 0
186 }
187 }
188 pub fn try_get_main_loop(&mut self) -> Option<Box<dyn FnOnce()>> {
189 let mut mainloops = self.sys_plugins.iter_mut().filter_map(|p| {
190 let p = unsafe { p.inner.get().as_mut().unwrap_unchecked() };
191 p.try_get_main_loop()
192 });
193 let res = mainloops.next();
194 if mainloops.next().is_some() {
195 log::warn!("more than 2 main loops in system plugins found")
196 }
197 res
198 }
199}
200