use crate::error::Error;
use crate::nodes::*;
pub(crate) fn castNode<T: NodeType>(node: Option<Node>) -> Result<Option<Box<T>>, Error> {
match node {
None => Ok(None),
Some(node) => T::from_node(node)
.map(Some)
.map_err(|_| Error::internal("castNode of a node of the wrong type")),
}
}
pub(crate) fn castList(node: Option<Node>) -> Result<List, Error> {
match node {
None => Ok(List::new()),
Some(Node::List(list)) => Ok(list),
Some(_) => Err(Error::internal("castNode of a node that is not a List")),
}
}
pub(crate) fn pointee<T>(pointer: &Option<Box<T>>) -> Result<&T, Error> {
pointer.as_deref().ok_or_else(|| Error::internal("a NULL pointer in an action"))
}
pub(crate) fn pointee_mut<T>(pointer: &mut Option<Box<T>>) -> Result<&mut T, Error> {
pointer.as_deref_mut().ok_or_else(|| Error::internal("a NULL pointer in an action"))
}
pub(crate) fn pointer<T>(pointer: Option<Box<T>>) -> Result<Box<T>, Error> {
pointer.ok_or_else(|| Error::internal("a NULL pointer in an action"))
}
pub(crate) fn castMut<T: NodeType>(node: &mut Option<Node>) -> Result<&mut T, Error> {
node.as_mut()
.and_then(T::peek_mut)
.ok_or_else(|| Error::internal("a cast of a node of the wrong type"))
}
pub(crate) fn castRef<T: NodeType>(node: Option<&Node>) -> Result<&T, Error> {
node.and_then(T::peek).ok_or_else(|| Error::internal("a cast of a node of the wrong type"))
}
pub(crate) fn linitial(list: &List) -> Option<&Node> {
list.first().and_then(Option::as_ref)
}
pub(crate) fn lsecond(list: &List) -> Option<&Node> {
list.get(1).and_then(Option::as_ref)
}
pub(crate) fn llast(list: &List) -> Option<&Node> {
list.last().and_then(Option::as_ref)
}
pub(crate) fn list_length(list: &List) -> i32 {
i32::try_from(list.len()).unwrap_or(i32::MAX)
}
pub(crate) fn listNode(list: List) -> Option<Node> {
(!list.is_empty()).then_some(Node::List(list))
}
pub(crate) fn list_make1(x1: Option<Node>) -> List {
vec![x1]
}
pub(crate) fn list_make2(x1: Option<Node>, x2: Option<Node>) -> List {
vec![x1, x2]
}
pub(crate) fn lcons(datum: Option<Node>, mut list: List) -> List {
list.insert(0, datum);
list
}
pub(crate) fn lappend(mut list: List, datum: Option<Node>) -> List {
list.push(datum);
list
}
pub(crate) fn list_concat(mut list1: List, mut list2: List) -> List {
list1.append(&mut list2);
list1
}
pub(crate) fn elements<const N: usize>(list: List) -> [Option<Node>; N] {
let mut items = list.into_iter();
std::array::from_fn(|_| items.next().flatten())
}
pub(crate) fn change<T>(mut node: Option<Box<T>>, f: impl FnOnce(&mut T)) -> Option<Box<T>> {
if let Some(n) = node.as_mut() {
f(n);
}
node
}