use std::{cell::Cell, mem};
use debris_common::clone_cell::CloneCell;
use debris_mir::{mir_context::MirContextId, mir_object::MirObjectId};
use elsa::FrozenMap;
use rustc_hash::FxHashMap;
use crate::{block_id::BlockId, llir_nodes::Function, ObjectRef, Runtime};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct SharedStateId(u32);
#[derive(Default)]
pub struct SharedStates {
counter: Cell<u32>,
inner: FrozenMap<SharedStateId, Box<SharedState>>,
}
impl SharedStates {
pub fn next_id(&self) -> SharedStateId {
let old_value = self.counter.get();
self.counter.set(old_value.checked_add(1).unwrap());
SharedStateId(old_value)
}
pub fn insert(&self, shared_state: SharedState) {
let id = shared_state.id;
assert!(self.inner.get(&id).is_none());
self.inner.insert(id, Box::new(shared_state));
}
pub fn get(&self, id: SharedStateId) -> Option<&SharedState> {
self.inner.get(&id)
}
}
#[derive(Debug)]
pub struct SharedState {
pub(super) id: SharedStateId,
pub(super) ancestor: Option<SharedStateId>,
pub(super) compiled_contexts: FxHashMap<MirContextId, BlockId>,
pub(super) functions: FxHashMap<BlockId, Function>,
pub(super) object_mapping: ObjectMapping,
pub(super) local_runtime: Runtime,
}
impl SharedState {
pub fn new(id: SharedStateId, ancestor: Option<SharedStateId>) -> Self {
SharedState {
id,
ancestor,
compiled_contexts: Default::default(),
functions: Default::default(),
object_mapping: Default::default(),
local_runtime: Default::default(),
}
}
#[must_use]
pub fn unify_with(&mut self, mut state: SharedState, mode: EvaluationMode) -> SharedState {
let is_monomorphization = match mode {
EvaluationMode::Full => true,
EvaluationMode::Monomorphization => false,
EvaluationMode::Check => return state,
};
self.functions.extend(mem::take(&mut state.functions));
self.local_runtime
.extend(mem::take(&mut state.local_runtime));
if is_monomorphization {
self.compiled_contexts
.extend(mem::take(&mut state.compiled_contexts));
self.object_mapping.extend(state.object_mapping.iter());
}
state
}
}
#[derive(Debug, Clone, Copy)]
pub enum EvaluationMode {
Full,
Monomorphization,
Check,
}
#[derive(Debug, Default)]
pub struct ObjectMapping {
inner: FxHashMap<MirObjectId, CloneCell<ObjectRef>>,
}
impl ObjectMapping {
pub fn get_raw(&self, id: MirObjectId) -> Option<&CloneCell<ObjectRef>> {
self.inner.get(&id)
}
pub fn insert(&mut self, id: MirObjectId, value: ObjectRef) -> Option<ObjectRef> {
self.inner.insert(id, value.into()).map(|cell| cell.get())
}
pub fn iter(&self) -> impl Iterator<Item = (MirObjectId, ObjectRef)> + '_ {
self.inner.iter().map(|(id, cell)| (*id, cell.get()))
}
}
impl Extend<(MirObjectId, ObjectRef)> for ObjectMapping {
fn extend<T: IntoIterator<Item = (MirObjectId, ObjectRef)>>(&mut self, iter: T) {
self.inner
.extend(iter.into_iter().map(|(id, obj)| (id, obj.into())));
}
}