incremental 0.2.8

incremental computations, based on Jane Street's incremental
Documentation
use core::fmt;
use std::rc::Weak;

use super::{node::NodeId, NodeRef, WeakNode};
use crate::incrsan::NotObserver;
use crate::node::ErasedNode;

pub(crate) trait BindScope: fmt::Debug + NotObserver {
    fn id(&self) -> NodeId;
    fn is_valid(&self) -> bool;
    fn is_necessary(&self) -> bool;
    fn height(&self) -> i32;
    fn add_node(&self, node: WeakNode);
}

#[derive(Clone)]
pub(crate) enum Scope {
    Top,
    Bind(Weak<dyn BindScope>),
}

impl fmt::Debug for Scope {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Scope::Top => write!(f, "Scope::Top"),
            Scope::Bind(bind) => {
                let Some(bind) = bind.upgrade() else {
                    return write!(f, "Scope::Bind(weak, deallocated)");
                };
                write!(f, "Scope::Bind({:?})", bind.id())
            }
        }
    }
}

impl Scope {
    fn equals(&self, other: &Self) -> bool {
        match self {
            Scope::Top => matches!(other, Scope::Top),
            Scope::Bind(w1) => match other {
                Scope::Bind(w2) => crate::weak_thin_ptr_eq(w1, w2),
                _ => false,
            },
        }
    }
    pub(crate) fn height(&self) -> i32 {
        match self {
            Self::Top => 0,
            Self::Bind(weak) => {
                let strong = weak.upgrade().unwrap();
                strong.height()
            }
        }
    }
    pub(crate) fn is_valid(&self) -> bool {
        match self {
            Self::Top => true,
            Self::Bind(weak) => {
                let strong = weak.upgrade().unwrap();
                strong.is_valid()
            }
        }
    }
    pub(crate) fn is_necessary(&self) -> bool {
        match self {
            Self::Top => true,
            Self::Bind(weak) => {
                let strong = weak.upgrade().unwrap();
                strong.is_necessary()
            }
        }
    }
    pub(crate) fn add_node(&self, node: NodeRef) {
        assert!(node.created_in().equals(self));
        match self {
            Self::Top => {}
            Self::Bind(bind_weak) => {
                let bind = bind_weak.upgrade().unwrap();
                bind.add_node(node.weak());
            }
        }
    }
}