1use crate::{Error, Identifier, Identifiers, Table};
2use smartstring::alias::String;
3use std::collections::VecDeque;
4use std::fmt;
5use std::ops::{Add, Div, Mul, Rem, Sub};
6
7#[derive(Debug, PartialEq, PartialOrd, Clone)]
8pub enum Expr {
9 Integer(i64),
10 Float(f64),
11 StringFmt(Identifiers),
12 StringRaw(String),
13 Identifier(Identifier),
14 Boolean(bool),
15 Inclusive(Box<Expr>, Box<Expr>),
16 Exclusive(Box<Expr>, Box<Expr>),
17 Array(Identifiers),
18 Table(Table),
19 Not(Box<Expr>),
20 BinOp(Box<Expr>, Op, Box<Expr>),
21 FnCall(Box<Expr>, Identifiers),
22 VarIndex(Box<Expr>, VecDeque<Expr>),
23 Impossible,
24}
25
26#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
27pub enum Op {
28 Add,
29 Sub,
30 Mul,
31 Div,
32 Pow,
33 Rem,
34 And,
35 Or,
36 In,
37 Greater,
38 Less,
39 GreaterEq,
40 LessEq,
41 Equals,
42 NotEquals,
43}
44
45impl Add for Expr {
46 type Output = Self;
47 fn add(self, by: Self) -> Self::Output {
48 match (self, by) {
49 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1 + f2),
50 (Self::Integer(i), Self::Float(f)) => Self::Float(i as f64 + f),
51 (Self::Float(f), Self::Integer(i)) => Self::Float(f + i as f64),
52 (Self::Integer(i1), Self::Integer(i2)) => Self::Integer(i1 + i2),
53 _ => Self::Impossible,
54 }
55 }
56}
57
58impl Sub for Expr {
59 type Output = Self;
60 fn sub(self, by: Self) -> Self::Output {
61 match (self, by) {
62 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1 - f2),
63 (Self::Integer(i), Self::Float(f)) => Self::Float(i as f64 - f),
64 (Self::Float(f), Self::Integer(i)) => Self::Float(f - i as f64),
65 (Self::Integer(i1), Self::Integer(i2)) => Self::Integer(i1 - i2),
66 _ => Self::Impossible,
67 }
68 }
69}
70
71impl Mul for Expr {
72 type Output = Self;
73 fn mul(self, by: Self) -> Self::Output {
74 match (self, by) {
75 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1 * f2),
76 (Self::Integer(i), Self::Float(f)) => Self::Float(i as f64 * f),
77 (Self::Float(f), Self::Integer(i)) => Self::Float(f * i as f64),
78 (Self::Integer(i1), Self::Integer(i2)) => Self::Integer(i1 * i2),
79 _ => Self::Impossible,
80 }
81 }
82}
83
84impl Div for Expr {
85 type Output = Self;
86 fn div(self, by: Self) -> Self::Output {
87 match (self, by) {
88 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1 / f2),
89 (Self::Integer(i), Self::Float(f)) => Self::Float(i as f64 / f),
90 (Self::Float(f), Self::Integer(i)) => Self::Float(f / i as f64),
91 (Self::Integer(i1), Self::Integer(i2)) => Self::Float(i1 as f64 / i2 as f64),
92 _ => Self::Impossible,
93 }
94 }
95}
96
97impl Rem for Expr {
98 type Output = Self;
99 fn rem(self, by: Self) -> Self::Output {
100 match (self, by) {
101 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1 % f2),
102 (Self::Integer(i), Self::Float(f)) => Self::Float(i as f64 % f),
103 (Self::Float(f), Self::Integer(i)) => Self::Float(f % i as f64),
104 (Self::Integer(i1), Self::Integer(i2)) => Self::Integer(i1 % i2),
105 _ => Self::Impossible,
106 }
107 }
108}
109
110impl Expr {
111 pub fn pow(self, by: Expr) -> Expr {
112 match (self, by) {
113 (Self::Float(f1), Self::Float(f2)) => Self::Float(f1.powf(f2)),
114 (Self::Integer(i), Self::Float(f)) => Self::Float((i as f64).powf(f)),
115 (Self::Float(f), Self::Integer(i)) => Self::Float(f.powf(i as f64)),
116 (Self::Integer(i1), Self::Integer(i2)) => Self::Float((i1 as f64).powf(i2 as f64)),
117 _ => Self::Impossible,
118 }
119 }
120
121 pub fn as_bool(&self) -> Result<bool, Error> {
122 if let Expr::Boolean(b) = self {
123 Ok(*b)
124 } else {
125 Err(Error::EvalNotBool)
126 }
127 }
128}
129
130impl fmt::Display for Op {
131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132 match self {
133 Op::Add => write!(f, "+"),
134 Op::Sub => write!(f, "-"),
135 Op::Mul => write!(f, "*"),
136 Op::Div => write!(f, "/"),
137 Op::Pow => write!(f, "^"),
138 Op::Rem => write!(f, "%"),
139 Op::Equals => write!(f, "=="),
140 Op::NotEquals => write!(f, "!="),
141 Op::Greater => write!(f, ">"),
142 Op::Less => write!(f, "<"),
143 Op::GreaterEq => write!(f, ">="),
144 Op::LessEq => write!(f, "<="),
145 Op::Or => write!(f, "or"),
146 Op::And => write!(f, "and"),
147 Op::In => write!(f, "in"),
148 }
149 }
150}
151
152impl fmt::Display for Expr {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 match self {
155 Expr::Integer(i) => write!(f, "{}", i),
156 Expr::Float(fl) => write!(f, "{}", fl),
157 Expr::Boolean(b) => write!(f, "{}", b),
158 Expr::Identifier(i) => write!(f, "{}", i.join(".")),
159 Expr::VarIndex(i, l) => write!(
160 f,
161 "{}{}",
162 i,
163 l.iter()
164 .map(|x| format!("[{}]", x))
165 .collect::<Vec<_>>()
166 .join("")
167 ),
168 Expr::Exclusive(s, e) => write!(f, "{}..{}", s, e),
169 Expr::Inclusive(s, e) => write!(f, "{}...{}", s, e),
170 Expr::StringRaw(s) => write!(f, "{}", s),
171 Expr::StringFmt(p) => write!(f, "{:?}", p),
172 Expr::Array(s) => write!(
173 f,
174 "[{}]",
175 s.iter()
176 .map(|i| format!("{}", i))
177 .collect::<Vec<_>>()
178 .join(", ")
179 ),
180 Expr::Table(s) => write!(f, "{}", s),
181 Expr::FnCall(i, a) => write!(
182 f,
183 "{}({})",
184 i,
185 a.iter()
186 .map(|i| format!("{}", i))
187 .collect::<Vec<_>>()
188 .join(", ")
189 ),
190 Expr::BinOp(l, o, r) => write!(f, "{} {} {}", l, o, r),
191 Expr::Not(e) => write!(f, "not {}", e),
192 _ => unreachable!(),
193 }
194 }
195}