#include "SimpleExpressionBinaryOperation.h" #include #include SimpleExpressionBinaryOperationType::SimpleExpressionBinaryOperationType(const SimpleBinaryOperationId id, std::string syntax, const SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction) : m_id(id), m_syntax(std::move(syntax)), m_precedence(precedence), m_evaluation_function(std::move(evaluationFunction)) { } const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_ADD( SimpleBinaryOperationId::ADD, "+", SimpleOperationPrecedence::ADDITION_SUBTRACTION, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value + operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value + static_cast(operand2.m_int_value)); if (operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(std::to_string(operand1.m_double_value) + *operand2.m_string_value); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(static_cast(operand1.m_int_value) + operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value + operand2.m_int_value); if (operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(std::to_string(operand1.m_int_value) + *operand2.m_string_value); } else if (operand1.m_type == SimpleExpressionValue::Type::STRING) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(*operand1.m_string_value + std::to_string(operand2.m_double_value)); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(*operand1.m_string_value + std::to_string(operand2.m_int_value)); if (operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(*operand1.m_string_value + *operand2.m_string_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SUBTRACT( SimpleBinaryOperationId::SUBTRACT, "-", SimpleOperationPrecedence::ADDITION_SUBTRACTION, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value - operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value - static_cast(operand2.m_int_value)); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(static_cast(operand1.m_int_value) - operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value - operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_MULTIPLY( SimpleBinaryOperationId::MULTIPLY, "*", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value * operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value * static_cast(operand2.m_int_value)); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(static_cast(operand1.m_int_value) * operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value * operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_DIVIDE( SimpleBinaryOperationId::DIVIDE, "/", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value / operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value / static_cast(operand2.m_int_value)); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(static_cast(operand1.m_int_value) / operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value / operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_REMAINDER( SimpleBinaryOperationId::REMAINDER, "%", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::INT && operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value % operand2.m_int_value); return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_AND( SimpleBinaryOperationId::BITWISE_AND, "&", SimpleOperationPrecedence::BITWISE_AND, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::INT && operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value & operand2.m_int_value); return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_OR( SimpleBinaryOperationId::BITWISE_OR, "|", SimpleOperationPrecedence::BITWISE_OR, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::INT && operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value | operand2.m_int_value); return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_LEFT( SimpleBinaryOperationId::SHIFT_LEFT, "<<", SimpleOperationPrecedence::BITWISE_SHIFT, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::INT && operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value << operand2.m_int_value); return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_RIGHT( SimpleBinaryOperationId::SHIFT_RIGHT, ">>", SimpleOperationPrecedence::BITWISE_SHIFT, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::INT && operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value >> operand2.m_int_value); return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_THAN( SimpleBinaryOperationId::GREATER_THAN, ">", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::STRING || operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(operand1.IsTruthy() > operand2.IsTruthy()); if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value > operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value > operand2.m_int_value); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_int_value > operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value > operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_EQUAL_THAN( SimpleBinaryOperationId::GREATER_EQUAL_THAN, ">=", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::STRING || operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(operand1.IsTruthy() >= operand2.IsTruthy()); if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value >= operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value >= operand2.m_int_value); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_int_value >= operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value >= operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_THAN( SimpleBinaryOperationId::LESS_THAN, "<", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::STRING || operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(operand1.IsTruthy() < operand2.IsTruthy()); if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value < operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value < operand2.m_int_value); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_int_value < operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value < operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_EQUAL_THAN( SimpleBinaryOperationId::LESS_EQUAL_THAN, "<=", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::STRING || operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(operand1.IsTruthy() <= operand2.IsTruthy()); if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_double_value <= operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_double_value <= operand2.m_int_value); } else if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(operand1.m_int_value <= operand2.m_double_value); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value <= operand2.m_int_value); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_EQUALS( SimpleBinaryOperationId::EQUALS, "==", SimpleOperationPrecedence::RELATIONAL_EQUALS, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) == FP_ZERO); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - static_cast(operand2.m_int_value)) == FP_ZERO); return SimpleExpressionValue(0); } if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) == FP_ZERO); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value == operand2.m_int_value); return SimpleExpressionValue(0); } if (operand1.m_type == SimpleExpressionValue::Type::STRING) { if (operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(*operand1.m_string_value == *operand2.m_string_value); return SimpleExpressionValue(0); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_NOT_EQUAL( SimpleBinaryOperationId::NOT_EQUAL, "!=", SimpleOperationPrecedence::RELATIONAL_EQUALS, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.m_type == SimpleExpressionValue::Type::DOUBLE) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) != FP_ZERO); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - static_cast(operand2.m_int_value)) != FP_ZERO); return SimpleExpressionValue(0); } if (operand1.m_type == SimpleExpressionValue::Type::INT) { if (operand2.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(std::fpclassify(operand1.m_double_value - operand2.m_double_value) != FP_ZERO); if (operand2.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(operand1.m_int_value != operand2.m_int_value); return SimpleExpressionValue(0); } if (operand1.m_type == SimpleExpressionValue::Type::STRING) { if (operand2.m_type == SimpleExpressionValue::Type::STRING) return SimpleExpressionValue(*operand1.m_string_value != *operand2.m_string_value); return SimpleExpressionValue(0); } return SimpleExpressionValue(0); }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_AND(SimpleBinaryOperationId::AND, "&&", SimpleOperationPrecedence::LOGICAL_AND, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.IsTruthy()) return operand2; return operand1; }); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_OR(SimpleBinaryOperationId::OR, "||", SimpleOperationPrecedence::LOGICAL_OR, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue { if (operand1.IsTruthy()) return operand1; return operand2; }); const SimpleExpressionBinaryOperationType* const SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[static_cast(SimpleBinaryOperationId::COUNT)]{ &OPERATION_ADD, &OPERATION_SUBTRACT, &OPERATION_MULTIPLY, &OPERATION_DIVIDE, &OPERATION_REMAINDER, &OPERATION_BITWISE_AND, &OPERATION_BITWISE_OR, &OPERATION_SHIFT_LEFT, &OPERATION_SHIFT_RIGHT, &OPERATION_GREATER_THAN, &OPERATION_GREATER_EQUAL_THAN, &OPERATION_LESS_THAN, &OPERATION_LESS_EQUAL_THAN, &OPERATION_EQUALS, &OPERATION_NOT_EQUAL, &OPERATION_AND, &OPERATION_OR, }; SimpleExpressionBinaryOperation::SimpleExpressionBinaryOperation(const SimpleExpressionBinaryOperationType* operationType, std::unique_ptr operand1, std::unique_ptr operand2) : m_operation_type(operationType), m_operand1(std::move(operand1)), m_operand2(std::move(operand2)) { } bool SimpleExpressionBinaryOperation::Operand1NeedsParenthesis() const { const auto* operation = dynamic_cast(m_operand1.get()); return operation && operation->m_operation_type->m_precedence > m_operation_type->m_precedence; } bool SimpleExpressionBinaryOperation::Operand2NeedsParenthesis() const { const auto* operation = dynamic_cast(m_operand2.get()); return operation && operation->m_operation_type->m_precedence > m_operation_type->m_precedence; } bool SimpleExpressionBinaryOperation::Equals(const ISimpleExpression* other) const { const auto* otherBinaryOperation = dynamic_cast(other); return otherBinaryOperation && m_operation_type->m_id == otherBinaryOperation->m_operation_type->m_id && m_operand1->Equals(otherBinaryOperation->m_operand1.get()) && m_operand2->Equals(otherBinaryOperation->m_operand2.get()); } bool SimpleExpressionBinaryOperation::IsStatic() const { assert(m_operand1 && m_operand2); return m_operand1->IsStatic() && m_operand2->IsStatic(); } SimpleExpressionValue SimpleExpressionBinaryOperation::EvaluateStatic() const { return m_operation_type->m_evaluation_function(m_operand1->EvaluateStatic(), m_operand2->EvaluateStatic()); } SimpleExpressionValue SimpleExpressionBinaryOperation::EvaluateNonStatic(const ISimpleExpressionScopeValues* scopeValues) const { return m_operation_type->m_evaluation_function(m_operand1->EvaluateNonStatic(scopeValues), m_operand2->EvaluateNonStatic(scopeValues)); }