raw
1#![allow(
2 clippy::todo,
3 clippy::cast_precision_loss,
4 clippy::unnecessary_cast,
5 trivial_casts
6)]
7
8use std::{borrow::Cow, collections::BTreeMap};
9
10use camino::Utf8Path;
11use chumsky::span::SimpleSpan;
12use jiff::{SignedDuration, civil::DateTime};
13
14use crate::filter::ast::{BinOp, Expr, UnOp};
15
16macro_rules! bast {
17 ($name:ident: f64 ) => {
18 if $name { 1.0 } else { 0.0 }
19 };
20 ($name:ident: i64 ) => {
21 if $name { 1 } else { 0 }
22 };
23}
24
25#[derive(Debug, PartialEq)]
26struct TypeError {
27 kind: ErrorKind,
28 pos: SimpleSpan,
29}
30
31#[derive(Debug, PartialEq)]
32enum ErrorKind {}
33
34#[derive(Debug, PartialEq)]
35struct Array<'r> {
36 scope: Vec<ScopeEntry<'r>>,
37}
38
39impl<'r> Array<'r> {
40 fn push<E: Into<ScopeEntry<'r>>>(&mut self, entry: E) {
41 self.scope.push(entry.into());
42 }
43}
44
45impl<'r> From<Array<'r>> for ScopeEntry<'r> {
46 fn from(value: Array<'r>) -> Self {
47 Self::Array(value)
48 }
49}
50
51#[derive(Debug, PartialEq)]
52struct Object<'r> {
53 scope: BTreeMap<&'r str, ScopeEntry<'r>>,
54}
55
56impl<'r> Object<'r> {
57 fn insert<E: Into<ScopeEntry<'r>>>(&mut self, ident: &'r str, entry: E) {
58 self.scope.insert(ident, entry.into());
59 }
60}
61
62impl<'r> From<Object<'r>> for ScopeEntry<'r> {
63 fn from(value: Object<'r>) -> Self {
64 Self::Object(value)
65 }
66}
67
68type Date = DateTime;
69type Duration = SignedDuration;
70
71#[derive(Debug, PartialEq)]
72struct File<'r> {
73 path: &'r Utf8Path,
74 creation_time: DateTime,
75 mondified_time: DateTime,
76}
77
78#[derive(Debug, PartialEq)]
79enum Value<'r, 'vm> {
80 Null,
81 Bool(bool),
82 Integer(i64),
83 Decimal(f64),
84 String(Cow<'r, str>),
85 Array(&'vm Array<'r>),
86 Object(&'vm Object<'r>),
87 Date(Date),
88 Duration(Duration),
89 Link(),
90 File(),
91}
92
93impl<'r, 'vm> Value<'r, 'vm> {
94 #[must_use]
95 const fn is_bool(&self) -> bool {
96 matches!(self, Self::Bool(..))
97 }
98
99 #[must_use]
100 const fn is_integer(&self) -> bool {
101 matches!(self, Self::Integer(..))
102 }
103
104 #[must_use]
105 const fn is_decimal(&self) -> bool {
106 matches!(self, Self::Decimal(..))
107 }
108
109 fn as_string(&self) -> Result<Cow<'r, str>, TypeError> {
110 if let Value::String(str) = self {
111 return Ok(str.clone());
112 }
113
114 todo!()
115 }
116
117 fn into_bool(self) -> Result<Self, TypeError> {
118 match self {
119 Value::Null => todo!(),
120 Value::Bool(value) => Ok(Value::Bool(value)),
121 Value::Integer(value) => Ok(Value::Bool(value != 0)),
122 Value::Decimal(value) => Ok(Value::Bool(value != 0.0)),
123 _ => todo!(),
124 }
125 }
126
127 fn into_integer(self) -> Result<Self, TypeError> {
128 match self {
129 Value::Null => todo!(),
130 Value::Bool(value) => Ok(Value::Integer(bast!(value: i64))),
131 Value::Integer(value) => Ok(Value::Integer(value)),
132 Value::Decimal(value) => Ok(Value::Integer(value.round() as i64)),
133 _ => todo!(),
134 }
135 }
136
137 fn into_decimal(self) -> Result<Self, TypeError> {
138 match self {
139 Value::Null => todo!(),
140 Value::Bool(value) => Ok(Value::Decimal(bast!(value: f64))),
141 Value::Integer(value) => Ok(Value::Decimal(value as f64)),
142 Value::Decimal(value) => Ok(Value::Decimal(value)),
143 _ => todo!(),
144 }
145 }
146
147 fn into_string(self) -> Result<Self, TypeError> {
148 match self {
149 Value::Null => todo!(),
150 Value::Bool(value) => Ok(Value::Bool(value)),
151 Value::Integer(value) => Ok(Value::String(Cow::from(format!("{value}")))),
152 Value::Decimal(value) => Ok(Value::String(Cow::from(format!("{value}")))),
153 Value::String(value) => Ok(Value::String(value)),
154 _ => todo!(),
155 }
156 }
157}
158
159#[derive(Debug, PartialEq)]
160enum ScopeEntry<'r> {
161 Bool(bool),
162 Integer(i64),
163 Decimal(f64),
164 String(&'r str),
165 Array(Array<'r>),
166 Object(Object<'r>),
167 Function(),
168}
169
170struct Vm<'r> {
171 scope: BTreeMap<&'r str, ScopeEntry<'r>>,
172 fallback: Option<&'r str>,
173}
174
175impl<'r> Vm<'r> {
176 const fn new() -> Self {
177 Self {
178 scope: BTreeMap::new(),
179 fallback: None,
180 }
181 }
182
183 fn add_scope<E: Into<ScopeEntry<'r>>>(&mut self, ident: &'r str, entry: E) {
184 self.scope.insert(ident, entry.into());
185 }
186
187 const fn set_fallback(&mut self, ident: &'r str) {
188 self.fallback = Some(ident);
189 }
190
191 fn eval<'vm, 'src: 'r>(&'vm self, expr: &Expr<'src>) -> Result<Value<'r, 'vm>, TypeError> {
192 match expr {
193 Expr::Ident(ident) => {
194 let entry = match (self.scope.get(ident.0.as_ref()), self.fallback.as_ref()) {
195 (Some(entry), _) => Some(entry),
196 (None, Some(fallback)) => self.scope.get(fallback),
197 (None, None) => return Ok(Value::Null),
198 };
199
200 if let Some(entry) = entry {
201 return match entry {
202 ScopeEntry::Bool(value) => Ok(Value::Bool(*value)),
203 ScopeEntry::Integer(value) => Ok(Value::Integer(*value)),
204 ScopeEntry::Decimal(value) => Ok(Value::Decimal(*value)),
205 ScopeEntry::String(value) => Ok(Value::String(Cow::from(*value))),
206 ScopeEntry::Array(value) => Ok(Value::Array(value)),
207 ScopeEntry::Object(value) => Ok(Value::Object(value)),
208 ScopeEntry::Function() => todo!(),
209 };
210 }
211
212 Ok(Value::Null)
213 }
214 Expr::Bool(value) => Ok(Value::Bool(*value)),
215 Expr::Integer(value) => Ok(Value::Integer(*value)),
216 Expr::Decimal(value) => Ok(Value::Decimal(*value)),
217 Expr::String(value) => Ok(Value::String(value.clone())),
218 Expr::Function(ident, params) => {
219 let ident = self.eval(&ident.inner)?;
220 let params = params
221 .inner
222 .iter()
223 .map(|param| self.eval(¶m.inner))
224 .collect::<Result<Vec<_>, _>>()?;
225
226 todo!()
227 }
228 Expr::Method(object, ident, params) => {
229 let object = self.eval(&object.inner)?;
230 let params = params
231 .inner
232 .iter()
233 .map(|param| self.eval(¶m.inner))
234 .collect::<Result<Vec<_>, _>>()?;
235
236 match object {
237 Value::Array(object) => todo!(),
238 Value::Object(object) => todo!(),
239 _ => todo!(),
240 }
241 }
242 Expr::Member(object, ident) => {
243 let object = self.eval(&object.inner)?;
244
245 match object {
246 Value::Array(object) => todo!(),
247 Value::Object(object) => todo!(),
248 _ => todo!(),
249 }
250 }
251 Expr::Index(ident, index) => {
252 let ident = self.eval(&ident.inner)?;
253
254 match ident {
255 Value::Array(object) => todo!(),
256 Value::Object(object) => todo!(),
257 _ => todo!(),
258 }
259 }
260 Expr::BinOp(op, lhs, rhs) => {
262 let lhs = self.eval(&lhs.inner)?;
263 let rhs = self.eval(&rhs.inner)?;
264
265 match op.inner {
266 BinOp::Add => match lhs {
267 Value::Bool(lhs) => match rhs {
268 Value::Bool(rhs) => {
269 Ok(Value::Integer(bast!(lhs: i64) + bast!(rhs: i64)))
270 }
271 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) + rhs)),
272 Value::Decimal(rhs) => Ok(Value::Decimal(bast!(lhs: f64) + rhs)),
273 _ => todo!(),
274 },
275 Value::Integer(lhs) => match rhs {
276 Value::Bool(rhs) => Ok(Value::Integer(lhs + bast!(rhs: i64))),
277 Value::Integer(rhs) => Ok(Value::Integer(lhs + rhs)),
278 Value::Decimal(rhs) => Ok(Value::Decimal(lhs as f64 + rhs)),
279 _ => todo!(),
280 },
281 Value::Decimal(lhs) => match rhs {
282 Value::Bool(rhs) => Ok(Value::Decimal(lhs + bast!(rhs: f64))),
283 Value::Integer(rhs) => Ok(Value::Decimal(lhs + rhs as f64)),
284 Value::Decimal(rhs) => Ok(Value::Decimal(lhs + rhs)),
285 _ => todo!(),
286 },
287 Value::String(lhs) => match rhs {
288 Value::Bool(rhs) => Ok(Value::String(Cow::from(format!("{lhs}{rhs}")))),
289 Value::Integer(rhs) => {
290 Ok(Value::String(Cow::from(format!("{lhs}{rhs}"))))
291 }
292 Value::Decimal(rhs) => {
293 Ok(Value::String(Cow::from(format!("{lhs}{rhs}"))))
294 }
295 Value::String(rhs) => {
296 Ok(Value::String(Cow::from(format!("{lhs}{rhs}"))))
297 }
298 _ => todo!(),
299 },
300 _ => todo!(),
301 },
302 BinOp::Sub => match lhs {
303 Value::Bool(lhs) => match rhs {
304 Value::Bool(rhs) => {
305 Ok(Value::Integer(bast!(lhs: i64) - bast!(rhs: i64)))
306 }
307 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) - rhs)),
308 Value::Decimal(rhs) => Ok(Value::Decimal(bast!(lhs: f64) - rhs)),
309 _ => todo!(),
310 },
311 Value::Integer(lhs) => match rhs {
312 Value::Bool(rhs) => Ok(Value::Integer(lhs - bast!(rhs: i64))),
313 Value::Integer(rhs) => Ok(Value::Integer(lhs - rhs)),
314 Value::Decimal(rhs) => Ok(Value::Decimal(lhs as f64 - rhs)),
315 _ => todo!(),
316 },
317 Value::Decimal(lhs) => match rhs {
318 Value::Bool(rhs) => Ok(Value::Decimal(lhs - bast!(rhs: f64))),
319 Value::Integer(rhs) => Ok(Value::Decimal(lhs - rhs as f64)),
320 Value::Decimal(rhs) => Ok(Value::Decimal(lhs - rhs)),
321 _ => todo!(),
322 },
323 _ => todo!(),
324 },
325 BinOp::Mul => match lhs {
326 Value::Bool(lhs) => match rhs {
327 Value::Bool(rhs) => {
328 Ok(Value::Integer(bast!(lhs: i64) * bast!(rhs: i64)))
329 }
330 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) * rhs)),
331 Value::Decimal(rhs) => Ok(Value::Decimal(bast!(lhs: f64) * rhs)),
332 _ => todo!(),
333 },
334 Value::Integer(lhs) => match rhs {
335 Value::Bool(rhs) => Ok(Value::Integer(lhs * bast!(rhs: i64))),
336 Value::Integer(rhs) => Ok(Value::Integer(lhs * rhs)),
337 Value::Decimal(rhs) => Ok(Value::Decimal(lhs as f64 * rhs)),
338 _ => todo!(),
339 },
340 Value::Decimal(lhs) => match rhs {
341 Value::Bool(rhs) => Ok(Value::Decimal(lhs * bast!(rhs: f64))),
342 Value::Integer(rhs) => Ok(Value::Decimal(lhs * rhs as f64)),
343 Value::Decimal(rhs) => Ok(Value::Decimal(lhs * rhs)),
344 _ => todo!(),
345 },
346 _ => todo!(),
347 },
348 BinOp::Div => match lhs {
349 Value::Bool(lhs) => match rhs {
350 Value::Bool(rhs) => {
351 Ok(Value::Integer(bast!(lhs: i64) / bast!(rhs: i64)))
352 }
353 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) / rhs)),
354 Value::Decimal(rhs) => Ok(Value::Decimal(bast!(lhs: f64) / rhs)),
355 _ => todo!(),
356 },
357 Value::Integer(lhs) => match rhs {
358 Value::Bool(rhs) => Ok(Value::Integer(lhs / bast!(rhs: i64))),
359 Value::Integer(rhs) => Ok(Value::Integer(lhs / rhs)),
360 Value::Decimal(rhs) => Ok(Value::Decimal(lhs as f64 / rhs)),
361 _ => todo!(),
362 },
363 Value::Decimal(lhs) => match rhs {
364 Value::Bool(rhs) => Ok(Value::Decimal(lhs / bast!(rhs: f64))),
365 Value::Integer(rhs) => Ok(Value::Decimal(lhs / rhs as f64)),
366 Value::Decimal(rhs) => Ok(Value::Decimal(lhs / rhs)),
367 _ => todo!(),
368 },
369 _ => todo!(),
370 },
371 BinOp::Mod => match lhs {
372 Value::Bool(lhs) => match rhs {
373 Value::Bool(rhs) => {
374 Ok(Value::Integer(bast!(lhs: i64) % bast!(rhs: i64)))
375 }
376 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) % rhs)),
377 Value::Decimal(rhs) => Ok(Value::Decimal(bast!(lhs: f64) % rhs)),
378 _ => todo!(),
379 },
380 Value::Integer(lhs) => match rhs {
381 Value::Bool(rhs) => Ok(Value::Integer(lhs % bast!(rhs: i64))),
382 Value::Integer(rhs) => Ok(Value::Integer(lhs % rhs)),
383 Value::Decimal(rhs) => Ok(Value::Decimal(lhs as f64 % rhs)),
384 _ => todo!(),
385 },
386 Value::Decimal(lhs) => match rhs {
387 Value::Bool(rhs) => Ok(Value::Decimal(lhs % bast!(rhs: f64))),
388 Value::Integer(rhs) => Ok(Value::Decimal(lhs % rhs as f64)),
389 Value::Decimal(rhs) => Ok(Value::Decimal(lhs % rhs)),
390 _ => todo!(),
391 },
392 _ => todo!(),
393 },
394 BinOp::Equal => match lhs {
395 Value::Bool(lhs) => match rhs {
396 Value::Bool(rhs) => Ok(Value::Bool(lhs == rhs)),
397 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) == rhs)),
398 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) == rhs)),
399 _ => todo!(),
400 },
401 Value::Integer(lhs) => match rhs {
402 Value::Bool(rhs) => Ok(Value::Bool(lhs == bast!(rhs: i64))),
403 Value::Integer(rhs) => Ok(Value::Bool(lhs == rhs)),
404 Value::Decimal(rhs) => Ok(Value::Bool(lhs as f64 == rhs)),
405 _ => todo!(),
406 },
407 Value::Decimal(lhs) => match rhs {
408 Value::Bool(rhs) => Ok(Value::Bool(lhs == bast!(rhs: f64))),
409 Value::Integer(rhs) => Ok(Value::Bool(lhs == rhs as f64)),
410 Value::Decimal(rhs) => Ok(Value::Bool(lhs == rhs)),
411 _ => todo!(),
412 },
413 _ => todo!(),
414 },
415 BinOp::NotEqual => match lhs {
416 Value::Bool(lhs) => match rhs {
417 Value::Bool(rhs) => Ok(Value::Bool(lhs != rhs)),
418 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) != rhs)),
419 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) != rhs)),
420 _ => todo!(),
421 },
422 Value::Integer(lhs) => match rhs {
423 Value::Bool(rhs) => Ok(Value::Bool(lhs != bast!(rhs: i64))),
424 Value::Integer(rhs) => Ok(Value::Bool(lhs != rhs)),
425 Value::Decimal(rhs) => Ok(Value::Bool(lhs as f64 != rhs)),
426 _ => todo!(),
427 },
428 Value::Decimal(lhs) => match rhs {
429 Value::Bool(rhs) => Ok(Value::Bool(lhs != bast!(rhs: f64))),
430 Value::Integer(rhs) => Ok(Value::Bool(lhs != rhs as f64)),
431 Value::Decimal(rhs) => Ok(Value::Bool(lhs != rhs)),
432 _ => todo!(),
433 },
434 _ => todo!(),
435 },
436 BinOp::GreaterThan => match lhs {
437 Value::Bool(lhs) => match rhs {
438 Value::Bool(rhs) => Ok(Value::Bool(lhs > rhs)),
439 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) > rhs)),
440 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) > rhs)),
441 _ => todo!(),
442 },
443 Value::Integer(lhs) => match rhs {
444 Value::Bool(rhs) => Ok(Value::Bool(lhs > bast!(rhs: i64))),
445 Value::Integer(rhs) => Ok(Value::Bool(lhs > rhs)),
446 Value::Decimal(rhs) => Ok(Value::Bool((lhs as f64) > rhs)),
447 _ => todo!(),
448 },
449 Value::Decimal(lhs) => match rhs {
450 Value::Bool(rhs) => Ok(Value::Bool(lhs > bast!(rhs: f64))),
451 Value::Integer(rhs) => Ok(Value::Bool(lhs > rhs as f64)),
452 Value::Decimal(rhs) => Ok(Value::Bool(lhs > rhs)),
453 _ => todo!(),
454 },
455 _ => todo!(),
456 },
457 BinOp::LessThan => match lhs {
458 Value::Bool(lhs) => match rhs {
459 Value::Bool(rhs) => Ok(Value::Bool(lhs < rhs)),
460 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) < rhs)),
461 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) < rhs)),
462 _ => todo!(),
463 },
464 Value::Integer(lhs) => match rhs {
465 Value::Bool(rhs) => Ok(Value::Bool(lhs < bast!(rhs: i64))),
466 Value::Integer(rhs) => Ok(Value::Bool(lhs < rhs)),
467 Value::Decimal(rhs) => Ok(Value::Bool((lhs as f64) < rhs)),
468 _ => todo!(),
469 },
470 Value::Decimal(lhs) => match rhs {
471 Value::Bool(rhs) => Ok(Value::Bool(lhs < bast!(rhs: f64))),
472 Value::Integer(rhs) => Ok(Value::Bool(lhs < rhs as f64)),
473 Value::Decimal(rhs) => Ok(Value::Bool(lhs < rhs)),
474 _ => todo!(),
475 },
476 _ => todo!(),
477 },
478 BinOp::GreaterEqual => match lhs {
479 Value::Bool(lhs) => match rhs {
480 Value::Bool(rhs) => Ok(Value::Bool(lhs >= rhs)),
481 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) >= rhs)),
482 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) >= rhs)),
483 _ => todo!(),
484 },
485 Value::Integer(lhs) => match rhs {
486 Value::Bool(rhs) => Ok(Value::Bool(lhs >= bast!(rhs: i64))),
487 Value::Integer(rhs) => Ok(Value::Bool(lhs >= rhs)),
488 Value::Decimal(rhs) => Ok(Value::Bool((lhs as f64) >= rhs)),
489 _ => todo!(),
490 },
491 Value::Decimal(lhs) => match rhs {
492 Value::Bool(rhs) => Ok(Value::Bool(lhs >= bast!(rhs: f64))),
493 Value::Integer(rhs) => Ok(Value::Bool(lhs >= rhs as f64)),
494 Value::Decimal(rhs) => Ok(Value::Bool(lhs >= rhs)),
495 _ => todo!(),
496 },
497 _ => todo!(),
498 },
499 BinOp::LessEqual => match lhs {
500 Value::Bool(lhs) => match rhs {
501 Value::Bool(rhs) => Ok(Value::Bool(lhs <= rhs)),
502 Value::Integer(rhs) => Ok(Value::Bool(bast!(lhs: i64) <= rhs)),
503 Value::Decimal(rhs) => Ok(Value::Bool(bast!(lhs: f64) <= rhs)),
504 _ => todo!(),
505 },
506 Value::Integer(lhs) => match rhs {
507 Value::Bool(rhs) => Ok(Value::Bool(lhs <= bast!(rhs: i64))),
508 Value::Integer(rhs) => Ok(Value::Bool(lhs <= rhs)),
509 Value::Decimal(rhs) => Ok(Value::Bool(lhs as f64 <= rhs)),
510 _ => todo!(),
511 },
512 Value::Decimal(lhs) => match rhs {
513 Value::Bool(rhs) => Ok(Value::Bool(lhs <= bast!(rhs: f64))),
514 Value::Integer(rhs) => Ok(Value::Bool(lhs <= rhs as f64)),
515 Value::Decimal(rhs) => Ok(Value::Bool(lhs <= rhs)),
516 _ => todo!(),
517 },
518 _ => todo!(),
519 },
520 BinOp::And => match lhs {
521 Value::Bool(lhs) => match rhs {
522 Value::Bool(rhs) => {
523 Ok(Value::Integer(bast!(lhs: i64) & bast!(rhs: i64)))
524 }
525 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) & rhs)),
526 _ => todo!(),
527 },
528 Value::Integer(lhs) => match rhs {
529 Value::Bool(rhs) => Ok(Value::Integer(lhs & bast!(rhs: i64))),
530 Value::Integer(rhs) => Ok(Value::Integer(lhs & rhs)),
531 _ => todo!(),
532 },
533 _ => todo!(),
534 },
535 BinOp::Or => match lhs {
536 Value::Bool(lhs) => match rhs {
537 Value::Bool(rhs) => {
538 Ok(Value::Integer(bast!(lhs: i64) | bast!(rhs: i64)))
539 }
540 Value::Integer(rhs) => Ok(Value::Integer(bast!(lhs: i64) | rhs)),
541 _ => todo!(),
542 },
543 Value::Integer(lhs) => match rhs {
544 Value::Bool(rhs) => Ok(Value::Integer(lhs | bast!(rhs: i64))),
545 Value::Integer(rhs) => Ok(Value::Integer(lhs | rhs)),
546 _ => todo!(),
547 },
548 _ => todo!(),
549 },
550 }
551 }
552 Expr::UnOp(op, expr) => {
553 let value = self.eval(&expr.inner)?;
554
555 match op.inner {
556 UnOp::Not => match value {
557 Value::Bool(value) => Ok(Value::Bool(!value)),
558 Value::Integer(value) => Ok(Value::Bool(value == 0)),
559 Value::Decimal(value) => Ok(Value::Bool(value == 0.0)),
560 _ => todo!(),
561 },
562 UnOp::Plus => todo!(),
563 UnOp::Neg => match value {
564 Value::Bool(value) => Ok(Value::Integer(-bast!(value: i64))),
565 Value::Integer(value) => Ok(Value::Integer(-value)),
566 Value::Decimal(value) => Ok(Value::Decimal(-value)),
567 _ => todo!(),
568 },
569 }
570 }
571 Expr::Group(expr) => self.eval(&expr.inner),
572 }
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use chumsky::span::WrappingSpan as _;
579
580 use crate::filter::ast::Ident;
581
582 use super::*;
583
584 fn binop<'src>(op: BinOp, lhs: Expr<'src>, rhs: Expr<'src>) -> Expr<'src> {
585 Expr::BinOp(
586 SimpleSpan::from(0..1).make_wrapped(op),
587 Box::new(SimpleSpan::from(0..1).make_wrapped(lhs)),
588 Box::new(SimpleSpan::from(0..1).make_wrapped(rhs)),
589 )
590 }
591
592 fn unop(op: UnOp, lhs: Expr<'_>) -> Expr<'_> {
593 Expr::UnOp(
594 SimpleSpan::from(0..1).make_wrapped(op),
595 Box::new(SimpleSpan::from(0..1).make_wrapped(lhs)),
596 )
597 }
598
599 #[test]
600 fn bool() {
601 let mut vm = Vm::new();
602
603 vm.add_scope("bool_false", ScopeEntry::Bool(false));
604 vm.add_scope("bool_true", ScopeEntry::Bool(true));
605
606 assert_eq!(Ok(Value::Bool(false)), vm.eval(&Expr::Bool(false)));
607 assert_eq!(Ok(Value::Bool(true)), vm.eval(&Expr::Bool(true)));
608
609 assert_eq!(
610 Ok(Value::Bool(true)),
611 vm.eval(&unop(UnOp::Not, Expr::Bool(false)))
612 );
613 assert_eq!(
614 Ok(Value::Bool(false)),
615 vm.eval(&unop(UnOp::Not, Expr::Bool(true)))
616 );
617
618 assert_eq!(
619 Ok(Value::Bool(false)),
620 vm.eval(&Expr::Ident(Ident("bool_false".into())))
621 );
622 assert_eq!(
623 Ok(Value::Bool(true)),
624 vm.eval(&Expr::Ident(Ident("bool_true".into())))
625 );
626
627 assert_eq!(
628 Ok(Value::Bool(true)),
629 vm.eval(&unop(UnOp::Not, Expr::Ident(Ident("bool_false".into()))))
630 );
631 assert_eq!(
632 Ok(Value::Bool(false)),
633 vm.eval(&unop(UnOp::Not, Expr::Ident(Ident("bool_true".into()))))
634 );
635 }
636
637 #[test]
638 fn integer() {
639 let mut vm = Vm::new();
640
641 vm.add_scope("integer_zero", ScopeEntry::Integer(0));
642 vm.add_scope("integer_one", ScopeEntry::Integer(1));
643
644 assert_eq!(Ok(Value::Integer(0)), vm.eval(&Expr::Integer(0)));
645 assert_eq!(Ok(Value::Integer(1)), vm.eval(&Expr::Integer(1)));
646
647 assert_eq!(
648 Ok(Value::Integer(2)),
649 vm.eval(&binop(BinOp::Add, Expr::Integer(1), Expr::Integer(1)))
650 );
651 assert_eq!(
652 Ok(Value::Integer(0)),
653 vm.eval(&binop(BinOp::Sub, Expr::Integer(1), Expr::Integer(1)))
654 );
655
656 assert_eq!(
657 Ok(Value::Integer(2)),
658 vm.eval(&binop(
659 BinOp::Add,
660 Expr::Ident(Ident("integer_one".into())),
661 Expr::Ident(Ident("integer_one".into()))
662 ))
663 );
664 assert_eq!(
665 Ok(Value::Integer(0)),
666 vm.eval(&binop(
667 BinOp::Sub,
668 Expr::Ident(Ident("integer_one".into())),
669 Expr::Ident(Ident("integer_one".into()))
670 ))
671 );
672 }
673
674 #[test]
675 fn decimal() {
676 let mut vm = Vm::new();
677
678 vm.add_scope("decimal_zero", ScopeEntry::Decimal(0.0));
679 vm.add_scope("decimal_one", ScopeEntry::Decimal(1.0));
680
681 assert_eq!(Ok(Value::Decimal(0.0)), vm.eval(&Expr::Decimal(0.0)));
682 assert_eq!(Ok(Value::Decimal(1.0)), vm.eval(&Expr::Decimal(1.0)));
683
684 assert_eq!(
685 Ok(Value::Decimal(2.0)),
686 vm.eval(&binop(BinOp::Add, Expr::Decimal(1.0), Expr::Decimal(1.0)))
687 );
688 assert_eq!(
689 Ok(Value::Decimal(0.0)),
690 vm.eval(&binop(BinOp::Sub, Expr::Decimal(1.0), Expr::Decimal(1.0)))
691 );
692
693 assert_eq!(
694 Ok(Value::Decimal(2.0)),
695 vm.eval(&binop(
696 BinOp::Add,
697 Expr::Ident(Ident("decimal_one".into())),
698 Expr::Ident(Ident("decimal_one".into()))
699 ))
700 );
701 assert_eq!(
702 Ok(Value::Decimal(0.0)),
703 vm.eval(&binop(
704 BinOp::Sub,
705 Expr::Ident(Ident("decimal_one".into())),
706 Expr::Ident(Ident("decimal_one".into()))
707 ))
708 );
709 }
710}
711