use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Hash, Debug, Clone, PartialEq, Eq)]
pub struct SourceInfo(pub std::ops::Range<usize>);
impl SourceInfo {
pub fn range_start(&self) -> usize {
self.0.start
}
pub fn range_end(&self) -> usize {
self.0.end
}
}
#[derive(Debug, Clone)]
pub struct ASTNode<N> {
pub node: N,
pub info: SourceInfo,
}
impl<N> ASTNode<N> {
pub fn new(node: N, left: usize, right: usize) -> Self {
let info = SourceInfo(left..right);
ASTNode { node, info }
}
pub fn from_source(node: N, info: SourceInfo) -> Self {
ASTNode { node, info }
}
pub fn as_ref(&self) -> ASTNode<&N> {
ASTNode {
node: &self.node,
info: self.info.clone(),
}
}
pub fn map<D>(self, f: impl FnOnce(N) -> D) -> ASTNode<D> {
ASTNode {
node: f(self.node),
info: self.info,
}
}
pub fn into_inner(self) -> (N, SourceInfo) {
(self.node, self.info)
}
}
impl<N: PartialEq> PartialEq for ASTNode<N> {
fn eq(&self, other: &Self) -> bool {
self.node == other.node
}
}
impl<N: Eq> Eq for ASTNode<N> {}
impl<T> ASTNode<Option<T>> {
pub fn as_inner_pair(&self) -> (&SourceInfo, Option<&T>) {
(&self.info, self.node.as_ref())
}
pub fn as_inner(&self) -> Option<&T> {
self.node.as_ref()
}
pub fn collapse(&self) -> Option<ASTNode<&T>> {
self.node.as_ref().map(|node| ASTNode {
node,
info: self.info.clone(),
})
}
pub fn apply<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T, &SourceInfo) -> Option<R>,
{
f(self.node.as_ref()?, &self.info)
}
pub fn into_apply<F, R>(self, f: F) -> Option<R>
where
F: FnOnce(T, SourceInfo) -> Option<R>,
{
f(self.node?, self.info)
}
}