package tests;
import static org.junit.Assert.assertEquals;
import gui.render.Evaluator;
import java.util.Map;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.Test;
import antlr.QLangLexer;
import antlr.QLangParser;
import ast.ASTNode;
import ast.expr.Expr;
import ast.expr.Identifier;
import ast.expr.binExpr.Add;
import ast.expr.binExpr.GT;
import ast.expr.binExpr.LT;
import ast.expr.binExpr.Mul;
import ast.expr.binExpr.Sub;
import ast.expr.literal.BoolLiteral;
import ast.expr.literal.IntLiteral;
import ast.expr.unExpr.Neg;
import ast.expr.unExpr.Not;
import ast.value.Bool;
import ast.value.Int;
import ast.value.Value;
public class EvaluatorTest {
public void test(Value expected, String str) {
ANTLRInputStream input = new ANTLRInputStream(str);
QLangLexer lexer = new QLangLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
QLangParser parser = new QLangParser(tokens);
ASTNode tree = parser.orExpr().result;
Map<Identifier, Value> m = null;
Value result = ((Expr) tree).accept(new Evaluator(m));
if (expected instanceof Int){
assertEqualsInt((Int) expected,(Int) result);
} else if(expected instanceof Bool){
assertEqualsBool((Bool) expected,(Bool) result);
}
}
private void assertEqualsBool(Bool expected, Bool result) {
assertEquals(expected.getValue(), result.getValue());
}
private void assertEqualsInt(Int expected, Int result) {
assertEquals(expected.getValue(), result.getValue());
}
@Test
public void testArithmetic(){
test(new Int(3), "1 + 2");
test(new Int(2), "1 + 2 - 1");
test(new Int(6), "(1 + 2) * 2");
test(new Int(10), "20/2");
test(new Int(12), "20/2 + 2");
test(new Int(-2), "4 - (2 * 3) ");
test(new Int(8), "4 - (2 * 3) + 10 ");
test(new Int(0), "4 - (2 * 3) + 10/5 ");
}
@Test
public void testBoolean(){
test(new Bool(true), "3 > 2");
test(new Bool(false), "3 < 2");
test(new Bool(true), "3 < 5");
test(new Bool(true), "3 <= 3");
test(new Bool(true), "3 >= 3");
test(new Bool(false), "5 <= 3");
test(new Bool(true), "2 <= 3");
test(new Bool(false), "5 >= 6");
test(new Bool(false), "true && false");
test(new Bool(false), "false && false");
test(new Bool(true), "true && true");
test(new Bool(true), "true || true");
test(new Bool(true), "true || false");
test(new Bool(true), "(true && true) || false");
test(new Bool(true), "(false || true) && true");
test(new Bool(false), "(false && true) && true");
test(new Bool(false), " ! (false || true) && true");
test(new Bool(true), "!true == false");
test(new Bool(true), "4 == 4");
test(new Bool(true), "4 != 3");
test(new Bool(true), "(10 - 3) == (6 + 1)");
test(new Bool(true), "-4 == 2-6");
test(new Bool(true), "+4 == 6-2");
}
@Test
public void testExpressions(){
IntLiteral a = new IntLiteral(5);
IntLiteral b = new IntLiteral(4);
assertEqualValue(new Bool(true), evaluate(new GT(a, b)));
assertEqualValue(new Bool(false), evaluate(new LT(a, b)));
assertEqualValue(new Int(9), evaluate(new Add(a, b)));
assertEqualValue(new Int(1), evaluate(new Sub(a, b)));
assertEqualValue(new Int(20), evaluate(new Mul(a, b)));
assertEqualValue(new Int(-5), evaluate(new Neg(a)));
assertEqualValue(new Bool(true), evaluate(new Not(new BoolLiteral(false))));
}
private void assertEqualValue(Value expected, Value value) {
if (expected instanceof Int){
assertEqualsInt((Int) expected,(Int) value);
} else if(expected instanceof Bool){
assertEqualsBool((Bool) expected,(Bool) value);
}
}
private Value evaluate(Expr expr){
Map<Identifier, Value> m = null;
return expr.accept(new Evaluator(m));
}
}