use std::collections::HashMap;
use crate::ir::{FnId, ModuleId};
use crate::ast::Spanned;
use super::expr::{MirEffectAnnotation, MirExpr};
use super::stats::LowerStats;
#[derive(Debug, Clone, Default)]
pub struct MirProgram {
pub fns: HashMap<FnId, MirFn>,
pub modules: Vec<ModuleId>,
pub stats: LowerStats,
pub builtins: Vec<String>,
pub external_callers_possible: bool,
}
impl MirProgram {
pub fn empty() -> Self {
Self::default()
}
pub fn fn_by_id(&self, id: FnId) -> Option<&MirFn> {
self.fns.get(&id)
}
pub fn iter(&self) -> impl Iterator<Item = (&FnId, &MirFn)> {
self.fns.iter()
}
pub fn builtin_name(&self, id: crate::ir::BuiltinId) -> &str {
self.builtins
.get(id.0 as usize)
.map(String::as_str)
.unwrap_or("")
}
pub fn intern_builtin(&mut self, name: &str) -> crate::ir::BuiltinId {
for (idx, existing) in self.builtins.iter().enumerate() {
if existing == name {
return crate::ir::BuiltinId(idx as u32);
}
}
let id = crate::ir::BuiltinId(self.builtins.len() as u32);
self.builtins.push(name.to_string());
id
}
}
#[derive(Debug, Clone)]
pub struct MirFn {
pub fn_id: FnId,
pub name: String,
pub params: Vec<MirParam>,
pub return_type: String,
pub effects: Vec<MirEffectAnnotation>,
pub body: Spanned<MirExpr>,
pub local_count: u32,
pub aliased_slots: std::sync::Arc<Vec<bool>>,
pub repr: MirFnRepr,
}
#[derive(Debug, Clone, Default)]
pub struct MirFnRepr {
pub bare_slots: std::collections::HashSet<LocalId>,
pub bare_params: Vec<bool>,
pub bare_return: bool,
pub carrier_slots: std::collections::HashSet<LocalId>,
}
impl MirFnRepr {
pub fn slot_is_bare(&self, slot: LocalId) -> bool {
self.bare_slots.contains(&slot)
}
pub fn slot_is_bare_carrier(&self, slot: LocalId) -> bool {
self.carrier_slots.contains(&slot)
}
pub fn param_is_bare(&self, i: usize) -> bool {
self.bare_params.get(i).copied().unwrap_or(false)
}
}
#[derive(Debug, Clone)]
pub struct MirParam {
pub local: LocalId,
pub name: String,
pub ty: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LocalId(pub u32);
impl std::fmt::Display for LocalId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "%{}", self.0)
}
}