kodept-ast 0.4.1

Simple compiler with dependent types support in mind
Documentation
use kodept_core::{ConvertibleToMut, ConvertibleToRef};

use crate::graph::{Change, AnyNode, PermTkn, Identifiable, SyntaxTree, NodeId};

#[repr(transparent)]
pub struct Uninit<T>(T);

impl<T> Uninit<T> {
    pub fn new(value: T) -> Self {
        Self(value)
    }

    #[allow(private_bounds)]
    pub fn unwrap(self, id: NodeId<T>) -> T
        where
            T: crate::graph::Identifiable,
    {
        self.0.set_id(id);
        self.0
    }

    #[inline]
    pub fn map_into<U>(self) -> Uninit<U>
        where
            T: Into<U>,
    {
        Uninit(self.0.into())
    }
}

pub trait NodeWithParent {
    type Parent;
}

#[allow(private_bounds)]
pub trait Node: Identifiable + Into<AnyNode> {
    fn parent<'b>(&self, tree: &'b SyntaxTree, token: &'b PermTkn) -> &'b Self::Parent
    where
        Self: NodeWithParent,
        AnyNode: ConvertibleToRef<Self::Parent>,
    {
        let id = self.get_id();
        tree.parent_of(id, token)
            .expect("NodeWithParent: contract violated")
            .try_as_ref()
            .expect("Node has wrong type")
    }

    fn parent_mut<'b>(
        &self,
        tree: &'b mut SyntaxTree,
        token: &'b mut PermTkn,
    ) -> &'b mut Self::Parent
    where
        Self: NodeWithParent,
        AnyNode: ConvertibleToMut<Self::Parent>,
    {
        let id = self.get_id();
        tree.parent_of_mut(id, token)
    }

    fn replace_with(&self, other: Uninit<Self>) -> Change {
        Change::Replace {
            from_id: self.get_id().widen(),
            to: other.map_into(),
        }
    }

    fn remove(&self) -> Change {
        Change::DeleteSelf {
            node_id: self.get_id().widen(),
        }
    }
}