use crate::{Call, MathOp, OrdOp, Path, Span, Spanned, Str};
use alloc::{boxed::Box, string::String, vec::Vec};
use core::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum AssignOp {
Assign,
Update,
UpdateWith(MathOp),
}
impl fmt::Display for AssignOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Assign => "=".fmt(f),
Self::Update => "|=".fmt(f),
Self::UpdateWith(op) => write!(f, "{op}="),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum BinaryOp {
Pipe(Option<String>),
Comma,
Alt,
Or,
And,
Math(MathOp),
Assign(AssignOp),
Ord(OrdOp),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum KeyVal<T> {
Filter(T, T),
Str(Str<T>, Option<T>),
}
impl<F> KeyVal<F> {
pub fn map<G>(self, mut f: impl FnMut(F) -> G) -> KeyVal<G> {
match self {
Self::Filter(k, v) => KeyVal::Filter(f(k), f(v)),
Self::Str(k, v) => KeyVal::Str(k.map(&mut f), v.map(f)),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Fold<F> {
pub xs: F,
pub x: String,
pub init: F,
pub f: F,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug)]
pub enum FoldType {
Reduce,
For,
Foreach,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum Filter<C = String, V = String, Num = String> {
Call(C, Vec<Spanned<Self>>),
Var(V),
Num(Num),
Str(Box<Str<Spanned<Self>>>),
Array(Option<Box<Spanned<Self>>>),
Object(Vec<KeyVal<Spanned<Self>>>),
Id,
Path(Box<Spanned<Self>>, Path<Self>),
Ite(
Vec<(Spanned<Self>, Spanned<Self>)>,
Option<Box<Spanned<Self>>>,
),
Fold(FoldType, Fold<Box<Spanned<Self>>>),
TryCatch(Box<Spanned<Self>>, Option<Box<Spanned<Self>>>),
Try(Box<Spanned<Self>>),
Neg(Box<Spanned<Self>>),
Recurse,
Binary(Box<Spanned<Self>>, BinaryOp, Box<Spanned<Self>>),
}
impl From<Str<Spanned<Self>>> for Filter {
fn from(s: Str<Spanned<Self>>) -> Self {
Self::Str(Box::new(s))
}
}
impl From<Call<Spanned<Self>>> for Filter {
fn from(c: Call<Spanned<Self>>) -> Self {
Self::Call(c.name, c.args)
}
}
impl Filter {
pub fn binary(a: Spanned<Self>, op: BinaryOp, b: Spanned<Self>) -> Spanned<Self> {
let span = a.1.start..b.1.end;
(Self::Binary(Box::new(a), op, Box::new(b)), span)
}
pub fn path(f: Spanned<Self>, path: Path<Self>, span: Span) -> Spanned<Self> {
if path.is_empty() {
f
} else {
(Self::Path(Box::new(f), path), span)
}
}
}