1use std::borrow::Cow;
2use std::ops::{Deref, DerefMut};
3
4use anathema_state::{Color, Hex, PendingValue, SubTo, Subscriber, Type};
5use anathema_store::smallmap::SmallMap;
6use anathema_templates::Expression;
7
8use crate::attributes::ValueKey;
9use crate::expression::{ValueExpr, ValueResolutionContext, resolve_value};
10use crate::immediate::Resolver;
11use crate::{AttributeStorage, ResolverCtx};
12
13pub type Values<'bp> = SmallMap<ValueKey<'bp>, Value<'bp>>;
14
15pub fn resolve<'bp>(expr: &'bp Expression, ctx: &ResolverCtx<'_, 'bp>, sub: impl Into<Subscriber>) -> Value<'bp> {
16 let resolver = Resolver::new(ctx);
17 let value_expr = resolver.resolve(expr);
18 Value::new(value_expr, sub.into(), ctx.attribute_storage)
19}
20
21pub fn resolve_collection<'bp>(
22 expr: &'bp Expression,
23 ctx: &ResolverCtx<'_, 'bp>,
24 sub: impl Into<Subscriber>,
25) -> Collection<'bp> {
26 let value = resolve(expr, ctx, sub);
27 Collection(value)
28}
29
30#[derive(Debug)]
31pub struct Collection<'bp>(pub(crate) Value<'bp>);
32
33impl<'bp> Collection<'bp> {
34 pub fn reload(&mut self, attributes: &AttributeStorage<'bp>) {
35 self.0.reload(attributes)
36 }
37
38 pub fn len(&self) -> usize {
39 match &self.0.kind {
40 ValueKind::List(vec) => vec.len(),
41 ValueKind::DynList(value) => {
42 let Some(state) = value.as_state() else { return 0 };
43 let Some(list) = state.as_any_list() else { return 0 };
44 list.len()
45 }
46 ValueKind::Int(_)
47 | ValueKind::Float(_)
48 | ValueKind::Bool(_)
49 | ValueKind::Char(_)
50 | ValueKind::Hex(_)
51 | ValueKind::Color(_)
52 | ValueKind::Str(_)
53 | ValueKind::DynMap(_)
54 | ValueKind::Map
55 | ValueKind::Composite(_)
56 | ValueKind::Attributes
57 | ValueKind::Null => 0,
58 }
59 }
60}
61
62#[derive(Debug)]
65pub struct Value<'bp> {
66 pub(crate) expr: ValueExpr<'bp>,
67 pub(crate) sub: Subscriber,
68 pub(crate) kind: ValueKind<'bp>,
69 pub(crate) sub_to: SubTo,
70}
71
72impl<'bp> Value<'bp> {
73 pub fn new(expr: ValueExpr<'bp>, sub: Subscriber, attribute_storage: &AttributeStorage<'bp>) -> Self {
74 let mut sub_to = SubTo::Zero;
75 let mut ctx = ValueResolutionContext::new(attribute_storage, sub, &mut sub_to);
76 let kind = resolve_value(&expr, &mut ctx);
77
78 match kind {
88 ValueKind::DynMap(pending) | ValueKind::Composite(pending) => {
89 pending.subscribe(ctx.sub);
90 ctx.sub_to.push(pending.sub_key());
91 }
92 _ => {}
93 }
94 Self {
95 expr,
96 sub,
97 kind,
98 sub_to,
99 }
100 }
101
102 pub fn truthiness(&self) -> bool {
103 self.kind.truthiness()
112 }
113
114 #[doc(hidden)]
115 pub fn kind(&self) -> &ValueKind<'_> {
116 &self.kind
117 }
118
119 pub fn reload(&mut self, attribute_storage: &AttributeStorage<'bp>) {
120 self.sub_to.unsubscribe(self.sub);
121 let mut ctx = ValueResolutionContext::new(attribute_storage, self.sub, &mut self.sub_to);
122 self.kind = resolve_value(&self.expr, &mut ctx);
123 }
124
125 pub fn try_as<T>(&self) -> Option<T>
126 where
127 T: for<'a> TryFrom<&'a ValueKind<'a>>,
128 {
129 (&self.kind).try_into().ok()
130 }
131
132 pub fn strings<F>(&self, mut f: F)
133 where
134 F: FnMut(&str) -> bool,
135 {
136 self.kind.strings(&mut f);
137 }
138}
139
140impl Drop for Value<'_> {
141 fn drop(&mut self) {
142 self.sub_to.unsubscribe(self.sub);
143 }
144}
145
146impl<'a> Deref for Value<'a> {
147 type Target = ValueKind<'a>;
148
149 fn deref(&self) -> &Self::Target {
150 &self.kind
151 }
152}
153
154impl<'a> DerefMut for Value<'a> {
155 fn deref_mut(&mut self) -> &mut Self::Target {
156 &mut self.kind
157 }
158}
159
160#[derive(Debug, PartialEq, PartialOrd, Clone)]
164pub enum ValueKind<'bp> {
165 Int(i64),
166 Float(f64),
167 Bool(bool),
168 Char(char),
169 Hex(Hex),
170 Color(Color),
171 Str(Cow<'bp, str>),
172 Null,
173
174 Map,
178 Attributes,
182 List(Box<[ValueKind<'bp>]>),
183 DynList(PendingValue),
184 DynMap(PendingValue),
185 Composite(PendingValue),
186}
187
188impl ValueKind<'_> {
189 pub fn to_int(&self) -> Option<i64> {
190 match self.as_int() {
191 Some(val) => Some(val),
192 None => Some(self.as_float()? as i64),
193 }
194 }
195
196 pub fn as_int(&self) -> Option<i64> {
197 let ValueKind::Int(i) = self else { return None };
198 Some(*i)
199 }
200
201 pub fn as_float(&self) -> Option<f64> {
202 let ValueKind::Float(i) = self else { return None };
203 Some(*i)
204 }
205
206 pub fn as_bool(&self) -> Option<bool> {
207 let ValueKind::Bool(b) = self else { return None };
208 Some(*b)
209 }
210
211 pub fn as_char(&self) -> Option<char> {
212 let ValueKind::Char(i) = self else { return None };
213 Some(*i)
214 }
215
216 pub fn as_hex(&self) -> Option<Hex> {
217 let ValueKind::Hex(i) = self else { return None };
218 Some(*i)
219 }
220
221 pub fn as_color(&self) -> Option<Color> {
222 let ValueKind::Color(i) = self else { return None };
223 Some(*i)
224 }
225
226 pub fn as_str(&self) -> Option<&str> {
227 let ValueKind::Str(i) = &self else { return None };
228 Some(i)
229 }
230
231 pub fn as_list(&self) -> Option<&[Self]> {
232 let ValueKind::List(list) = &self else { return None };
233 Some(list)
234 }
235
236 pub fn is_null(&self) -> bool {
237 matches!(self, ValueKind::Null)
238 }
239
240 pub fn strings<F>(&self, mut f: F)
241 where
242 F: FnMut(&str) -> bool,
243 {
244 self.internal_strings(&mut f);
245 }
246
247 fn internal_strings<F>(&self, f: &mut F) -> bool
248 where
249 F: FnMut(&str) -> bool,
250 {
251 match self {
252 ValueKind::Int(n) => f(&n.to_string()),
253 ValueKind::Float(n) => f(&n.to_string()),
254 ValueKind::Bool(b) => f(&b.to_string()),
255 ValueKind::Char(c) => f(&c.to_string()),
256 ValueKind::Hex(x) => f(&x.to_string()),
257 ValueKind::Color(col) => f(&col.to_string()),
258 ValueKind::Str(cow) => f(cow.as_ref()),
259 ValueKind::List(vec) => vec.iter().take_while(|val| val.internal_strings(f)).count() == vec.len(),
260 ValueKind::DynList(value) => dyn_string(*value, f),
261 ValueKind::DynMap(_) => f("<dyn map>"),
262 ValueKind::Map => f("<map>"),
263 ValueKind::Composite(_) => f("<composite>"),
264 ValueKind::Attributes => f("<attributes>"),
265 ValueKind::Null => true,
266 }
267 }
268
269 pub(crate) fn truthiness(&self) -> bool {
270 match self {
271 ValueKind::Int(0) | ValueKind::Float(0.0) | ValueKind::Bool(false) => false,
272 ValueKind::Str(cow) if cow.is_empty() => false,
273 ValueKind::Null => false,
274 ValueKind::List(list) if list.is_empty() => false,
275 ValueKind::DynList(list) => {
276 let Some(state) = list.as_state() else { return false };
277 let Some(state) = state.as_any_list() else { return false };
278 !state.is_empty()
279 }
280 ValueKind::DynMap(map) => {
281 let Some(state) = map.as_state() else { return false };
282 let Some(state) = state.as_any_map() else { return false };
283 !state.is_empty()
284 }
285 _ => true,
287 }
288 }
289
290 pub(crate) fn value_eq(&self, other: &Self) -> bool {
291 match (self, other) {
292 (ValueKind::Int(lhs), ValueKind::Int(rhs)) => lhs == rhs,
293 (ValueKind::Float(lhs), ValueKind::Float(rhs)) => lhs == rhs,
294 (ValueKind::Bool(lhs), ValueKind::Bool(rhs)) => lhs == rhs,
295 (ValueKind::Char(lhs), ValueKind::Char(rhs)) => lhs == rhs,
296 (ValueKind::Hex(lhs), ValueKind::Hex(rhs)) => lhs == rhs,
297 (ValueKind::Color(lhs), ValueKind::Color(rhs)) => lhs == rhs,
298 (ValueKind::Str(lhs), ValueKind::Str(rhs)) => lhs == rhs,
299 (ValueKind::Null, ValueKind::Null) => true,
300 (ValueKind::Attributes, ValueKind::Attributes) => true,
301 (ValueKind::List(lhs), ValueKind::List(rhs)) => lhs == rhs,
302 (ValueKind::DynList(lhs), ValueKind::DynList(rhs)) => lhs.pending_eq(*rhs),
303 (ValueKind::DynList(lhs), ValueKind::List(rhs)) => dyn_static_eq(*lhs, rhs),
304 (ValueKind::List(lhs), ValueKind::DynList(rhs)) => dyn_static_eq(*rhs, lhs),
305 (ValueKind::DynMap(lhs), ValueKind::DynMap(rhs)) => lhs.pending_eq(*rhs),
306 (ValueKind::Composite(lhs), ValueKind::Composite(rhs)) => lhs.pending_eq(*rhs),
307 _ => false,
308 }
309 }
310
311 pub(crate) fn compare_pending(&self, pending: PendingValue) -> bool {
312 let type_info = pending.type_info();
313 let Some(rhs) = pending.as_state() else { return false };
314
315 match type_info {
316 Type::Int => compare_owned(self.as_int(), rhs.as_int()),
317 Type::Float => compare_owned(self.as_float(), rhs.as_float()),
318 Type::Char => compare_owned(self.as_char(), rhs.as_char()),
319 Type::Bool => compare_owned(self.as_bool(), rhs.as_bool()),
320 Type::Hex => compare_owned(self.as_hex(), rhs.as_hex()),
321 Type::Color => compare_owned(self.as_color(), rhs.as_color()),
322 Type::String => compare_owned(self.as_str(), rhs.as_str()),
323 Type::Map => false,
324 Type::List => match self {
325 ValueKind::List(rhs) => dyn_static_eq(pending, rhs),
326 ValueKind::DynList(rhs) => rhs.pending_eq(pending),
327 _ => false,
328 },
329 Type::Composite => match self {
330 ValueKind::Composite(pending_value) => pending.pending_eq(*pending_value),
331 _ => false,
332 },
333 Type::Unit => self.is_null(),
334 Type::Maybe => unreachable!("ValueKind can never be a Maybe as it's the final value"),
335 }
336 }
337}
338
339fn compare_owned<T: PartialEq>(lhs: Option<T>, rhs: Option<T>) -> bool {
340 lhs.is_some() && lhs == rhs
341}
342
343fn dyn_static_eq(pending: PendingValue, val_kind: &[ValueKind<'_>]) -> bool {
344 let Some(state) = pending.as_state() else { return false };
345 let Some(lhs) = state.as_any_list() else { return false };
346
347 if lhs.len() != val_kind.len() {
348 return false;
349 }
350
351 for (lhs, rhs) in lhs.iter().zip(val_kind) {
352 if !rhs.compare_pending(lhs) {
353 return false;
354 }
355 }
356
357 true
358}
359
360fn dyn_string<F>(value: PendingValue, f: &mut F) -> bool
361where
362 F: FnMut(&str) -> bool,
363{
364 let Some(state) = value.as_state() else { return true };
365 let Some(list) = state.as_any_list() else { return true };
366 for i in 0..list.len() {
367 let value = list.lookup(i).expect("the value exists");
368 let Some(state) = value.as_state() else { continue };
369 let should_continue = match value.type_info() {
370 Type::Int => f(&state.as_int().expect("type info dictates this").to_string()),
371 Type::Float => f(&state.as_float().expect("type info dictates this").to_string()),
372 Type::Char => f(&state.as_char().expect("type info dictates this").to_string()),
373 Type::String => f(state.as_str().expect("type info dictates this")),
374 Type::Bool => f(&state.as_bool().expect("type info dictates this").to_string()),
375 Type::Hex => f(&state.as_hex().expect("type info dictates this").to_string()),
376 Type::Map => f("<map>"),
377 Type::List => dyn_string(value, f),
378 Type::Composite => f(&state.as_hex().expect("type info dictates this").to_string()),
379 Type::Unit => f(""),
380 Type::Color => f(&state.as_color().expect("type info dictates this").to_string()),
381 Type::Maybe => panic!(),
382 };
383
384 if !should_continue {
385 return false;
386 }
387 }
388 true
389}
390
391macro_rules! from_int {
395 ($int:ty) => {
396 impl From<$int> for ValueKind<'_> {
397 fn from(value: $int) -> Self {
398 ValueKind::Int(value as i64)
399 }
400 }
401 };
402}
403
404from_int!(i64);
405from_int!(i32);
406from_int!(i16);
407from_int!(i8);
408from_int!(u64);
409from_int!(u32);
410from_int!(u16);
411from_int!(u8);
412
413impl From<f64> for ValueKind<'_> {
414 fn from(value: f64) -> Self {
415 ValueKind::Float(value)
416 }
417}
418
419impl From<f32> for ValueKind<'_> {
420 fn from(value: f32) -> Self {
421 ValueKind::Float(value as f64)
422 }
423}
424
425impl From<bool> for ValueKind<'_> {
426 fn from(value: bool) -> Self {
427 ValueKind::Bool(value)
428 }
429}
430
431impl From<char> for ValueKind<'_> {
432 fn from(value: char) -> Self {
433 ValueKind::Char(value)
434 }
435}
436
437impl From<Hex> for ValueKind<'_> {
438 fn from(value: Hex) -> Self {
439 ValueKind::Hex(value)
440 }
441}
442
443impl From<Color> for ValueKind<'_> {
444 fn from(value: Color) -> Self {
445 ValueKind::Color(value)
446 }
447}
448
449impl<'bp, T> From<Vec<T>> for ValueKind<'bp>
450where
451 T: Into<ValueKind<'bp>>,
452{
453 fn from(value: Vec<T>) -> Self {
454 let list = value.into_iter().map(T::into).collect();
455 ValueKind::List(list)
456 }
457}
458
459impl<'a> From<&'a str> for ValueKind<'a> {
460 fn from(value: &'a str) -> Self {
461 ValueKind::Str(Cow::Borrowed(value))
462 }
463}
464
465impl From<String> for ValueKind<'_> {
466 fn from(value: String) -> Self {
467 ValueKind::Str(value.into())
468 }
469}
470
471macro_rules! try_from_valuekind {
475 ($t:ty, $kind:ident) => {
476 impl TryFrom<&ValueKind<'_>> for $t {
477 type Error = ();
478
479 fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
480 match value {
481 ValueKind::$kind(val) => Ok(*val),
482 _ => Err(()),
483 }
484 }
485 }
486 };
487}
488
489macro_rules! try_from_valuekind_int {
490 ($t:ty, $kind:ident) => {
491 impl TryFrom<&ValueKind<'_>> for $t {
492 type Error = ();
493
494 fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
495 match value {
496 ValueKind::$kind(val) => Ok(*val as $t),
497 _ => Err(()),
498 }
499 }
500 }
501 };
502}
503
504try_from_valuekind!(i64, Int);
505try_from_valuekind!(f64, Float);
506try_from_valuekind!(bool, Bool);
507try_from_valuekind!(Hex, Hex);
508try_from_valuekind!(Color, Color);
509
510try_from_valuekind_int!(usize, Int);
511try_from_valuekind_int!(isize, Int);
512try_from_valuekind_int!(i32, Int);
513try_from_valuekind_int!(f32, Float);
514try_from_valuekind_int!(i16, Int);
515try_from_valuekind_int!(i8, Int);
516try_from_valuekind_int!(u32, Int);
517try_from_valuekind_int!(u64, Int);
518try_from_valuekind_int!(u16, Int);
519try_from_valuekind_int!(u8, Int);
520
521impl<'bp> TryFrom<&ValueKind<'bp>> for char {
522 type Error = ();
523
524 fn try_from(value: &ValueKind<'bp>) -> Result<Self, Self::Error> {
525 match value {
526 ValueKind::Char(c) => Ok(*c),
527 ValueKind::Str(s) => s.chars().next().ok_or(()),
528 _ => Err(()),
529 }
530 }
531}
532
533impl<'a, 'bp> TryFrom<&'a ValueKind<'bp>> for &'a str {
534 type Error = ();
535
536 fn try_from(value: &'a ValueKind<'bp>) -> Result<Self, Self::Error> {
537 match value {
538 ValueKind::Str(Cow::Borrowed(val)) => Ok(val),
539 ValueKind::Str(Cow::Owned(val)) => Ok(val.as_str()),
540 _ => Err(()),
541 }
542 }
543}
544
545#[cfg(test)]
546pub(crate) mod test {
547 use anathema_state::{Hex, Map, Maybe, States};
548 use anathema_templates::Variables;
549 use anathema_templates::expressions::{
550 add, and, boolean, chr, div, either, eq, float, greater_than, greater_than_equal, hex, ident, index, less_than,
551 less_than_equal, list, map, modulo, mul, neg, not, num, or, strlit, sub, text_segments,
552 };
553
554 use crate::ValueKind;
555 use crate::testing::setup;
556
557 #[test]
558 fn attribute_lookup() {
559 let expr = index(ident("attributes"), strlit("a"));
560 let int = num(123);
561
562 let mut states = States::new();
563 setup(&mut states, Default::default(), |test| {
564 test.set_attribute("a", &int);
565 let value = test.eval(&expr);
566 assert_eq!(123, value.as_int().unwrap());
567 });
568 }
569
570 #[test]
571 fn expr_list_dyn_index() {
572 let expr = index(list([1, 2, 3]), add(ident("index"), num(1)));
573
574 let mut states = States::new();
575 let mut globals = Variables::new();
576 globals.declare("index", 0);
577
578 setup(&mut states, globals, |test| {
579 let value = test.eval(&expr);
580 assert_eq!(2, value.as_int().unwrap());
581 });
582 }
583
584 #[test]
585 fn expr_list() {
586 let expr = index(list([1, 2, 3]), num(0));
587
588 let mut states = States::new();
589 setup(&mut states, Default::default(), |test| {
590 let value = test.eval(&expr);
591 assert_eq!(1, value.as_int().unwrap());
592 });
593 }
594
595 #[test]
596 fn either_index() {
597 let expr = either(
599 index(index(ident("state"), strlit("list")), num(0)),
600 index(index(ident("attributes"), strlit("list")), num(0)),
601 );
602
603 let list = list([strlit("from attribute")]);
604
605 let mut states = States::new();
606 setup(&mut states, Default::default(), |test| {
607 test.set_attribute("list", &list);
609
610 let mut value = test.eval(&expr);
613 assert_eq!("from attribute", value.as_str().unwrap());
614
615 test.with_state(|state| state.list.push("from state"));
617
618 value.reload(&test.attributes);
620 assert_eq!("from state", value.as_str().unwrap());
621 });
622 }
623
624 #[test]
625 fn either_then_index() {
626 let list = list([num(123)]);
629 let mut states = States::new();
630 setup(&mut states, Default::default(), |test| {
631 let expr = index(
632 either(
633 index(ident("attributes"), strlit("list")),
634 index(ident("state"), strlit("list")),
635 ),
636 num(0),
637 );
638
639 test.with_state(|state| state.list.push("a string"));
640 let value = test.eval(&expr);
641 assert_eq!("a string", value.as_str().unwrap());
642
643 test.set_attribute("list", &list);
644 let value = test.eval(&expr);
645 assert_eq!(123, value.as_int().unwrap());
646 });
647 }
648
649 #[test]
650 fn either_or() {
651 let mut states = States::new();
652 setup(&mut states, Default::default(), |test| {
653 test.with_state(|state| state.num.set(1));
654 test.with_state(|state| state.num_2.set(2));
655
656 let expr = either(
658 index(ident("state"), strlit("num_3")),
659 index(ident("state"), strlit("num_2")),
660 );
661 let value = test.eval(&expr);
662 assert_eq!(2, value.as_int().unwrap());
663
664 let expr = either(
666 index(ident("state"), strlit("num")),
667 index(ident("state"), strlit("num_2")),
668 );
669 let value = test.eval(&expr);
670 assert_eq!(1, value.as_int().unwrap());
671 });
672 }
673
674 #[test]
675 fn mods() {
676 let mut states = States::new();
677 setup(&mut states, Default::default(), |test| {
678 test.with_state(|state| state.num.set(5));
679 let lookup = index(ident("state"), strlit("num"));
680 let expr = modulo(lookup, num(3));
681 let value = test.eval(&expr);
682 assert_eq!(2, value.as_int().unwrap());
683 });
684 }
685
686 #[test]
687 fn division() {
688 let mut states = States::new();
689 setup(&mut states, Default::default(), |test| {
690 test.with_state(|state| state.num.set(6));
691 let lookup = index(ident("state"), strlit("num"));
692 let expr = div(lookup, num(2));
693 let value = test.eval(&expr);
694 assert_eq!(3, value.as_int().unwrap());
695 });
696 }
697
698 #[test]
699 fn multiplication() {
700 let mut states = States::new();
701 setup(&mut states, Default::default(), |test| {
702 test.with_state(|state| state.num.set(2));
703 let lookup = index(ident("state"), strlit("num"));
704 let expr = mul(lookup, num(2));
705 let value = test.eval(&expr);
706 assert_eq!(4, value.as_int().unwrap());
707 });
708 }
709
710 #[test]
711 fn subtraction() {
712 let mut states = States::new();
713 setup(&mut states, Default::default(), |test| {
714 test.with_state(|state| state.num.set(1));
715 let lookup = index(ident("state"), strlit("num"));
716 let expr = sub(lookup, num(2));
717 let value = test.eval(&expr);
718 assert_eq!(-1, value.as_int().unwrap());
719 });
720 }
721
722 #[test]
723 fn addition() {
724 let mut states = States::new();
725 setup(&mut states, Default::default(), |test| {
726 test.with_state(|state| state.num.set(1));
727 let lookup = index(ident("state"), strlit("num"));
728 let expr = add(lookup, num(2));
729 let value = test.eval(&expr);
730 assert_eq!(3, value.as_int().unwrap());
731 });
732 }
733
734 #[test]
735 fn test_or() {
736 let mut states = States::new();
737 setup(&mut states, Default::default(), |test| {
738 let is_true = or(boolean(false), boolean(true));
739 let is_true = test.eval(&is_true);
740 assert!(is_true.as_bool().unwrap());
741 });
742 }
743
744 #[test]
745 fn test_and() {
746 let mut states = States::new();
747 setup(&mut states, Default::default(), |test| {
748 let is_true = and(boolean(true), boolean(true));
749 let is_true = test.eval(&is_true);
750 assert!(is_true.as_bool().unwrap());
751 });
752 }
753
754 #[test]
755 fn lte() {
756 let mut states = States::new();
757 setup(&mut states, Default::default(), |test| {
758 let is_true = less_than_equal(num(1), num(2));
759 let is_also_true = less_than_equal(num(1), num(1));
760 let is_true = test.eval(&is_true);
761 let is_also_true = test.eval(&is_also_true);
762 assert!(is_true.as_bool().unwrap());
763 assert!(is_also_true.as_bool().unwrap());
764 });
765 }
766
767 #[test]
768 fn lt() {
769 let mut states = States::new();
770 setup(&mut states, Default::default(), |test| {
771 let is_true = less_than(num(1), num(2));
772 let is_false = less_than(num(1), num(1));
773 let is_true = test.eval(&is_true);
774 let is_false = test.eval(&is_false);
775 assert!(is_true.as_bool().unwrap());
776 assert!(!is_false.as_bool().unwrap());
777 });
778 }
779
780 #[test]
781 fn gte() {
782 let mut states = States::new();
783 setup(&mut states, Default::default(), |test| {
784 let is_true = greater_than_equal(num(2), num(1));
785 let is_also_true = greater_than_equal(num(2), num(2));
786 let is_true = test.eval(&is_true);
787 let is_also_true = test.eval(&is_also_true);
788 assert!(is_true.as_bool().unwrap());
789 assert!(is_also_true.as_bool().unwrap());
790 });
791 }
792
793 #[test]
794 fn gt() {
795 let mut states = States::new();
796 setup(&mut states, Default::default(), |test| {
797 let is_true = greater_than(num(2), num(1));
798 let is_false = greater_than(num(2), num(2));
799 let is_true = test.eval(&is_true);
800 let is_false = test.eval(&is_false);
801 assert!(is_true.as_bool().unwrap());
802 assert!(!is_false.as_bool().unwrap());
803 });
804 }
805
806 #[test]
807 fn equality() {
808 let mut states = States::new();
809 setup(&mut states, Default::default(), |test| {
810 let is_true = eq(num(1), num(1));
811 let is_true = test.eval(&is_true);
812 let is_false = ¬(eq(num(1), num(1)));
813 let is_false = test.eval(is_false);
814 assert!(is_true.as_bool().unwrap());
815 assert!(!is_false.as_bool().unwrap());
816 });
817 }
818
819 #[test]
820 fn neg_float() {
821 let mut states = States::new();
822 setup(&mut states, Default::default(), |test| {
823 let expr = neg(float(123.1));
824 let value = test.eval(&expr);
825 assert_eq!(-123.1, value.as_float().unwrap());
826 });
827 }
828
829 #[test]
830 fn neg_num() {
831 let mut states = States::new();
832 setup(&mut states, Default::default(), |test| {
833 let expr = neg(num(123));
834 let value = test.eval(&expr);
835 assert_eq!(-123, value.as_int().unwrap());
836 });
837 }
838
839 #[test]
840 fn not_true() {
841 let mut states = States::new();
842 setup(&mut states, Default::default(), |test| {
843 let expr = not(boolean(false));
844 let value = test.eval(&expr);
845 assert!(value.as_bool().unwrap());
846 });
847 }
848
849 #[test]
850 fn map_resolve() {
851 let mut states = States::new();
852 setup(&mut states, Default::default(), |test| {
853 let expr = map([("a", 123), ("b", 456)]);
854 let value = test.eval(&expr);
855 assert_eq!(ValueKind::Map, value.kind);
856 });
857 }
858
859 #[test]
860 fn optional_map_resolve() {
861 let mut states = States::new();
862 setup(&mut states, Default::default(), |test| {
863 let expr = index(ident("state"), strlit("opt_map"));
865 let mut value = test.eval(&expr);
866 assert!(matches!(value.kind, ValueKind::Null));
867
868 test.with_state(|state| {
870 let map = Map::empty();
871 state.opt_map.set(Maybe::some(map));
872 });
873
874 value.reload(&test.attributes);
875 assert!(matches!(value.kind, ValueKind::DynMap(_)));
876 });
877 }
878
879 #[test]
880 fn str_resolve() {
881 let mut states = States::new();
883 let mut globals = Variables::new();
884 globals.declare("full", "string");
885 setup(&mut states, globals, |test| {
886 let expr = index(ident("state"), either(ident("empty"), ident("full")));
887 test.with_state(|state| state.string.set("a string"));
888 let value = test.eval(&expr);
889 assert_eq!("a string", value.as_str().unwrap());
890 });
891 }
892
893 #[test]
894 fn state_string() {
895 let mut states = States::new();
896 setup(&mut states, Default::default(), |test| {
897 test.with_state(|state| state.string.set("a string"));
898 let expr = index(ident("state"), strlit("string"));
899 let value = test.eval(&expr);
900 assert_eq!("a string", value.as_str().unwrap());
901 });
902 }
903
904 #[test]
905 fn state_float() {
906 let mut states = States::new();
907 setup(&mut states, Default::default(), |test| {
908 let expr = index(ident("state"), strlit("float"));
909 test.with_state(|state| state.float.set(1.2));
910 let value = test.eval(&expr);
911 assert_eq!(1.2, value.as_float().unwrap());
912 });
913 }
914
915 #[test]
916 fn test_either() {
917 let mut states = States::new();
918 let mut globals = Variables::new();
919 globals.declare("missing", 111);
920 setup(&mut states, globals, |test| {
921 let expr = either(ident("missings"), num(2));
922 let value = test.eval(&expr);
923 assert_eq!(2, value.as_int().unwrap());
924 });
925 }
926
927 #[test]
928 fn test_hex() {
929 let mut states = States::new();
930 setup(&mut states, Default::default(), |test| {
931 let expr = hex((1, 2, 3));
932 let value = test.eval(&expr);
933 assert_eq!(Hex::from((1, 2, 3)), value.as_hex().unwrap());
934 });
935 }
936
937 #[test]
938 fn test_char() {
939 let mut states = States::new();
940 setup(&mut states, Default::default(), |test| {
941 let expr = chr('x');
942 let value = test.eval(&expr);
943 assert_eq!('x', value.as_char().unwrap());
944 });
945 }
946
947 #[test]
948 fn test_float() {
949 let mut states = States::new();
950 setup(&mut states, Default::default(), |test| {
951 let expr = float(123.123);
952 let value = test.eval(&expr);
953 assert_eq!(123.123, value.as_float().unwrap());
954 });
955 }
956
957 #[test]
958 fn test_int() {
959 let mut states = States::new();
960 setup(&mut states, Default::default(), |test| {
961 let expr = num(123);
962 let value = test.eval(&expr);
963 assert_eq!(123, value.as_int().unwrap());
964 });
965 }
966
967 #[test]
968 fn test_bool() {
969 let mut states = States::new();
970 setup(&mut states, Default::default(), |test| {
971 let expr = boolean(true);
972 let value = test.eval(&expr);
973 assert!(value.as_bool().unwrap());
974 });
975 }
976
977 #[test]
978 fn test_dyn_list() {
979 let mut states = States::new();
980 setup(&mut states, Default::default(), |test| {
981 test.with_state(|state| {
982 state.list.push("abc");
983 state.list.push("def");
984 });
985 let expr = index(index(ident("state"), strlit("list")), num(1));
986 let value = test.eval(&expr);
987 assert_eq!("def", value.as_str().unwrap());
988 });
989 }
990
991 #[test]
992 fn test_expression_map_state_key() {
993 let mut states = States::new();
994 setup(&mut states, Default::default(), |test| {
995 let expr = index(map([("value", 123)]), index(ident("state"), strlit("string")));
996 test.with_state(|state| state.string.set("value"));
997 let value = test.eval(&expr);
998 assert_eq!(123, value.as_int().unwrap());
999 });
1000 }
1001
1002 #[test]
1003 fn test_expression_map() {
1004 let mut states = States::new();
1005 setup(&mut states, Default::default(), |test| {
1006 let expr = index(map([("value", 123)]), strlit("value"));
1007 let value = test.eval(&expr);
1008 assert_eq!(123, value.as_int().unwrap());
1009 });
1010 }
1011
1012 #[test]
1013 fn test_state_lookup() {
1014 let mut states = States::new();
1015 setup(&mut states, Default::default(), |test| {
1016 let expr = index(ident("state"), strlit("num"));
1017 let value = test.eval(&expr);
1018 assert_eq!(0, value.as_int().unwrap());
1019 });
1020 }
1021
1022 #[test]
1023 fn test_nested_map() {
1024 let mut states = States::new();
1025 setup(&mut states, Default::default(), |test| {
1026 let expr = index(index(ident("state"), strlit("map")), strlit("value"));
1027 test.with_state(|state| state.map.to_mut().insert("value", 123));
1028 let value = test.eval(&expr);
1029 assert_eq!(123, value.as_int().unwrap());
1030 });
1031 }
1032
1033 #[test]
1053 fn stringify() {
1054 let mut states = States::new();
1055 setup(&mut states, Default::default(), |test| {
1056 let expr = text_segments([strlit("hello"), strlit(" "), strlit("world")]);
1057 let value = test.eval(&expr);
1058 let mut actual = String::new();
1059 value.strings(|st| {
1060 actual.push_str(st);
1061 true
1062 });
1063 assert_eq!("hello world", &actual);
1064 });
1065 }
1066}