Skip to main content

anathema_value_resolver/
value.rs

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