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::{
19 any::Any,
20 cell::{RefCell, UnsafeCell},
21 rc::Rc,
22 sync::Arc,
23};
24pub type SystemPluginFnType<T> = fn(&mut T, &mut Machine) -> ReturnCode;
25pub type SystemPluginMacroType<T> = fn(&mut T, &[(Value, TypeNodeId)]) -> Value;
26
27pub struct SysPluginSignature {
32 name: &'static str,
33 fun: Rc<dyn Any>,
36 ty: TypeNodeId,
37 stage: EvalStage,
41}
42impl SysPluginSignature {
43 pub fn new<F, T>(name: &'static str, fun: F, ty: TypeNodeId) -> Self
44 where
45 F: Fn(&mut T, &mut Machine) -> ReturnCode + 'static,
46 T: SystemPlugin,
47 {
48 Self {
49 name,
50 fun: Rc::new(fun),
51 ty,
52 stage: EvalStage::Stage(1),
53 }
54 }
55 pub fn new_macro<F, T>(name: &'static str, fun: F, ty: TypeNodeId) -> Self
56 where
57 F: Fn(&mut T, &[(Value, TypeNodeId)]) -> Value + 'static,
58 T: SystemPlugin,
59 {
60 Self {
61 name,
62 fun: Rc::new(fun),
63 ty,
64 stage: EvalStage::Stage(0),
65 }
66 }
67}
68
69pub trait SystemPlugin {
75 fn on_init(&mut self, _machine: &mut Machine) -> ReturnCode {
76 0
77 }
78 fn after_main(&mut self, _machine: &mut Machine) -> ReturnCode {
79 0
80 }
81 fn on_sample(&mut self, _time: Time, _machine: &mut Machine) -> ReturnCode {
82 0
83 }
84 fn gen_interfaces(&self) -> Vec<SysPluginSignature>;
85 fn try_get_main_loop(&mut self) -> Option<Box<dyn FnOnce()>> {
86 None
87 }
88}
89
90#[derive(Clone)]
91pub struct DynSystemPlugin {
93 pub inner: Arc<UnsafeCell<dyn SystemPlugin>>,
94 pub clsinfos: Vec<ExtClsInfo>,
95 pub macroinfos: Vec<MacroInfo>,
96}
97impl<T> From<T> for DynSystemPlugin
103where
104 T: SystemPlugin + Sized + 'static,
105{
106 fn from(plugin: T) -> Self {
107 let ifs = plugin.gen_interfaces();
108 let inner = Arc::new(UnsafeCell::new(plugin));
109 let macroinfos = ifs
110 .iter()
111 .filter(|&SysPluginSignature { stage, .. }| matches!(stage, EvalStage::Stage(0)))
112 .map(|SysPluginSignature { name, fun, ty, .. }| {
113 let inner = inner.clone();
114 let fun = fun
115 .clone()
116 .downcast::<SystemPluginMacroType<T>>()
117 .expect("invalid conversion applied in the system plugin resolution.");
118 MacroInfo::new(
119 name.to_symbol(),
120 *ty,
121 Rc::new(RefCell::new(move |args: &[(Value, TypeNodeId)]| -> Value {
122 unsafe {
125 let p = inner.get().as_mut().unwrap();
126 fun(p, args)
127 }
128 })),
129 )
130 })
131 .collect();
132 let clsinfos = ifs
133 .into_iter()
134 .filter(|SysPluginSignature { stage, .. }| matches!(stage, EvalStage::Stage(1)))
135 .map(|SysPluginSignature { name, fun, ty, .. }| {
136 let inner = inner.clone();
137 let fun = fun
138 .clone()
139 .downcast::<SystemPluginFnType<T>>()
140 .expect("invalid conversion applied in the system plugin resolution.");
141 let fun = Rc::new(RefCell::new(move |machine: &mut Machine| -> ReturnCode {
142 unsafe {
145 let p = inner.get().as_mut().unwrap();
146 fun(p, machine)
147 }
148 }));
149 ExtClsInfo::new(name.to_symbol(), ty, fun)
150 })
151 .collect();
152
153 DynSystemPlugin {
154 inner,
155 clsinfos,
156 macroinfos,
157 }
158 }
159}