use std::cell::{Ref, RefCell};
use std::{
collections::HashSet,
fmt::{Debug, Formatter},
hash::Hash,
};
use crate::completeness::{
Completeness, Implicit, ScopeExtPerm, UncheckedCompleteness, UserClosed,
};
use crate::label::ArrayInit;
use crate::storage::Storage;
use crate::Label;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Scope(pub usize);
impl Debug for Scope {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "#{}", self.0)
}
}
pub struct InnerScopeGraph<'sg, LABEL: Label, DATA> {
pub storage: &'sg Storage,
#[allow(clippy::type_complexity)]
pub edges: RefCell<Vec<&'sg RefCell<LABEL::Array<HashSet<Scope>>>>>, pub data: RefCell<Vec<&'sg DATA>>,
}
impl<LABEL: Label + Debug, DATA: Debug> Debug for InnerScopeGraph<'_, LABEL, DATA> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let edges = self.edges.borrow();
struct Wrapper<F>(F);
impl<F: Fn(&mut Formatter) -> std::fmt::Result> Debug for Wrapper<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0(f)
}
}
f.debug_struct("InnerScopeGraph")
.field(
"edges",
&Wrapper(|f: &mut Formatter| -> std::fmt::Result {
f.debug_list()
.entries(edges.iter().map(|i| Ref::map(i.borrow(), |i| i.as_ref())))
.finish()
}),
)
.field("data", &*self.data.borrow())
.finish()
}
}
impl<'sg, LABEL: Label, DATA> InnerScopeGraph<'sg, LABEL, DATA> {
fn new(storage: &'sg Storage) -> Self {
Self {
storage,
edges: RefCell::new(Vec::new()),
data: RefCell::new(Vec::new()),
}
}
pub fn add_scope(&self, data: DATA) -> Scope {
let id = self.data.borrow().len();
self.data.borrow_mut().push(self.storage.0.alloc(data));
self.edges.borrow_mut().push(
self.storage
.0
.alloc(RefCell::new(LABEL::Array::init_from_fn(HashSet::new))),
);
Scope(id)
}
fn get_data(&self, scope: Scope) -> &'sg DATA {
self.data.borrow()[scope.0]
}
}
impl<LABEL: Label, DATA> InnerScopeGraph<'_, LABEL, DATA> {
pub fn add_edge(&self, src: Scope, lbl: LABEL, dst: Scope) {
self.edges.borrow()[src.0].borrow_mut().as_mut()[lbl.to_usize()].insert(dst);
}
pub fn get_edges(&self, scope: Scope, lbl: LABEL) -> Vec<Scope> {
self.edges.borrow()[scope.0].borrow().as_ref()[lbl.to_usize()]
.iter()
.copied()
.collect()
}
}
pub struct ScopeGraph<'storage, LABEL: Label, DATA, CMPL> {
pub(crate) inner_scope_graph: InnerScopeGraph<'storage, LABEL, DATA>,
pub(crate) completeness: CMPL,
}
impl<LABEL: Label + Debug, DATA: Debug, CMPL: Debug> Debug for ScopeGraph<'_, LABEL, DATA, CMPL> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ScopeGraph")
.field("inner_scope_graph", &self.inner_scope_graph)
.field("completeness", &self.inner_scope_graph)
.finish()
}
}
impl<'storage, LABEL: Label, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
pub fn new(storage: &'storage Storage, completeness: CMPL) -> Self {
ScopeGraph {
inner_scope_graph: InnerScopeGraph::new(storage),
completeness,
}
}
}
impl<'sg, LABEL: Label, DATA> ScopeGraph<'sg, LABEL, DATA, UncheckedCompleteness> {
pub unsafe fn raw(storage: &'sg Storage) -> Self {
Self::new(storage, UncheckedCompleteness::new())
}
}
impl<LABEL: Label, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
CMPL: Completeness<LABEL, DATA>,
{
pub fn add_scope(&self, data: DATA) -> Scope {
let scope = self.inner_scope_graph.add_scope(data);
self.completeness
.cmpl_new_scope(&self.inner_scope_graph, scope);
scope
}
pub fn get_data(&self, scope: Scope) -> &DATA {
self.inner_scope_graph.get_data(scope)
}
pub fn get_edges(&self, src: Scope, lbl: LABEL) -> CMPL::GetEdgesResult<'_> {
self.completeness
.cmpl_get_edges(&self.inner_scope_graph, src, lbl)
}
}
impl<LABEL: Label, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
CMPL: Implicit<LABEL, DATA>,
{
pub fn add_edge(&self, src: Scope, lbl: LABEL, dst: Scope) -> CMPL::NewEdgeResult {
self.completeness
.cmpl_new_edge(&self.inner_scope_graph, src, lbl, dst)
}
pub fn add_decl(&self, src: Scope, lbl: LABEL, data: DATA) -> CMPL::NewEdgeResult {
let s_data = self.inner_scope_graph.add_scope(data);
self.completeness
.cmpl_new_complete_scope(&self.inner_scope_graph, s_data);
self.add_edge(src, lbl, s_data)
}
}
impl<LABEL: Hash + Label + Copy + Debug, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
CMPL: UserClosed<LABEL, DATA>,
{
pub fn ext_edge<'ext>(
&'ext self,
ext: &ScopeExtPerm<'ext, LABEL, DATA, CMPL>,
dst: Scope,
) -> CMPL::NewEdgeResult {
self.completeness
.cmpl_new_edge(&self.inner_scope_graph, *ext.scope(), *ext.label(), dst)
}
pub fn ext_decl<'ext>(
&'ext self,
ext: &ScopeExtPerm<'ext, LABEL, DATA, CMPL>,
data: DATA,
) -> CMPL::NewEdgeResult {
let s_data = self.inner_scope_graph.add_scope(data);
self.completeness
.cmpl_new_complete_scope(&self.inner_scope_graph, s_data);
self.ext_edge(ext, s_data)
}
}
impl<LABEL: Label, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
DATA: Default,
CMPL: Completeness<LABEL, DATA>,
{
pub fn add_scope_default(&self) -> Scope {
self.add_scope(DATA::default())
}
}