1use crate::ast::Ast;
20use crate::ast::BinaryOperator;
21use crate::ast::PostfixOperator;
22use crate::ast::PrefixOperator;
23use crate::env::Env;
24use crate::token::Term;
25use crate::token::Value;
26use std::ops::Range;
27use thiserror::Error;
28
29#[derive(Clone, Debug, Eq, Error, Hash, PartialEq)]
34pub enum EvalError<E1, E2> {
35 #[error("invalid variable value: {0:?}")]
37 InvalidVariableValue(String),
38 #[error("overflow")]
40 Overflow,
41 #[error("division by zero")]
43 DivisionByZero,
44 #[error("left-shifting a negative integer")]
46 LeftShiftingNegative,
47 #[error("negative shift width")]
49 ReverseShifting,
50 #[error("assignment to a non-variable")]
52 AssignmentToValue,
53 #[error(transparent)]
58 GetVariableError(E1),
59 #[error(transparent)]
64 AssignVariableError(E2),
65}
66
67#[derive(Clone, Debug, Eq, Error, Hash, PartialEq)]
69#[error("{cause}")]
70pub struct Error<E1, E2> {
71 pub cause: EvalError<E1, E2>,
73 pub location: Range<usize>,
75}
76
77fn expand_variable<E: Env>(
79 name: &str,
80 location: &Range<usize>,
81 env: &E,
82) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
83 match env.get_variable(name) {
84 Ok(None) => Ok(Value::Integer(0)),
85 Ok(Some(value)) => match value.parse() {
87 Ok(number) => Ok(Value::Integer(number)),
88 Err(_) => Err(Error {
89 cause: EvalError::InvalidVariableValue(value.to_string()),
90 location: location.clone(),
91 }),
92 },
93 Err(e) => Err(Error {
94 cause: EvalError::GetVariableError(e),
95 location: location.clone(),
96 }),
97 }
98}
99
100pub fn into_value<E: Env>(
102 term: Term,
103 env: &E,
104) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
105 match term {
106 Term::Value(value) => Ok(value),
107 Term::Variable { name, location } => expand_variable(name, &location, env),
108 }
109}
110
111fn require_variable<'a, E1, E2>(
116 term: Term<'a>,
117 op_location: &Range<usize>,
118) -> Result<(&'a str, Range<usize>), Error<E1, E2>> {
119 match term {
120 Term::Variable { name, location } => Ok((name, location)),
121 Term::Value(_) => Err(Error {
122 cause: EvalError::AssignmentToValue,
123 location: op_location.clone(),
124 }),
125 }
126}
127
128fn unwrap_or_overflow<T, E1, E2>(
130 checked_computation: Option<T>,
131 location: &Range<usize>,
132) -> Result<T, Error<E1, E2>> {
133 checked_computation.ok_or_else(|| Error {
134 cause: EvalError::Overflow,
135 location: location.clone(),
136 })
137}
138
139fn assign<E: Env>(
141 name: &str,
142 value: Value,
143 location: Range<usize>,
144 env: &mut E,
145) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
146 match env.assign_variable(name, value.to_string(), location.clone()) {
147 Ok(()) => Ok(value),
148 Err(e) => Err(Error {
149 cause: EvalError::AssignVariableError(e),
150 location,
151 }),
152 }
153}
154
155fn apply_prefix<E: Env>(
157 term: Term,
158 operator: PrefixOperator,
159 op_location: &Range<usize>,
160 env: &mut E,
161) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
162 match operator {
163 PrefixOperator::Increment => {
164 let (name, location) = require_variable(term, op_location)?;
165 match expand_variable(name, &location, env)? {
166 Value::Integer(value) => {
167 let new_value =
168 Value::Integer(unwrap_or_overflow(value.checked_add(1), op_location)?);
169 assign(name, new_value, location, env)
170 }
171 }
172 }
173 PrefixOperator::Decrement => {
174 let (name, location) = require_variable(term, op_location)?;
175 match expand_variable(name, &location, env)? {
176 Value::Integer(value) => {
177 let new_value =
178 Value::Integer(unwrap_or_overflow(value.checked_sub(1), op_location)?);
179 assign(name, new_value, location, env)
180 }
181 }
182 }
183 PrefixOperator::NumericCoercion => into_value(term, env),
184 PrefixOperator::NumericNegation => match into_value(term, env)? {
185 Value::Integer(value) => match value.checked_neg() {
186 Some(result) => Ok(Value::Integer(result)),
187 None => Err(Error {
188 cause: EvalError::Overflow,
189 location: op_location.clone(),
190 }),
191 },
192 },
193 PrefixOperator::LogicalNegation => match into_value(term, env)? {
194 Value::Integer(value) => Ok(Value::Integer((value == 0) as _)),
195 },
196 PrefixOperator::BitwiseNegation => match into_value(term, env)? {
197 Value::Integer(value) => Ok(Value::Integer(!value)),
198 },
199 }
200}
201
202fn apply_postfix<E: Env>(
204 term: Term,
205 operator: PostfixOperator,
206 op_location: &Range<usize>,
207 env: &mut E,
208) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
209 let (name, location) = require_variable(term, op_location)?;
210 match expand_variable(name, &location, env)? {
211 old_value @ Value::Integer(value) => {
212 let result = match operator {
213 PostfixOperator::Increment => value.checked_add(1),
214 PostfixOperator::Decrement => value.checked_sub(1),
215 };
216 let new_value = Value::Integer(unwrap_or_overflow(result, op_location)?);
217 assign(name, new_value, location, env)?;
218 Ok(old_value)
219 }
220 }
221}
222
223fn binary_result<E1, E2>(
228 lhs: Value,
229 rhs: Value,
230 operator: BinaryOperator,
231 op_location: &Range<usize>,
232) -> Result<Value, Error<E1, E2>> {
233 fn require_non_negative<E1, E2>(v: i64, location: &Range<usize>) -> Result<u32, Error<E1, E2>> {
234 v.try_into().map_err(|_| Error {
235 cause: if v < 0 {
236 EvalError::ReverseShifting
237 } else {
238 EvalError::Overflow
239 },
240 location: location.clone(),
241 })
242 }
243 fn require_non_zero<E1, E2>(v: i64, location: &Range<usize>) -> Result<(), Error<E1, E2>> {
244 if v != 0 {
245 Ok(())
246 } else {
247 Err(Error {
248 cause: EvalError::DivisionByZero,
249 location: location.clone(),
250 })
251 }
252 }
253
254 let Value::Integer(lhs) = lhs;
255 let Value::Integer(rhs) = rhs;
256 use BinaryOperator::*;
257 let result = match operator {
258 LogicalOr => Some((lhs != 0 || rhs != 0) as _),
259 LogicalAnd => Some((lhs != 0 && rhs != 0) as _),
260 BitwiseOr | BitwiseOrAssign => Some(lhs | rhs),
261 BitwiseXor | BitwiseXorAssign => Some(lhs ^ rhs),
262 BitwiseAnd | BitwiseAndAssign => Some(lhs & rhs),
263 EqualTo => Some((lhs == rhs) as _),
264 NotEqualTo => Some((lhs != rhs) as _),
265 LessThan => Some((lhs < rhs) as _),
266 GreaterThan => Some((lhs > rhs) as _),
267 LessThanOrEqualTo => Some((lhs <= rhs) as _),
268 GreaterThanOrEqualTo => Some((lhs >= rhs) as _),
269 ShiftLeft | ShiftLeftAssign => {
270 if lhs < 0 {
271 return Err(Error {
272 cause: EvalError::LeftShiftingNegative,
273 location: op_location.clone(),
274 });
275 }
276 let rhs = require_non_negative(rhs, op_location)?;
277 lhs.checked_shl(rhs)
278 .filter(|&result| result >= 0 && result >> rhs == lhs)
279 }
280 ShiftRight | ShiftRightAssign => {
281 let rhs = require_non_negative(rhs, op_location)?;
282 lhs.checked_shr(rhs)
283 }
284 Add | AddAssign => lhs.checked_add(rhs),
285 Subtract | SubtractAssign => lhs.checked_sub(rhs),
286 Multiply | MultiplyAssign => lhs.checked_mul(rhs),
287 Divide | DivideAssign => {
288 require_non_zero(rhs, op_location)?;
289 lhs.checked_div(rhs)
290 }
291 Remainder | RemainderAssign => {
292 require_non_zero(rhs, op_location)?;
293 lhs.checked_rem(rhs)
294 }
295 Assign => Some(rhs),
296 };
297 let result = unwrap_or_overflow(result, op_location)?;
298 Ok(Value::Integer(result))
299}
300
301fn apply_binary<'a, E: Env>(
303 lhs: Term<'a>,
304 rhs: Term<'a>,
305 operator: BinaryOperator,
306 op_location: &Range<usize>,
307 env: &mut E,
308) -> Result<Value, Error<E::GetVariableError, E::AssignVariableError>> {
309 use BinaryOperator::*;
310 match operator {
311 LogicalOr | LogicalAnd | BitwiseOr | BitwiseXor | BitwiseAnd | EqualTo | NotEqualTo
312 | LessThan | GreaterThan | LessThanOrEqualTo | GreaterThanOrEqualTo | ShiftLeft
313 | ShiftRight | Add | Subtract | Multiply | Divide | Remainder => {
314 let lhs = into_value(lhs, env)?;
315 let rhs = into_value(rhs, env)?;
316 binary_result(lhs, rhs, operator, op_location)
317 }
318 Assign => {
319 let (name, location) = require_variable(lhs, op_location)?;
320 let value = into_value(rhs, env)?;
321 assign(name, value, location, env)
322 }
323 BitwiseOrAssign | BitwiseXorAssign | BitwiseAndAssign | ShiftLeftAssign
324 | ShiftRightAssign | AddAssign | SubtractAssign | MultiplyAssign | DivideAssign
325 | RemainderAssign => {
326 let (name, location) = require_variable(lhs, op_location)?;
327 let lhs = expand_variable(name, &location, env)?;
328 let rhs = into_value(rhs, env)?;
329 let result = binary_result(lhs, rhs, operator, op_location)?;
330 assign(name, result, location, env)
331 }
332 }
333}
334
335pub fn eval<'a, E: Env>(
339 ast: &[Ast<'a>],
340 env: &mut E,
341) -> Result<Term<'a>, Error<E::GetVariableError, E::AssignVariableError>> {
342 let (root, children) = ast
343 .split_last()
344 .expect("the expression should not be empty");
345 match root {
346 Ast::Term(term) => Ok(term.clone()),
347
348 Ast::Prefix { operator, location } => {
349 let term = eval(children, env)?;
350 apply_prefix(term, *operator, location, env).map(Term::Value)
351 }
352
353 Ast::Postfix { operator, location } => {
354 let term = eval(children, env)?;
355 apply_postfix(term, *operator, location, env).map(Term::Value)
356 }
357
358 Ast::Binary {
359 operator: BinaryOperator::LogicalOr,
360 rhs_len,
361 location,
362 } => {
363 let (lhs_ast, rhs_ast) = children.split_at(children.len() - rhs_len);
364 let lhs = into_value(eval(lhs_ast, env)?, env)?;
365 if lhs != Value::Integer(0) {
366 return Ok(Term::Value(Value::Integer(1)));
367 }
368 let rhs = into_value(eval(rhs_ast, env)?, env)?;
369 binary_result(lhs, rhs, BinaryOperator::LogicalOr, location).map(Term::Value)
370 }
371
372 Ast::Binary {
373 operator: BinaryOperator::LogicalAnd,
374 rhs_len,
375 location,
376 } => {
377 let (lhs_ast, rhs_ast) = children.split_at(children.len() - rhs_len);
378 let lhs = into_value(eval(lhs_ast, env)?, env)?;
379 if lhs == Value::Integer(0) {
380 return Ok(Term::Value(Value::Integer(0)));
381 }
382 let rhs = into_value(eval(rhs_ast, env)?, env)?;
383 binary_result(lhs, rhs, BinaryOperator::LogicalAnd, location).map(Term::Value)
384 }
385
386 Ast::Binary {
387 operator,
388 rhs_len,
389 location,
390 } => {
391 let (lhs_ast, rhs_ast) = children.split_at(children.len() - rhs_len);
392 let lhs = eval(lhs_ast, env)?;
393 let rhs = eval(rhs_ast, env)?;
394 apply_binary(lhs, rhs, *operator, location, env).map(Term::Value)
395 }
396
397 Ast::Conditional { then_len, else_len } => {
398 let (children_2, else_ast) = children.split_at(children.len() - else_len);
399 let (condition_ast, then_ast) = children_2.split_at(children_2.len() - then_len);
400 let condition = into_value(eval(condition_ast, env)?, env)?;
401 let result_ast = if condition != Value::Integer(0) {
402 then_ast
403 } else {
404 else_ast
405 };
406 eval(result_ast, env)
407 }
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414 use std::collections::HashMap;
415 use std::convert::Infallible;
416
417 #[test]
418 fn expand_variable_non_existing() {
419 let env = &mut HashMap::new();
420 assert_eq!(expand_variable("a", &(10..11), env), Ok(Value::Integer(0)));
421 assert_eq!(expand_variable("b", &(11..12), env), Ok(Value::Integer(0)));
422 }
423
424 #[test]
425 fn expand_variable_valid() {
426 let env = &mut HashMap::new();
427 env.insert("a".to_string(), "42".to_string());
428 env.insert("b".to_string(), "-123".to_string());
429 assert_eq!(expand_variable("a", &(10..11), env), Ok(Value::Integer(42)));
430 assert_eq!(
431 expand_variable("b", &(11..12), env),
432 Ok(Value::Integer(-123))
433 );
434 }
435
436 #[test]
437 fn expand_variable_invalid() {
438 let env = &mut HashMap::new();
439 env.insert("a".to_string(), "*".to_string());
440 assert_eq!(
441 expand_variable("a", &(10..11), env),
442 Err(Error {
443 cause: EvalError::InvalidVariableValue("*".to_string()),
444 location: 10..11,
445 })
446 );
447 }
448
449 #[test]
450 fn apply_prefix_increment() {
451 let env = &mut HashMap::new();
452
453 assert_eq!(
454 apply_prefix(
455 Term::Variable {
456 name: "i",
457 location: 6..7
458 },
459 PrefixOperator::Increment,
460 &(3..5),
461 env
462 ),
463 Ok(Value::Integer(1))
464 );
465 assert_eq!(env["i"], "1");
466
467 assert_eq!(
468 apply_prefix(
469 Term::Variable {
470 name: "i",
471 location: 6..7
472 },
473 PrefixOperator::Increment,
474 &(3..5),
475 env
476 ),
477 Ok(Value::Integer(2))
478 );
479 assert_eq!(env["i"], "2");
480 }
481
482 #[test]
483 fn apply_prefix_increment_overflow() {
484 let env = &mut HashMap::new();
485 env.insert("i".to_string(), "9223372036854775807".to_string());
486 assert_eq!(
487 apply_prefix(
488 Term::Variable {
489 name: "i",
490 location: 6..7
491 },
492 PrefixOperator::Increment,
493 &(3..5),
494 env
495 ),
496 Err(Error {
497 cause: EvalError::Overflow,
498 location: 3..5,
499 })
500 );
501 }
502
503 #[test]
504 fn apply_prefix_increment_not_variable() {
505 let env = &mut HashMap::new();
506 assert_eq!(
507 apply_prefix(
508 Term::Value(Value::Integer(3)),
509 PrefixOperator::Increment,
510 &(3..5),
511 env
512 ),
513 Err(Error {
514 cause: EvalError::AssignmentToValue,
515 location: 3..5,
516 })
517 );
518 }
519
520 #[test]
521 fn apply_prefix_decrement() {
522 let env = &mut HashMap::new();
523
524 assert_eq!(
525 apply_prefix(
526 Term::Variable {
527 name: "i",
528 location: 6..7
529 },
530 PrefixOperator::Decrement,
531 &(3..5),
532 env
533 ),
534 Ok(Value::Integer(-1))
535 );
536 assert_eq!(env["i"], "-1");
537
538 assert_eq!(
539 apply_prefix(
540 Term::Variable {
541 name: "i",
542 location: 6..7
543 },
544 PrefixOperator::Decrement,
545 &(3..5),
546 env
547 ),
548 Ok(Value::Integer(-2))
549 );
550 assert_eq!(env["i"], "-2");
551 }
552
553 #[test]
554 fn apply_prefix_decrement_overflow() {
555 let env = &mut HashMap::new();
556 env.insert("i".to_string(), "-9223372036854775808".to_string());
557 assert_eq!(
558 apply_prefix(
559 Term::Variable {
560 name: "i",
561 location: 6..7
562 },
563 PrefixOperator::Decrement,
564 &(3..5),
565 env
566 ),
567 Err(Error {
568 cause: EvalError::Overflow,
569 location: 3..5,
570 })
571 );
572 }
573
574 #[test]
575 fn apply_prefix_decrement_not_variable() {
576 let env = &mut HashMap::new();
577 assert_eq!(
578 apply_prefix(
579 Term::Value(Value::Integer(3)),
580 PrefixOperator::Decrement,
581 &(3..5),
582 env
583 ),
584 Err(Error {
585 cause: EvalError::AssignmentToValue,
586 location: 3..5,
587 })
588 );
589 }
590
591 #[test]
592 fn apply_prefix_numeric_coercion() {
593 let env = &mut HashMap::new();
594 env.insert("a".to_string(), "12".to_string());
595 assert_eq!(
596 apply_prefix(
597 Term::Value(Value::Integer(7)),
598 PrefixOperator::NumericCoercion,
599 &(3..4),
600 env
601 ),
602 Ok(Value::Integer(7))
603 );
604 assert_eq!(
605 apply_prefix(
606 Term::Variable {
607 name: "a",
608 location: 5..7,
609 },
610 PrefixOperator::NumericCoercion,
611 &(3..4),
612 env
613 ),
614 Ok(Value::Integer(12))
615 );
616 }
617
618 #[test]
619 fn apply_prefix_numeric_negation() {
620 let env = &mut HashMap::new();
621 assert_eq!(
622 apply_prefix(
623 Term::Value(Value::Integer(7)),
624 PrefixOperator::NumericNegation,
625 &(3..4),
626 env
627 ),
628 Ok(Value::Integer(-7))
629 );
630 assert_eq!(
631 apply_prefix(
632 Term::Value(Value::Integer(-10)),
633 PrefixOperator::NumericNegation,
634 &(3..4),
635 env
636 ),
637 Ok(Value::Integer(10))
638 );
639 }
640
641 #[test]
642 fn apply_prefix_numeric_negation_overflow() {
643 let env = &mut HashMap::new();
644 assert_eq!(
645 apply_prefix(
646 Term::Value(Value::Integer(i64::MIN)),
647 PrefixOperator::NumericNegation,
648 &(3..4),
649 env
650 ),
651 Err(Error {
652 cause: EvalError::Overflow,
653 location: 3..4,
654 })
655 );
656 }
657
658 #[test]
659 fn apply_prefix_logical_negation() {
660 let env = &mut HashMap::new();
661 assert_eq!(
662 apply_prefix(
663 Term::Value(Value::Integer(0)),
664 PrefixOperator::LogicalNegation,
665 &(3..4),
666 env
667 ),
668 Ok(Value::Integer(1))
669 );
670
671 for i in [-1, 1, 2, 100, i64::MAX, i64::MIN] {
672 assert_eq!(
673 apply_prefix(
674 Term::Value(Value::Integer(i)),
675 PrefixOperator::LogicalNegation,
676 &(3..4),
677 env
678 ),
679 Ok(Value::Integer(0)),
680 "i={i:?}"
681 );
682 }
683 }
684
685 #[test]
686 fn apply_prefix_bitwise_negation() {
687 let env = &mut HashMap::new();
688 assert_eq!(
689 apply_prefix(
690 Term::Value(Value::Integer(0)),
691 PrefixOperator::BitwiseNegation,
692 &(3..4),
693 env
694 ),
695 Ok(Value::Integer(!0))
696 );
697 assert_eq!(
698 apply_prefix(
699 Term::Value(Value::Integer(-10000)),
700 PrefixOperator::BitwiseNegation,
701 &(3..4),
702 env
703 ),
704 Ok(Value::Integer(!-10000))
705 );
706 }
707
708 #[test]
709 fn apply_postfix_increment() {
710 let env = &mut HashMap::new();
711
712 assert_eq!(
713 apply_postfix(
714 Term::Variable {
715 name: "i",
716 location: 0..1,
717 },
718 PostfixOperator::Increment,
719 &(3..5),
720 env
721 ),
722 Ok(Value::Integer(0))
723 );
724 assert_eq!(env["i"], "1");
725
726 assert_eq!(
727 apply_postfix(
728 Term::Variable {
729 name: "i",
730 location: 0..1,
731 },
732 PostfixOperator::Increment,
733 &(3..5),
734 env
735 ),
736 Ok(Value::Integer(1))
737 );
738 assert_eq!(env["i"], "2");
739 }
740
741 #[test]
742 fn apply_postfix_increment_overflow() {
743 let env = &mut HashMap::new();
744 env.insert("i".to_string(), "9223372036854775807".to_string());
745 assert_eq!(
746 apply_postfix(
747 Term::Variable {
748 name: "i",
749 location: 0..1,
750 },
751 PostfixOperator::Increment,
752 &(3..5),
753 env
754 ),
755 Err(Error {
756 cause: EvalError::Overflow,
757 location: 3..5,
758 })
759 );
760 }
761
762 #[test]
763 fn apply_postfix_increment_not_variable() {
764 let env = &mut HashMap::new();
765 assert_eq!(
766 apply_postfix(
767 Term::Value(Value::Integer(13)),
768 PostfixOperator::Increment,
769 &(3..5),
770 env
771 ),
772 Err(Error {
773 cause: EvalError::AssignmentToValue,
774 location: 3..5,
775 })
776 );
777 }
778
779 #[test]
780 fn apply_postfix_decrement() {
781 let env = &mut HashMap::new();
782
783 assert_eq!(
784 apply_postfix(
785 Term::Variable {
786 name: "i",
787 location: 0..1,
788 },
789 PostfixOperator::Decrement,
790 &(3..5),
791 env
792 ),
793 Ok(Value::Integer(0))
794 );
795 assert_eq!(env["i"], "-1");
796
797 assert_eq!(
798 apply_postfix(
799 Term::Variable {
800 name: "i",
801 location: 0..1,
802 },
803 PostfixOperator::Decrement,
804 &(3..5),
805 env
806 ),
807 Ok(Value::Integer(-1))
808 );
809 assert_eq!(env["i"], "-2");
810 }
811
812 #[test]
813 fn apply_postfix_decrement_overflow() {
814 let env = &mut HashMap::new();
815 env.insert("i".to_string(), "-9223372036854775808".to_string());
816 assert_eq!(
817 apply_postfix(
818 Term::Variable {
819 name: "i",
820 location: 0..1,
821 },
822 PostfixOperator::Decrement,
823 &(3..5),
824 env
825 ),
826 Err(Error {
827 cause: EvalError::Overflow,
828 location: 3..5,
829 })
830 );
831 }
832
833 #[test]
834 fn apply_postfix_decrement_not_variable() {
835 let env = &mut HashMap::new();
836 assert_eq!(
837 apply_postfix(
838 Term::Value(Value::Integer(13)),
839 PostfixOperator::Decrement,
840 &(3..5),
841 env
842 ),
843 Err(Error {
844 cause: EvalError::AssignmentToValue,
845 location: 3..5,
846 })
847 );
848 }
849
850 #[test]
851 fn binary_result_logical_or() {
852 let zero = Value::Integer(0);
853 let one = Value::Integer(1);
854 let two = Value::Integer(2);
855 let operator = BinaryOperator::LogicalOr;
856 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
857 assert_eq!(result, Ok(Value::Integer(0)));
858 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
859 assert_eq!(result, Ok(Value::Integer(1)));
860 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
861 assert_eq!(result, Ok(Value::Integer(1)));
862 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
863 assert_eq!(result, Ok(Value::Integer(1)));
864 }
865
866 #[test]
867 fn binary_result_logical_and() {
868 let zero = Value::Integer(0);
869 let one = Value::Integer(1);
870 let two = Value::Integer(2);
871 let operator = BinaryOperator::LogicalAnd;
872 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
873 assert_eq!(result, Ok(Value::Integer(0)));
874 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
875 assert_eq!(result, Ok(Value::Integer(0)));
876 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
877 assert_eq!(result, Ok(Value::Integer(1)));
878 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
879 assert_eq!(result, Ok(Value::Integer(0)));
880 }
881
882 #[test]
883 fn binary_result_bitwise_or() {
884 let zero = Value::Integer(0);
885 let three = Value::Integer(3);
886 let six = Value::Integer(6);
887 for operator in [BinaryOperator::BitwiseOr, BinaryOperator::BitwiseOrAssign] {
888 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..4));
889 assert_eq!(result, Ok(Value::Integer(0)));
890 let result = binary_result::<Infallible, Infallible>(three, zero, operator, &(3..4));
891 assert_eq!(result, Ok(Value::Integer(3)));
892 let result = binary_result::<Infallible, Infallible>(three, six, operator, &(3..4));
893 assert_eq!(result, Ok(Value::Integer(7)));
894 let result = binary_result::<Infallible, Infallible>(zero, six, operator, &(3..4));
895 assert_eq!(result, Ok(Value::Integer(6)));
896 }
897 }
898
899 #[test]
900 fn binary_result_bitwise_xor() {
901 let zero = Value::Integer(0);
902 let three = Value::Integer(3);
903 let six = Value::Integer(6);
904 for operator in [BinaryOperator::BitwiseXor, BinaryOperator::BitwiseXorAssign] {
905 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..4));
906 assert_eq!(result, Ok(Value::Integer(0)));
907 let result = binary_result::<Infallible, Infallible>(three, zero, operator, &(3..4));
908 assert_eq!(result, Ok(Value::Integer(3)));
909 let result = binary_result::<Infallible, Infallible>(three, six, operator, &(3..4));
910 assert_eq!(result, Ok(Value::Integer(5)));
911 let result = binary_result::<Infallible, Infallible>(zero, six, operator, &(3..4));
912 assert_eq!(result, Ok(Value::Integer(6)));
913 }
914 }
915
916 #[test]
917 fn binary_result_bitwise_and() {
918 let zero = Value::Integer(0);
919 let three = Value::Integer(3);
920 let six = Value::Integer(6);
921 for operator in [BinaryOperator::BitwiseAnd, BinaryOperator::BitwiseAndAssign] {
922 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..4));
923 assert_eq!(result, Ok(Value::Integer(0)));
924 let result = binary_result::<Infallible, Infallible>(three, zero, operator, &(3..4));
925 assert_eq!(result, Ok(Value::Integer(0)));
926 let result = binary_result::<Infallible, Infallible>(three, six, operator, &(3..4));
927 assert_eq!(result, Ok(Value::Integer(2)));
928 let result = binary_result::<Infallible, Infallible>(zero, six, operator, &(3..4));
929 assert_eq!(result, Ok(Value::Integer(0)));
930 }
931 }
932
933 #[test]
934 fn binary_result_equal_to() {
935 let zero = Value::Integer(0);
936 let one = Value::Integer(1);
937 let two = Value::Integer(2);
938 let operator = BinaryOperator::EqualTo;
939 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
940 assert_eq!(result, Ok(Value::Integer(1)));
941 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
942 assert_eq!(result, Ok(Value::Integer(1)));
943 let result = binary_result::<Infallible, Infallible>(two, two, operator, &(3..5));
944 assert_eq!(result, Ok(Value::Integer(1)));
945 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
946 assert_eq!(result, Ok(Value::Integer(0)));
947 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
948 assert_eq!(result, Ok(Value::Integer(0)));
949 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
950 assert_eq!(result, Ok(Value::Integer(0)));
951 }
952
953 #[test]
954 fn binary_result_not_equal_to() {
955 let zero = Value::Integer(0);
956 let one = Value::Integer(1);
957 let two = Value::Integer(2);
958 let operator = BinaryOperator::NotEqualTo;
959 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
960 assert_eq!(result, Ok(Value::Integer(0)));
961 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
962 assert_eq!(result, Ok(Value::Integer(0)));
963 let result = binary_result::<Infallible, Infallible>(two, two, operator, &(3..5));
964 assert_eq!(result, Ok(Value::Integer(0)));
965 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
966 assert_eq!(result, Ok(Value::Integer(1)));
967 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
968 assert_eq!(result, Ok(Value::Integer(1)));
969 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
970 assert_eq!(result, Ok(Value::Integer(1)));
971 }
972
973 #[test]
974 fn binary_result_less_than() {
975 let zero = Value::Integer(0);
976 let one = Value::Integer(1);
977 let two = Value::Integer(2);
978 let operator = BinaryOperator::LessThan;
979 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
980 assert_eq!(result, Ok(Value::Integer(0)));
981 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
982 assert_eq!(result, Ok(Value::Integer(0)));
983 let result = binary_result::<Infallible, Infallible>(two, two, operator, &(3..5));
984 assert_eq!(result, Ok(Value::Integer(0)));
985 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
986 assert_eq!(result, Ok(Value::Integer(0)));
987 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
988 assert_eq!(result, Ok(Value::Integer(1)));
989 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
990 assert_eq!(result, Ok(Value::Integer(1)));
991 }
992
993 #[test]
994 fn binary_result_greater_than() {
995 let zero = Value::Integer(0);
996 let one = Value::Integer(1);
997 let two = Value::Integer(2);
998 let operator = BinaryOperator::GreaterThan;
999 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
1000 assert_eq!(result, Ok(Value::Integer(0)));
1001 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
1002 assert_eq!(result, Ok(Value::Integer(0)));
1003 let result = binary_result::<Infallible, Infallible>(two, one, operator, &(3..5));
1004 assert_eq!(result, Ok(Value::Integer(1)));
1005 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
1006 assert_eq!(result, Ok(Value::Integer(1)));
1007 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
1008 assert_eq!(result, Ok(Value::Integer(0)));
1009 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
1010 assert_eq!(result, Ok(Value::Integer(0)));
1011 }
1012
1013 #[test]
1014 fn binary_result_less_than_or_equal_to() {
1015 let zero = Value::Integer(0);
1016 let one = Value::Integer(1);
1017 let two = Value::Integer(2);
1018 let operator = BinaryOperator::LessThanOrEqualTo;
1019 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
1020 assert_eq!(result, Ok(Value::Integer(1)));
1021 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
1022 assert_eq!(result, Ok(Value::Integer(1)));
1023 let result = binary_result::<Infallible, Infallible>(two, one, operator, &(3..5));
1024 assert_eq!(result, Ok(Value::Integer(0)));
1025 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
1026 assert_eq!(result, Ok(Value::Integer(0)));
1027 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
1028 assert_eq!(result, Ok(Value::Integer(1)));
1029 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
1030 assert_eq!(result, Ok(Value::Integer(1)));
1031 }
1032
1033 #[test]
1034 fn binary_result_greater_than_or_equal_to() {
1035 let zero = Value::Integer(0);
1036 let one = Value::Integer(1);
1037 let two = Value::Integer(2);
1038 let operator = BinaryOperator::GreaterThanOrEqualTo;
1039 let result = binary_result::<Infallible, Infallible>(zero, zero, operator, &(3..5));
1040 assert_eq!(result, Ok(Value::Integer(1)));
1041 let result = binary_result::<Infallible, Infallible>(one, one, operator, &(3..5));
1042 assert_eq!(result, Ok(Value::Integer(1)));
1043 let result = binary_result::<Infallible, Infallible>(two, one, operator, &(3..5));
1044 assert_eq!(result, Ok(Value::Integer(1)));
1045 let result = binary_result::<Infallible, Infallible>(one, zero, operator, &(3..5));
1046 assert_eq!(result, Ok(Value::Integer(1)));
1047 let result = binary_result::<Infallible, Infallible>(one, two, operator, &(3..5));
1048 assert_eq!(result, Ok(Value::Integer(0)));
1049 let result = binary_result::<Infallible, Infallible>(zero, two, operator, &(3..5));
1050 assert_eq!(result, Ok(Value::Integer(0)));
1051 }
1052
1053 #[test]
1054 fn binary_result_shift_left() {
1055 let lhs = Value::Integer(0x94E239);
1056 let rhs = Value::Integer(7);
1057 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1058 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1059 assert_eq!(result, Ok(Value::Integer(0x94E239 << 7)));
1060 }
1061 }
1062
1063 #[test]
1064 fn binary_result_shift_left_negative_lhs() {
1065 let lhs = Value::Integer(-1);
1066 let rhs = Value::Integer(0);
1067 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1068 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1069 assert_eq!(
1070 result,
1071 Err(Error {
1072 cause: EvalError::LeftShiftingNegative,
1073 location: 3..4,
1074 })
1075 );
1076 }
1077 }
1078
1079 #[test]
1080 fn binary_result_shift_left_negative_rhs() {
1081 let lhs = Value::Integer(0);
1082 let rhs = Value::Integer(-1);
1083 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1084 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1085 assert_eq!(
1086 result,
1087 Err(Error {
1088 cause: EvalError::ReverseShifting,
1089 location: 3..4,
1090 })
1091 );
1092 }
1093 }
1094
1095 #[test]
1096 fn binary_result_shift_left_too_large_rhs() {
1097 let lhs = Value::Integer(0);
1098 for rhs in [i64::BITS as i64, i64::MAX] {
1099 let rhs = Value::Integer(rhs);
1100 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1101 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1102 assert_eq!(
1103 result,
1104 Err(Error {
1105 cause: EvalError::Overflow,
1106 location: 3..4,
1107 })
1108 );
1109 }
1110 }
1111 }
1112
1113 #[test]
1114 fn binary_result_shift_left_overflow_to_sign_bit() {
1115 let lhs = Value::Integer(0x4000_0000_0000_0000);
1116 let rhs = Value::Integer(1);
1117 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1118 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1119 assert_eq!(
1120 result,
1121 Err(Error {
1122 cause: EvalError::Overflow,
1123 location: 3..4,
1124 })
1125 );
1126 }
1127 }
1128
1129 #[test]
1130 fn binary_result_shift_left_overflow_beyond_sign_bit() {
1131 let lhs = Value::Integer(0x4000_0000_0000_0000);
1132 let rhs = Value::Integer(2);
1133 for operator in [BinaryOperator::ShiftLeft, BinaryOperator::ShiftLeftAssign] {
1134 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1135 assert_eq!(
1136 result,
1137 Err(Error {
1138 cause: EvalError::Overflow,
1139 location: 3..4,
1140 })
1141 );
1142 }
1143 }
1144
1145 #[test]
1146 fn binary_result_shift_right() {
1147 let lhs = Value::Integer(0x94E239);
1148 let rhs = Value::Integer(7);
1149 for operator in [BinaryOperator::ShiftRight, BinaryOperator::ShiftRightAssign] {
1150 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1151 assert_eq!(result, Ok(Value::Integer(0x94E239 >> 7)));
1152 }
1153 }
1154
1155 #[test]
1156 fn binary_result_shift_right_negative_rhs() {
1157 let lhs = Value::Integer(0);
1158 let rhs = Value::Integer(-1);
1159 for operator in [BinaryOperator::ShiftRight, BinaryOperator::ShiftRightAssign] {
1160 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1161 assert_eq!(
1162 result,
1163 Err(Error {
1164 cause: EvalError::ReverseShifting,
1165 location: 3..4,
1166 })
1167 );
1168 }
1169 }
1170
1171 #[test]
1172 fn binary_result_shift_right_too_large_rhs() {
1173 let lhs = Value::Integer(0);
1174 let rhs = Value::Integer(i64::BITS as _);
1175 for operator in [BinaryOperator::ShiftRight, BinaryOperator::ShiftRightAssign] {
1176 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1177 assert_eq!(
1178 result,
1179 Err(Error {
1180 cause: EvalError::Overflow,
1181 location: 3..4,
1182 })
1183 );
1184 }
1185 }
1186
1187 #[test]
1188 fn binary_result_add() {
1189 let lhs = Value::Integer(15);
1190 let rhs = Value::Integer(27);
1191 for operator in [BinaryOperator::Add, BinaryOperator::AddAssign] {
1192 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1193 assert_eq!(result, Ok(Value::Integer(42)));
1194 }
1195 }
1196
1197 #[test]
1198 fn binary_result_add_overflow() {
1199 let lhs = Value::Integer(i64::MIN);
1200 let rhs = Value::Integer(-1);
1201 for operator in [BinaryOperator::Add, BinaryOperator::AddAssign] {
1202 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1203 assert_eq!(
1204 result,
1205 Err(Error {
1206 cause: EvalError::Overflow,
1207 location: 3..4,
1208 })
1209 );
1210 }
1211 }
1212
1213 #[test]
1214 fn binary_result_subtract() {
1215 let lhs = Value::Integer(15);
1216 let rhs = Value::Integer(27);
1217 for operator in [BinaryOperator::Subtract, BinaryOperator::SubtractAssign] {
1218 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1219 assert_eq!(result, Ok(Value::Integer(-12)));
1220 }
1221 }
1222
1223 #[test]
1224 fn binary_result_subtract_overflow() {
1225 let lhs = Value::Integer(i64::MAX);
1226 let rhs = Value::Integer(-1);
1227 for operator in [BinaryOperator::Subtract, BinaryOperator::SubtractAssign] {
1228 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1229 assert_eq!(
1230 result,
1231 Err(Error {
1232 cause: EvalError::Overflow,
1233 location: 3..4,
1234 })
1235 );
1236 }
1237 }
1238
1239 #[test]
1240 fn binary_result_multiply() {
1241 let lhs = Value::Integer(15);
1242 let rhs = Value::Integer(27);
1243 for operator in [BinaryOperator::Multiply, BinaryOperator::MultiplyAssign] {
1244 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1245 assert_eq!(result, Ok(Value::Integer(405)));
1246 }
1247 }
1248
1249 #[test]
1250 fn binary_result_multiply_overflow() {
1251 let lhs = Value::Integer(0x4000_0000_0000_0000);
1252 let rhs = Value::Integer(2);
1253 for operator in [BinaryOperator::Multiply, BinaryOperator::MultiplyAssign] {
1254 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1255 assert_eq!(
1256 result,
1257 Err(Error {
1258 cause: EvalError::Overflow,
1259 location: 3..4,
1260 })
1261 );
1262 }
1263 }
1264
1265 #[test]
1266 fn binary_result_divide() {
1267 let lhs = Value::Integer(268);
1268 let rhs = Value::Integer(17);
1269 for operator in [BinaryOperator::Divide, BinaryOperator::DivideAssign] {
1270 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1271 assert_eq!(result, Ok(Value::Integer(15)));
1272 }
1273 }
1274
1275 #[test]
1276 fn binary_result_divide_overflow() {
1277 let lhs = Value::Integer(i64::MIN);
1278 let rhs = Value::Integer(-1);
1279 for operator in [BinaryOperator::Divide, BinaryOperator::DivideAssign] {
1280 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1281 assert_eq!(
1282 result,
1283 Err(Error {
1284 cause: EvalError::Overflow,
1285 location: 3..4,
1286 })
1287 );
1288 }
1289 }
1290
1291 #[test]
1292 fn binary_result_divide_by_zero() {
1293 let lhs = Value::Integer(1);
1294 let rhs = Value::Integer(0);
1295 for operator in [BinaryOperator::Divide, BinaryOperator::DivideAssign] {
1296 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1297 assert_eq!(
1298 result,
1299 Err(Error {
1300 cause: EvalError::DivisionByZero,
1301 location: 3..4,
1302 })
1303 );
1304 }
1305 }
1306
1307 #[test]
1308 fn binary_result_remainder() {
1309 let lhs = Value::Integer(268);
1310 let rhs = Value::Integer(17);
1311 for operator in [BinaryOperator::Remainder, BinaryOperator::RemainderAssign] {
1312 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1313 assert_eq!(result, Ok(Value::Integer(13)));
1314 }
1315 }
1316
1317 #[test]
1318 fn binary_result_remainder_overflow() {
1319 let lhs = Value::Integer(i64::MIN);
1320 let rhs = Value::Integer(-1);
1321 for operator in [BinaryOperator::Remainder, BinaryOperator::RemainderAssign] {
1322 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1323 assert_eq!(
1324 result,
1325 Err(Error {
1326 cause: EvalError::Overflow,
1327 location: 3..4,
1328 })
1329 );
1330 }
1331 }
1332
1333 #[test]
1334 fn binary_result_remainder_by_zero() {
1335 let lhs = Value::Integer(1);
1336 let rhs = Value::Integer(0);
1337 for operator in [BinaryOperator::Remainder, BinaryOperator::RemainderAssign] {
1338 let result = binary_result::<Infallible, Infallible>(lhs, rhs, operator, &(3..4));
1339 assert_eq!(
1340 result,
1341 Err(Error {
1342 cause: EvalError::DivisionByZero,
1343 location: 3..4,
1344 })
1345 );
1346 }
1347 }
1348
1349 #[test]
1350 fn apply_binary_add() {
1351 let env = &mut HashMap::new();
1352 let lhs = Term::Value(Value::Integer(30));
1353 let rhs = Term::Value(Value::Integer(12));
1354 let operator = BinaryOperator::Add;
1355 let op_location = 4..5;
1356 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1357 assert_eq!(result, Ok(Value::Integer(42)));
1358 }
1359
1360 #[test]
1361 fn apply_binary_add_overflow() {
1362 let env = &mut HashMap::new();
1363 let lhs = Term::Value(Value::Integer(i64::MAX));
1364 let rhs = Term::Value(Value::Integer(1));
1365 let operator = BinaryOperator::Add;
1366 let op_location = 4..5;
1367 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1368 assert_eq!(
1369 result,
1370 Err(Error {
1371 cause: EvalError::Overflow,
1372 location: 4..5,
1373 })
1374 );
1375 }
1376
1377 #[test]
1378 fn apply_binary_subtract() {
1379 let env = &mut HashMap::new();
1380 let lhs = Term::Value(Value::Integer(30));
1381 let rhs = Term::Value(Value::Integer(12));
1382 let operator = BinaryOperator::Subtract;
1383 let op_location = 4..5;
1384 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1385 assert_eq!(result, Ok(Value::Integer(18)));
1386 }
1387
1388 #[test]
1389 fn apply_binary_subtract_overflow() {
1390 let env = &mut HashMap::new();
1391 let lhs = Term::Value(Value::Integer(i64::MIN));
1392 let rhs = Term::Value(Value::Integer(1));
1393 let operator = BinaryOperator::Subtract;
1394 let op_location = 4..5;
1395 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1396 assert_eq!(
1397 result,
1398 Err(Error {
1399 cause: EvalError::Overflow,
1400 location: 4..5,
1401 })
1402 );
1403 }
1404
1405 #[test]
1406 fn apply_binary_assign() {
1407 let env = &mut HashMap::new();
1408 let lhs = Term::Variable {
1409 name: "foo",
1410 location: 1..4,
1411 };
1412 let rhs = Term::Value(Value::Integer(42));
1413 let operator = BinaryOperator::Assign;
1414 let op_location = 4..5;
1415 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1416 assert_eq!(result, Ok(Value::Integer(42)));
1417 assert_eq!(env["foo"], "42");
1418 }
1419
1420 #[test]
1421 fn apply_binary_assign_not_variable() {
1422 let env = &mut HashMap::new();
1423 let lhs = Term::Value(Value::Integer(3));
1424 let rhs = Term::Value(Value::Integer(42));
1425 let operator = BinaryOperator::Assign;
1426 let op_location = 4..5;
1427 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1428 assert_eq!(
1429 result,
1430 Err(Error {
1431 cause: EvalError::AssignmentToValue,
1432 location: 4..5,
1433 })
1434 );
1435 }
1436
1437 #[test]
1438 fn apply_binary_add_assign() {
1439 let env = &mut HashMap::new();
1440 env.insert("a".to_string(), "10".to_string());
1441 let lhs = Term::Variable {
1442 name: "a",
1443 location: 1..2,
1444 };
1445 let rhs = Term::Value(Value::Integer(32));
1446 let operator = BinaryOperator::AddAssign;
1447 let op_location = 4..6;
1448 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1449 assert_eq!(result, Ok(Value::Integer(42)));
1450 assert_eq!(env["a"], "42");
1451 }
1452
1453 #[test]
1454 fn apply_binary_add_assign_not_variable() {
1455 let env = &mut HashMap::new();
1456 let lhs = Term::Value(Value::Integer(3));
1457 let rhs = Term::Value(Value::Integer(42));
1458 let operator = BinaryOperator::AddAssign;
1459 let op_location = 4..6;
1460 let result = apply_binary(lhs, rhs, operator, &op_location, env);
1461 assert_eq!(
1462 result,
1463 Err(Error {
1464 cause: EvalError::AssignmentToValue,
1465 location: 4..6,
1466 })
1467 );
1468 }
1469
1470 #[test]
1471 fn eval_term() {
1472 let env = &mut HashMap::new();
1473
1474 let t = Term::Value(Value::Integer(42));
1475 assert_eq!(eval(&[Ast::Term(t.clone())], env), Ok(t));
1476
1477 let t = Term::Variable {
1478 name: "a",
1479 location: 10..11,
1480 };
1481 assert_eq!(eval(&[Ast::Term(t.clone())], env), Ok(t));
1482 }
1483
1484 #[test]
1485 fn eval_prefix() {
1486 let env = &mut HashMap::new();
1487 let ast = &[
1488 Ast::Term(Term::Value(Value::Integer(15))),
1489 Ast::Prefix {
1490 operator: PrefixOperator::NumericNegation,
1491 location: 2..3,
1492 },
1493 ];
1494 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(-15))));
1495 }
1496
1497 #[test]
1498 fn eval_postfix() {
1499 let env = &mut HashMap::new();
1500 let ast = &[
1501 Ast::Term(Term::Variable {
1502 name: "x",
1503 location: 0..1,
1504 }),
1505 Ast::Postfix {
1506 operator: PostfixOperator::Increment,
1507 location: 1..3,
1508 },
1509 ];
1510 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(0))));
1511 }
1512
1513 #[test]
1514 fn eval_logical_or_short_circuit() {
1515 let env = &mut HashMap::new();
1516 env.insert("a".to_string(), "*".to_string());
1517 let ast = &[
1518 Ast::Term(Term::Value(Value::Integer(-1))),
1519 Ast::Term(Term::Variable {
1520 name: "a",
1521 location: 4..5,
1522 }),
1523 Ast::Binary {
1524 operator: BinaryOperator::LogicalOr,
1525 rhs_len: 1,
1526 location: 2..3,
1527 },
1528 ];
1529 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(1))));
1530 }
1531
1532 #[test]
1533 fn eval_logical_or_full_evaluation() {
1534 let env = &mut HashMap::new();
1535 let ast = &[
1536 Ast::Term(Term::Value(Value::Integer(0))),
1537 Ast::Term(Term::Value(Value::Integer(2))),
1538 Ast::Binary {
1539 operator: BinaryOperator::LogicalOr,
1540 rhs_len: 1,
1541 location: 2..3,
1542 },
1543 ];
1544 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(1))));
1545
1546 let env = &mut HashMap::new();
1547 let ast = &[
1548 Ast::Term(Term::Value(Value::Integer(0))),
1549 Ast::Term(Term::Value(Value::Integer(0))),
1550 Ast::Binary {
1551 operator: BinaryOperator::LogicalOr,
1552 rhs_len: 1,
1553 location: 2..3,
1554 },
1555 ];
1556 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(0))));
1557 }
1558
1559 #[test]
1560 fn eval_logical_and_short_circuit() {
1561 let env = &mut HashMap::new();
1562 env.insert("a".to_string(), "*".to_string());
1563 let ast = &[
1564 Ast::Term(Term::Value(Value::Integer(0))),
1565 Ast::Term(Term::Variable {
1566 name: "a",
1567 location: 4..5,
1568 }),
1569 Ast::Binary {
1570 operator: BinaryOperator::LogicalAnd,
1571 rhs_len: 1,
1572 location: 2..3,
1573 },
1574 ];
1575 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(0))));
1576 }
1577
1578 #[test]
1579 fn eval_logical_and_full_evaluation() {
1580 let env = &mut HashMap::new();
1581 let ast = &[
1582 Ast::Term(Term::Value(Value::Integer(2))),
1583 Ast::Term(Term::Value(Value::Integer(3))),
1584 Ast::Binary {
1585 operator: BinaryOperator::LogicalAnd,
1586 rhs_len: 1,
1587 location: 2..3,
1588 },
1589 ];
1590 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(1))));
1591
1592 let env = &mut HashMap::new();
1593 let ast = &[
1594 Ast::Term(Term::Value(Value::Integer(2))),
1595 Ast::Term(Term::Value(Value::Integer(0))),
1596 Ast::Binary {
1597 operator: BinaryOperator::LogicalAnd,
1598 rhs_len: 1,
1599 location: 2..3,
1600 },
1601 ];
1602 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(0))));
1603 }
1604
1605 #[test]
1606 fn eval_binary() {
1607 let env = &mut HashMap::new();
1608 let ast = &[
1609 Ast::Term(Term::Value(Value::Integer(12))),
1610 Ast::Term(Term::Value(Value::Integer(34))),
1611 Ast::Binary {
1612 operator: BinaryOperator::Add,
1613 rhs_len: 1,
1614 location: 2..3,
1615 },
1616 ];
1617 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(46))));
1618 }
1619
1620 #[test]
1621 fn eval_conditional_then() {
1622 let env = &mut HashMap::new();
1623 env.insert("a".to_string(), "*".to_string());
1624 let ast = &[
1625 Ast::Term(Term::Value(Value::Integer(1))),
1626 Ast::Term(Term::Value(Value::Integer(10))),
1627 Ast::Term(Term::Variable {
1628 name: "a",
1629 location: 4..5,
1630 }),
1631 Ast::Conditional {
1632 then_len: 1,
1633 else_len: 1,
1634 },
1635 ];
1636 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(10))));
1637 }
1638
1639 #[test]
1640 fn eval_conditional_else() {
1641 let env = &mut HashMap::new();
1642 env.insert("a".to_string(), "*".to_string());
1643 let ast = &[
1644 Ast::Term(Term::Value(Value::Integer(0))),
1645 Ast::Term(Term::Variable {
1646 name: "a",
1647 location: 4..5,
1648 }),
1649 Ast::Term(Term::Value(Value::Integer(21))),
1650 Ast::Conditional {
1651 then_len: 1,
1652 else_len: 1,
1653 },
1654 ];
1655 assert_eq!(eval(ast, env), Ok(Term::Value(Value::Integer(21))));
1656 }
1657}