Преглед на файлове

Added 'using' field invocation support to debugger

Brian Fiete преди 3 години
родител
ревизия
1a0e28af92
променени са 5 файла, в които са добавени 134 реда и са изтрити 7 реда
  1. 9 0
      IDE/Tests/Test1/scripts/UsingFields.txt
  2. 1 0
      IDE/Tests/Test1/src/Program.bf
  3. 43 0
      IDE/Tests/Test1/src/UsingFields.bf
  4. 79 5
      IDEHelper/DbgExprEvaluator.cpp
  5. 2 2
      IDEHelper/DbgExprEvaluator.h

+ 9 - 0
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")

+ 1 - 0
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();

+ 43 - 0
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();
+		}
+	}
+}

+ 79 - 5
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<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
+	const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, bool& failed)
 {
 	SetAndRestoreValue<String*> 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<DbgTypedValue(DbgTypedValue)> _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<addr_target>(checkTarget.mPtr);
+							int32 virtThisOffset = mDebugger->ReadMemory<int32>(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<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
+void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, bool& failed)
 {
 	bool allowImplicitThis = false;
 	BfAstNode* methodNodeSrc = target;
@@ -8221,7 +8291,8 @@ void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExp
 		}*/
 	}
 
-	mResult = MatchMethod(methodNodeSrc, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, args, methodGenericArguments);
+
+	mResult = MatchMethod(methodNodeSrc, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, args, methodGenericArguments, failed);
 }
 
 void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
@@ -8235,7 +8306,10 @@ void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
 	BfSizedArray<ASTREF(BfAstNode*)>* 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))
 	{

+ 2 - 2
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<BfExpression*>& argValues, BfSizedArray<BfTupleNameNode*>* names);
 	DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues);
-	void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
+	void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, bool& failed);
 	bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues);
 	DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
 	DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
 	DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues);
 	DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
-		const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
+		const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* 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);