use std::fmt::{Display, Formatter};
use derive_more::From;
use crate::Number;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Identifier(pub String);
impl Display for Identifier {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum UnaryOp {
Plus,
Minus,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BinaryArithmeticOp {
Add,
Subtract,
Multiply,
Divide,
Modulo,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BinaryOp {
Arithmetic(BinaryArithmeticOp),
Alt,
And,
Or,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum UpdateOp {
Arithmetic(BinaryArithmeticOp),
Alt,
Modify,
Assign,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Comparator {
Eq,
Neq,
Gt,
Ge,
Lt,
Le,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Suffix {
Optional,
Iterate,
Index(Identifier),
Query(Box<Query>),
Slice(Option<Box<Query>>, Option<Box<Query>>),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum StringFragment {
String(String),
Query(Query),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ObjectBindPatternEntry {
KeyOnly(Identifier),
ValueOnly(Box<Query>, Box<BindPattern>),
KeyAndValue(Identifier, Box<BindPattern>),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum BindPattern {
Variable(Identifier),
Array(Vec<BindPattern>),
Object(Vec<ObjectBindPatternEntry>),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum FuncArg {
Variable(Identifier),
Closure(Identifier),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FuncDef {
pub name: Identifier,
pub args: Vec<FuncArg>,
pub body: Box<Query>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Term {
Constant(ConstantPrimitive),
String(Vec<StringFragment>),
Identity,
Recurse,
Suffix(Box<Term>, Suffix),
Variable(Identifier),
FunctionCall { name: Identifier, args: Vec<Query> },
Format(Identifier, Option<Vec<StringFragment>>),
Query(Box<Query>),
Unary(UnaryOp, Box<Term>),
Object(Vec<(Query, Option<Query>)>),
Array(Option<Box<Query>>),
Break(Identifier),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Query {
Term(Box<Term>),
WithFunc {
function: FuncDef,
query: Box<Query>,
},
Pipe { lhs: Box<Query>, rhs: Box<Query> },
Concat { lhs: Box<Query>, rhs: Box<Query> },
Bind {
source: Box<Term>,
patterns: Vec<BindPattern>,
body: Box<Query>,
},
Reduce {
source: Box<Term>,
pattern: BindPattern,
initial: Box<Query>,
accumulator: Box<Query>,
},
ForEach {
source: Box<Term>,
pattern: BindPattern,
initial: Box<Query>,
update: Box<Query>,
extract: Option<Box<Query>>,
},
If {
cond: Box<Query>,
positive: Box<Query>,
negative: Option<Box<Query>>,
},
Try {
body: Box<Query>,
catch: Option<Box<Query>>,
},
Label { label: Identifier, body: Box<Query> },
Operate {
lhs: Box<Query>,
operator: BinaryOp,
rhs: Box<Query>,
},
Update {
lhs: Box<Query>,
operator: UpdateOp,
rhs: Box<Query>,
},
Compare {
lhs: Box<Query>,
comparator: Comparator,
rhs: Box<Query>,
},
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ConstantPrimitive {
Null,
False,
True,
Number(Number),
String(String),
}
#[derive(Debug, Clone, Eq, PartialEq, From)]
pub enum ConstantValue {
Primitive(ConstantPrimitive),
Array(ConstantArray),
Object(ConstantObject),
}
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ConstantArray(pub Vec<ConstantValue>);
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ConstantObject(pub Vec<(String, ConstantValue)>);
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Import {
pub path: String,
pub alias: Option<Identifier>,
pub meta: Option<ConstantObject>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Program {
pub module_header: Option<ConstantObject>,
pub imports: Vec<Import>,
pub functions: Vec<FuncDef>,
pub query: Query,
}
impl From<&str> for Identifier {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}
impl From<Term> for Query {
fn from(term: Term) -> Self {
if let Term::Query(query) = term {
*query
} else {
Query::Term(Box::new(term))
}
}
}
impl From<Query> for Term {
fn from(query: Query) -> Self {
if let Query::Term(term) = query {
*term
} else {
Term::Query(Box::new(query))
}
}
}