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