1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Fixed constrained property lookups

This commit is contained in:
Brian Fiete 2021-01-19 10:40:38 -08:00
parent 15c62583a2
commit 6d06ee3430
4 changed files with 139 additions and 19 deletions

View file

@ -8576,7 +8576,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
prevBindResult.mPrevVal->mCheckedMultipleMethods = true; prevBindResult.mPrevVal->mCheckedMultipleMethods = true;
BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher); BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher);
if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc)) if ((moduleMethodInstance.mMethodInstance != NULL) && (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc)))
return BfTypedValue(); return BfTypedValue();
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized)) if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized))
@ -16498,7 +16498,8 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
if (bestMethodInstance != NULL) if (bestMethodInstance != NULL)
{ {
mPropTarget = mOrigPropTarget; mPropTarget = mOrigPropTarget;
mPropTarget.mType = checkTypeInst; //mPropTarget.mType = checkTypeInst;
//mPropTarget = mModule->Cast( mOrigPropTarget, checkTypeInst);
return mModule->GetMethodInstanceAtIdx(ifaceMethodEntry.mMethodRef.mTypeInstance, ifaceMethodEntry.mMethodRef.mMethodNum); return mModule->GetMethodInstanceAtIdx(ifaceMethodEntry.mMethodRef.mTypeInstance, ifaceMethodEntry.mMethodRef.mMethodNum);
} }
} }
@ -16638,9 +16639,23 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
if (!matchedMethod->mIsStatic) if (!matchedMethod->mIsStatic)
{ {
auto owner = methodInstance.mMethodInstance->GetOwner(); auto owner = methodInstance.mMethodInstance->GetOwner();
if ((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake()))
{ bool isTypeMatch = mPropTarget.mType == owner;
if (owner->IsTypedPrimitive())
isTypeMatch |= mPropTarget.mType == owner->GetUnderlyingType();
if ((!isTypeMatch) ||
((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake())))
{
auto prevPropTarget = mPropTarget;
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner); mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner);
if (!mPropTarget)
{
mModule->Fail("Internal property error", mPropSrc);
return BfTypedValue();
}
} }
if ((mPropGetMethodFlags & BfGetMethodInstanceFlag_DisableObjectAccessChecks) == 0) if ((mPropGetMethodFlags & BfGetMethodInstanceFlag_DisableObjectAccessChecks) == 0)
@ -17439,6 +17454,11 @@ void BfExprEvaluator::DoTupleAssignment(BfAssignmentExpression* assignExpr)
void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue) void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue)
{ {
if (assignExpr->ToString() == "state.StateMachine = this")
{
NOP;
}
auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp); auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp);
BfExpression* targetNode = assignExpr->mLeft; BfExpression* targetNode = assignExpr->mLeft;
@ -17589,10 +17609,18 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
if (!setMethod->mIsStatic) if (!setMethod->mIsStatic)
{ {
auto owner = methodInstance.mMethodInstance->GetOwner(); auto owner = methodInstance.mMethodInstance->GetOwner();
if (mPropTarget.mType != owner) if ((mPropTarget.mType != owner) ||
((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake())))
{ {
if (mPropDefBypassVirtual) if ((mPropDefBypassVirtual) || (!mPropTarget.mType->IsInterface()))
{
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner); mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner);
if (!mPropTarget)
{
mModule->Fail("Internal property error", mPropSrc);
return;
}
}
} }
mModule->EmitObjectAccessCheck(mPropTarget); mModule->EmitObjectAccessCheck(mPropTarget);

View file

@ -12362,7 +12362,7 @@ BfModuleMethodInstance BfModule::ReferenceExternalMethodInstance(BfMethodInstanc
inlineMethodRequest->mFromModuleRevision = mRevision; inlineMethodRequest->mFromModuleRevision = mRevision;
inlineMethodRequest->mMethodInstance = methodInstance; inlineMethodRequest->mMethodInstance = methodInstance;
BF_ASSERT(mIsModuleMutable); BF_ASSERT(mIsModuleMutable);
BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in ReferenceExternalMethodInstance\n", inlineMethodRequest, methodInstance, this); BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in ReferenceExternalMethodInstance\n", inlineMethodRequest, methodInstance, this);
} }
} }
@ -13047,7 +13047,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
inlineMethodRequest->mFunc = methodInstance->mIRFunction; inlineMethodRequest->mFunc = methodInstance->mIRFunction;
inlineMethodRequest->mFromModuleRevision = mRevision; inlineMethodRequest->mFromModuleRevision = mRevision;
inlineMethodRequest->mMethodInstance = methodInstance; inlineMethodRequest->mMethodInstance = methodInstance;
BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this); BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this);
BF_ASSERT(mIsModuleMutable); BF_ASSERT(mIsModuleMutable);
} }
@ -14650,8 +14650,11 @@ void BfModule::CreateReturn(BfIRValue val)
mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx())); mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
return; return;
} }
if (mCurMethodInstance->mReturnType->IsVar())
return;
if (mCurMethodInstance->mReturnType->IsValuelessType()) if (mCurMethodInstance->mReturnType->IsValuelessType())
{ {
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
@ -14740,7 +14743,11 @@ void BfModule::EmitDefaultReturn()
} }
else else
{ {
if (mCurMethodInstance->mReturnType->IsVoid()) if (mCurMethodInstance->mReturnType->IsVar())
{
// Ignore
}
else if (mCurMethodInstance->mReturnType->IsVoid())
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
else if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == -1)) else if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == -1))
mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType)); mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType));
@ -17994,8 +18001,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
// We set mHasBeenProcessed to true immediately -- this helps avoid stack overflow during recursion for things like // We set mHasBeenProcessed to true immediately -- this helps avoid stack overflow during recursion for things like
// self-referencing append allocations in ctor@calcAppend // self-referencing append allocations in ctor@calcAppend
methodInstance->mHasBeenProcessed = true; methodInstance->mHasBeenProcessed = true;
mIncompleteMethodCount--; mIncompleteMethodCount--;
BF_ASSERT((mIsSpecialModule) || (mIncompleteMethodCount >= 0)); BF_ASSERT((mIsSpecialModule) || (mIncompleteMethodCount >= 0));
auto typeDef = methodInstance->mMethodInstanceGroup->mOwner->mTypeDef; auto typeDef = methodInstance->mMethodInstanceGroup->mOwner->mTypeDef;
@ -18126,7 +18133,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
} }
} }
BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified); BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d Incomplete:%d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified, mIncompleteMethodCount);
if (methodInstance->GetImportCallKind() != BfImportCallKind_None) if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
{ {
@ -18242,11 +18249,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
BF_ASSERT(unspecializedMethodInstance != methodInstance); BF_ASSERT(unspecializedMethodInstance != methodInstance);
if (!unspecializedMethodInstance->mHasBeenProcessed) if (!unspecializedMethodInstance->mHasBeenProcessed)
{ {
// Make sure the unspecialized method is processed so we can take its bindings // Make sure the unspecialized method is processed so we can take its bindings
// Clear mCurMethodState so we don't think we're in a local method // Clear mCurMethodState so we don't think we're in a local method
SetAndRestoreValue<BfMethodState*> prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal); SetAndRestoreValue<BfMethodState*> prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal);
mContext->ProcessMethod(unspecializedMethodInstance); if (unspecializedMethodInstance->mMethodProcessRequest == NULL)
unspecializedMethodInstance->mDeclModule->mIncompleteMethodCount++;
mContext->ProcessMethod(unspecializedMethodInstance);
} }
methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings; methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings;
} }
@ -20726,7 +20734,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth
closureState.mReturnType = methodInstance->mReturnType; closureState.mReturnType = methodInstance->mReturnType;
mCompiler->mStats.mMethodsQueued++; mCompiler->mStats.mMethodsQueued++;
mCompiler->UpdateCompletion(); mCompiler->UpdateCompletion();
declareModule->mIncompleteMethodCount++; declareModule->mIncompleteMethodCount++;
mCompiler->mStats.mMethodsProcessed++; mCompiler->mStats.mMethodsProcessed++;
if (!methodInstance->mIsReified) if (!methodInstance->mIsReified)
mCompiler->mStats.mUnreifiedMethodsProcessed++; mCompiler->mStats.mUnreifiedMethodsProcessed++;
@ -22156,7 +22164,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
auto func = methodInstance->mIRFunction; auto func = methodInstance->mIRFunction;
// if (methodInstance->mIsReified) // if (methodInstance->mIsReified)
// CheckHotMethod(methodInstance, mangledName); // CheckHotMethod(methodInstance, mangledName);
BfLogSysM("DoMethodDeclaration %s Module: %p Type: %p MethodInst: %p Reified: %d Unspecialized: %d IRFunction: %d MethodId:%llx\n", mangledName.c_str(), this, mCurTypeInstance, methodInstance, methodInstance->mIsReified, mCurTypeInstance->IsUnspecializedType(), methodInstance->mIRFunction.mId, methodInstance->mIdHash); BfLogSysM("DoMethodDeclaration %s Module: %p Type: %p MethodInst: %p Reified: %d Unspecialized: %d IRFunction: %d MethodId:%llx\n", mangledName.c_str(), this, mCurTypeInstance, methodInstance, methodInstance->mIsReified, mCurTypeInstance->IsUnspecializedType(), methodInstance->mIRFunction.mId, methodInstance->mIdHash);

View file

@ -183,6 +183,13 @@ namespace Tests
IFaceA ifa = cba; IFaceA ifa = cba;
Test.Assert(ifa.GetType() == typeof(ClassB)); Test.Assert(ifa.GetType() == typeof(ClassB));
ClassF cf = scope .();
TestIFaceD(cf);
Test.Assert(cf.mA == 999);
ClassG cg = scope .();
TestIFaceD(cg);
Test.Assert(cg.mA == 999);
GameItem gameItem = scope .(); GameItem gameItem = scope .();
var hitbox = GetHitbox(gameItem); var hitbox = GetHitbox(gameItem);
Test.Assert(hitbox.mArea == .() { x=1, y=2, width=3, height=4 }); Test.Assert(hitbox.mArea == .() { x=1, y=2, width=3, height=4 });
@ -267,6 +274,47 @@ namespace Tests
return T.SMethod2(val.GetVal()); return T.SMethod2(val.GetVal());
} }
interface IFaceD
{
int32 Val
{
get; set;
}
}
class ClassF : IFaceD
{
public int32 mA;
int32 IFaceD.Val
{
get
{
return mA;
}
set
{
mA = value;
}
}
}
class ClassG : ClassF
{
}
static void TestIFaceD<T>(T val) where T : IFaceD
{
val.Val = 999;
}
static int TestIFaceD2<T>(T val) where T : IFaceD
{
return val.Val;
}
[Test] [Test]
public static void TestDefaults() public static void TestDefaults()
{ {
@ -297,6 +345,15 @@ namespace Tests
Test.Assert(v == 3234); Test.Assert(v == 3234);
v = SGet2<ClassE, int16>(ce); v = SGet2<ClassE, int16>(ce);
Test.Assert(v == 4234); Test.Assert(v == 4234);
ClassF cf = scope .();
TestIFaceD(cf);
Test.Assert(cf.mA == 999);
Test.Assert(TestIFaceD2(cf) == 999);
ClassG cg = scope .();
TestIFaceD(cg);
Test.Assert(cg.mA == 999);
Test.Assert(TestIFaceD2(cg) == 999);
} }
} }
} }

View file

@ -71,6 +71,8 @@ namespace Tests
} }
} }
class ClassB class ClassB
{ {
public StructA B { get; set; } public StructA B { get; set; }
@ -90,6 +92,26 @@ namespace Tests
public override int IVal2 { get => base.IVal2 + 100; } public override int IVal2 { get => base.IVal2 + 100; }
} }
abstract class ClassD
{
public int32 Val { get; set; }
}
class ClassE : ClassD
{
}
static void MethodC<T>(T val) where T : ClassD
{
val.Val = 999;
}
static int MethodD<T>(T val) where T : ClassD
{
return val.Val;
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -122,6 +144,11 @@ namespace Tests
ClassB cb2 = cc; ClassB cb2 = cc;
Test.Assert(cb2.IVal == 1); Test.Assert(cb2.IVal == 1);
Test.Assert(cb2.IVal2 == 102); Test.Assert(cb2.IVal2 == 102);
ClassE ce = scope .();
MethodC(ce);
Test.Assert(ce.Val == 999);
Test.Assert(MethodD(ce) == 999);
} }
} }
} }