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