From e648013e1d5c9625b78cd41395cef513954dea32 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Fri, 24 May 2019 15:31:11 +0200 Subject: [PATCH] Implements binary operation for floats --- src/Evaluator/BinaryEvaluation.cpp | 73 +++++++++++++++ src/Evaluator/Evaluator.cpp | 90 ++++--------------- .../numerical_operations_tests.cpp | 52 ++++++++++- 3 files changed, 142 insertions(+), 73 deletions(-) diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index b556f64..2812ea1 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -1,4 +1,77 @@ +#include "../Script.hpp" #include "EvaluationException.hpp" #include "Evaluator.hpp" +long Evaluator::EvaluateIntegerBinary(BoundBinaryExpression *expression) { + long leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); + long rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); + + switch (expression->GetOperation()){ + case BoundBinaryOperation ::Addition: return leftValue + rightValue; + case BoundBinaryOperation ::Subtraction: return leftValue - rightValue; + case BoundBinaryOperation ::Multiplication: return leftValue * rightValue; + case BoundBinaryOperation ::Division: return leftValue / rightValue; + + default: + throw EvaluationException("Can't evaluate operation to integer"); + } +} + +double EvaluateBinaryOperation(double l, double r, BoundBinaryOperation op){ + switch (op){ + case BoundBinaryOperation ::Addition: return l + r; + case BoundBinaryOperation ::Subtraction: return l - r; + case BoundBinaryOperation ::Multiplication: return l * r; + case BoundBinaryOperation ::Division: return l / r; + + default: + throw EvaluationException("Can't evaluate operation to float"); + } +} + +double EvaluateBinaryOperation(double l, long r, BoundBinaryOperation op){ + switch (op){ + case BoundBinaryOperation ::Addition: return l + r; + case BoundBinaryOperation ::Subtraction: return l - r; + case BoundBinaryOperation ::Multiplication: return l * r; + case BoundBinaryOperation ::Division: return l / r; + + default: + throw EvaluationException("Can't evaluate operation to float"); + } +} + +double EvaluateBinaryOperation(long l, double r, BoundBinaryOperation op){ + switch (op){ + case BoundBinaryOperation ::Addition: return l + r; + case BoundBinaryOperation ::Subtraction: return l - r; + case BoundBinaryOperation ::Multiplication: return l * r; + case BoundBinaryOperation ::Division: return l / r; + + default: + throw EvaluationException("Can't evaluate operation to float"); + } +} + +double Evaluator::EvaluateFloatBinary(BoundBinaryExpression *expression) { + auto left = expression->GetLeft(); + auto right = expression->GetRight(); + auto leftType = (NumericScriptType*)left->GetType(); + auto rightType = (NumericScriptType*)right->GetType(); + if (leftType->IsFloat()){ + double leftValue = this -> EvaluateFloatExpression(left); + if (rightType->IsFloat()){ + double rightValue = this -> EvaluateFloatExpression(right); + return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); + } else{ + long rightValue = this -> EvaluateIntegerExpression(right); + return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); + } + } else{ + long leftValue = this-> EvaluateIntegerExpression(left); + // If the left is an integer, we know the right must be a float, otherwise we'd be evaluating as integer; + double rightValue = this -> EvaluateFloatExpression(right); + return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); + } +} \ No newline at end of file diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 96695c9..d270e51 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -1,7 +1,6 @@ #include "Evaluator.hpp" #include "EvaluationException.hpp" -#include "BinaryEvaluation.cpp" #include "../Script.hpp" void Evaluator::Evaluate(BoundScriptStatement *statement) { @@ -68,7 +67,24 @@ long Evaluator::EvaluateIntegerExpression(BoundExpression *expression) { } double Evaluator::EvaluateFloatExpression(BoundExpression *expression) { - return 0; + auto exprType = expression->GetType(); + if (exprType->GetClass() != TypeClass::Number){ + throw EvaluationException("Can't evaluate expression as float, it will not return a number."); + } + auto numType = (NumericScriptType*)exprType; + if (numType->IsAwareOfFloat() && !numType->IsFloat()){ + throw EvaluationException("Can't evaluate expression as integer, it will return an integer, not a float."); + } + switch (expression->GetKind()){ + case BoundExpressionKind ::LiteralFloat: return ((BoundLiteralIntegerExpression*)expression)->GetValue(); + case BoundExpressionKind ::Binary: return this -> EvaluateFloatBinary((BoundBinaryExpression*)expression); + + case BoundExpressionKind ::LiteralInteger: + case BoundExpressionKind ::LiteralString: + case BoundExpressionKind ::LiteralBool: + case BoundExpressionKind ::Bad: + throw; + } } bool Evaluator::EvaluateBoolExpression(BoundExpression *expression) { @@ -79,73 +95,3 @@ std::string Evaluator::EvaluateStringExpression(BoundExpression *expression) { return std::__cxx11::string(); } -long Evaluator::EvaluateIntegerBinary(BoundBinaryExpression *expression) { - long leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); - long rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); - - switch (expression->GetOperation()){ - case BoundBinaryOperation ::Addition: return leftValue + rightValue; - case BoundBinaryOperation ::Subtraction: return leftValue - rightValue; - case BoundBinaryOperation ::Multiplication: return leftValue * rightValue; - case BoundBinaryOperation ::Division: return leftValue / rightValue; - - default: - throw EvaluationException("Can't evaluate operation to integer"); - } -} - -double EvaluateBinaryOperation(double l, double r, BoundBinaryOperation op){ - switch (op){ - case BoundBinaryOperation ::Addition: return l + r; - case BoundBinaryOperation ::Subtraction: return l - r; - case BoundBinaryOperation ::Multiplication: return l * r; - case BoundBinaryOperation ::Division: return l / r; - - default: - throw EvaluationException("Can't evaluate operation to float"); - } -} -double EvaluateBinaryOperation(double l, long r, BoundBinaryOperation op){ - switch (op){ - case BoundBinaryOperation ::Addition: return l + r; - case BoundBinaryOperation ::Subtraction: return l - r; - case BoundBinaryOperation ::Multiplication: return l * r; - case BoundBinaryOperation ::Division: return l / r; - - default: - throw EvaluationException("Can't evaluate operation to float"); - } -} -double EvaluateBinaryOperation(long l, double r, BoundBinaryOperation op){ - switch (op){ - case BoundBinaryOperation ::Addition: return l + r; - case BoundBinaryOperation ::Subtraction: return l - r; - case BoundBinaryOperation ::Multiplication: return l * r; - case BoundBinaryOperation ::Division: return l / r; - - default: - throw EvaluationException("Can't evaluate operation to float"); - } -} - -double Evaluator::EvaluateFloatBinary(BoundBinaryExpression *expression) { - auto left = expression->GetLeft(); - auto right = expression->GetRight(); - auto leftType = (NumericScriptType*)left->GetType(); - auto rightType = (NumericScriptType*)right->GetType(); - if (leftType->IsFloat()){ - double leftValue = this -> EvaluateFloatExpression(left); - if (rightType->IsFloat()){ - double rightValue = this -> EvaluateFloatExpression(right); - return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); - } else{ - long rightValue = this -> EvaluateIntegerExpression(right); - return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); - } - } else{ - long leftValue = this-> EvaluateIntegerExpression(left); - // If the left is an integer, we know the right must be a float, otherwise we'd be evaluating as integer; - double rightValue = this -> EvaluateFloatExpression(right); - return EvaluateBinaryOperation(leftValue, rightValue, expression->GetOperation()); - } -} \ No newline at end of file diff --git a/tests/integration/numerical_operations_tests.cpp b/tests/integration/numerical_operations_tests.cpp index 18e7c5f..472d80f 100644 --- a/tests/integration/numerical_operations_tests.cpp +++ b/tests/integration/numerical_operations_tests.cpp @@ -2,11 +2,61 @@ #include #include "../src/Script.hpp" -TEST_CASE( "Simple addition", "[integration]" ) { +TEST_CASE( "Integer Addition", "[integration]" ) { Script script = Script::Create("1 + 5"); REQUIRE(!script.Diagnostics -> HasErrors()); script.Evaluate(); auto lastValue = script.GetLastValue(); REQUIRE(*any_cast(lastValue) == 6); } +TEST_CASE( "Integer Subtraction", "[integration]" ) { + Script script = Script::Create("1 - 5"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == -4); +} +TEST_CASE( "Integer Multiplication", "[integration]" ) { + Script script = Script::Create("5 * 8"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == 40); +} +TEST_CASE( "Integer Division", "[integration]" ) { + Script script = Script::Create("40 / 8"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == 5); +} + +TEST_CASE( "Float Addition", "[integration]" ) { + Script script = Script::Create("1.2 + 5.34"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == 6.54); +} +TEST_CASE( "Float Subtraction", "[integration]" ) { + Script script = Script::Create("1.8 - 5.14"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == -3.34); +} +TEST_CASE( "Float Multiplication", "[integration]" ) { + Script script = Script::Create("5.2 * 8.9"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == 46.28); +} +TEST_CASE( "Float Division", "[integration]" ) { + Script script = Script::Create("95.18 / 8.87"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(*any_cast(lastValue) == Approx(10.730)); +} #endif