Implemented comparison equality operators

This commit is contained in:
Deukhoofd 2019-06-08 15:38:08 +02:00
parent fc66c15c2f
commit 7d75131822
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 274 additions and 0 deletions

View File

@ -275,6 +275,26 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
case BinaryOperatorKind ::Inequality:
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength());
case BinaryOperatorKind ::Less:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan, std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength());
}
case BinaryOperatorKind ::LessOrEquals:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals, std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength());
}
case BinaryOperatorKind ::Greater:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan, std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength());
}
case BinaryOperatorKind ::GreaterOrEquals:
if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals, std::make_shared<ScriptType>(TypeClass::Bool),
expression->GetStartPosition(), expression->GetLength());
}
case BinaryOperatorKind ::LogicalAnd:
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool)
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, std::make_shared<ScriptType>(TypeClass::Bool),

View File

@ -9,6 +9,11 @@ enum class BoundBinaryOperation{
Division,
Equality,
Inequality,
LessThan,
LessThanEquals,
GreaterThan,
GreaterThanEquals,
LogicalAnd,
LogicalOr,
Concatenation

View File

@ -45,6 +45,35 @@ shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanBinary(BoundBinaryExpress
bool equals = leftValue.get()->operator!=(rightValue.get());
return make_shared<BooleanEvalValue>(equals);
}
case BoundBinaryOperation ::LessThan:
{
auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight());
BooleanEvalValue* b = leftValue->operator<(rightValue.get());
return shared_ptr<BooleanEvalValue>(b);
}
case BoundBinaryOperation ::LessThanEquals:
{
auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight());
BooleanEvalValue* b = leftValue->operator<=(rightValue.get());
return shared_ptr<BooleanEvalValue>(b);
}
case BoundBinaryOperation ::GreaterThan:
{
auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight());
BooleanEvalValue* b = leftValue->operator>(rightValue.get());
return shared_ptr<BooleanEvalValue>(b);
}
case BoundBinaryOperation ::GreaterThanEquals:
{
auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight());
BooleanEvalValue* b = leftValue->operator>=(rightValue.get());
return shared_ptr<BooleanEvalValue>(b);
}
case BoundBinaryOperation::LogicalAnd:
{
auto leftValue = this -> EvaluateBoolExpression(expression->GetLeft());

View File

@ -78,3 +78,67 @@ bool NumericEvalValue::operator==(EvalValue *b) {
return this->EvaluateInteger() == numVal->EvaluateInteger();
}
}
BooleanEvalValue *NumericEvalValue::operator<(NumericEvalValue *b) {
if (this->IsFloat()){
if (b->IsFloat()){
return new BooleanEvalValue(this->GetFloatValue() < b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetFloatValue() < b->GetIntegerValue());
}
} else {
if (b->IsFloat()){
return new BooleanEvalValue(this->GetIntegerValue() < b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetIntegerValue() < b->GetIntegerValue());
}
}
}
BooleanEvalValue *NumericEvalValue::operator<=(NumericEvalValue *b) {
if (this->IsFloat()){
if (b->IsFloat()){
return new BooleanEvalValue(this->GetFloatValue() <= b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetFloatValue() <= b->GetIntegerValue());
}
} else {
if (b->IsFloat()){
return new BooleanEvalValue(this->GetIntegerValue() <= b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetIntegerValue() <= b->GetIntegerValue());
}
}
}
BooleanEvalValue *NumericEvalValue::operator>(NumericEvalValue *b) {
if (this->IsFloat()){
if (b->IsFloat()){
return new BooleanEvalValue(this->GetFloatValue() > b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetFloatValue() > b->GetIntegerValue());
}
} else {
if (b->IsFloat()){
return new BooleanEvalValue(this->GetIntegerValue() > b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetIntegerValue() > b->GetIntegerValue());
}
}
}
BooleanEvalValue *NumericEvalValue::operator>=(NumericEvalValue *b) {
if (this->IsFloat()){
if (b->IsFloat()){
return new BooleanEvalValue(this->GetFloatValue() >= b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetFloatValue() >= b->GetIntegerValue());
}
} else {
if (b->IsFloat()){
return new BooleanEvalValue(this->GetIntegerValue() >= b->GetFloatValue());
} else{
return new BooleanEvalValue(this->GetIntegerValue() >= b->GetIntegerValue());
}
}
}

View File

@ -22,6 +22,10 @@ public:
NumericEvalValue* operator -(NumericEvalValue* b);
NumericEvalValue* operator *(NumericEvalValue* b);
NumericEvalValue* operator /(NumericEvalValue* b);
BooleanEvalValue* operator <(NumericEvalValue* b);
BooleanEvalValue* operator <=(NumericEvalValue* b);
BooleanEvalValue* operator >(NumericEvalValue* b);
BooleanEvalValue* operator >=(NumericEvalValue* b);
bool operator ==(EvalValue* b) final;
};

View File

@ -2,12 +2,21 @@
#ifndef PORYGONLANG_BINARYOPERATORKIND_HPP
#define PORYGONLANG_BINARYOPERATORKIND_HPP
enum class BinaryOperatorKind{
// Math
Addition,
Subtraction,
Multiplication,
Division,
// Equality
Equality,
Inequality,
Less,
LessOrEquals,
Greater,
GreaterOrEquals,
// Logical
LogicalAnd,
LogicalOr,
};

View File

@ -79,6 +79,18 @@ IToken* Lexer::LexNext(char c){
return new SimpleToken(TokenKind::EqualityToken, this -> _position - 2, 2);
}
return new SimpleToken(TokenKind::AssignmentToken, this -> _position - 1, 1);
case '<':
if (Lexer::Peek() == '='){
Lexer::Next();
return new SimpleToken(TokenKind::LessEquals, this -> _position - 2, 2);
}
return new SimpleToken(TokenKind::Less, this -> _position - 1, 1);
case '>':
if (Lexer::Peek() == '='){
Lexer::Next();
return new SimpleToken(TokenKind::GreaterEquals, this -> _position - 2, 2);
}
return new SimpleToken(TokenKind::Greater, this -> _position - 1, 1);
case '~':
if (Lexer::Peek() == '='){
Lexer::Next();

View File

@ -223,12 +223,21 @@ UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind){
BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){
switch (kind){
// Math operators
case TokenKind::PlusToken: return BinaryOperatorKind ::Addition;
case TokenKind::MinusToken: return BinaryOperatorKind ::Subtraction;
case TokenKind::StarToken: return BinaryOperatorKind ::Multiplication;
case TokenKind::SlashToken: return BinaryOperatorKind ::Division;
// Equality operators
case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality;
case TokenKind::InequalityToken: return BinaryOperatorKind ::Inequality;
case TokenKind ::Less: return BinaryOperatorKind ::Less;
case TokenKind ::LessEquals: return BinaryOperatorKind ::LessOrEquals;
case TokenKind ::Greater: return BinaryOperatorKind ::Greater;
case TokenKind ::GreaterEquals: return BinaryOperatorKind ::GreaterOrEquals;
// logical operators
case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd;
case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr;
default: // This should never trigger, so throw.
@ -238,12 +247,22 @@ BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){
OperatorPrecedence GetBinaryPrecedence(TokenKind kind){
switch (kind){
// Math
case TokenKind::PlusToken: return OperatorPrecedence ::Additive;
case TokenKind::MinusToken: return OperatorPrecedence ::Additive;
case TokenKind::StarToken: return OperatorPrecedence ::Multiplication;
case TokenKind::SlashToken: return OperatorPrecedence ::Multiplication;
// Equality
case TokenKind::EqualityToken: return OperatorPrecedence ::Equality;
case TokenKind::InequalityToken: return OperatorPrecedence ::Equality;
case TokenKind ::Less: return OperatorPrecedence ::Equality;
case TokenKind ::LessEquals: return OperatorPrecedence ::Equality;
case TokenKind ::Greater: return OperatorPrecedence ::Equality;
case TokenKind ::GreaterEquals: return OperatorPrecedence ::Equality;
// Logical
case TokenKind::AndKeyword: return OperatorPrecedence ::LogicalAnd;
case TokenKind::OrKeyword: return OperatorPrecedence ::LogicalOr;
default:

View File

@ -13,6 +13,11 @@ enum class TokenKind{
AssignmentToken,
EqualityToken,
InequalityToken,
Less,
LessEquals,
Greater,
GreaterEquals,
OpenParenthesis,
CloseParenthesis,
OpenSquareBracket,

View File

@ -63,6 +63,113 @@ TEST_CASE( "10 Not Equals 5", "[integration]" ) {
delete script;
}
TEST_CASE( "10 < 5 == false", "[integration]" ) {
auto script = Script::Create("10 < 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "2 < 60 == true", "[integration]" ) {
auto script = Script::Create("2 < 60");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "5 < 5 == false", "[integration]" ) {
auto script = Script::Create("5 < 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "10 <= 5 == false", "[integration]" ) {
auto script = Script::Create("10 <= 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "2 <= 60 == true", "[integration]" ) {
auto script = Script::Create("2 <= 60");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "5 <= 5 == true", "[integration]" ) {
auto script = Script::Create("5 <= 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "10 > 5 == true", "[integration]" ) {
auto script = Script::Create("10 > 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "2 > 60 == false", "[integration]" ) {
auto script = Script::Create("2 > 60");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "5 > 5 == false", "[integration]" ) {
auto script = Script::Create("5 > 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "10 >= 5 == true", "[integration]" ) {
auto script = Script::Create("10 >= 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "2 >= 60 == false", "[integration]" ) {
auto script = Script::Create("2 >= 60");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE_FALSE(lastValue->EvaluateBool());
delete script;
}
TEST_CASE( "5 >= 5 == true", "[integration]" ) {
auto script = Script::Create("5 >= 5");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto lastValue = script->GetLastValue();
REQUIRE(lastValue->EvaluateBool());
delete script;
}
#endif