Implements binary operation for floats

This commit is contained in:
Deukhoofd 2019-05-24 15:31:11 +02:00
parent d949d9aa8f
commit e648013e1d
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
3 changed files with 142 additions and 73 deletions

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -2,11 +2,61 @@
#include <catch.hpp>
#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<long>(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<long>(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<long>(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<long>(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<double>(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<double>(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<double>(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<double>(lastValue) == Approx(10.730));
}
#endif