151 lines
5.9 KiB
C++
151 lines
5.9 KiB
C++
|
|
||
|
#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());
|
||
|
}
|
||
|
}
|