diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index cbb5f0c..f2a3389 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -133,6 +133,9 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ case BinaryOperatorKind ::Equality: return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, new ScriptType(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); + case BinaryOperatorKind ::Inequality: + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, new 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, new ScriptType(TypeClass::Bool), @@ -143,8 +146,6 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, new ScriptType(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); break; - default: - break; } this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); diff --git a/src/Binder/BoundOperators.hpp b/src/Binder/BoundOperators.hpp index 32dadb7..cd2315d 100644 --- a/src/Binder/BoundOperators.hpp +++ b/src/Binder/BoundOperators.hpp @@ -8,6 +8,7 @@ enum class BoundBinaryOperation{ Multiplication, Division, Equality, + Inequality, LogicalAnd, LogicalOr, Concatenation diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index c83d525..73ad493 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -43,6 +43,15 @@ BooleanEvalValue* Evaluator::EvaluateBooleanBinary(BoundBinaryExpression* expres delete rightValue; return new BooleanEvalValue(equals); } + case BoundBinaryOperation::Inequality: + { + EvalValue* leftValue = this -> EvaluateExpression(expression->GetLeft()); + EvalValue* rightValue = this -> EvaluateExpression(expression->GetRight()); + bool equals = leftValue->operator!=(rightValue); + delete leftValue; + delete rightValue; + return new BooleanEvalValue(equals); + } case BoundBinaryOperation::LogicalAnd: { BooleanEvalValue* leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); diff --git a/src/Parser/BinaryOperatorKind.hpp b/src/Parser/BinaryOperatorKind.hpp index 0f7effb..352e8b2 100644 --- a/src/Parser/BinaryOperatorKind.hpp +++ b/src/Parser/BinaryOperatorKind.hpp @@ -7,6 +7,7 @@ enum class BinaryOperatorKind{ Multiplication, Division, Equality, + Inequality, LogicalAnd, LogicalOr, }; diff --git a/src/Parser/Lexer.cpp b/src/Parser/Lexer.cpp index 7685f29..595b276 100644 --- a/src/Parser/Lexer.cpp +++ b/src/Parser/Lexer.cpp @@ -62,6 +62,13 @@ 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::InequalityToken, this -> Position - 2, 2); + } + this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedCharacter, this -> Position - 1, 1); + return new SimpleToken(TokenKind::BadToken, this -> Position - 1, 1); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return LexNumber(c); case '"': diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 2196992..37d3dfa 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -56,6 +56,7 @@ BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){ case TokenKind::StarToken: return BinaryOperatorKind ::Multiplication; case TokenKind::SlashToken: return BinaryOperatorKind ::Division; case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality; + case TokenKind::InequalityToken: return BinaryOperatorKind ::Inequality; case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd; case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr; default: // This should never trigger, so throw. @@ -70,6 +71,7 @@ OperatorPrecedence GetBinaryPrecedence(TokenKind kind){ case TokenKind::StarToken: return OperatorPrecedence ::Multiplication; case TokenKind::SlashToken: return OperatorPrecedence ::Multiplication; case TokenKind::EqualityToken: return OperatorPrecedence ::Equality; + case TokenKind::InequalityToken: return OperatorPrecedence ::Equality; case TokenKind::AndKeyword: return OperatorPrecedence ::LogicalAnd; case TokenKind::OrKeyword: return OperatorPrecedence ::LogicalOr; default: diff --git a/src/Parser/TokenKind.hpp b/src/Parser/TokenKind.hpp index ad4d7a0..5a688e3 100644 --- a/src/Parser/TokenKind.hpp +++ b/src/Parser/TokenKind.hpp @@ -12,6 +12,7 @@ enum class TokenKind{ StarToken, AssignmentToken, EqualityToken, + InequalityToken, OpenParenthesis, CloseParenthesis, diff --git a/tests/integration/EqualityOperationsTests.cpp b/tests/integration/EqualityOperationsTests.cpp index 00a4545..6ac40dd 100644 --- a/tests/integration/EqualityOperationsTests.cpp +++ b/tests/integration/EqualityOperationsTests.cpp @@ -17,6 +17,21 @@ TEST_CASE( "True Not Equals True", "[integration]" ) { auto lastValue = script.GetLastValue(); REQUIRE(!lastValue->EvaluateBool()); } +TEST_CASE( "True Nequals False", "[integration]" ) { + Script script = Script::Create("true ~= false"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(lastValue->EvaluateBool()); +} +TEST_CASE( "True Not Nequals True", "[integration]" ) { + Script script = Script::Create("true ~= true"); + REQUIRE(!script.Diagnostics -> HasErrors()); + script.Evaluate(); + auto lastValue = script.GetLastValue(); + REQUIRE(!lastValue->EvaluateBool()); +} + TEST_CASE( "False Equals False", "[integration]" ) { Script script = Script::Create("false == false");