1use rimu_ast::{BinaryOperator, Expression, SpannedExpression, UnaryOperator};
5use rimu_meta::{Span, Spanned};
6use rimu_value::{
7 convert_value_object_to_serde_value_object, Environment, Function, FunctionBody, Number,
8 SpannedValue, Value, ValueObject,
9};
10use rust_decimal::prelude::ToPrimitive;
11use std::{cell::RefCell, ops::Deref, rc::Rc};
12
13use crate::{common, EvalError, Result};
14
15pub fn evaluate(
16 expression: &SpannedExpression,
17 env: Rc<RefCell<Environment>>,
18) -> Result<SpannedValue> {
19 Evaluator::new(env).expression(expression)
20}
21
22struct Evaluator {
25 env: Rc<RefCell<Environment>>,
26}
27
28impl Evaluator {
29 fn new(env: Rc<RefCell<Environment>>) -> Self {
30 Self { env }
31 }
32
33 fn expression(&self, expr: &SpannedExpression) -> Result<SpannedValue> {
34 let span = expr.span();
35 match expr.inner() {
36 Expression::Null => Ok(Spanned::new(Value::Null, span)),
37
38 Expression::Boolean(boolean) => Ok(Spanned::new(Value::Boolean(*boolean), span)),
39
40 Expression::String(string) => self.string(span, string),
41
42 Expression::Number(decimal) => Ok(Spanned::new(
43 Value::Number(Into::<Number>::into(*decimal)),
44 span,
45 )),
46
47 Expression::List(ref items) => self.list(span, items),
48
49 Expression::Object(ref entries) => self.object(span, entries),
50
51 Expression::Function { ref args, ref body } => self.function(span, args, body),
52
53 Expression::Identifier(var) => self.variable(span, var),
54
55 Expression::Unary {
56 ref right,
57 ref operator,
58 } => self.unary(span, right, operator),
59
60 Expression::Binary {
61 ref left,
62 ref right,
63 ref operator,
64 } => self.binary(span, left, operator, right),
65
66 Expression::Call {
67 ref function,
68 ref args,
69 } => self.call(span, function, args),
70
71 Expression::GetIndex { container, index } => self.get_index(span, container, index),
72
73 Expression::GetKey { container, key } => self.get_key(span, container, key),
74
75 Expression::GetSlice {
76 container,
77 ref start,
78 ref end,
79 } => self.get_slice(
80 span,
81 container,
82 start.as_ref().map(|s| s.deref()),
83 end.as_ref().map(|e| e.deref()),
84 ),
85
86 Expression::Error => Err(EvalError::ErrorExpression { span }),
87 }
88 }
89
90 fn string(&self, span: Span, string: &str) -> Result<SpannedValue> {
91 let value = Value::String(string.to_string());
93 Ok(Spanned::new(value, span))
94 }
95
96 fn function(
97 &self,
98 span: Span,
99 args: &[Spanned<String>],
100 body: &SpannedExpression,
101 ) -> Result<SpannedValue> {
102 let args: Vec<String> = args.iter().map(|a| a.inner()).cloned().collect();
103 let body = FunctionBody::Expression(body.clone());
104 let env = self.env.clone();
105 let value = Value::Function(Function { args, body, env });
106 Ok(Spanned::new(value, span))
107 }
108
109 fn unary(
110 &self,
111 span: Span,
112 right: &SpannedExpression,
113 operator: &UnaryOperator,
114 ) -> Result<SpannedValue> {
115 let (right, right_span) = self.expression(right)?.take();
116 let value = match operator {
117 UnaryOperator::Negate => match right.clone() {
118 Value::Number(number) => Ok(Value::Number(-number)),
119 _ => Err(EvalError::TypeError {
120 span: right_span,
121 expected: "number".into(),
122 got: right.clone().into(),
123 }),
124 },
125 UnaryOperator::Not => {
126 let boolean: bool = right.into();
127 Ok(Value::Boolean(!boolean))
128 }
129 }?;
130 Ok(Spanned::new(value, span))
131 }
132
133 fn binary(
134 &self,
135 span: Span,
136 left: &SpannedExpression,
137 operator: &BinaryOperator,
138 right: &SpannedExpression,
139 ) -> Result<SpannedValue> {
140 let (left, left_span) = self.expression(left)?.take();
141 match operator {
142 BinaryOperator::And => self.boolean(span, left, right, true),
143 BinaryOperator::Or => self.boolean(span, left, right, false),
144 _ => {
145 let (right, right_span) = self.expression(right)?.take();
146 let value = match operator {
147 BinaryOperator::Or => unreachable!(),
148 BinaryOperator::And => unreachable!(),
149 BinaryOperator::Add => match (left.clone(), right.clone()) {
150 (Value::Number(left), Value::Number(right)) => {
151 Ok(Value::Number(left + right))
152 }
153 (Value::Number(_left), right) => Err(EvalError::TypeError {
154 span: right_span,
155 expected: "number".into(),
156 got: right.into(),
157 }),
158 (Value::String(left), Value::String(right)) => {
159 Ok(Value::String([left, right].join("")))
160 }
161 (Value::String(_left), right) => Err(EvalError::TypeError {
162 span: right_span,
163 expected: "string".into(),
164 got: right.into(),
165 }),
166 (Value::List(left), Value::List(right)) => {
167 Ok(Value::List([left, right].concat()))
168 }
169 (Value::List(_left), right) => Err(EvalError::TypeError {
170 span: right_span,
171 expected: "list".into(),
172 got: right.into(),
173 }),
174 _ => Err(EvalError::TypeError {
175 span: left_span,
176 expected: "number | string | list".into(),
177 got: left.into(),
178 }),
179 },
180 BinaryOperator::Subtract => match (left.clone(), right.clone()) {
181 (Value::Number(left), Value::Number(right)) => {
182 Ok(Value::Number(left - right))
183 }
184 (Value::Number(_left), right) => Err(EvalError::TypeError {
185 span: right_span,
186 expected: "number".into(),
187 got: right.into(),
188 }),
189 _ => Err(EvalError::TypeError {
190 span: left_span,
191 expected: "number".into(),
192 got: left.into(),
193 }),
194 },
195 BinaryOperator::Multiply => match (left.clone(), right.clone()) {
196 (Value::Number(left), Value::Number(right)) => {
197 Ok(Value::Number(left * right))
198 }
199 (Value::Number(_left), right) => Err(EvalError::TypeError {
200 span: right_span,
201 expected: "number".into(),
202 got: right.into(),
203 }),
204 _ => Err(EvalError::TypeError {
205 span: left_span,
206 expected: "number".into(),
207 got: left.into(),
208 }),
209 },
210 BinaryOperator::Divide => match (left.clone(), right.clone()) {
211 (Value::Number(left), Value::Number(right)) => {
212 Ok(Value::Number(left / right))
213 }
214 (Value::Number(_left), right) => Err(EvalError::TypeError {
215 span: right_span,
216 expected: "number".into(),
217 got: right.into(),
218 }),
219 _ => Err(EvalError::TypeError {
220 span: left_span,
221 expected: "number".into(),
222 got: left.into(),
223 }),
224 },
225 BinaryOperator::Rem => match (left.clone(), right.clone()) {
226 (Value::Number(left), Value::Number(right)) => {
227 Ok(Value::Number(left % right))
228 }
229 (Value::Number(_left), right) => Err(EvalError::TypeError {
230 span: right_span,
231 expected: "number".into(),
232 got: right.into(),
233 }),
234 _ => Err(EvalError::TypeError {
235 span: left_span,
236 expected: "number".into(),
237 got: left.into(),
238 }),
239 },
240 BinaryOperator::Xor => match (left.clone(), right.clone()) {
241 (Value::Boolean(left), Value::Boolean(right)) => {
242 Ok(Value::Boolean(left ^ right))
243 }
244 (Value::Boolean(_left), right) => Err(EvalError::TypeError {
245 span: right_span,
246 expected: "boolean".into(),
247 got: right.into(),
248 }),
249 _ => Err(EvalError::TypeError {
250 span: left_span,
251 expected: "boolean".into(),
252 got: left.into(),
253 }),
254 },
255 BinaryOperator::Greater => match (left.clone(), right.clone()) {
256 (Value::Number(left), Value::Number(right)) => {
257 Ok(Value::Boolean(left > right))
258 }
259 (Value::Number(_left), right) => Err(EvalError::TypeError {
260 span: right_span,
261 expected: "number".into(),
262 got: right.into(),
263 }),
264 _ => Err(EvalError::TypeError {
265 span: left_span,
266 expected: "number".into(),
267 got: left.into(),
268 }),
269 },
270 BinaryOperator::GreaterEqual => match (left.clone(), right.clone()) {
271 (Value::Number(left), Value::Number(right)) => {
272 Ok(Value::Boolean(left >= right))
273 }
274 (Value::Number(_left), right) => Err(EvalError::TypeError {
275 span: right_span,
276 expected: "number".into(),
277 got: right.into(),
278 }),
279 _ => Err(EvalError::TypeError {
280 span: left_span,
281 expected: "number".into(),
282 got: left.into(),
283 }),
284 },
285 BinaryOperator::Less => match (left.clone(), right.clone()) {
286 (Value::Number(left), Value::Number(right)) => {
287 Ok(Value::Boolean(left < right))
288 }
289 (Value::Number(_left), right) => Err(EvalError::TypeError {
290 span: right_span,
291 expected: "number".into(),
292 got: right.into(),
293 }),
294 _ => Err(EvalError::TypeError {
295 span: left_span,
296 expected: "number".into(),
297 got: left.into(),
298 }),
299 },
300 BinaryOperator::LessEqual => match (left.clone(), right.clone()) {
301 (Value::Number(left), Value::Number(right)) => {
302 Ok(Value::Boolean(left <= right))
303 }
304 (Value::Number(_left), right) => Err(EvalError::TypeError {
305 span: right_span,
306 expected: "number".into(),
307 got: right.into(),
308 }),
309 _ => Err(EvalError::TypeError {
310 span: left_span,
311 expected: "number".into(),
312 got: left.into(),
313 }),
314 },
315 BinaryOperator::Equal => Ok(Value::Boolean(left == right)),
316 BinaryOperator::NotEqual => Ok(Value::Boolean(left != right)),
317 }?;
318 Ok(Spanned::new(value, span))
319 }
320 }
321 }
322
323 fn boolean(
324 &self,
325 span: Span,
326 left: Value,
327 right: &SpannedExpression,
328 full_evaluate_on: bool,
329 ) -> Result<SpannedValue> {
330 let left: bool = left.into();
331 let value = if left == full_evaluate_on {
332 let right = self.expression(right)?.into_inner();
334 let right: bool = right.into();
335 Value::Boolean(right)
336 } else {
337 Value::Boolean(left) };
339 Ok(Spanned::new(value, span))
340 }
341
342 fn list(&self, span: Span, items: &Vec<SpannedExpression>) -> Result<SpannedValue> {
343 let mut next_items = Vec::with_capacity(items.len());
344 for item in items {
345 let next_item = self.expression(item)?;
346 next_items.push(next_item);
347 }
348 let value = Value::List(next_items);
349 Ok(Spanned::new(value, span))
350 }
351
352 fn object(
353 &self,
354 span: Span,
355 entries: &[(Spanned<String>, SpannedExpression)],
356 ) -> Result<SpannedValue> {
357 let mut object = ValueObject::new();
358 for (key, value) in entries.iter() {
359 let key = key.clone().into_inner();
360 let value = self.expression(value)?;
361 object.insert(key, value);
362 }
363 let value = Value::Object(object);
364 Ok(Spanned::new(value, span))
365 }
366
367 fn variable(&self, span: Span, var: &str) -> Result<SpannedValue> {
368 let value = self
369 .env
370 .borrow()
371 .get(var)
372 .ok_or_else(|| EvalError::MissingVariable {
373 span: span.clone(),
374 var: var.to_string(),
375 })?;
376 Ok(value.with_span(span))
377 }
378
379 fn call(
380 &self,
381 span: Span,
382 function: &SpannedExpression,
383 args: &[SpannedExpression],
384 ) -> Result<SpannedValue> {
385 let Value::Function(function) = self.expression(function)?.into_inner() else {
386 return Err(EvalError::CallNonFunction {
387 span: function.span(),
388 expr: function.clone().into_inner(),
389 });
390 };
391
392 let args: Vec<SpannedValue> = args
393 .iter()
394 .map(|expression| self.expression(expression))
395 .collect::<Result<Vec<SpannedValue>>>()?;
396
397 common::call(span, function, &args)
398 }
399
400 fn get_index(
401 &self,
402 span: Span,
403 container: &SpannedExpression,
404 index: &SpannedExpression,
405 ) -> Result<SpannedValue> {
406 let (container, container_span) = self.expression(container)?.take();
407 let (index, index_span) = self.expression(index)?.take();
408
409 let value = match (container.clone(), index.clone()) {
410 (Value::List(list), index_value) => {
411 let index = get_index(container_span, index_span, index_value, list.len(), false)?;
412 list[index as usize].clone()
413 }
414 (Value::String(string), index_value) => {
415 let index =
416 get_index(container_span, index_span, index_value, string.len(), false)?;
417 let ch = string[index as usize..].chars().next().unwrap();
418 Spanned::new(Value::String(ch.into()), span.clone())
419 }
420 (Value::Object(object), Value::String(key)) => object
421 .get(&key)
422 .map(Clone::clone)
423 .ok_or_else(|| EvalError::KeyNotFound {
424 object_span: container_span,
425 object: convert_value_object_to_serde_value_object(object),
426 key_span: index_span,
427 key: key.clone(),
428 })?,
429 (Value::Object(_list), _) => {
430 return Err(EvalError::TypeError {
431 span: index_span,
432 expected: "string".into(),
433 got: index.into(),
434 })
435 }
436 _ => {
437 return Err(EvalError::TypeError {
438 span: container_span,
439 expected: "list | string | object".into(),
440 got: container.into(),
441 })
442 }
443 };
444
445 Ok(Spanned::new(value.into_inner(), span))
446 }
447
448 fn get_key(
449 &self,
450 span: Span,
451 container: &SpannedExpression,
452 key: &Spanned<String>,
453 ) -> Result<SpannedValue> {
454 let (container, container_span) = self.expression(container)?.take();
455
456 let Value::Object(object) = container.clone() else {
457 return Err(EvalError::TypeError {
458 span: container_span,
459 expected: "object".into(),
460 got: container.into(),
461 });
462 };
463
464 let value = object
465 .get(key.inner())
466 .ok_or_else(|| EvalError::KeyNotFound {
467 object_span: container_span,
468 object: convert_value_object_to_serde_value_object(object.clone()),
469 key: key.clone().into_inner(),
470 key_span: key.span(),
471 })
472 .map(Clone::clone)?;
473
474 Ok(Spanned::new(value.into_inner(), span))
475 }
476
477 fn get_slice(
478 &self,
479 span: Span,
480 container: &SpannedExpression,
481 start: Option<&SpannedExpression>,
482 end: Option<&SpannedExpression>,
483 ) -> Result<SpannedValue> {
484 let (container, container_span) = self.expression(container)?.take();
485 let start = match start {
486 Some(start) => Some(self.expression(start)?.take()),
487 None => None,
488 };
489 let end = match end {
490 Some(end) => Some(self.expression(end)?.take()),
491 None => None,
492 };
493
494 let value = match container.clone() {
495 Value::List(list) => {
496 let length = list.len();
497 match (start.clone(), end.clone()) {
498 (None, None) => Value::List(list),
499 (Some((start, start_span)), None) => {
500 let start = get_index(container_span, start_span, start, length, false)?;
501 Value::List(list[start..].to_vec())
502 }
503 (None, Some((end, end_span))) => {
504 let end = get_index(container_span, end_span, end, length, true)?;
505 Value::List(list[..end].to_vec())
506 }
507 (Some((start, start_span)), Some((end, end_span))) => {
508 let start =
509 get_index(container_span.clone(), start_span, start, length, false)?;
510 let end = get_index(container_span.clone(), end_span, end, length, true)?;
511 if start >= end {
512 return Err(EvalError::RangeStartGreaterThanOrEqualToEnd {
513 span,
514 start,
515 end,
516 });
517 }
518 Value::List(list[start..end].to_vec())
519 }
520 }
521 }
522 Value::String(string) => {
523 let length = string.len();
524 match (start.clone(), end.clone()) {
525 (None, None) => Value::String(string),
526 (Some((start, start_span)), None) => {
527 let start = get_index(container_span, start_span, start, length, false)?;
528 Value::String(string[start..].to_string())
529 }
530 (None, Some((end, end_span))) => {
531 let end = get_index(container_span, end_span, end, length, true)?;
532 Value::String(string[..end].to_string())
533 }
534 (Some((start, start_span)), Some((end, end_span))) => {
535 let start =
536 get_index(container_span.clone(), start_span, start, length, false)?;
537 let end = get_index(container_span.clone(), end_span, end, length, true)?;
538 if start >= end {
539 return Err(EvalError::RangeStartGreaterThanOrEqualToEnd {
540 span,
541 start,
542 end,
543 });
544 }
545 Value::String(string[start..end].to_string())
546 }
547 }
548 }
549 _ => {
550 return Err(EvalError::TypeError {
551 span: container_span,
552 expected: "list".into(),
553 got: container.into(),
554 })
555 }
556 };
557
558 Ok(Spanned::new(value, span))
559 }
560}
561
562fn get_index(
563 container_span: Span,
564 value_span: Span,
565 value: Value,
566 length: usize,
567 is_range_end: bool,
568) -> Result<usize> {
569 let Value::Number(number) = value else {
570 return Err(EvalError::TypeError {
571 span: value_span,
572 expected: "number".into(),
573 got: value.into(),
574 });
575 };
576 let number = if number.is_integer() {
577 number.to_isize()
578 } else {
579 None
580 };
581 let Some(mut index) = number else {
582 return Err(EvalError::TypeError {
583 span: value_span,
584 expected: "integer".into(),
585 got: value.into(),
586 });
587 };
588 let is_under = index <= -(length as isize);
589 let is_over = if !is_range_end {
590 index >= length as isize
591 } else {
592 index > length as isize
593 };
594 if is_under || is_over {
595 return Err(EvalError::IndexOutOfBounds {
596 container_span,
597 index_span: value_span,
598 index,
599 length,
600 });
601 }
602 if index < 0 {
604 index += length as isize
605 }
606 Ok(index as usize)
607}
608
609#[cfg(test)]
610mod tests {
611 use indexmap::IndexMap;
612 use std::{cell::RefCell, ops::Range, rc::Rc};
613
614 use indexmap::indexmap;
615 use pretty_assertions::assert_eq;
616 use rimu_ast::{BinaryOperator, Expression, SpannedExpression};
617 use rimu_meta::{SourceId, Span, Spanned};
618 use rimu_parse::parse_expression;
619 use rimu_value::{Environment, Function, FunctionBody, SerdeValue};
620 use rust_decimal_macros::dec;
621
622 use super::{evaluate, EvalError};
623
624 fn span(range: Range<usize>) -> Span {
625 Span::new(SourceId::empty(), range.start, range.end)
626 }
627
628 fn test_expression(
629 expr: SpannedExpression,
630 env_object: Option<IndexMap<String, SerdeValue>>,
631 ) -> Result<SerdeValue, EvalError> {
632 let mut env = Environment::new();
633 if let Some(env_object) = env_object {
634 for (key, value) in env_object.into_iter() {
635 env.insert(key, value);
636 }
637 }
638
639 let value = evaluate(&expr, Rc::new(RefCell::new(env)))?;
640 let value: SerdeValue = value.into();
641 Ok(value)
642 }
643
644 fn test_code(
645 code: &str,
646 env_object: Option<IndexMap<String, SerdeValue>>,
647 ) -> Result<SerdeValue, EvalError> {
648 let (Some(expr), errors) = parse_expression(code, SourceId::empty()) else {
649 panic!()
650 };
651 assert_eq!(errors.len(), 0);
652 test_expression(expr, env_object)
653 }
654
655 #[test]
656 fn simple_null() {
657 let expr = Spanned::new(Expression::Null, span(0..1));
658 let actual = test_expression(expr, None);
659
660 let expected = Ok(SerdeValue::Null);
661
662 assert_eq!(actual, expected);
663 }
664
665 #[test]
666 fn simple_bool() {
667 let expr = Spanned::new(Expression::Boolean(false), span(0..1));
668 let actual = test_expression(expr, None);
669
670 let expected = Ok(SerdeValue::Boolean(false));
671
672 assert_eq!(actual, expected);
673 }
674
675 #[test]
676 fn simple_number() {
677 let number = dec!(9001);
678 let expr = Spanned::new(Expression::Number(number), span(0..1));
679 let actual = test_expression(expr, None);
680
681 let expected = Ok(SerdeValue::Number(number.into()));
682
683 assert_eq!(actual, expected);
684 }
685
686 #[test]
687 fn simple_list() {
688 let expr = Spanned::new(
689 Expression::List(vec![
690 Spanned::new(Expression::String("hello".into()), span(1..2)),
691 Spanned::new(Expression::Boolean(true), span(3..4)),
692 Spanned::new(Expression::String("world".into()), span(5..6)),
693 ]),
694 span(0..8),
695 );
696 let actual = test_expression(expr, None);
697
698 let expected = Ok(SerdeValue::List(vec![
699 SerdeValue::String("hello".into()),
700 SerdeValue::Boolean(true),
701 SerdeValue::String("world".into()),
702 ]));
703
704 assert_eq!(actual, expected);
705 }
706
707 #[test]
708 fn simple_object() {
709 let expr = Spanned::new(
710 Expression::Object(vec![
711 (
712 Spanned::new("a".into(), span(1..2)),
713 Spanned::new(Expression::String("hello".into()), span(3..4)),
714 ),
715 (
716 Spanned::new("b".into(), span(5..6)),
717 Spanned::new(Expression::String("world".into()), span(7..8)),
718 ),
719 ]),
720 span(0..10),
721 );
722 let actual = test_expression(expr, None);
723
724 let expected = Ok(SerdeValue::Object(indexmap! {
725 "a".into() => "hello".into(),
726 "b".into() => "world".into(),
727 }));
728
729 assert_eq!(actual, expected);
730 }
731
732 #[test]
733 fn simple_function_call() {
734 let env = indexmap! {
735 "add".into() => SerdeValue::Function(Function {
736 args: vec!["a".into(), "b".into()],
737 body: FunctionBody::Expression(Spanned::new(
738 Expression::Binary {
739 left: Box::new(Spanned::new(
740 Expression::Identifier("a".into()),
741 span(0..1),
742 )),
743 operator: BinaryOperator::Add,
744 right: Box::new(Spanned::new(
745 Expression::Identifier("b".into()),
746 span(2..3),
747 )),
748 },
749 span(0..3),
750 )),
751 env: Rc::new(RefCell::new(Environment::new())),
752 }),
753 "one".into() => SerdeValue::Number(dec!(1).into()),
754 "two".into() => SerdeValue::Number(dec!(2).into()),
755 };
756
757 let expr = Spanned::new(
758 Expression::Call {
759 function: Box::new(Spanned::new(
760 Expression::Identifier("add".into()),
761 span(0..1),
762 )),
763 args: vec![
764 Spanned::new(Expression::Identifier("one".into()), span(2..3)),
765 Spanned::new(Expression::Identifier("two".into()), span(4..5)),
766 ],
767 },
768 span(0..7),
769 );
770
771 let actual = test_expression(expr, Some(env));
772
773 let expected = Ok(SerdeValue::Number(dec!(3).into()));
774
775 assert_eq!(actual, expected);
776 }
777
778 #[test]
779 fn arithmetic() {
780 let env = indexmap! {
781 "x".into() => SerdeValue::Number(dec!(10).into()),
782 "y".into() => SerdeValue::Number(dec!(20).into()),
783 "z".into() => SerdeValue::Number(dec!(40).into()),
784 "w".into() => SerdeValue::Number(dec!(80).into()),
785 };
786 let actual = test_code("x + y * (z / w)", Some(env));
787
788 let expected = Ok(SerdeValue::Number(dec!(20).into()));
789
790 assert_eq!(actual, expected);
791 }
792
793 #[test]
794 fn get_list_index() {
795 let env = indexmap! {
796 "list".into() => SerdeValue::List(vec![
797 SerdeValue::String("a".into()),
798 SerdeValue::String("b".into()),
799 SerdeValue::String("c".into()),
800 SerdeValue::String("d".into()),
801 ]),
802 };
804 let actual = test_code("list[2]", Some(env));
806
807 let expected = Ok(SerdeValue::String("c".into()));
808
809 assert_eq!(actual, expected);
810 }
811
812 #[test]
813 fn get_list_index_negative() {
814 let env = indexmap! {
815 "list".into() => SerdeValue::List(vec![
816 SerdeValue::String("a".into()),
817 SerdeValue::String("b".into()),
818 SerdeValue::String("c".into()),
819 SerdeValue::String("d".into()),
820 ]),
821 };
823 let actual = test_code("list[-2]", Some(env));
825
826 let expected = Ok(SerdeValue::String("c".into()));
827
828 assert_eq!(actual, expected);
829 }
830
831 #[test]
832 fn get_key() {
833 let env = indexmap! {
834 "object".into() => SerdeValue::Object(indexmap! {
835 "a".into() => SerdeValue::String("apple".into()),
836 "b".into() => SerdeValue::String("bear".into()),
837 "c".into() => SerdeValue::String("cranberry".into()),
838 "d".into() => SerdeValue::String("dog".into()),
839 }),
840 };
841 let actual = test_code("object.a", Some(env));
842
843 let expected = Ok(SerdeValue::String("apple".into()));
844
845 assert_eq!(actual, expected);
846 }
847
848 #[test]
849 fn get_slice_start_end() {
850 let env = indexmap! {
851 "list".into() => SerdeValue::List(vec![
852 SerdeValue::String("a".into()),
853 SerdeValue::String("b".into()),
854 SerdeValue::String("c".into()),
855 SerdeValue::String("d".into()),
856 SerdeValue::String("e".into()),
857 ]),
858 "start".into() => SerdeValue::Number(dec!(1).into()),
859 "end".into() => SerdeValue::Number(dec!(3).into()),
860 };
861 let actual = test_code("list[start:end]", Some(env));
862
863 let expected = Ok(SerdeValue::List(vec![
864 SerdeValue::String("b".into()),
865 SerdeValue::String("c".into()),
866 ]));
867
868 assert_eq!(actual, expected);
869 }
870}