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 get_system_plugins_mut(&mut self) -> impl ExactSizeIterator<Item = &mut DynSystemPlugin> {
86 self.sys_plugins.iter_mut()
87 }
88 pub fn add_system_plugin<T: SystemPlugin + 'static>(&mut self, plug: T) {
90 let plugin_dyn = DynSystemPlugin::from(plug);
91
92 self.sys_plugins.push(plugin_dyn)
93 }
94 pub fn get_compiler(&self) -> Option<&compiler::Context> {
95 self.compiler.as_ref()
96 }
97 pub fn take_compiler(&mut self) -> Option<compiler::Context> {
98 self.compiler.take()
99 }
100 pub fn take_vm(&mut self) -> Option<runtime::vm::Machine> {
101 self.vm.take()
102 }
103 pub fn get_vm(&self) -> Option<&runtime::vm::Machine> {
104 self.vm.as_ref()
105 }
106 pub fn get_compiler_mut(&mut self) -> Option<&mut compiler::Context> {
107 self.compiler.as_mut()
108 }
109 pub fn get_vm_mut(&mut self) -> Option<&mut runtime::vm::Machine> {
110 self.vm.as_mut()
111 }
112 fn get_extfun_types(&self) -> Vec<ExtFunTypeInfo> {
113 plugin::get_extfun_types(&self.plugins)
114 .chain(
115 self.sys_plugins
116 .iter()
117 .flat_map(|p| p.clsinfos.clone().into_iter().map(ExtFunTypeInfo::from)),
118 )
119 .collect()
120 }
121 fn get_macro_types(&self) -> Vec<Box<dyn MacroFunction>> {
122 plugin::get_macro_functions(&self.plugins)
123 .chain(self.sys_plugins.iter().flat_map(|p| {
124 p.macroinfos
125 .iter()
126 .map(|i| Box::new(i.clone()) as Box<dyn MacroFunction>)
127 }))
128 .collect()
129 }
130 pub fn prepare_compiler(&mut self) {
131 let macroinfos = plugin::get_macro_functions(&self.plugins).chain(
132 self.sys_plugins.iter().flat_map(|p| {
133 p.macroinfos
134 .iter()
135 .map(|i| Box::new(i.clone()) as Box<dyn MacroFunction>)
136 }),
137 );
138 self.compiler = Some(compiler::Context::new(
139 self.get_extfun_types(),
140 macroinfos,
141 self.path.clone(),
142 self.config.compiler,
143 ));
144 }
145 pub fn prepare_machine(&mut self, src: &str) -> Result<(), Vec<Box<dyn ReportableError>>> {
147 if self.compiler.is_none() {
148 self.prepare_compiler();
149 }
150
151 let prog = self.compiler.as_ref().unwrap().emit_bytecode(src)?;
152 self.prepare_machine_with_bytecode(prog);
153 Ok(())
154 }
155
156 pub fn prepare_machine_with_bytecode(&mut self, prog: Program) {
158 let cls =
159 plugin::get_ext_closures(&self.plugins).chain(self.sys_plugins.iter().flat_map(|p| {
160 p.clsinfos
161 .clone()
162 .into_iter()
163 .map(|c| Box::new(c) as Box<dyn MachineFunction>)
164 }));
165 let vm = vm::Machine::new(prog, [].into_iter(), cls);
166 self.vm = Some(vm);
167 }
168
169 pub fn get_iochannel_count(&self) -> Option<IoChannelInfo> {
170 self.vm.as_ref().and_then(|vm| vm.prog.iochannels)
171 }
172 pub fn run_main(&mut self) -> ReturnCode {
174 if let Some(vm) = self.vm.as_mut() {
175 self.sys_plugins.iter().for_each(|plug: &DynSystemPlugin| {
176 let p = unsafe { plug.inner.get().as_mut().unwrap_unchecked() };
178 let _ = p.on_init(vm);
179 });
180 let res = vm.execute_main();
181 self.sys_plugins.iter().for_each(|plug: &DynSystemPlugin| {
182 let p = unsafe { plug.inner.get().as_mut().unwrap_unchecked() };
184 let _ = p.after_main(vm);
185 });
186 res
187 } else {
188 0
189 }
190 }
191 pub fn try_get_main_loop(&mut self) -> Option<Box<dyn FnOnce()>> {
192 let mut mainloops = self.sys_plugins.iter_mut().filter_map(|p| {
193 let p = unsafe { p.inner.get().as_mut().unwrap_unchecked() };
194 p.try_get_main_loop()
195 });
196 let res = mainloops.next();
197 if mainloops.next().is_some() {
198 log::warn!("more than 2 main loops in system plugins found")
199 }
200 res
201 }
202}
203