#![cfg(feature = "conch-parser")]
extern crate conch_parser;
extern crate conch_runtime;
use conch_parser::ast::Arithmetic;
use conch_runtime::error::ExpansionError;
use conch_runtime::eval::ArithEval;
use conch_runtime::env::{VarEnv, VariableEnvironment};
#[test]
fn test_eval_arith() {
use conch_parser::ast::Arithmetic::*;
use std::isize::MAX;
fn lit(i: isize) -> Box<Arithmetic<String>> {
Box::new(Literal(i))
}
let env = &mut VarEnv::new();
let var = "var name".to_owned();
let var_value = 10;
let var_string = "var string".to_owned();
let var_string_value = "asdf";
env.set_var(var.clone(), var_value.to_string());
env.set_var(var_string.clone(), var_string_value.to_owned());
assert_eq!(lit(5).eval(env), Ok(5));
assert_eq!(Var(var.clone()).eval(env), Ok(var_value));
assert_eq!(Var(var_string.clone()).eval(env), Ok(0));
assert_eq!(Var("missing var".to_owned()).eval(env), Ok(0));
assert_eq!(PostIncr(var.clone()).eval(env), Ok(var_value));
assert_eq!(env.var(&var), Some(&(var_value + 1).to_string()));
assert_eq!(PostDecr(var.clone()).eval(env), Ok(var_value + 1));
assert_eq!(env.var(&var), Some(&var_value.to_string()));
assert_eq!(PreIncr(var.clone()).eval(env), Ok(var_value + 1));
assert_eq!(env.var(&var), Some(&(var_value + 1).to_string()));
assert_eq!(PreDecr(var.clone()).eval(env), Ok(var_value));
assert_eq!(env.var(&var), Some(&var_value.to_string()));
assert_eq!(UnaryPlus(lit(5)).eval(env), Ok(5));
assert_eq!(UnaryPlus(lit(-5)).eval(env), Ok(5));
assert_eq!(UnaryMinus(lit(5)).eval(env), Ok(-5));
assert_eq!(UnaryMinus(lit(-5)).eval(env), Ok(5));
assert_eq!(BitwiseNot(lit(5)).eval(env), Ok(!5));
assert_eq!(BitwiseNot(lit(0)).eval(env), Ok(!0));
assert_eq!(LogicalNot(lit(5)).eval(env), Ok(0));
assert_eq!(LogicalNot(lit(0)).eval(env), Ok(1));
assert_eq!(Less(lit(1), lit(1)).eval(env), Ok(0));
assert_eq!(Less(lit(1), lit(0)).eval(env), Ok(0));
assert_eq!(Less(lit(0), lit(1)).eval(env), Ok(1));
assert_eq!(LessEq(lit(1), lit(1)).eval(env), Ok(1));
assert_eq!(LessEq(lit(1), lit(0)).eval(env), Ok(0));
assert_eq!(LessEq(lit(0), lit(1)).eval(env), Ok(1));
assert_eq!(Great(lit(1), lit(1)).eval(env), Ok(0));
assert_eq!(Great(lit(1), lit(0)).eval(env), Ok(1));
assert_eq!(Great(lit(0), lit(1)).eval(env), Ok(0));
assert_eq!(GreatEq(lit(1), lit(1)).eval(env), Ok(1));
assert_eq!(GreatEq(lit(1), lit(0)).eval(env), Ok(1));
assert_eq!(GreatEq(lit(0), lit(1)).eval(env), Ok(0));
assert_eq!(Eq(lit(0), lit(1)).eval(env), Ok(0));
assert_eq!(Eq(lit(1), lit(1)).eval(env), Ok(1));
assert_eq!(NotEq(lit(0), lit(1)).eval(env), Ok(1));
assert_eq!(NotEq(lit(1), lit(1)).eval(env), Ok(0));
assert_eq!(Pow(lit(4), lit(3)).eval(env), Ok(64));
assert_eq!(Pow(lit(4), lit(0)).eval(env), Ok(1));
assert_eq!(Pow(lit(4), lit(-2)).eval(env), Err(ExpansionError::NegativeExponent));
assert_eq!(Div(lit(6), lit(2)).eval(env), Ok(3));
assert_eq!(Div(lit(1), lit(0)).eval(env), Err(ExpansionError::DivideByZero));
assert_eq!(Modulo(lit(6), lit(5)).eval(env), Ok(1));
assert_eq!(Modulo(lit(1), lit(0)).eval(env), Err(ExpansionError::DivideByZero));
assert_eq!(Mult(lit(3), lit(2)).eval(env), Ok(6));
assert_eq!(Mult(lit(1), lit(0)).eval(env), Ok(0));
assert_eq!(Add(lit(3), lit(2)).eval(env), Ok(5));
assert_eq!(Add(lit(1), lit(0)).eval(env), Ok(1));
assert_eq!(Sub(lit(3), lit(2)).eval(env), Ok(1));
assert_eq!(Sub(lit(0), lit(1)).eval(env), Ok(-1));
assert_eq!(ShiftLeft(lit(4), lit(3)).eval(env), Ok(32));
assert_eq!(ShiftRight(lit(32), lit(2)).eval(env), Ok(8));
assert_eq!(BitwiseAnd(lit(135), lit(97)).eval(env), Ok(1));
assert_eq!(BitwiseAnd(lit(135), lit(0)).eval(env), Ok(0));
assert_eq!(BitwiseAnd(lit(135), lit(MAX)).eval(env), Ok(135));
assert_eq!(BitwiseXor(lit(135), lit(150)).eval(env), Ok(17));
assert_eq!(BitwiseXor(lit(135), lit(0)).eval(env), Ok(135));
assert_eq!(BitwiseXor(lit(135), lit(MAX)).eval(env), Ok(135 ^ MAX));
assert_eq!(BitwiseOr(lit(135), lit(97)).eval(env), Ok(231));
assert_eq!(BitwiseOr(lit(135), lit(0)).eval(env), Ok(135));
assert_eq!(BitwiseOr(lit(135), lit(MAX)).eval(env), Ok(MAX));
assert_eq!(LogicalAnd(lit(135), lit(97)).eval(env), Ok(1));
assert_eq!(LogicalAnd(lit(135), lit(0)).eval(env), Ok(0));
assert_eq!(LogicalAnd(lit(0), lit(0)).eval(env), Ok(0));
assert_eq!(LogicalOr(lit(135), lit(97)).eval(env), Ok(1));
assert_eq!(LogicalOr(lit(135), lit(0)).eval(env), Ok(1));
assert_eq!(LogicalOr(lit(0), lit(0)).eval(env), Ok(0));
assert_eq!(Ternary(lit(2), lit(4), lit(5)).eval(env), Ok(4));
assert_eq!(Ternary(lit(0), lit(4), lit(5)).eval(env), Ok(5));
assert_eq!(env.var(&var), Some(&(var_value).to_string()));
assert_eq!(Assign(var.clone(), lit(42)).eval(env), Ok(42));
assert_eq!(env.var(&var).map(|s| &**s), Some("42"));
assert_eq!(Sequence(vec!(
Assign("x".to_owned(), lit(5)),
Assign("y".to_owned(), lit(10)),
Add(Box::new(PreIncr("x".to_owned())), Box::new(PostDecr("y".to_owned()))),
)).eval(env), Ok(16));
assert_eq!(env.var("x").map(|s| &**s), Some("6"));
assert_eq!(env.var("y").map(|s| &**s), Some("9"));
}