From 1a0e28af92de266db463aa453ef528f6264d4844 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 30 Jul 2022 09:41:05 -0400 Subject: [PATCH] Added 'using' field invocation support to debugger --- IDE/Tests/Test1/scripts/UsingFields.txt | 9 +++ IDE/Tests/Test1/src/Program.bf | 1 + IDE/Tests/Test1/src/UsingFields.bf | 43 +++++++++++++ IDEHelper/DbgExprEvaluator.cpp | 84 +++++++++++++++++++++++-- IDEHelper/DbgExprEvaluator.h | 4 +- 5 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 IDE/Tests/Test1/scripts/UsingFields.txt create mode 100644 IDE/Tests/Test1/src/UsingFields.bf diff --git a/IDE/Tests/Test1/scripts/UsingFields.txt b/IDE/Tests/Test1/scripts/UsingFields.txt new file mode 100644 index 00000000..0e16e2e3 --- /dev/null +++ b/IDE/Tests/Test1/scripts/UsingFields.txt @@ -0,0 +1,9 @@ +ShowFile("src/UsingFields.bf") +GotoText("//Test_Start") +ToggleBreakpoint() +RunWithCompiling() + +AssertEvalEquals("v0.x", "123") +AssertEvalEquals("v0.GetX()", "123") +AssertEvalEquals("v1.x", "345") +AssertEvalEquals("v1.GetX()", "345") \ No newline at end of file diff --git a/IDE/Tests/Test1/src/Program.bf b/IDE/Tests/Test1/src/Program.bf index 7db5c7da..e17d8dd2 100644 --- a/IDE/Tests/Test1/src/Program.bf +++ b/IDE/Tests/Test1/src/Program.bf @@ -31,6 +31,7 @@ namespace IDETest Stepping_Scope.Test(); TypedPrimitives.Test(); Unions.Test(); + UsingFields.Test(); Virtuals.Test(); Bug001.Test(); diff --git a/IDE/Tests/Test1/src/UsingFields.bf b/IDE/Tests/Test1/src/UsingFields.bf new file mode 100644 index 00000000..f7952135 --- /dev/null +++ b/IDE/Tests/Test1/src/UsingFields.bf @@ -0,0 +1,43 @@ +#pragma warning disable 168 + +using System; + +namespace IDETest +{ + class UsingFields + { + struct Vector2Int + { + [Union] + struct XWidth + { + public int x; + public int width; + + public int GetX() => x; + } + [Union] struct YHeight : this(int y, int height); + + public using XWidth xWidth; + public using YHeight yHeight; + } + + struct TestVec : Vector2Int + { + } + + public static void Test() + { + Vector2Int v0; + v0.x = 123; + v0.y = 234; + + TestVec v1; + v1.x = 345; + v0.y = 456; + + //Test_Start + int v = v0.GetX(); + } + } +} \ No newline at end of file diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index eb922082..52ff9ac0 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -7489,7 +7489,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl } DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, - const BfSizedArray& arguments, BfSizedArray* methodGenericArguments) + const BfSizedArray& arguments, BfSizedArray* methodGenericArguments, bool& failed) { SetAndRestoreValue prevReferenceId(mReferenceId, NULL); @@ -7983,7 +7983,77 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue if (methodDef == NULL) { - Fail("Method does not exist", targetSrc); + if (target) + { + std::function _CheckUsingFields = [&](DbgTypedValue checkTarget) + { + auto curCheckType = checkTarget.mType->RemoveModifiers(); + curCheckType = curCheckType->GetPrimaryType(); + curCheckType->PopulateType(); + + auto nextMember = curCheckType->mMemberList.mHead; + while (nextMember != NULL) + { + auto checkMember = nextMember; + nextMember = checkMember->mNext; + + if (checkMember->mName == NULL) + { + //TODO: Check inside anonymous type + DbgTypedValue innerTarget; + + addr_target targetPtr = checkTarget.mSrcAddress; + if ((checkTarget.mType != NULL) && (checkTarget.mType->HasPointer())) + targetPtr = checkTarget.mPtr; + innerTarget.mSrcAddress = targetPtr + checkMember->mMemberOffset; + innerTarget.mType = checkMember->mType; + + failed = false; + auto result = MatchMethod(targetSrc, innerTarget, false, bypassVirtual, methodName, arguments, methodGenericArguments, failed); + if (!failed) + return result; + } + } + + for (auto baseTypeEntry : curCheckType->mBaseTypes) + { + auto baseType = baseTypeEntry->mBaseType; + + DbgTypedValue baseTarget = target; + addr_target* ptrRef = NULL; + if ((baseTarget.mPtr != 0) && (checkTarget.mType->HasPointer())) + ptrRef = &baseTarget.mPtr; + else if (baseTarget.mSrcAddress != 0) + ptrRef = &baseTarget.mSrcAddress; + + if (ptrRef != NULL) + { + if (baseTypeEntry->mVTableOffset != -1) + { + addr_target vtableAddr = mDebugger->ReadMemory(checkTarget.mPtr); + int32 virtThisOffset = mDebugger->ReadMemory(vtableAddr + baseTypeEntry->mVTableOffset * sizeof(int32)); + *ptrRef += virtThisOffset; + } + else + *ptrRef += baseTypeEntry->mThisOffset; + } + + baseTarget.mType = baseType; + auto result = _CheckUsingFields(baseTarget); + if (!failed) + return result; + } + + failed = true; + return DbgTypedValue(); + }; + + auto result = _CheckUsingFields(target); + if (!failed) + return result; + } + + failed = true; return DbgTypedValue(); } @@ -8030,7 +8100,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue return CreateCall(targetSrc, callTarget, methodDef, bypassVirtual, arguments, argValues); } -void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments) +void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments, bool& failed) { bool allowImplicitThis = false; BfAstNode* methodNodeSrc = target; @@ -8221,7 +8291,8 @@ void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray* methodGenericArguments = NULL; if (invocationExpr->mGenericArgs != NULL) methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs; - DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments); + bool failed = false; + DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments, failed); + if (failed) + Fail("Method does not exist", invocationExpr->mTarget); if ((wasCapturingMethodInfo) && (!mAutoComplete->mIsCapturingMethodMatchInfo)) { diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index 6d37ae6b..ecfa164f 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -388,13 +388,13 @@ public: DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType); bool CheckTupleCreation(addr_target receiveAddr, BfAstNode* targetSrc, DbgType* tupleType, const BfSizedArray& argValues, BfSizedArray* names); DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray& argValues); - void DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments); + void DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments, bool& failed); bool ResolveArgValues(const BfSizedArray& arguments, SizedArrayImpl& outArgValues); DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers); DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl& argPushQueue, bool bypassVirtual); DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray& arguments, SizedArrayImpl& argValues); DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, - const BfSizedArray& arguments, BfSizedArray* methodGenericArguments); + const BfSizedArray& arguments, BfSizedArray* methodGenericArguments, bool& failed); DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name); void PerformBinaryOperation(ASTREF(BfExpression*)& leftExpression, ASTREF(BfExpression*)& rightExpression, BfBinaryOp binaryOp, BfTokenNode* opToken, bool forceLeftType); void PerformBinaryOperation(DbgType* resultType, DbgTypedValue convLeftValue, DbgTypedValue convRightValue, BfBinaryOp binaryOp, BfTokenNode* opToken);