mimium_lang/runtime/vm/
program.rs

1use std::path::PathBuf;
2
3use super::{ConstPos, Instruction, RawVal};
4use crate::compiler::IoChannelInfo;
5use crate::interner::TypeNodeId;
6use crate::mir;
7pub use mir::OpenUpValue;
8use state_tree::tree::StateTreeSkeleton;
9
10/// Function prototype definition in the bytecode program.
11
12#[derive(Debug, Clone, PartialEq)]
13pub struct FuncProto {
14    pub nparam: usize,
15    pub nret: usize,
16    pub upindexes: Vec<OpenUpValue>,
17    pub bytecodes: Vec<Instruction>,
18    pub constants: Vec<RawVal>,
19    pub delay_sizes: Vec<u64>,
20    /// StateTree skeleton information inherited from MIR for this function's state layout
21    pub state_skeleton: StateTreeSkeleton<mir::StateType>,
22}
23
24impl Default for FuncProto {
25    fn default() -> Self {
26        Self {
27            nparam: 0,
28            nret: 0,
29            upindexes: Vec::new(),
30            bytecodes: Vec::new(),
31            constants: Vec::new(),
32            delay_sizes: Vec::new(),
33            state_skeleton: StateTreeSkeleton::FnCall(vec![]), // Initialize as empty FnCall
34        }
35    }
36}
37impl FuncProto {
38    pub fn new(nparam: usize, nret: usize) -> Self {
39        Self {
40            nparam,
41            nret,
42            state_skeleton: StateTreeSkeleton::FnCall(vec![]), // Initialize as empty FnCall
43            ..Default::default()
44        }
45    }
46    /// Adds new constant to the program. Returns index in the array.
47    pub fn add_new_constant(&mut self, cval: RawVal) -> ConstPos {
48        self.constants.binary_search(&cval).unwrap_or_else(|_err| {
49            self.constants.push(cval);
50            self.constants.len() - 1
51        }) as _
52    }
53}
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub struct WordSize(pub u64);
56/// Complete bytecode programs.
57#[derive(Debug, Default, Clone, PartialEq)]
58pub struct Program {
59    pub global_fn_table: Vec<(String, FuncProto)>,
60    pub ext_fun_table: Vec<(String, TypeNodeId)>,
61    pub global_vals: Vec<WordSize>,
62    pub strings: Vec<String>,
63    pub file_path: Option<PathBuf>,
64    pub iochannels: Option<IoChannelInfo>,
65    //hold absolute index of dsp function because the symbol interner can't be used in the audio thread
66    pub dsp_index: Option<usize>,
67}
68impl Program {
69    pub fn get_fun_index(&self, name: &str) -> Option<usize> {
70        self.global_fn_table
71            .iter()
72            .position(|(label, _f)| label.as_str() == name)
73    }
74    pub fn get_dsp_fn(&self) -> Option<&FuncProto> {
75        self.get_fun_index("dsp")
76            .and_then(|idx| self.global_fn_table.get(idx).map(|(_, f)| f))
77    }
78
79    /// Get the StateTreeSkeleton for the dsp function (commonly used for audio processing)
80    pub fn get_dsp_state_skeleton(&self) -> Option<&StateTreeSkeleton<mir::StateType>> {
81        let dsp_i = self.dsp_index?;
82        self.global_fn_table
83            .get(dsp_i)
84            .map(|(_, f)| &f.state_skeleton)
85    }
86    pub fn add_new_str(&mut self, s: String) -> usize {
87        self.strings
88            .iter()
89            .position(|c| s == *c)
90            .unwrap_or_else(|| {
91                self.strings.push(s);
92                self.strings.len() - 1
93            })
94    }
95}
96
97impl std::fmt::Display for Program {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        for fns in self.global_fn_table.iter() {
100            let _ = writeln!(f, "{}", fns.0);
101            let _ = writeln!(f, "nparams:{} nret: {}", fns.1.nparam, fns.1.nret);
102            let _ = write!(f, "upindexes: {:?}  ", fns.1.upindexes);
103            let _ = writeln!(f, "state_skeleton: {:?}", fns.1.state_skeleton);
104            let _ = writeln!(f, "constants:  {:?}", fns.1.constants);
105            let _ = writeln!(f, "instructions:");
106            for inst in fns.1.bytecodes.iter() {
107                let _ = writeln!(f, "  {}", inst);
108            }
109        }
110        let _ = write!(
111            f,
112            "ext_fun:\n{:?}\n",
113            self.ext_fun_table
114                .iter()
115                .fold("".to_string(), |s, (f, _)| if s.is_empty() {
116                    format!("{f}")
117                } else {
118                    format!("{s}, {f}")
119                })
120        );
121        let _ = write!(f, "globals:\n{:?}", self.global_vals);
122        writeln!(
123            f,
124            "strings:  {:?}",
125            self.strings
126                .iter()
127                .map(|s| s.to_string())
128                .collect::<Vec<_>>()
129        )
130    }
131}