use crate::filter::Filter;
use crate::Spanned;
use alloc::{string::String, vec::Vec};
use core::ops::Deref;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Call<A = Arg, N = String> {
pub name: N,
pub args: Vec<A>,
}
impl<A, N> Call<A, N> {
pub fn map_args<B>(self, f: impl FnMut(A) -> B) -> Call<B, N> {
Call {
name: self.name,
args: self.args.into_iter().map(f).collect(),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Def<Rhs = Main> {
pub lhs: Call,
pub rhs: Rhs,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Arg<V = String, F = V> {
Var(V),
Fun(F),
}
impl<T> Arg<T, T> {
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Arg<U, U> {
match self {
Self::Var(x) => Arg::Var(f(x)),
Self::Fun(x) => Arg::Fun(f(x)),
}
}
}
impl<V, F> Arg<V, F> {
pub fn as_ref(&self) -> Arg<&V, &F> {
match self {
Self::Var(x) => Arg::Var(x),
Self::Fun(x) => Arg::Fun(x),
}
}
}
impl<V: Deref, F: Deref> Arg<V, F> {
pub fn as_deref(&self) -> Arg<&<V as Deref>::Target, &<F as Deref>::Target> {
match self {
Self::Var(x) => Arg::Var(x),
Self::Fun(x) => Arg::Fun(x),
}
}
}
impl<V, F> Arg<V, F> {
pub fn new_var(name: V) -> Self {
Self::Var(name)
}
pub fn new_filter(name: F) -> Self {
Self::Fun(name)
}
pub fn is_var(&self) -> bool {
matches!(self, Self::Var(_))
}
}
impl<V: Deref, F: Deref> Arg<V, F> {
pub fn get_var(&self) -> Option<&<V as Deref>::Target> {
match self {
Self::Var(v) => Some(v),
Self::Fun(_) => None,
}
}
pub fn get_filter(&self) -> Option<&<F as Deref>::Target> {
match self {
Self::Var(_) => None,
Self::Fun(f) => Some(f),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Main<F = Filter> {
pub defs: Vec<Def<Self>>,
pub body: Spanned<F>,
}