From faa3000d95fcd29461223700826cb13455652da3 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 18 Aug 2019 15:44:55 +0200 Subject: [PATCH] Fixed issue where an indexer followed by a binary operator would ignore the binary --- src/Parser/Parser.cpp | 10 ++++-- src/Parser/Parser.hpp | 1 + tests/integration/UserDataTests.cpp | 48 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index f65a59c..b852534 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -331,7 +331,10 @@ namespace Porygon::Parser { ///////////////// ParsedExpression *Parser::ParseExpression(const Token *current) { - auto expression = this->ParseBinaryExpression(current, OperatorPrecedence::No); + return this->ParseBinaryExpression(current, OperatorPrecedence::No); + } + + ParsedExpression* Parser::ParseComplexExpression(ParsedExpression* expression){ auto peekKind = this->Peek()->GetKind(); while (peekKind == TokenKind::OpenParenthesis || peekKind == TokenKind::OpenSquareBracket || @@ -455,8 +458,10 @@ namespace Porygon::Parser { auto operand = this->ParseBinaryExpression(next, unaryPrecedence); auto startPos = current->GetStartPosition(); left = new UnaryExpression(operatorKind, operand, startPos, operand->GetEndPosition() - startPos); + left = this -> ParseComplexExpression(left); } else { left = this->ParsePrimaryExpression(current); + left = this -> ParseComplexExpression(left); } while (true) { auto next = this->Peek(); @@ -469,8 +474,9 @@ namespace Porygon::Parser { auto right = this->ParseBinaryExpression(this->Next(), binaryPrecedence); auto startPos = left->GetStartPosition(); left = new BinaryExpression(operatorKind, left, right, startPos, right->GetEndPosition() - startPos); + left = this -> ParseComplexExpression(left); } - return left; + return this -> ParseComplexExpression(left); } ParsedExpression *Parser::ParsePrimaryExpression(const Token *current) { diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp index 01f1494..2f9a158 100644 --- a/src/Parser/Parser.hpp +++ b/src/Parser/Parser.hpp @@ -45,6 +45,7 @@ namespace Porygon::Parser { // Expressions ParsedExpression *ParseExpression(const Token *current); + ParsedExpression *ParseComplexExpression(ParsedExpression* previous); ParsedExpression *ParseBinaryExpression(const Token *current, OperatorPrecedence parentPrecedence); ParsedExpression *ParsePrimaryExpression(const Token *current); ParsedExpression *ParseParenthesizedExpression(const Token *current); diff --git a/tests/integration/UserDataTests.cpp b/tests/integration/UserDataTests.cpp index 2531e6d..7b695cd 100644 --- a/tests/integration/UserDataTests.cpp +++ b/tests/integration/UserDataTests.cpp @@ -20,6 +20,7 @@ using namespace Porygon::Utilities; class UserDataTestObject{ public: int foo = 10; + int readonly = 5; vector fooVector = {5,10,15,25}; int getFoo(){ return foo; @@ -41,6 +42,7 @@ private: public: PORYGON_USERDATA(UserDataTestObject, PORYGON_INTEGER_FIELD(foo) + PORYGON_READONLY_INTEGER_FIELD(readonly) PORYGON_INTEGER_FUNCTION(getFoo) PORYGON_INTEGER_FUNCTION(Addition, PORYGON_INTEGER_TYPE, PORYGON_INTEGER_TYPE) PORYGON_READONLY_VECTOR_FIELD(fooVector, PORYGON_INTEGER_TYPE) @@ -173,6 +175,52 @@ end UserDataStorage::RemoveType(HashedString::ConstHash("testObject")); } +TEST_CASE( "returns readonly value + 2", "[integration]" ) { + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); + Script* script = Script::Create(R"( +function testFunc(testObject obj) + return obj.readonly + 2 +end +)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto func = (GenericFunctionEvalValue*)script -> GetVariable(u"testFunc"); + auto funcType = func -> GetType(); + auto obj = new UserDataTestObject(); + auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), obj); + auto result = script->CallFunction(u"testFunc", {parameter}); + REQUIRE(result -> EvaluateInteger() == 7); + delete obj; + delete parameter; + delete script; + delete func; + delete result; + UserDataStorage::RemoveType(HashedString::ConstHash("testObject")); +} + +TEST_CASE( "returns negative readonly value", "[integration]" ) { + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); + Script* script = Script::Create(R"( +function testFunc(testObject obj) + return -obj.readonly +end +)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto func = (GenericFunctionEvalValue*)script -> GetVariable(u"testFunc"); + auto funcType = func -> GetType(); + auto obj = new UserDataTestObject(); + auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), obj); + auto result = script->CallFunction(u"testFunc", {parameter}); + REQUIRE(result -> EvaluateInteger() == -5); + delete obj; + delete parameter; + delete script; + delete func; + delete result; + UserDataStorage::RemoveType(HashedString::ConstHash("testObject")); +} + TEST_CASE( "Iterate over userdata vector keys", "[integration]" ) { UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); Script* script = Script::Create(R"(