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:
parent
15c62583a2
commit
6d06ee3430
4 changed files with 139 additions and 19 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue