mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Fixes for default interface properties and bindings
This commit is contained in:
parent
4e5baf3b84
commit
4cae7ff373
3 changed files with 146 additions and 96 deletions
|
@ -2594,6 +2594,9 @@ BfType* BfExprEvaluator::BindGenericType(BfAstNode* node, BfType* bindType)
|
|||
if ((mModule->mCurMethodState == NULL) || (mModule->mCurMethodInstance == NULL) || (bindType == NULL))
|
||||
return bindType;
|
||||
|
||||
if ((mModule->mCurMethodState->mClosureState != NULL) && (mModule->mCurMethodState->mClosureState->mCapturing))
|
||||
return bindType;
|
||||
|
||||
BF_ASSERT(!mModule->mCurMethodInstance->mIsUnspecializedVariation);
|
||||
|
||||
auto parser = node->GetSourceData()->ToParserData();
|
||||
|
@ -2616,10 +2619,6 @@ BfType* BfExprEvaluator::BindGenericType(BfAstNode* node, BfType* bindType)
|
|||
if (genericTypeBindings == NULL)
|
||||
return bindType;
|
||||
|
||||
/*auto itr = mModule->mCurMethodState->mGenericTypeBindings->find(nodeId);
|
||||
if (itr != mModule->mCurMethodState->mGenericTypeBindings->end())
|
||||
return itr->second;*/
|
||||
|
||||
BfType** typePtr = NULL;
|
||||
if (genericTypeBindings->TryGetValue(nodeId, &typePtr))
|
||||
return *typePtr;
|
||||
|
@ -3640,7 +3639,11 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
|||
{
|
||||
if (forcedIFaceLookup)
|
||||
{
|
||||
|
||||
if (mPropTarget == thisValue)
|
||||
{
|
||||
mPropDefBypassVirtual = true;
|
||||
mOrigPropTarget = mModule->GetThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((!result) && (mPropDef == NULL))
|
||||
|
@ -3788,6 +3791,20 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
if ((target.mType != NULL && (target.mType->IsGenericParam())))
|
||||
{
|
||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)target.mType);
|
||||
|
||||
if (target.mValue)
|
||||
{
|
||||
for (auto iface : genericParamInst->mInterfaceConstraints)
|
||||
{
|
||||
auto result = LookupField(targetSrc, BfTypedValue(target.mValue, iface), fieldName, flags);
|
||||
if ((result) || (mPropDef != NULL))
|
||||
{
|
||||
//BindGenericType(targetSrc, iface);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mModule->mCurMethodInstance->mIsUnspecialized)
|
||||
{
|
||||
if (genericParamInst->mTypeConstraint != NULL)
|
||||
|
@ -6414,7 +6431,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
|
||||
if (!methodDef->mIsStatic)
|
||||
{
|
||||
if ((methodInstance->GetOwner()->IsInterface()) && (!target.mType->IsGenericParam()) && (!target.mType->IsConcreteInterfaceType()))
|
||||
bool ignoreVirtualError = (mModule->mBfIRBuilder->mIgnoreWrites) && (mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsForeignMethodDef);
|
||||
|
||||
if ((methodInstance->GetOwner()->IsInterface()) && (!target.mType->IsGenericParam()) && (!target.mType->IsConcreteInterfaceType()) &&
|
||||
(!mModule->mCurTypeInstance->IsInterface()) && (!ignoreVirtualError))
|
||||
{
|
||||
if (methodInstance->mVirtualTableIdx == -1)
|
||||
{
|
||||
|
@ -8301,44 +8321,8 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
if (!mResult)
|
||||
return;
|
||||
|
||||
//if (mResult.mType->IsVar())
|
||||
//ResolveGenericType();
|
||||
|
||||
auto origResult = mResult;
|
||||
auto lookupType = BindGenericType(nameNode, mResult.mType);
|
||||
if (mResult.mType->IsGenericParam())
|
||||
{
|
||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)mResult.mType);
|
||||
if (mModule->mCurMethodInstance->mIsUnspecialized)
|
||||
{
|
||||
if (genericParamInst->mTypeConstraint != NULL)
|
||||
mResult.mType = genericParamInst->mTypeConstraint;
|
||||
else
|
||||
mResult.mType = mModule->mContext->mBfObjectType;
|
||||
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
||||
{
|
||||
mResult.mType = mModule->GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
||||
{
|
||||
//mResult.mType = mModule->ResolveGenericType(mResult.mType);
|
||||
}
|
||||
else if (genericParamInst->mTypeConstraint != NULL)
|
||||
{
|
||||
mResult = mModule->Cast(nameNode, mResult, genericParamInst->mTypeConstraint);
|
||||
BF_ASSERT(mResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This shouldn't occur - this would infer that we are accessing a member of Object or something...
|
||||
//mResult.mType = mModule->ResolveGenericType(mResult.mType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mResult.mType->IsVar())
|
||||
{
|
||||
|
@ -8346,7 +8330,7 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
return;
|
||||
}
|
||||
|
||||
if (!mResult.mType->IsTypeInstance())
|
||||
if ((!mResult.mType->IsTypeInstance()) && (!mResult.mType->IsGenericParam()))
|
||||
{
|
||||
if (hadError != NULL)
|
||||
*hadError = true;
|
||||
|
@ -8363,7 +8347,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
SizedArray<BfTypeInstance*, 8> searchConstraints;
|
||||
for (auto ifaceConstraint : genericParamInst->mInterfaceConstraints)
|
||||
{
|
||||
//if (std::find(searchConstraints.begin(), searchConstraints.end(), ifaceConstraint) == searchConstraints.end())
|
||||
if (!searchConstraints.Contains(ifaceConstraint))
|
||||
{
|
||||
searchConstraints.push_back(ifaceConstraint);
|
||||
|
@ -8371,7 +8354,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
for (auto& innerIFaceEntry : ifaceConstraint->mInterfaces)
|
||||
{
|
||||
auto innerIFace = innerIFaceEntry.mInterfaceType;
|
||||
//if (std::find(searchConstraints.begin(), searchConstraints.end(), innerIFace) == searchConstraints.end())
|
||||
if (!searchConstraints.Contains(innerIFace))
|
||||
{
|
||||
searchConstraints.push_back(innerIFace);
|
||||
|
@ -8384,7 +8366,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
BfPropertyDef* prevDef = NULL;
|
||||
for (auto ifaceConstraint : searchConstraints)
|
||||
{
|
||||
//auto lookupVal = mModule->GetDefaultTypedValue(ifaceConstraint, origResult.IsAddr());
|
||||
BfTypedValue lookupVal = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), ifaceConstraint);
|
||||
|
||||
mResult = LookupField(nameNode->mRight, lookupVal, fieldName);
|
||||
|
@ -8502,48 +8483,13 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
|||
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||
|
||||
auto origResult = mResult;
|
||||
auto lookupType = BindGenericType(nameNode, mResult.mType);
|
||||
if (mResult.mType->IsGenericParam())
|
||||
{
|
||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)mResult.mType);
|
||||
if (mModule->mCurMethodInstance->mIsUnspecialized)
|
||||
{
|
||||
if (genericParamInst->mTypeConstraint != NULL)
|
||||
mResult.mType = genericParamInst->mTypeConstraint;
|
||||
else
|
||||
mResult.mType = mModule->mContext->mBfObjectType;
|
||||
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
||||
{
|
||||
mResult.mType = mModule->GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
||||
{
|
||||
//mResult.mType = mModule->ResolveGenericType(mResult.mType);
|
||||
}
|
||||
else if (genericParamInst->mTypeConstraint != NULL)
|
||||
{
|
||||
mResult = mModule->Cast(nameNode, mResult, genericParamInst->mTypeConstraint);
|
||||
BF_ASSERT(mResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This shouldn't occur - this would infer that we are accessing a member of Object or something...
|
||||
//mResult.mType = mModule->ResolveGenericType(mResult.mType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mResult.mType->IsVar())
|
||||
{
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mResult.mType->IsTypeInstance())
|
||||
if ((!mResult.mType->IsTypeInstance()) && (!mResult.mType->IsGenericParam()))
|
||||
{
|
||||
if (mResult.mType->IsSizedArray())
|
||||
{
|
||||
|
@ -8565,7 +8511,21 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
|||
}
|
||||
|
||||
BfTypedValue lookupVal = mResult;
|
||||
mResult = LookupField(nameRight, lookupVal, fieldName);
|
||||
auto lookupType = BindGenericType(nameNode, mResult.mType);
|
||||
if ((lookupType->IsGenericParam()) && (!mResult.mType->IsGenericParam()))
|
||||
{
|
||||
// Try to lookup from generic binding
|
||||
mResult = LookupField(nameRight, BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), lookupType), fieldName);
|
||||
if (mPropDef != NULL)
|
||||
{
|
||||
mOrigPropTarget = lookupVal;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPropDef == NULL)
|
||||
mResult = LookupField(nameRight, lookupVal, fieldName);
|
||||
|
||||
if ((!mResult) && (mPropDef == NULL) && (lookupType->IsGenericParam()))
|
||||
{
|
||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)lookupType);
|
||||
|
@ -15474,9 +15434,12 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
|
|||
auto curTypeInst = mPropTarget.mType->ToTypeInstance();
|
||||
if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, curTypeInst))
|
||||
{
|
||||
// This is an explicit call to a default static interface method. We pull the methodDef into our own concrete type.
|
||||
mPropTarget = mModule->GetThis();
|
||||
return mModule->GetMethodInstance(mModule->mCurTypeInstance, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_ForeignMethodDef, curTypeInst);
|
||||
if (methodDef->mBody != NULL)
|
||||
{
|
||||
// This is an explicit call to a default static interface method. We pull the methodDef into our own concrete type.
|
||||
mPropTarget = mModule->GetThis();
|
||||
return mModule->GetMethodInstance(mModule->mCurTypeInstance, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_ForeignMethodDef, curTypeInst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -15688,9 +15651,15 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
|||
return mResult;
|
||||
}
|
||||
|
||||
if (matchedMethod->mName == "get__Hitbox")
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
auto methodInstance = GetPropertyMethodInstance(matchedMethod);
|
||||
if (methodInstance.mMethodInstance == NULL)
|
||||
return mResult;
|
||||
BF_ASSERT(methodInstance.mMethodInstance->mMethodDef->mName == matchedMethod->mName);
|
||||
if (!mModule->mBfIRBuilder->mIgnoreWrites)
|
||||
{
|
||||
BF_ASSERT(!methodInstance.mFunc.IsFake());
|
||||
|
@ -15722,8 +15691,14 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
|||
SizedArray<BfIRValue, 4> args;
|
||||
if (!matchedMethod->mIsStatic)
|
||||
{
|
||||
if ((mPropDefBypassVirtual) && (mPropTarget.mType != methodInstance.mMethodInstance->GetOwner()))
|
||||
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, methodInstance.mMethodInstance->GetOwner());
|
||||
auto owner = methodInstance.mMethodInstance->GetOwner();
|
||||
if (mPropTarget.mType != owner)
|
||||
{
|
||||
/*if (owner->IsInterface())
|
||||
mPropTarget = mModule->Cast(mPropSrc, mPropTarget, owner);
|
||||
else */ if (mPropDefBypassVirtual)
|
||||
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner);
|
||||
}
|
||||
|
||||
if ((mPropGetMethodFlags & BfGetMethodInstanceFlag_DisableObjectAccessChecks) == 0)
|
||||
mModule->EmitObjectAccessCheck(mPropTarget);
|
||||
|
@ -16616,7 +16591,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
|||
auto methodInstance = GetPropertyMethodInstance(setMethod);
|
||||
if (methodInstance.mMethodInstance == NULL)
|
||||
return;
|
||||
BF_ASSERT(methodInstance.mMethodInstance->mMethodDef == setMethod);
|
||||
//BF_ASSERT(methodInstance.mMethodInstance->mMethodDef == setMethod);
|
||||
CheckPropFail(setMethod, methodInstance.mMethodInstance, (mPropGetMethodFlags & BfGetMethodInstanceFlag_Friend) == 0);
|
||||
|
||||
auto autoComplete = GetAutoComplete();
|
||||
|
@ -16670,6 +16645,13 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
|||
SizedArray<BfIRValue, 4> args;
|
||||
if (!setMethod->mIsStatic)
|
||||
{
|
||||
auto owner = methodInstance.mMethodInstance->GetOwner();
|
||||
if (mPropTarget.mType != owner)
|
||||
{
|
||||
if (mPropDefBypassVirtual)
|
||||
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner);
|
||||
}
|
||||
|
||||
mModule->EmitObjectAccessCheck(mPropTarget);
|
||||
PushThis(mPropSrc, mPropTarget, methodInstance.mMethodInstance, args);
|
||||
}
|
||||
|
|
|
@ -9728,6 +9728,15 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
|
|||
|
||||
auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
|
||||
|
||||
BfMethodDef* methodDef = NULL;
|
||||
BfTypeInstance* foreignType = NULL;
|
||||
if (methodInstance != NULL)
|
||||
{
|
||||
methodDef = methodInstance->mMethodDef;
|
||||
if (methodInstance->mMethodInfoEx != NULL)
|
||||
foreignType = methodInstance->mMethodInfoEx->mForeignType;
|
||||
}
|
||||
|
||||
if ((methodInstance != NULL) && (mIsReified) && (!methodInstance->mIsReified))
|
||||
{
|
||||
// Can't use it, not reified
|
||||
|
@ -9741,6 +9750,8 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
|
|||
return BfModuleMethodInstance(methodInstance, func);
|
||||
}
|
||||
|
||||
if (foreignType != NULL)
|
||||
return GetMethodInstance(typeInstance, methodDef, BfTypeVector(), (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ForeignMethodDef), foreignType);
|
||||
return GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,58 @@ namespace Tests
|
|||
}
|
||||
}
|
||||
|
||||
public struct Rect
|
||||
{
|
||||
public float x, y, width, height;
|
||||
}
|
||||
|
||||
public class Component
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Hitbox : Component
|
||||
{
|
||||
public Rect mArea = .() { x=1, y=2, width=3, height=4, };
|
||||
}
|
||||
|
||||
public interface IEntity
|
||||
{
|
||||
public T GetComponent<T>() where T : Component;
|
||||
}
|
||||
|
||||
public interface IHitbox : IEntity
|
||||
{
|
||||
public Hitbox HitboxValue { get; set; }
|
||||
|
||||
public Hitbox Hitbox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (HitboxValue == null)
|
||||
{
|
||||
HitboxValue = GetComponent<Hitbox>();
|
||||
}
|
||||
|
||||
return HitboxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GameItem : IEntity, IHitbox
|
||||
{
|
||||
public T GetComponent<T>() where T : Component
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
public Hitbox HitboxValue { get; set; }
|
||||
}
|
||||
|
||||
static Hitbox GetHitbox<T>(T val) where T : IHitbox
|
||||
{
|
||||
return val.Hitbox;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -130,6 +182,11 @@ namespace Tests
|
|||
|
||||
IFaceA ifa = cba;
|
||||
Test.Assert(ifa.GetType() == typeof(ClassB));
|
||||
|
||||
GameItem gameItem = scope .();
|
||||
var hitbox = GetHitbox(gameItem);
|
||||
Test.Assert(hitbox.mArea == .() { x=1, y=2, width=3, height=4 });
|
||||
delete hitbox;
|
||||
}
|
||||
|
||||
////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue