1use std::fmt;
4
5use super::expression::{BExpression, Expression};
6use super::return_value::{LabelSetOp, ReturnKind, ReturnValue};
7use super::misc::Span;
8
9#[derive(Debug, PartialEq, Eq, Copy, Clone)]
11pub enum OperatorKind {
12 Power,
13 Multiply, Divide, Modulo,
14 Add, Subtract,
15 Equal, NotEqual,
16 LessThan, LessThanEqual,
17 GreaterThan, GreaterThanEqual,
18 And, Unless, Or
19}
20
21impl OperatorKind {
22 pub fn as_str(self) -> &'static str {
23 use OperatorKind::*;
24 match self {
25 Power => "^",
26 Multiply => "*",
27 Divide => "/",
28 Modulo => "%",
29 Add => "+",
30 Subtract => "-",
31 Equal => "==",
32 NotEqual => "!=",
33 LessThan => "<",
34 LessThanEqual => "<=",
35 GreaterThan => ">",
36 GreaterThanEqual => ">=",
37 And => "and",
38 Unless => "unless",
39 Or => "or"
40 }
41 }
42}
43
44impl fmt::Display for OperatorKind {
45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 write!(f, "{}", self.as_str())
47 }
48}
49
50#[derive(Debug, PartialEq, Eq, Clone)]
52pub enum MatchingGroupOp {
53 Left,
54 Right
55}
56
57impl fmt::Display for MatchingGroupOp {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 match self {
60 MatchingGroupOp::Left => write!(f, "group_left"),
61 MatchingGroupOp::Right => write!(f, "group_right")
62 }
63 }
64}
65
66#[derive(Debug, PartialEq, Eq, Clone)]
68pub struct MatchingGroup {
69 pub op: MatchingGroupOp,
71
72 pub labels: Vec<String>,
75
76 pub span: Option<Span>
77}
78
79impl MatchingGroup {
80 pub fn new(op: MatchingGroupOp) -> Self {
81 MatchingGroup {
82 op,
83 labels: vec![],
84 span: None
85 }
86 }
87
88 pub fn left() -> Self {
90 MatchingGroup::new(MatchingGroupOp::Left)
91 }
92
93 pub fn right() -> Self {
95 MatchingGroup::new(MatchingGroupOp::Right)
96 }
97
98 pub fn op(mut self, op: MatchingGroupOp) -> Self {
100 self.op = op;
101 self
102 }
103
104 pub fn label<S: Into<String>>(mut self, label: S) -> Self {
106 self.labels.push(label.into());
107 self
108 }
109
110 pub fn labels(mut self, labels: &[&str]) -> Self {
112 self.labels = labels.iter().map(|l| (*l).to_string()).collect();
113 self
114 }
115
116 pub fn clear_labels(mut self) -> Self {
118 self.labels.clear();
119 self
120 }
121
122 pub fn span<S: Into<Span>>(mut self, span: S) -> Self {
123 self.span = Some(span.into());
124 self
125 }
126}
127
128impl fmt::Display for MatchingGroup {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130 write!(f, "{}", self.op)?;
131
132 if !self.labels.is_empty() {
133 write!(f, "(")?;
134
135 for (i, label) in self.labels.iter().enumerate() {
136 if i > 0 {
137 write!(f, ", ")?;
138 }
139
140 write!(f, "{}", label)?;
141 }
142
143 write!(f, ")")?;
144 }
145
146 Ok(())
147 }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone)]
152pub enum MatchingOp {
153 On,
154 Ignoring
155}
156
157impl fmt::Display for MatchingOp {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 match self {
160 MatchingOp::On => write!(f, "on"),
161 MatchingOp::Ignoring => write!(f, "ignoring")
162 }
163 }
164}
165
166#[derive(Debug, PartialEq, Eq, Clone)]
168pub struct Matching {
169 pub op: MatchingOp,
170
171 pub labels: Vec<String>,
173
174 pub group: Option<MatchingGroup>,
176
177 pub span: Option<Span>
178}
179
180impl Matching {
181 pub fn new(op: MatchingOp) -> Self {
182 Matching {
183 op,
184 labels: vec![],
185 group: None,
186 span: None
187 }
188 }
189
190 pub fn on() -> Self {
192 Matching::new(MatchingOp::On)
193 }
194
195 pub fn ignoring() -> Self {
197 Matching::new(MatchingOp::Ignoring)
198 }
199
200 pub fn op(mut self, op: MatchingOp) -> Self {
202 self.op = op;
203 self
204 }
205
206 pub fn label<S: Into<String>>(mut self, label: S) -> Self {
208 self.labels.push(label.into());
209 self
210 }
211
212 pub fn labels(mut self, labels: &[&str]) -> Self {
214 self.labels = labels.iter().map(|l| (*l).to_string()).collect();
215 self
216 }
217
218 pub fn clear_labels(mut self) -> Self {
220 self.labels.clear();
221 self
222 }
223
224 pub fn group(mut self, group: MatchingGroup) -> Self {
226 self.group = Some(group);
227 self
228 }
229
230 pub fn clear_group(mut self) -> Self {
232 self.group = None;
233 self
234 }
235
236 pub fn span<S: Into<Span>>(mut self, span: S) -> Self {
237 self.span = Some(span.into());
238 self
239 }
240}
241
242impl fmt::Display for Matching {
243 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244 write!(f, "{}(", self.op)?;
245
246 for (i, label) in self.labels.iter().enumerate() {
247 if i > 0 {
248 write!(f, ", ")?;
249 }
250
251 write!(f, "{}", label)?;
252 }
253
254 write!(f, ")")?;
255
256 if let Some(group) = &self.group {
257 write!(f, " {}", group)?;
258 }
259
260 Ok(())
261 }
262}
263
264#[derive(Debug, PartialEq, Clone)]
273pub struct Operator {
274 pub kind: OperatorKind,
276
277 pub lhs: BExpression,
279
280 pub rhs: BExpression,
282
283 pub matching: Option<Matching>,
285
286 pub span: Option<Span>
287}
288
289impl Operator {
290 pub fn new(kind: OperatorKind, lhs: Expression, rhs: Expression) -> Self {
291 Operator {
292 kind,
293 lhs: Box::new(lhs),
294 rhs: Box::new(rhs),
295 matching: None,
296 span: None
297 }
298 }
299
300 pub fn matching(mut self, matching: Matching) -> Self {
302 self.matching = Some(matching);
303 self
304 }
305
306 pub fn clear_matching(mut self) -> Self {
308 self.matching = None;
309 self
310 }
311
312 pub fn span<S: Into<Span>>(mut self, span: S) -> Self {
313 self.span = Some(span.into());
314 self
315 }
316
317 pub fn wrap(self) -> Expression {
319 Expression::Operator(self)
320 }
321
322 pub fn return_value(&self) -> ReturnValue {
323 let lhs_ret = self.lhs.return_value();
328 let rhs_ret = self.rhs.return_value();
329
330 if !lhs_ret.kind.is_operator_valid() {
332 return ReturnValue::unknown(
333 format!("lhs return type ({:?}) is not valid in an operator", &lhs_ret.kind),
334 self.clone().wrap()
335 );
336 }
337
338 if !rhs_ret.kind.is_operator_valid() {
339 return ReturnValue::unknown(
340 format!("rhs return type ({:?}) is not valid in an operator", &rhs_ret.kind),
341 self.clone().wrap()
342 );
343 }
344
345 let kind;
346 let mut label_ops;
347
348 if lhs_ret.kind.is_scalar() && rhs_ret.kind.is_scalar() {
349 kind = ReturnKind::Scalar;
351 label_ops = vec![LabelSetOp::clear(self.clone().wrap(), self.span)];
352 } else if lhs_ret.kind.is_scalar() {
353 kind = ReturnKind::InstantVector;
355 label_ops = rhs_ret.label_ops;
356 } else if rhs_ret.kind.is_scalar() {
357 kind = ReturnKind::InstantVector;
359 label_ops = lhs_ret.label_ops;
360 } else {
361 kind = ReturnKind::InstantVector;
362
363 if let Some(matching) = &self.matching {
370 if let Some(group) = &matching.group {
371 match &group.op {
372 MatchingGroupOp::Left => label_ops = lhs_ret.label_ops,
373 MatchingGroupOp::Right => label_ops = rhs_ret.label_ops
374 };
375
376 label_ops.push(LabelSetOp::append(
380 self.clone().wrap(),
381 group.span,
382 group.labels.iter().cloned().collect(),
383 ));
384 } else {
385 label_ops = lhs_ret.label_ops;
386 }
387 } else {
388 label_ops = lhs_ret.label_ops;
389 }
390 };
391
392 ReturnValue { kind, label_ops }
393 }
394}
395
396impl fmt::Display for Operator {
397 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
398 write!(f, "{} {}", self.lhs, self.kind)?;
399
400 if let Some(matching) = &self.matching {
401 write!(f, " {}", matching)?;
402 }
403
404 write!(f, " {}", self.rhs)?;
405
406 Ok(())
407 }
408}