use std::path::PathBuf;
use super::{ConstPos, Instruction, RawVal};
use crate::compiler::IoChannelInfo;
use crate::interner::TypeNodeId;
use crate::mir;
pub use mir::OpenUpValue;
use state_tree::tree::StateTreeSkeleton;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct JumpTable {
pub min: i64,
pub offsets: Vec<i16>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FuncProto {
pub nparam: usize,
pub nret: usize,
pub upindexes: Vec<OpenUpValue>,
pub bytecodes: Vec<Instruction>,
pub constants: Vec<RawVal>,
pub delay_sizes: Vec<u64>,
pub jump_tables: Vec<JumpTable>,
pub state_skeleton: StateTreeSkeleton<mir::StateType>,
}
impl Default for FuncProto {
fn default() -> Self {
Self {
nparam: 0,
nret: 0,
upindexes: Vec::new(),
bytecodes: Vec::new(),
constants: Vec::new(),
delay_sizes: Vec::new(),
jump_tables: Vec::new(),
state_skeleton: StateTreeSkeleton::FnCall(vec![]), }
}
}
impl FuncProto {
pub fn new(nparam: usize, nret: usize) -> Self {
Self {
nparam,
nret,
state_skeleton: StateTreeSkeleton::FnCall(vec![]), ..Default::default()
}
}
pub fn add_new_constant(&mut self, cval: RawVal) -> ConstPos {
self.constants.binary_search(&cval).unwrap_or_else(|_err| {
self.constants.push(cval);
self.constants.len() - 1
}) as _
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WordSize(pub u64);
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Program {
pub global_fn_table: Vec<(String, FuncProto)>,
pub ext_fun_table: Vec<(String, TypeNodeId)>,
pub global_vals: Vec<WordSize>,
pub strings: Vec<String>,
pub file_path: Option<PathBuf>,
pub iochannels: Option<IoChannelInfo>,
pub dsp_index: Option<usize>,
pub type_table: Vec<TypeNodeId>,
}
impl Program {
pub fn get_fun_index(&self, name: &str) -> Option<usize> {
self.global_fn_table
.iter()
.position(|(label, _f)| label.as_str() == name)
}
pub fn get_dsp_fn(&self) -> Option<&FuncProto> {
self.get_fun_index("dsp")
.and_then(|idx| self.global_fn_table.get(idx).map(|(_, f)| f))
}
pub fn get_dsp_state_skeleton(&self) -> Option<&StateTreeSkeleton<mir::StateType>> {
let dsp_i = self.dsp_index?;
self.global_fn_table
.get(dsp_i)
.map(|(_, f)| &f.state_skeleton)
}
pub fn add_type_to_table(&mut self, ty: TypeNodeId) -> Option<u8> {
if let Some(idx) = self.type_table.iter().position(|&t| t == ty) {
return Some(idx as u8);
}
if self.type_table.len() < 256 {
self.type_table.push(ty);
Some((self.type_table.len() - 1) as u8)
} else {
None }
}
pub fn get_type_from_table(&self, idx: u8) -> Option<TypeNodeId> {
self.type_table.get(idx as usize).copied()
}
pub fn add_new_str(&mut self, s: String) -> usize {
self.strings
.iter()
.position(|c| s == *c)
.unwrap_or_else(|| {
self.strings.push(s);
self.strings.len() - 1
})
}
}
impl std::fmt::Display for Program {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for fns in self.global_fn_table.iter() {
let _ = writeln!(f, "{}", fns.0);
let _ = writeln!(f, "nparams:{} nret: {}", fns.1.nparam, fns.1.nret);
let _ = write!(f, "upindexes: {:?} ", fns.1.upindexes);
let _ = writeln!(f, "state_skeleton: {:?}", fns.1.state_skeleton);
let _ = writeln!(f, "constants: {:?}", fns.1.constants);
let _ = writeln!(f, "jump_tables: {:?}", fns.1.jump_tables);
let _ = writeln!(f, "instructions:");
for inst in fns.1.bytecodes.iter() {
let _ = writeln!(f, " {inst}");
}
}
let _ = write!(
f,
"ext_fun:\n{:?}\n",
self.ext_fun_table
.iter()
.fold("".to_string(), |s, (f, _)| if s.is_empty() {
format!("{f}")
} else {
format!("{s}, {f}")
})
);
let _ = write!(f, "globals:\n{:?}", self.global_vals);
writeln!(
f,
"strings: {:?}",
self.strings
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
)
}
}