mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added 'using' field invocation support to debugger
This commit is contained in:
parent
14f20f10c8
commit
1a0e28af92
5 changed files with 134 additions and 7 deletions
9
IDE/Tests/Test1/scripts/UsingFields.txt
Normal file
9
IDE/Tests/Test1/scripts/UsingFields.txt
Normal file
|
@ -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")
|
|
@ -31,6 +31,7 @@ namespace IDETest
|
||||||
Stepping_Scope.Test();
|
Stepping_Scope.Test();
|
||||||
TypedPrimitives.Test();
|
TypedPrimitives.Test();
|
||||||
Unions.Test();
|
Unions.Test();
|
||||||
|
UsingFields.Test();
|
||||||
Virtuals.Test();
|
Virtuals.Test();
|
||||||
|
|
||||||
Bug001.Test();
|
Bug001.Test();
|
||||||
|
|
43
IDE/Tests/Test1/src/UsingFields.bf
Normal file
43
IDE/Tests/Test1/src/UsingFields.bf
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7489,7 +7489,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
|
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);
|
SetAndRestoreValue<String*> prevReferenceId(mReferenceId, NULL);
|
||||||
|
|
||||||
|
@ -7983,7 +7983,77 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
|
||||||
|
|
||||||
if (methodDef == NULL)
|
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();
|
return DbgTypedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8030,7 +8100,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
|
||||||
return CreateCall(targetSrc, callTarget, methodDef, bypassVirtual, arguments, argValues);
|
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;
|
bool allowImplicitThis = false;
|
||||||
BfAstNode* methodNodeSrc = target;
|
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)
|
void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
|
||||||
|
@ -8235,7 +8306,10 @@ void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
|
||||||
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
|
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
|
||||||
if (invocationExpr->mGenericArgs != NULL)
|
if (invocationExpr->mGenericArgs != NULL)
|
||||||
methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs;
|
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))
|
if ((wasCapturingMethodInfo) && (!mAutoComplete->mIsCapturingMethodMatchInfo))
|
||||||
{
|
{
|
||||||
|
|
|
@ -388,13 +388,13 @@ public:
|
||||||
DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType);
|
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);
|
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);
|
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);
|
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, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
|
||||||
DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
|
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 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,
|
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);
|
DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name);
|
||||||
void PerformBinaryOperation(ASTREF(BfExpression*)& leftExpression, ASTREF(BfExpression*)& rightExpression, BfBinaryOp binaryOp, BfTokenNode* opToken, bool forceLeftType);
|
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);
|
void PerformBinaryOperation(DbgType* resultType, DbgTypedValue convLeftValue, DbgTypedValue convRightValue, BfBinaryOp binaryOp, BfTokenNode* opToken);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue