From 4a4a71ca73af48493aacba69ce4bb88ca68b233f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 25 May 2019 13:30:20 +0200 Subject: [PATCH] Added logical and and or binary operations --- src/Evaluator/BinaryEvaluation.cpp | 22 ++++++ src/Evaluator/EvalValues/EvalValue.hpp | 22 ++++++ src/Evaluator/Evaluator.cpp | 19 +++-- src/Evaluator/Evaluator.hpp | 3 +- tests/integration/LogicalOperationsTests.cpp | 81 ++++++++++++++++++++ 5 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 tests/integration/LogicalOperationsTests.cpp diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index eb6ef5e..ee8e049 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -30,4 +30,26 @@ NumericEvalValue* Evaluator::EvaluateIntegerBinary(BoundBinaryExpression *expres delete leftValue; delete rightValue; return result; +} + +BooleanEvalValue* Evaluator::EvaluateBooleanBinary(BoundBinaryExpression* expression){ + switch (expression->GetOperation()){ + case BoundBinaryOperation::Equality:break; + case BoundBinaryOperation::LogicalAnd: + { + BooleanEvalValue* leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); + if (!leftValue->EvaluateBool()) return leftValue; + delete leftValue; + BooleanEvalValue* rightValue = this -> EvaluateBoolExpression(expression->GetRight()); + return rightValue; + } + case BoundBinaryOperation::LogicalOr: + { + BooleanEvalValue* leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); + if (leftValue->EvaluateBool()) return leftValue; + delete leftValue; + BooleanEvalValue* rightValue = this -> EvaluateBoolExpression(expression->GetRight()); + return rightValue; + } + } } \ No newline at end of file diff --git a/src/Evaluator/EvalValues/EvalValue.hpp b/src/Evaluator/EvalValues/EvalValue.hpp index 36e1d40..d3bfaac 100644 --- a/src/Evaluator/EvalValues/EvalValue.hpp +++ b/src/Evaluator/EvalValues/EvalValue.hpp @@ -25,4 +25,26 @@ public: } }; +class BooleanEvalValue : public EvalValue{ + bool _value; + ScriptType* _type; +public: + explicit BooleanEvalValue(bool val){ + _value = val; + _type = new ScriptType(TypeClass::Bool); + } + + ~BooleanEvalValue() final{ + delete _type; + } + + ScriptType* GetType() final{ + return _type; + }; + + bool EvaluateBool() final{ + return _value; + } +}; + #endif //PORYGONLANG_EVALVALUE_HPP diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 8b27cff..9a099ad 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -32,15 +32,12 @@ EvalValue *Evaluator::EvaluateExpression(BoundExpression *expression) { auto type = expression -> GetType(); switch (type->GetClass()){ case TypeClass ::Number: return this -> EvaluateIntegerExpression(expression); + case TypeClass ::Bool: return this -> EvaluateBoolExpression(expression); default: throw; } } NumericEvalValue* Evaluator::EvaluateIntegerExpression(BoundExpression *expression) { - auto exprType = expression->GetType(); - if (exprType->GetClass() != TypeClass::Number){ - throw EvaluationException("Can't evaluate expression as integer, it will not return a number."); - } switch (expression->GetKind()){ case BoundExpressionKind ::LiteralInteger: return new IntegerEvalValue(((BoundLiteralIntegerExpression*)expression)->GetValue()); case BoundExpressionKind ::LiteralFloat: return new FloatEvalValue(((BoundLiteralFloatExpression*)expression)->GetValue()); @@ -53,8 +50,18 @@ NumericEvalValue* Evaluator::EvaluateIntegerExpression(BoundExpression *expressi } } -EvalValue* Evaluator::EvaluateBoolExpression(BoundExpression *expression) { - return nullptr; +BooleanEvalValue* Evaluator::EvaluateBoolExpression(BoundExpression *expression) { + switch (expression->GetKind()) { + case BoundExpressionKind::LiteralBool: return new BooleanEvalValue(((BoundLiteralBoolExpression*)expression)->GetValue()); + case BoundExpressionKind::Unary:break; + case BoundExpressionKind::Binary: return this -> EvaluateBooleanBinary((BoundBinaryExpression*)expression); + case BoundExpressionKind::Bad: + case BoundExpressionKind::LiteralInteger: + case BoundExpressionKind::LiteralFloat: + case BoundExpressionKind::LiteralString: + throw; + + } } EvalValue* Evaluator::EvaluateStringExpression(BoundExpression *expression) { diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index ad9dce6..7577b0b 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -23,10 +23,11 @@ class Evaluator { EvalValue* EvaluateExpression(BoundExpression* expression); NumericEvalValue* EvaluateIntegerExpression(BoundExpression* expression); - EvalValue* EvaluateBoolExpression(BoundExpression* expression); + BooleanEvalValue* EvaluateBoolExpression(BoundExpression* expression); EvalValue* EvaluateStringExpression(BoundExpression* expression); NumericEvalValue* EvaluateIntegerBinary(BoundBinaryExpression* expression); + BooleanEvalValue *EvaluateBooleanBinary(BoundBinaryExpression *expression); public: Evaluator(Script* script){ _scriptData = script; diff --git a/tests/integration/LogicalOperationsTests.cpp b/tests/integration/LogicalOperationsTests.cpp new file mode 100644 index 0000000..0f00eba --- /dev/null +++ b/tests/integration/LogicalOperationsTests.cpp @@ -0,0 +1,81 @@ +#ifdef TESTS_BUILD +#include +#include "../src/Script.hpp" + +TEST_CASE( "Basic True", "[integration]" ) { + Script script = Script::Create("true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} + +TEST_CASE( "Basic False", "[integration]" ) { + Script script = Script::Create("false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} + +TEST_CASE( "True and True", "[integration]" ) { + Script script = Script::Create("true and true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} +TEST_CASE( "True and False", "[integration]" ) { + Script script = Script::Create("true and false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} +TEST_CASE( "False and True", "[integration]" ) { + Script script = Script::Create("false and true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} +TEST_CASE( "False and False", "[integration]" ) { + Script script = Script::Create("false and false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} + +TEST_CASE( "True or True", "[integration]" ) { + Script script = Script::Create("true or true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} +TEST_CASE( "True or False", "[integration]" ) { + Script script = Script::Create("true or false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} +TEST_CASE( "False or True", "[integration]" ) { + Script script = Script::Create("false or true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} +TEST_CASE( "False or False", "[integration]" ) { + Script script = Script::Create("false or false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} + + +#endif +