Implements exponent and modulus operators

This commit is contained in:
Deukhoofd 2019-09-22 17:38:17 +02:00
parent de39464b33
commit 30d82085cc
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
9 changed files with 92 additions and 4 deletions

View File

@ -540,6 +540,31 @@ namespace Porygon::Binder {
}
}
break;
case BinaryOperatorKind::Exponent:
if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Exponent,
NumericScriptType::AwareFloat,
expression->GetStartPosition(), expression->GetLength());
}
break;
case BinaryOperatorKind::Modulus:
if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) {
auto leftNumeric = std::dynamic_pointer_cast<const NumericScriptType>(boundLeftType);
auto rightNumeric = std::dynamic_pointer_cast<const NumericScriptType>(boundRightType);
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()) {
return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperation::Modulus,
NumericScriptType::ResolveType(true,
leftNumeric->IsFloat() ||
rightNumeric->IsFloat()),
expression->GetStartPosition(), expression->GetLength());
} else {
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Modulus,
NumericScriptType::Unaware,
expression->GetStartPosition(), expression->GetLength());
}
}
break;
case BinaryOperatorKind::Equality:
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality,
ScriptType::BoolType,

View File

@ -279,11 +279,13 @@ namespace Porygon::Binder {
static std::string GetOperationString(BoundBinaryOperation op){
switch (op){
case BoundBinaryOperation::Addition: return "addition";
case BoundBinaryOperation::Subtraction: return "subtraction";
case BoundBinaryOperation::Multiplication: return "multiplication";
case BoundBinaryOperation::Division: return "division";
case BoundBinaryOperation::Modulus: return "modulus";
case BoundBinaryOperation::Exponent: return "exponent";
case BoundBinaryOperation::Equality: return "equality";
case BoundBinaryOperation::Inequality: return "inequality";
case BoundBinaryOperation::LessThan: return "lessThan";

View File

@ -9,6 +9,8 @@ namespace Porygon::Binder {
Subtraction = 1,
Multiplication = 2,
Division = 3,
Modulus = 13,
Exponent = 14,
Equality = 4,
Inequality = 5,
LessThan = 6,

View File

@ -1,5 +1,6 @@
#include "NumericEvalValue.hpp"
#include <cmath>
namespace Porygon::Evaluation {
EvalValue *NumericEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
@ -14,6 +15,8 @@ namespace Porygon::Evaluation {
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Exponent: return new NumericEvalValue(std::pow(v1, v2));
case Binder::BoundBinaryOperation::Modulus: return new NumericEvalValue(std::fmod(v1, v2));
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
@ -31,6 +34,8 @@ namespace Porygon::Evaluation {
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Exponent: return new NumericEvalValue(std::pow(v1, v2));
case Binder::BoundBinaryOperation::Modulus: return new NumericEvalValue(std::fmod(v1, v2));
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
@ -44,13 +49,15 @@ namespace Porygon::Evaluation {
else{
int64_t v1 = std::get<int64_t >(_intValue);
if (right->_isFloat){
double v2 =std::get<double>(right->_floatValue);;
double v2 =std::get<double>(right->_floatValue);
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Exponent: return new NumericEvalValue(std::pow(v1, v2));
case Binder::BoundBinaryOperation::Modulus: return new NumericEvalValue(std::fmod(v1, v2));
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
@ -67,6 +74,8 @@ namespace Porygon::Evaluation {
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Exponent: return new NumericEvalValue(std::pow(v1, v2));
case Binder::BoundBinaryOperation::Modulus: return new NumericEvalValue(v1 % v2);
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
@ -101,7 +110,7 @@ namespace Porygon::Evaluation {
size_t NumericEvalValue::GetHashCode() const {
if (_isFloat)
return std::get<double >(_floatValue);
return std::get<int64_t >(_intValue);;
return std::get<int64_t >(_intValue);
}
bool NumericEvalValue::operator==(const EvalValue *b) const {
@ -117,7 +126,7 @@ namespace Porygon::Evaluation {
}
int64_t NumericEvalValue::EvaluateInteger() const {
return std::get<int64_t >(_intValue);;
return std::get<int64_t >(_intValue);
}
double NumericEvalValue::EvaluateFloat() const {

View File

@ -9,6 +9,8 @@ namespace Porygon::Parser {
Subtraction,
Multiplication,
Division,
Exponent,
Modulus,
// Equality
Equality,

View File

@ -111,6 +111,10 @@ namespace Porygon::Parser {
return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1);
case '#':
return new SimpleToken(TokenKind::HashToken, this->_position - 1, 1);
case '^':
return new SimpleToken(TokenKind::RoofToken, this->_position - 1, 1);
case '%':
return new SimpleToken(TokenKind::PercentToken, this->_position - 1, 1);
case '0':
case '1':
case '2':

View File

@ -414,6 +414,10 @@ namespace Porygon::Parser {
return BinaryOperatorKind::Multiplication;
case TokenKind::SlashToken:
return BinaryOperatorKind::Division;
case TokenKind::RoofToken:
return BinaryOperatorKind ::Exponent;
case TokenKind::PercentToken:
return BinaryOperatorKind ::Modulus;
// Equality operators
case TokenKind::EqualityToken:
@ -450,6 +454,11 @@ namespace Porygon::Parser {
return OperatorPrecedence::Multiplication;
case TokenKind::SlashToken:
return OperatorPrecedence::Multiplication;
case TokenKind::RoofToken:
return OperatorPrecedence ::Multiplication;
case TokenKind::PercentToken:
return OperatorPrecedence ::Multiplication;
// Equality
case TokenKind::EqualityToken:

View File

@ -20,6 +20,8 @@ namespace Porygon::Parser {
Greater,
GreaterEquals,
HashToken,
RoofToken,
PercentToken,
OpenParenthesis,
CloseParenthesis,

View File

@ -47,6 +47,22 @@ TEST_CASE( "Integer Division", "[integration]" ) {
delete script;
}
TEST_CASE( "Integer Exponent", "[integration]" ) {
auto script = Script::Create("return 9 ^ 3");
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
REQUIRE(result->EvaluateFloat() == 729);
delete script;
}
TEST_CASE( "Integer Modulus", "[integration]" ) {
auto script = Script::Create("return 9 % 2");
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
REQUIRE(result->EvaluateInteger() == 1);
delete script;
}
TEST_CASE( "Float Addition", "[integration]" ) {
auto script = Script::Create("1.2 + 5.34");
REQUIRE(!script->Diagnostics -> HasErrors());
@ -75,4 +91,21 @@ TEST_CASE( "Float Division", "[integration]" ) {
REQUIRE(result->EvaluateFloat() == Approx(10.7305524239));
delete script;
}
TEST_CASE( "Float Exponent", "[integration]" ) {
auto script = Script::Create("95.18 ^ 2.0");
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
REQUIRE(result->EvaluateFloat() == Approx(9059.2324));
delete script;
}
TEST_CASE( "Float Modulus", "[integration]" ) {
auto script = Script::Create("return 9.2 % 2.0");
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
REQUIRE(result->EvaluateFloat() == Approx(1.2));
delete script;
}
#endif