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#[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 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 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#[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 Map,
179 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 _ => 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
394macro_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
474macro_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 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 test.set_attribute("list", &list);
612
613 let mut value = test.eval(&expr);
616 assert_eq!("from attribute", value.as_str().unwrap());
617
618 test.with_state(|state| state.list.push("from state"));
620
621 value.reload(&test.attributes);
623 assert_eq!("from state", value.as_str().unwrap());
624 });
625 }
626
627 #[test]
628 fn either_then_index() {
629 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 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 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 = ¬(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 let expr = index(ident("state"), strlit("opt_map"));
868 let mut value = test.eval(&expr);
869 assert!(matches!(value.kind, ValueKind::Null));
870
871 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 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}