use crate::{
paths::{self, Path},
shared::*,
};
use std::{
cmp::Ordering,
collections::{BTreeMap, BTreeSet},
fmt,
fmt::Debug,
};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct RefID(pub(crate) usize);
impl RefID {
pub const fn new(x: usize) -> Self {
RefID(x)
}
pub fn number(&self) -> usize {
self.0
}
}
#[derive(Clone)]
pub(crate) struct BorrowEdge<Loc: Copy, Lbl: Clone + Ord> {
pub(crate) strong: bool,
pub(crate) path: Path<Lbl>,
pub(crate) loc: Loc,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct BorrowEdges<Loc: Copy, Lbl: Clone + Ord>(
pub(crate) BTreeMap<RefID, BTreeSet<BorrowEdge<Loc, Lbl>>>,
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Ref<Loc: Copy, Lbl: Clone + Ord> {
pub(crate) borrowed_by: BorrowEdges<Loc, Lbl>,
pub(crate) borrows_from: BTreeSet<RefID>,
pub(crate) mutable: bool,
}
impl<Loc: Copy, Lbl: Clone + Ord> BorrowEdge<Loc, Lbl> {
pub(crate) fn leq(&self, other: &Self) -> bool {
self == other || (!self.strong && paths::leq(&self.path, &other.path))
}
}
impl<Loc: Copy, Lbl: Clone + Ord> BorrowEdges<Loc, Lbl> {
pub(crate) fn new() -> Self {
Self(BTreeMap::new())
}
}
impl<Loc: Copy, Lbl: Clone + Ord> Ref<Loc, Lbl> {
pub(crate) fn new(mutable: bool) -> Self {
let borrowed_by = BorrowEdges::new();
let borrows_from = BTreeSet::new();
Self {
borrowed_by,
borrows_from,
mutable,
}
}
}
impl<Loc: Copy, Lbl: Clone + Ord> BorrowEdges<Loc, Lbl> {
pub(crate) fn remap_refs(&mut self, id_map: &BTreeMap<RefID, RefID>) {
for (old, new) in id_map {
if let Some(edges) = self.0.remove(old) {
self.0.insert(*new, edges);
}
}
}
}
impl<Loc: Copy, Lbl: Clone + Ord> Ref<Loc, Lbl> {
pub(crate) fn remap_refs(&mut self, id_map: &BTreeMap<RefID, RefID>) {
self.borrowed_by.remap_refs(id_map);
remap_set(&mut self.borrows_from, id_map)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct BorrowEdgeNoLoc<'a, Lbl: Clone> {
strong: bool,
path: &'a Path<Lbl>,
}
impl<'a, Lbl: Clone + Ord> BorrowEdgeNoLoc<'a, Lbl> {
fn new<Loc: Copy>(e: &'a BorrowEdge<Loc, Lbl>) -> Self {
BorrowEdgeNoLoc {
strong: e.strong,
path: &e.path,
}
}
}
impl<Loc: Copy, Lbl: Clone + Ord> PartialEq for BorrowEdge<Loc, Lbl> {
fn eq(&self, other: &BorrowEdge<Loc, Lbl>) -> bool {
BorrowEdgeNoLoc::new(self) == BorrowEdgeNoLoc::new(other)
}
}
impl<Loc: Copy, Lbl: Clone + Ord> Eq for BorrowEdge<Loc, Lbl> {}
impl<Loc: Copy, Lbl: Clone + Ord> PartialOrd for BorrowEdge<Loc, Lbl> {
fn partial_cmp(&self, other: &BorrowEdge<Loc, Lbl>) -> Option<Ordering> {
BorrowEdgeNoLoc::new(self).partial_cmp(&BorrowEdgeNoLoc::new(other))
}
}
impl<Loc: Copy, Lbl: Clone + Ord> Ord for BorrowEdge<Loc, Lbl> {
fn cmp(&self, other: &BorrowEdge<Loc, Lbl>) -> Ordering {
BorrowEdgeNoLoc::new(self).cmp(&BorrowEdgeNoLoc::new(other))
}
}
impl<Loc: Copy, Lbl: Clone + Ord + Debug> Debug for BorrowEdge<Loc, Lbl> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
BorrowEdgeNoLoc::new(self).fmt(f)
}
}