mimium_lang/plugin/
system_plugin.rs1use super::ExtClsInfo;
8use crate::{
9 compiler::EvalStage,
10 interner::{ToSymbol, TypeNodeId},
11 interpreter::Value,
12 plugin::MacroInfo,
13 runtime::{
14 Time,
15 vm::{Machine, ReturnCode},
16 },
17};
18use std::{any::Any, cell::RefCell, rc::Rc};
19pub type SystemPluginFnType<T> = fn(&mut T, &mut Machine) -> ReturnCode;
20pub type SystemPluginMacroType<T> = fn(&mut T, &[(Value, TypeNodeId)]) -> Value;
21
22pub struct SysPluginSignature {
27 name: &'static str,
28 fun: Rc<dyn Any>,
31 ty: TypeNodeId,
32 stage: EvalStage,
36}
37impl SysPluginSignature {
38 pub fn new<F, T>(name: &'static str, fun: F, ty: TypeNodeId) -> Self
39 where
40 F: Fn(&mut T, &mut Machine) -> ReturnCode + 'static,
41 T: SystemPlugin,
42 {
43 Self {
44 name,
45 fun: Rc::new(fun),
46 ty,
47 stage: EvalStage::Stage(1),
48 }
49 }
50 pub fn new_macro<F, T>(name: &'static str, fun: F, ty: TypeNodeId) -> Self
51 where
52 F: Fn(&mut T, &[(Value, TypeNodeId)]) -> Value + 'static,
53 T: SystemPlugin,
54 {
55 Self {
56 name,
57 fun: Rc::new(fun),
58 ty,
59 stage: EvalStage::Stage(0),
60 }
61 }
62
63 pub fn get_name(&self) -> &'static str {
65 self.name
66 }
67
68 pub fn get_type(&self) -> TypeNodeId {
70 self.ty
71 }
72
73 pub fn get_stage(&self) -> EvalStage {
75 self.stage
76 }
77}
78
79pub trait SystemPlugin {
85 fn as_any_mut(&mut self) -> &mut dyn Any;
87
88 fn generate_audioworker(&mut self) -> Option<Box<dyn SystemPluginAudioWorker>> {
89 None
90 }
91 fn on_init(&mut self, _machine: &mut Machine) -> ReturnCode {
92 0
93 }
94 fn after_main(&mut self, _machine: &mut Machine) -> ReturnCode {
95 0
96 }
97
98 #[cfg(not(target_arch = "wasm32"))]
104 fn on_init_wasm(
105 &mut self,
106 _engine: &mut crate::runtime::wasm::engine::WasmEngine,
107 ) -> ReturnCode {
108 0
109 }
110
111 #[cfg(not(target_arch = "wasm32"))]
117 fn after_main_wasm(
118 &mut self,
119 _engine: &mut crate::runtime::wasm::engine::WasmEngine,
120 ) -> ReturnCode {
121 0
122 }
123
124 fn gen_interfaces(&self) -> Vec<SysPluginSignature>;
125 fn try_get_main_loop(&mut self) -> Option<Box<dyn FnOnce()>> {
126 None
127 }
128 fn freeze_audio_handle(&mut self) -> Option<Box<dyn Any + Send>> {
135 None
136 }
137
138 #[cfg(not(target_arch = "wasm32"))]
149 fn freeze_for_wasm(&mut self) -> Option<crate::runtime::wasm::WasmPluginFnMap> {
150 None
151 }
152
153 #[cfg(not(target_arch = "wasm32"))]
160 fn generate_wasm_audioworker(
161 &mut self,
162 ) -> Option<Box<dyn crate::runtime::wasm::WasmSystemPluginAudioWorker>> {
163 None
164 }
165}
166
167pub trait SystemPluginAudioWorker {
168 fn on_sample(&mut self, _time: Time, _machine: &mut Machine) -> ReturnCode {
169 0
170 }
171 fn gen_interfaces(&self) -> Vec<SysPluginSignature>;
172}
173
174pub struct DynSystemPlugin {
176 inner: Rc<RefCell<dyn SystemPlugin>>,
177 audioworker: Option<Box<dyn SystemPluginAudioWorker>>,
178 pub clsinfos: Vec<ExtClsInfo>,
179 pub macroinfos: Vec<MacroInfo>,
180}
181
182impl DynSystemPlugin {
183 pub fn take_audioworker(&mut self) -> Option<Box<dyn SystemPluginAudioWorker>> {
184 self.audioworker.take()
185 }
186 pub fn freeze_audio_handle(&mut self) -> Option<Box<dyn Any + Send>> {
190 self.inner.borrow_mut().freeze_audio_handle()
191 }
192
193 #[cfg(not(target_arch = "wasm32"))]
195 pub fn freeze_for_wasm(&mut self) -> Option<crate::runtime::wasm::WasmPluginFnMap> {
196 self.inner.borrow_mut().freeze_for_wasm()
197 }
198
199 #[cfg(not(target_arch = "wasm32"))]
201 pub fn generate_wasm_audioworker(
202 &mut self,
203 ) -> Option<Box<dyn crate::runtime::wasm::WasmSystemPluginAudioWorker>> {
204 self.inner.borrow_mut().generate_wasm_audioworker()
205 }
206
207 #[cfg(not(target_arch = "wasm32"))]
209 pub fn on_init_wasm(
210 &self,
211 engine: &mut crate::runtime::wasm::engine::WasmEngine,
212 ) -> crate::runtime::vm::ReturnCode {
213 self.inner.borrow_mut().on_init_wasm(engine)
214 }
215
216 #[cfg(not(target_arch = "wasm32"))]
218 pub fn after_main_wasm(
219 &self,
220 engine: &mut crate::runtime::wasm::engine::WasmEngine,
221 ) -> crate::runtime::vm::ReturnCode {
222 self.inner.borrow_mut().after_main_wasm(engine)
223 }
224
225 pub fn borrow_inner_mut(&self) -> std::cell::RefMut<'_, dyn SystemPlugin> {
230 self.inner.borrow_mut()
231 }
232}
233impl<T> From<T> for DynSystemPlugin
239where
240 T: SystemPlugin + Sized + 'static,
241{
242 fn from(mut plugin: T) -> Self {
243 let mut audioworker = plugin.generate_audioworker();
244
245 let ifs = plugin.gen_interfaces();
246 let inner: Rc<RefCell<dyn SystemPlugin>> = Rc::new(RefCell::new(plugin));
247 let macroinfos = ifs
248 .iter()
249 .filter(|&SysPluginSignature { stage, .. }| matches!(stage, EvalStage::Stage(0)))
250 .map(|SysPluginSignature { name, fun, ty, .. }| {
251 let inner = inner.clone();
252 let fun = fun
253 .clone()
254 .downcast::<SystemPluginMacroType<T>>()
255 .expect("invalid conversion applied in the system plugin resolution.");
256 MacroInfo::new(
257 name.to_symbol(),
258 *ty,
259 Rc::new(RefCell::new(move |args: &[(Value, TypeNodeId)]| -> Value {
260 let mut plugin_ref = inner.borrow_mut();
263 let p: &mut T = plugin_ref
264 .as_any_mut()
265 .downcast_mut::<T>()
266 .expect("plugin type mismatch");
267 fun(p, args)
268 })),
269 )
270 })
271 .collect();
272 let clsinfos = ifs
273 .into_iter()
274 .chain(
275 audioworker
276 .as_mut()
277 .map(|worker| worker.gen_interfaces())
278 .into_iter()
279 .flatten(),
280 )
281 .filter(|SysPluginSignature { stage, .. }| matches!(stage, EvalStage::Stage(1)))
282 .map(|SysPluginSignature { name, fun, ty, .. }| {
283 let inner = inner.clone();
284 let fun = fun
285 .clone()
286 .downcast::<SystemPluginFnType<T>>()
287 .expect("invalid conversion applied in the system plugin resolution.");
288 let fun = Rc::new(RefCell::new(move |machine: &mut Machine| -> ReturnCode {
289 let mut plugin_ref = inner.borrow_mut();
290 let p: &mut T = plugin_ref
291 .as_any_mut()
292 .downcast_mut::<T>()
293 .expect("plugin type mismatch");
294 fun(p, machine)
295 }));
296 ExtClsInfo::new(name.to_symbol(), ty, fun)
297 })
298 .collect();
299 DynSystemPlugin {
300 inner,
301 audioworker,
302 clsinfos,
303 macroinfos,
304 }
305 }
306}