mimium_lang/
plugin.rs

1//! # Plugin System for mimium
2//! In order to extend mimium's capability to communicate between host system, mimium has its own FFI system.
3//! The FFI is done through some traits in this plugin module in order to decouple dependencies(modules may depends on external crates).
4//! There are 3 types of interfaces you need to define depending on what you need.
5//!
6//! 1. **IO Plugins** Sets of instance-free external functions such as `print` and `println`. They are mostly for glue functions for host system's IO. `mimium-core` is an example of this type of module.
7//! 2. **External Unit Generator(UGen) Plugin.** If you need to define native Unit Generator, use `UGenPlugin` interface. In mimium code, you need to call higher-order function that returns instance of the UGen. You need to write small wrapper for this which simply calls object's constructor (In the future, this wrapper will be automatically implemented through proc-macro). Multiple instances may exist at the same time. `mimium-symphonia` is a example of this type of module.
8//! 3. **System Plugin**. If your plugin needs to mutate states of system-wide instance (1 plugin instance per 1 vm), you need to implement `SystemPlugin` traits. System plugin can have callbacks invoked at the important timings of the system like `on_init`, `before_on_sample` & so on. Internal synchronous event scheduler is implemented through this plugins system. `mimium-rand` is also an example of this type of module.
9
10mod builtin_functins;
11mod system_plugin;
12pub use builtin_functins::get_builtin_fns_as_plugins;
13use std::{cell::RefCell, rc::Rc};
14
15pub use system_plugin::{
16    DynSystemPlugin, SysPluginSignature, SystemPlugin, SystemPluginFnType, SystemPluginMacroType,
17};
18
19use crate::{
20    compiler::EvalStage,
21    interner::{Symbol, TypeNodeId},
22    interpreter::Value,
23    vm::{Machine, ReturnCode},
24};
25trait EvalStageT {
26    fn get_stage() -> EvalStage;
27}
28trait MacroStageT {}
29trait MachineStageT {}
30trait PersistentStageT: MacroStageT + MachineStageT {}
31trait ExternalFunction {
32    /// Declare the type signature of the external function.
33    fn get_type_info(&self) -> TypeNodeId;
34    fn get_name(&self) -> Symbol;
35    type Stage: EvalStageT;
36}
37struct MacroStage {}
38impl EvalStageT for MacroStage {
39    fn get_stage() -> EvalStage {
40        EvalStage::Stage(0)
41    }
42}
43impl MacroStageT for MacroStage {}
44struct MachineStage;
45impl EvalStageT for MachineStage {
46    fn get_stage() -> EvalStage {
47        EvalStage::Stage(1)
48    }
49}
50impl MachineStageT for MachineStage {}
51struct PersistentStage;
52impl EvalStageT for PersistentStage {
53    fn get_stage() -> EvalStage {
54        EvalStage::Persistent
55    }
56}
57impl MacroStageT for PersistentStage {}
58impl MachineStageT for PersistentStage {}
59impl PersistentStageT for PersistentStage {}
60pub type MacroFunType = Rc<RefCell<dyn Fn(&[(Value, TypeNodeId)]) -> Value>>;
61pub trait MacroFunction {
62    //name is still needed for linking program
63    fn get_name(&self) -> Symbol;
64    fn get_type(&self) -> TypeNodeId;
65    /// Main macro function. If you need to receive 2 or more arguments, you need to pass struct or tuple as the argument instead.
66    fn get_fn(&self) -> MacroFunType;
67}
68pub type ExtFunType = fn(&mut Machine) -> ReturnCode;
69pub type ExtClsType = Rc<RefCell<dyn FnMut(&mut Machine) -> ReturnCode>>;
70pub trait MachineFunction {
71    //name is still needed for linking program
72    fn get_name(&self) -> Symbol;
73    /// Main function that will be called by the machine.
74    fn get_fn(&self) -> ExtClsType;
75}
76#[derive(Clone)]
77pub struct MacroInfo {
78    pub name: Symbol,
79    pub ty: TypeNodeId,
80    pub fun: MacroFunType,
81}
82impl MacroInfo {
83    pub fn new(name: Symbol, ty: TypeNodeId, fun: MacroFunType) -> Self {
84        Self { name, ty, fun }
85    }
86}
87impl ExternalFunction for MacroInfo {
88    type Stage = MacroStage;
89    fn get_type_info(&self) -> TypeNodeId {
90        self.ty
91    }
92    fn get_name(&self) -> Symbol {
93        self.name
94    }
95}
96impl MacroFunction for MacroInfo {
97    fn get_name(&self) -> Symbol {
98        self.name
99    }
100    fn get_type(&self) -> TypeNodeId {
101        self.ty
102    }
103    fn get_fn(&self) -> MacroFunType {
104        self.fun.clone()
105    }
106}
107
108#[derive(Clone, Debug)]
109pub struct ExtFunInfo {
110    pub name: Symbol,
111    pub ty: TypeNodeId,
112    pub fun: ExtFunType,
113}
114impl ExtFunInfo {
115    pub fn new(name: Symbol, ty: TypeNodeId, fun: ExtFunType) -> Self {
116        Self { name, ty, fun }
117    }
118}
119impl ExternalFunction for ExtFunInfo {
120    type Stage = MachineStage;
121    fn get_type_info(&self) -> TypeNodeId {
122        self.ty
123    }
124    fn get_name(&self) -> Symbol {
125        self.name
126    }
127}
128impl MachineFunction for ExtFunInfo {
129    fn get_name(&self) -> Symbol {
130        self.name
131    }
132    fn get_fn(&self) -> ExtClsType {
133        Rc::new(RefCell::new(self.fun))
134    }
135}
136
137#[derive(Clone)]
138pub struct ExtClsInfo {
139    pub name: Symbol,
140    pub ty: TypeNodeId,
141    pub fun: ExtClsType,
142}
143impl ExtClsInfo {
144    pub fn new(name: Symbol, ty: TypeNodeId, fun: ExtClsType) -> Self {
145        Self { name, ty, fun }
146    }
147}
148impl From<ExtClsInfo> for ExtFunTypeInfo {
149    fn from(info: ExtClsInfo) -> Self {
150        ExtFunTypeInfo {
151            name: info.name,
152            ty: info.ty,
153            stage: MachineStage::get_stage(),
154        }
155    }
156}
157impl From<ExtFunInfo> for ExtFunTypeInfo {
158    fn from(info: ExtFunInfo) -> Self {
159        ExtFunTypeInfo {
160            name: info.name,
161            ty: info.ty,
162            stage: MachineStage::get_stage(),
163        }
164    }
165}
166impl ExternalFunction for ExtClsInfo {
167    type Stage = MachineStage;
168    fn get_type_info(&self) -> TypeNodeId {
169        self.ty
170    }
171    fn get_name(&self) -> Symbol {
172        self.name
173    }
174}
175impl MachineFunction for ExtClsInfo {
176    fn get_name(&self) -> Symbol {
177        self.name
178    }
179    fn get_fn(&self) -> ExtClsType {
180        self.fun.clone()
181    }
182}
183
184#[derive(Clone)]
185pub struct CommonFunction {
186    name: Symbol,
187    ty: TypeNodeId,
188    macro_fun: fn(&[(Value, TypeNodeId)]) -> Value,
189    fun: ExtFunType,
190}
191impl ExternalFunction for CommonFunction {
192    type Stage = PersistentStage;
193    fn get_type_info(&self) -> TypeNodeId {
194        self.ty
195    }
196    fn get_name(&self) -> Symbol {
197        self.name
198    }
199}
200impl MachineFunction for CommonFunction {
201    fn get_name(&self) -> Symbol {
202        self.name
203    }
204    fn get_fn(&self) -> ExtClsType {
205        Rc::new(RefCell::new(self.fun))
206    }
207}
208impl MacroFunction for CommonFunction {
209    fn get_name(&self) -> Symbol {
210        self.name
211    }
212    fn get_type(&self) -> TypeNodeId {
213        self.ty
214    }
215    fn get_fn(&self) -> MacroFunType {
216        Rc::new(RefCell::new(self.macro_fun))
217    }
218}
219#[derive(Clone, Copy)]
220pub struct ExtFunTypeInfo {
221    pub name: Symbol,
222    pub ty: TypeNodeId,
223    pub stage: EvalStage,
224}
225impl ExtFunTypeInfo {
226    pub fn new(name: Symbol, ty: TypeNodeId, stage: EvalStage) -> Self {
227        Self { name, ty, stage }
228    }
229}
230pub trait Plugin {
231    fn get_macro_functions(&self) -> Vec<Box<dyn MacroFunction>>;
232    fn get_ext_closures(&self) -> Vec<Box<dyn MachineFunction>>;
233
234    //limitation: if the functin contains persistent functions, you have to override this method.
235    fn get_type_infos(&self) -> Vec<ExtFunTypeInfo>;
236}
237
238#[derive(Clone)]
239pub struct InstantPlugin {
240    pub macros: Vec<MacroInfo>,
241    pub extcls: Vec<ExtClsInfo>,
242    pub commonfns: Vec<CommonFunction>,
243}
244impl Plugin for InstantPlugin {
245    // type MacroT = MacroInfo;
246    // type MachineT = ExtClsInfo;
247
248    fn get_macro_functions(&self) -> Vec<Box<dyn MacroFunction>> {
249        let macros = self
250            .macros
251            .clone()
252            .into_iter()
253            .map(|m| Box::new(m) as Box<dyn MacroFunction>);
254        let commons = self
255            .commonfns
256            .clone()
257            .into_iter()
258            .map(|c| Box::new(c) as Box<dyn MacroFunction>);
259        macros.chain(commons).collect()
260    }
261
262    fn get_ext_closures(&self) -> Vec<Box<dyn MachineFunction>> {
263        let extfns = self
264            .extcls
265            .clone()
266            .into_iter()
267            .map(|e| Box::new(e) as Box<dyn MachineFunction>);
268        let commons = self
269            .commonfns
270            .clone()
271            .into_iter()
272            .map(|c| Box::new(c) as Box<dyn MachineFunction>);
273        extfns.chain(commons).collect()
274    }
275
276    fn get_type_infos(&self) -> Vec<ExtFunTypeInfo> {
277        let macros = self
278            .macros
279            .iter()
280            .map(|m| ExtFunTypeInfo::new(m.name, m.ty, MacroStage::get_stage()));
281        let extcls = self
282            .extcls
283            .iter()
284            .map(|e| ExtFunTypeInfo::new(e.name, e.ty, MachineStage::get_stage()));
285        let commons = self
286            .commonfns
287            .iter()
288            .map(|c| ExtFunTypeInfo::new(c.name, c.ty, PersistentStage::get_stage()));
289        macros.chain(extcls).chain(commons).collect()
290    }
291}
292
293/// Todo: Make wrapper macro for auto impl `Plugin`
294pub trait UGenPlugin {
295    type InitParam;
296    type Args;
297    type Ret;
298    fn new(param: Self::InitParam) -> Self;
299    fn on_sample(&mut self, arg: Self::Args) -> Self::Ret;
300}
301// type DynUgenPlugin{}
302// pub type UGenPluginCollection(Vec<DynUGenPlugin>);
303// impl Plugin for UGenPluginCollection{}
304
305pub fn get_extfun_types(plugins: &[Box<dyn Plugin>]) -> impl Iterator<Item = ExtFunTypeInfo> + '_ {
306    plugins
307        .iter()
308        .flat_map(|plugin| plugin.get_type_infos().into_iter())
309}
310
311pub fn get_macro_functions(
312    plugins: &[Box<dyn Plugin>],
313) -> impl Iterator<Item = Box<dyn MacroFunction>> + '_ {
314    plugins
315        .iter()
316        .flat_map(|plugin| plugin.get_macro_functions().into_iter())
317}
318pub fn get_ext_closures(
319    plugins: &[Box<dyn Plugin>],
320) -> impl Iterator<Item = Box<dyn MachineFunction>> + '_ {
321    plugins
322        .iter()
323        .flat_map(|plugin| plugin.get_ext_closures().into_iter())
324}