Implements exponent and modulus operators
This commit is contained in:
parent
de39464b33
commit
30d82085cc
|
@ -540,6 +540,31 @@ namespace Porygon::Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case BinaryOperatorKind::Equality:
|
||||||
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality,
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality,
|
||||||
ScriptType::BoolType,
|
ScriptType::BoolType,
|
||||||
|
|
|
@ -279,11 +279,13 @@ namespace Porygon::Binder {
|
||||||
|
|
||||||
static std::string GetOperationString(BoundBinaryOperation op){
|
static std::string GetOperationString(BoundBinaryOperation op){
|
||||||
switch (op){
|
switch (op){
|
||||||
|
|
||||||
case BoundBinaryOperation::Addition: return "addition";
|
case BoundBinaryOperation::Addition: return "addition";
|
||||||
case BoundBinaryOperation::Subtraction: return "subtraction";
|
case BoundBinaryOperation::Subtraction: return "subtraction";
|
||||||
case BoundBinaryOperation::Multiplication: return "multiplication";
|
case BoundBinaryOperation::Multiplication: return "multiplication";
|
||||||
case BoundBinaryOperation::Division: return "division";
|
case BoundBinaryOperation::Division: return "division";
|
||||||
|
case BoundBinaryOperation::Modulus: return "modulus";
|
||||||
|
case BoundBinaryOperation::Exponent: return "exponent";
|
||||||
|
|
||||||
case BoundBinaryOperation::Equality: return "equality";
|
case BoundBinaryOperation::Equality: return "equality";
|
||||||
case BoundBinaryOperation::Inequality: return "inequality";
|
case BoundBinaryOperation::Inequality: return "inequality";
|
||||||
case BoundBinaryOperation::LessThan: return "lessThan";
|
case BoundBinaryOperation::LessThan: return "lessThan";
|
||||||
|
|
|
@ -9,6 +9,8 @@ namespace Porygon::Binder {
|
||||||
Subtraction = 1,
|
Subtraction = 1,
|
||||||
Multiplication = 2,
|
Multiplication = 2,
|
||||||
Division = 3,
|
Division = 3,
|
||||||
|
Modulus = 13,
|
||||||
|
Exponent = 14,
|
||||||
Equality = 4,
|
Equality = 4,
|
||||||
Inequality = 5,
|
Inequality = 5,
|
||||||
LessThan = 6,
|
LessThan = 6,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "NumericEvalValue.hpp"
|
#include "NumericEvalValue.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace Porygon::Evaluation {
|
namespace Porygon::Evaluation {
|
||||||
EvalValue *NumericEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
|
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::Subtraction: return new NumericEvalValue(v1 - v2);
|
||||||
case Binder::BoundBinaryOperation::Multiplication: 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::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::Equality: return new BooleanEvalValue(v1 == v2);
|
||||||
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
||||||
case Binder::BoundBinaryOperation::LessThan: 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::Subtraction: return new NumericEvalValue(v1 - v2);
|
||||||
case Binder::BoundBinaryOperation::Multiplication: 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::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::Equality: return new BooleanEvalValue(v1 == v2);
|
||||||
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
||||||
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
|
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
|
||||||
|
@ -44,13 +49,15 @@ namespace Porygon::Evaluation {
|
||||||
else{
|
else{
|
||||||
int64_t v1 = std::get<int64_t >(_intValue);
|
int64_t v1 = std::get<int64_t >(_intValue);
|
||||||
if (right->_isFloat){
|
if (right->_isFloat){
|
||||||
double v2 =std::get<double>(right->_floatValue);;
|
double v2 =std::get<double>(right->_floatValue);
|
||||||
switch (operation){
|
switch (operation){
|
||||||
|
|
||||||
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
|
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
|
||||||
case Binder::BoundBinaryOperation::Subtraction: 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::Multiplication: return new NumericEvalValue(v1 * v2);
|
||||||
case Binder::BoundBinaryOperation::Division: 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::Equality: return new BooleanEvalValue(v1 == v2);
|
||||||
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
||||||
case Binder::BoundBinaryOperation::LessThan: 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::Subtraction: return new NumericEvalValue(v1 - v2);
|
||||||
case Binder::BoundBinaryOperation::Multiplication: 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::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::Equality: return new BooleanEvalValue(v1 == v2);
|
||||||
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
|
||||||
case Binder::BoundBinaryOperation::LessThan: 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 {
|
size_t NumericEvalValue::GetHashCode() const {
|
||||||
if (_isFloat)
|
if (_isFloat)
|
||||||
return std::get<double >(_floatValue);
|
return std::get<double >(_floatValue);
|
||||||
return std::get<int64_t >(_intValue);;
|
return std::get<int64_t >(_intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumericEvalValue::operator==(const EvalValue *b) const {
|
bool NumericEvalValue::operator==(const EvalValue *b) const {
|
||||||
|
@ -117,7 +126,7 @@ namespace Porygon::Evaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t NumericEvalValue::EvaluateInteger() const {
|
int64_t NumericEvalValue::EvaluateInteger() const {
|
||||||
return std::get<int64_t >(_intValue);;
|
return std::get<int64_t >(_intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
double NumericEvalValue::EvaluateFloat() const {
|
double NumericEvalValue::EvaluateFloat() const {
|
||||||
|
|
|
@ -9,6 +9,8 @@ namespace Porygon::Parser {
|
||||||
Subtraction,
|
Subtraction,
|
||||||
Multiplication,
|
Multiplication,
|
||||||
Division,
|
Division,
|
||||||
|
Exponent,
|
||||||
|
Modulus,
|
||||||
|
|
||||||
// Equality
|
// Equality
|
||||||
Equality,
|
Equality,
|
||||||
|
|
|
@ -111,6 +111,10 @@ namespace Porygon::Parser {
|
||||||
return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1);
|
return new SimpleToken(TokenKind::BadToken, this->_position - 1, 1);
|
||||||
case '#':
|
case '#':
|
||||||
return new SimpleToken(TokenKind::HashToken, this->_position - 1, 1);
|
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 '0':
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
|
|
|
@ -414,6 +414,10 @@ namespace Porygon::Parser {
|
||||||
return BinaryOperatorKind::Multiplication;
|
return BinaryOperatorKind::Multiplication;
|
||||||
case TokenKind::SlashToken:
|
case TokenKind::SlashToken:
|
||||||
return BinaryOperatorKind::Division;
|
return BinaryOperatorKind::Division;
|
||||||
|
case TokenKind::RoofToken:
|
||||||
|
return BinaryOperatorKind ::Exponent;
|
||||||
|
case TokenKind::PercentToken:
|
||||||
|
return BinaryOperatorKind ::Modulus;
|
||||||
|
|
||||||
// Equality operators
|
// Equality operators
|
||||||
case TokenKind::EqualityToken:
|
case TokenKind::EqualityToken:
|
||||||
|
@ -450,6 +454,11 @@ namespace Porygon::Parser {
|
||||||
return OperatorPrecedence::Multiplication;
|
return OperatorPrecedence::Multiplication;
|
||||||
case TokenKind::SlashToken:
|
case TokenKind::SlashToken:
|
||||||
return OperatorPrecedence::Multiplication;
|
return OperatorPrecedence::Multiplication;
|
||||||
|
case TokenKind::RoofToken:
|
||||||
|
return OperatorPrecedence ::Multiplication;
|
||||||
|
case TokenKind::PercentToken:
|
||||||
|
return OperatorPrecedence ::Multiplication;
|
||||||
|
|
||||||
|
|
||||||
// Equality
|
// Equality
|
||||||
case TokenKind::EqualityToken:
|
case TokenKind::EqualityToken:
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace Porygon::Parser {
|
||||||
Greater,
|
Greater,
|
||||||
GreaterEquals,
|
GreaterEquals,
|
||||||
HashToken,
|
HashToken,
|
||||||
|
RoofToken,
|
||||||
|
PercentToken,
|
||||||
|
|
||||||
OpenParenthesis,
|
OpenParenthesis,
|
||||||
CloseParenthesis,
|
CloseParenthesis,
|
||||||
|
|
|
@ -47,6 +47,22 @@ TEST_CASE( "Integer Division", "[integration]" ) {
|
||||||
delete script;
|
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]" ) {
|
TEST_CASE( "Float Addition", "[integration]" ) {
|
||||||
auto script = Script::Create("1.2 + 5.34");
|
auto script = Script::Create("1.2 + 5.34");
|
||||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
@ -75,4 +91,21 @@ TEST_CASE( "Float Division", "[integration]" ) {
|
||||||
REQUIRE(result->EvaluateFloat() == Approx(10.7305524239));
|
REQUIRE(result->EvaluateFloat() == Approx(10.7305524239));
|
||||||
delete script;
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue