#include "Evaluator.hpp" #include "EvaluationException.hpp" #include "BinaryEvaluation.cpp" #include "../Script.hpp" void Evaluator::Evaluate(BoundScriptStatement *statement) { EvaluateBlockStatement(statement); } void Evaluator::EvaluateStatement(BoundStatement *statement) { switch (statement->GetKind()){ case BoundStatementKind ::Script: throw; // Should never happen case BoundStatementKind ::Block: return this -> EvaluateBlockStatement((BoundBlockStatement*)statement); case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement); } } void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement) { for (auto s: statement->GetStatements()){ this -> EvaluateStatement(s); } } void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) { this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression()); } any *Evaluator::EvaluateExpression(BoundExpression *expression) { auto type = expression -> GetType(); switch (type->GetClass()){ case TypeClass ::Number: { auto numType = (NumericScriptType*)type; if (numType->IsAwareOfFloat()){ if (numType->IsFloat()){ double d = this -> EvaluateFloatExpression(expression); return new boost::any(d); } else{ long l = this -> EvaluateIntegerExpression(expression); return new boost::any(l); } } break; } } } long 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."); } auto numType = (NumericScriptType*)exprType; if (numType->IsAwareOfFloat() && numType->IsFloat()){ throw EvaluationException("Can't evaluate expression as integer, it will return a float, not an integer."); } switch (expression->GetKind()){ case BoundExpressionKind ::LiteralInteger: return ((BoundLiteralIntegerExpression*)expression)->GetValue(); case BoundExpressionKind ::Binary: return this -> EvaluateIntegerBinary((BoundBinaryExpression*)expression); case BoundExpressionKind ::LiteralFloat: case BoundExpressionKind ::LiteralString: case BoundExpressionKind ::LiteralBool: case BoundExpressionKind ::Bad: throw; } } double Evaluator::EvaluateFloatExpression(BoundExpression *expression) { return 0; } bool Evaluator::EvaluateBoolExpression(BoundExpression *expression) { return false; } 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()); } }