use std::sync::Arc;
#[derive(Debug, Clone)]
pub enum Expr {
Null,
Bool(bool),
Int(i64),
Float(f64),
Str(String),
FString(Vec<FStringPart>),
Root, Current, Ident(String),
Chain(Box<Expr>, Vec<Step>),
BinOp(Box<Expr>, BinOp, Box<Expr>),
UnaryNeg(Box<Expr>),
Not(Box<Expr>),
Kind {
expr: Box<Expr>,
ty: KindType,
negate: bool,
},
Coalesce(Box<Expr>, Box<Expr>),
Object(Vec<ObjField>),
Array(Vec<ArrayElem>),
Pipeline {
base: Box<Expr>,
steps: Vec<PipeStep>,
},
ListComp {
expr: Box<Expr>,
vars: Vec<String>,
iter: Box<Expr>,
cond: Option<Box<Expr>>,
},
DictComp {
key: Box<Expr>,
val: Box<Expr>,
vars: Vec<String>,
iter: Box<Expr>,
cond: Option<Box<Expr>>,
},
SetComp {
expr: Box<Expr>,
vars: Vec<String>,
iter: Box<Expr>,
cond: Option<Box<Expr>>,
},
GenComp {
expr: Box<Expr>,
vars: Vec<String>,
iter: Box<Expr>,
cond: Option<Box<Expr>>,
},
Lambda {
params: Vec<String>,
body: Box<Expr>,
},
Let {
name: String,
init: Box<Expr>,
body: Box<Expr>,
},
IfElse {
cond: Box<Expr>,
then_: Box<Expr>,
else_: Box<Expr>,
},
GlobalCall {
name: String,
args: Vec<Arg>,
},
Cast {
expr: Box<Expr>,
ty: CastType,
},
Patch {
root: Box<Expr>,
ops: Vec<PatchOp>,
},
DeleteMark,
}
#[derive(Debug, Clone)]
pub struct PatchOp {
pub path: Vec<PathStep>,
pub val: Expr,
pub cond: Option<Expr>,
}
#[derive(Debug, Clone)]
pub enum PathStep {
Field(String),
Index(i64),
DynIndex(Expr),
Wildcard,
WildcardFilter(Box<Expr>),
Descendant(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CastType {
Int, Float, Number, Str, Bool, Array, Object, Null,
}
#[derive(Debug, Clone)]
pub enum PipeStep {
Forward(Expr),
Bind(BindTarget),
}
#[derive(Debug, Clone)]
pub enum BindTarget {
Name(String),
Obj { fields: Vec<String>, rest: Option<String> },
Arr(Vec<String>),
}
#[derive(Debug, Clone)]
pub enum FStringPart {
Lit(String),
Interp { expr: Expr, fmt: Option<FmtSpec> },
}
#[derive(Debug, Clone)]
pub enum FmtSpec {
Spec(String), Pipe(String), }
#[derive(Debug, Clone)]
pub enum ArrayElem {
Expr(Expr),
Spread(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum QuantifierKind {
First,
One,
}
#[derive(Debug, Clone)]
pub enum Step {
Field(String), OptField(String), Descendant(String), DescendAll, Index(i64), DynIndex(Box<Expr>), Slice(Option<i64>, Option<i64>), Method(String, Vec<Arg>), OptMethod(String, Vec<Arg>), InlineFilter(Box<Expr>), Quantifier(QuantifierKind), }
#[derive(Debug, Clone)]
pub enum Arg {
Pos(Expr),
Named(String, Expr),
}
#[derive(Debug, Clone)]
pub enum ObjField {
Kv { key: String, val: Expr, optional: bool, cond: Option<Expr> },
Short(String),
Dynamic { key: Expr, val: Expr },
Spread(Expr),
SpreadDeep(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add, Sub, Mul, Div, Mod,
Eq, Neq, Lt, Lte, Gt, Gte,
Fuzzy,
And, Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KindType {
Null, Bool, Number, Str, Array, Object,
}
#[derive(Debug, Clone)]
pub struct SortKey {
pub expr: Expr,
pub desc: bool,
}
impl Expr {
pub fn maybe_chain(self, steps: Vec<Step>) -> Self {
if steps.is_empty() { self } else { Expr::Chain(Box::new(self), steps) }
}
}
pub type ExprRef = Arc<Expr>;