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))
|
if ((mModule->mCurMethodState == NULL) || (mModule->mCurMethodInstance == NULL) || (bindType == NULL))
|
||||||
return bindType;
|
return bindType;
|
||||||
|
|
||||||
|
if ((mModule->mCurMethodState->mClosureState != NULL) && (mModule->mCurMethodState->mClosureState->mCapturing))
|
||||||
|
return bindType;
|
||||||
|
|
||||||
BF_ASSERT(!mModule->mCurMethodInstance->mIsUnspecializedVariation);
|
BF_ASSERT(!mModule->mCurMethodInstance->mIsUnspecializedVariation);
|
||||||
|
|
||||||
auto parser = node->GetSourceData()->ToParserData();
|
auto parser = node->GetSourceData()->ToParserData();
|
||||||
|
@ -2616,10 +2619,6 @@ BfType* BfExprEvaluator::BindGenericType(BfAstNode* node, BfType* bindType)
|
||||||
if (genericTypeBindings == NULL)
|
if (genericTypeBindings == NULL)
|
||||||
return bindType;
|
return bindType;
|
||||||
|
|
||||||
/*auto itr = mModule->mCurMethodState->mGenericTypeBindings->find(nodeId);
|
|
||||||
if (itr != mModule->mCurMethodState->mGenericTypeBindings->end())
|
|
||||||
return itr->second;*/
|
|
||||||
|
|
||||||
BfType** typePtr = NULL;
|
BfType** typePtr = NULL;
|
||||||
if (genericTypeBindings->TryGetValue(nodeId, &typePtr))
|
if (genericTypeBindings->TryGetValue(nodeId, &typePtr))
|
||||||
return *typePtr;
|
return *typePtr;
|
||||||
|
@ -3640,7 +3639,11 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
||||||
{
|
{
|
||||||
if (forcedIFaceLookup)
|
if (forcedIFaceLookup)
|
||||||
{
|
{
|
||||||
|
if (mPropTarget == thisValue)
|
||||||
|
{
|
||||||
|
mPropDefBypassVirtual = true;
|
||||||
|
mOrigPropTarget = mModule->GetThis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((!result) && (mPropDef == NULL))
|
if ((!result) && (mPropDef == NULL))
|
||||||
|
@ -3788,6 +3791,20 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
||||||
if ((target.mType != NULL && (target.mType->IsGenericParam())))
|
if ((target.mType != NULL && (target.mType->IsGenericParam())))
|
||||||
{
|
{
|
||||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)target.mType);
|
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 (mModule->mCurMethodInstance->mIsUnspecialized)
|
||||||
{
|
{
|
||||||
if (genericParamInst->mTypeConstraint != NULL)
|
if (genericParamInst->mTypeConstraint != NULL)
|
||||||
|
@ -6414,7 +6431,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
|
|
||||||
if (!methodDef->mIsStatic)
|
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)
|
if (methodInstance->mVirtualTableIdx == -1)
|
||||||
{
|
{
|
||||||
|
@ -8301,44 +8321,8 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
||||||
if (!mResult)
|
if (!mResult)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//if (mResult.mType->IsVar())
|
|
||||||
//ResolveGenericType();
|
|
||||||
|
|
||||||
auto origResult = mResult;
|
auto origResult = mResult;
|
||||||
auto lookupType = BindGenericType(nameNode, mResult.mType);
|
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())
|
if (mResult.mType->IsVar())
|
||||||
{
|
{
|
||||||
|
@ -8346,7 +8330,7 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mResult.mType->IsTypeInstance())
|
if ((!mResult.mType->IsTypeInstance()) && (!mResult.mType->IsGenericParam()))
|
||||||
{
|
{
|
||||||
if (hadError != NULL)
|
if (hadError != NULL)
|
||||||
*hadError = true;
|
*hadError = true;
|
||||||
|
@ -8363,7 +8347,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
||||||
SizedArray<BfTypeInstance*, 8> searchConstraints;
|
SizedArray<BfTypeInstance*, 8> searchConstraints;
|
||||||
for (auto ifaceConstraint : genericParamInst->mInterfaceConstraints)
|
for (auto ifaceConstraint : genericParamInst->mInterfaceConstraints)
|
||||||
{
|
{
|
||||||
//if (std::find(searchConstraints.begin(), searchConstraints.end(), ifaceConstraint) == searchConstraints.end())
|
|
||||||
if (!searchConstraints.Contains(ifaceConstraint))
|
if (!searchConstraints.Contains(ifaceConstraint))
|
||||||
{
|
{
|
||||||
searchConstraints.push_back(ifaceConstraint);
|
searchConstraints.push_back(ifaceConstraint);
|
||||||
|
@ -8371,7 +8354,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
||||||
for (auto& innerIFaceEntry : ifaceConstraint->mInterfaces)
|
for (auto& innerIFaceEntry : ifaceConstraint->mInterfaces)
|
||||||
{
|
{
|
||||||
auto innerIFace = innerIFaceEntry.mInterfaceType;
|
auto innerIFace = innerIFaceEntry.mInterfaceType;
|
||||||
//if (std::find(searchConstraints.begin(), searchConstraints.end(), innerIFace) == searchConstraints.end())
|
|
||||||
if (!searchConstraints.Contains(innerIFace))
|
if (!searchConstraints.Contains(innerIFace))
|
||||||
{
|
{
|
||||||
searchConstraints.push_back(innerIFace);
|
searchConstraints.push_back(innerIFace);
|
||||||
|
@ -8384,7 +8366,6 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
||||||
BfPropertyDef* prevDef = NULL;
|
BfPropertyDef* prevDef = NULL;
|
||||||
for (auto ifaceConstraint : searchConstraints)
|
for (auto ifaceConstraint : searchConstraints)
|
||||||
{
|
{
|
||||||
//auto lookupVal = mModule->GetDefaultTypedValue(ifaceConstraint, origResult.IsAddr());
|
|
||||||
BfTypedValue lookupVal = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), ifaceConstraint);
|
BfTypedValue lookupVal = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), ifaceConstraint);
|
||||||
|
|
||||||
mResult = LookupField(nameNode->mRight, lookupVal, fieldName);
|
mResult = LookupField(nameNode->mRight, lookupVal, fieldName);
|
||||||
|
@ -8502,48 +8483,13 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
||||||
mResult.mType = mResult.mType->GetUnderlyingType();
|
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||||
|
|
||||||
auto origResult = mResult;
|
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())
|
if (mResult.mType->IsVar())
|
||||||
{
|
{
|
||||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true);
|
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mResult.mType->IsTypeInstance())
|
if ((!mResult.mType->IsTypeInstance()) && (!mResult.mType->IsGenericParam()))
|
||||||
{
|
{
|
||||||
if (mResult.mType->IsSizedArray())
|
if (mResult.mType->IsSizedArray())
|
||||||
{
|
{
|
||||||
|
@ -8565,7 +8511,21 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypedValue lookupVal = mResult;
|
BfTypedValue lookupVal = mResult;
|
||||||
|
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);
|
mResult = LookupField(nameRight, lookupVal, fieldName);
|
||||||
|
|
||||||
if ((!mResult) && (mPropDef == NULL) && (lookupType->IsGenericParam()))
|
if ((!mResult) && (mPropDef == NULL) && (lookupType->IsGenericParam()))
|
||||||
{
|
{
|
||||||
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)lookupType);
|
auto genericParamInst = mModule->GetGenericParamInstance((BfGenericParamType*)lookupType);
|
||||||
|
@ -15473,11 +15433,14 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
|
||||||
{
|
{
|
||||||
auto curTypeInst = mPropTarget.mType->ToTypeInstance();
|
auto curTypeInst = mPropTarget.mType->ToTypeInstance();
|
||||||
if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, curTypeInst))
|
if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, 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.
|
// This is an explicit call to a default static interface method. We pull the methodDef into our own concrete type.
|
||||||
mPropTarget = mModule->GetThis();
|
mPropTarget = mModule->GetThis();
|
||||||
return mModule->GetMethodInstance(mModule->mCurTypeInstance, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_ForeignMethodDef, curTypeInst);
|
return mModule->GetMethodInstance(mModule->mCurTypeInstance, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_ForeignMethodDef, curTypeInst);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mModule->Fail("Property is not implemented by this type", mPropSrc);
|
mModule->Fail("Property is not implemented by this type", mPropSrc);
|
||||||
|
@ -15688,9 +15651,15 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
||||||
return mResult;
|
return mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (matchedMethod->mName == "get__Hitbox")
|
||||||
|
{
|
||||||
|
NOP;
|
||||||
|
}
|
||||||
|
|
||||||
auto methodInstance = GetPropertyMethodInstance(matchedMethod);
|
auto methodInstance = GetPropertyMethodInstance(matchedMethod);
|
||||||
if (methodInstance.mMethodInstance == NULL)
|
if (methodInstance.mMethodInstance == NULL)
|
||||||
return mResult;
|
return mResult;
|
||||||
|
BF_ASSERT(methodInstance.mMethodInstance->mMethodDef->mName == matchedMethod->mName);
|
||||||
if (!mModule->mBfIRBuilder->mIgnoreWrites)
|
if (!mModule->mBfIRBuilder->mIgnoreWrites)
|
||||||
{
|
{
|
||||||
BF_ASSERT(!methodInstance.mFunc.IsFake());
|
BF_ASSERT(!methodInstance.mFunc.IsFake());
|
||||||
|
@ -15722,8 +15691,14 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
||||||
SizedArray<BfIRValue, 4> args;
|
SizedArray<BfIRValue, 4> args;
|
||||||
if (!matchedMethod->mIsStatic)
|
if (!matchedMethod->mIsStatic)
|
||||||
{
|
{
|
||||||
if ((mPropDefBypassVirtual) && (mPropTarget.mType != methodInstance.mMethodInstance->GetOwner()))
|
auto owner = methodInstance.mMethodInstance->GetOwner();
|
||||||
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, 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)
|
if ((mPropGetMethodFlags & BfGetMethodInstanceFlag_DisableObjectAccessChecks) == 0)
|
||||||
mModule->EmitObjectAccessCheck(mPropTarget);
|
mModule->EmitObjectAccessCheck(mPropTarget);
|
||||||
|
@ -16616,7 +16591,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
||||||
auto methodInstance = GetPropertyMethodInstance(setMethod);
|
auto methodInstance = GetPropertyMethodInstance(setMethod);
|
||||||
if (methodInstance.mMethodInstance == NULL)
|
if (methodInstance.mMethodInstance == NULL)
|
||||||
return;
|
return;
|
||||||
BF_ASSERT(methodInstance.mMethodInstance->mMethodDef == setMethod);
|
//BF_ASSERT(methodInstance.mMethodInstance->mMethodDef == setMethod);
|
||||||
CheckPropFail(setMethod, methodInstance.mMethodInstance, (mPropGetMethodFlags & BfGetMethodInstanceFlag_Friend) == 0);
|
CheckPropFail(setMethod, methodInstance.mMethodInstance, (mPropGetMethodFlags & BfGetMethodInstanceFlag_Friend) == 0);
|
||||||
|
|
||||||
auto autoComplete = GetAutoComplete();
|
auto autoComplete = GetAutoComplete();
|
||||||
|
@ -16670,6 +16645,13 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
||||||
SizedArray<BfIRValue, 4> args;
|
SizedArray<BfIRValue, 4> args;
|
||||||
if (!setMethod->mIsStatic)
|
if (!setMethod->mIsStatic)
|
||||||
{
|
{
|
||||||
|
auto owner = methodInstance.mMethodInstance->GetOwner();
|
||||||
|
if (mPropTarget.mType != owner)
|
||||||
|
{
|
||||||
|
if (mPropDefBypassVirtual)
|
||||||
|
mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner);
|
||||||
|
}
|
||||||
|
|
||||||
mModule->EmitObjectAccessCheck(mPropTarget);
|
mModule->EmitObjectAccessCheck(mPropTarget);
|
||||||
PushThis(mPropSrc, mPropTarget, methodInstance.mMethodInstance, args);
|
PushThis(mPropSrc, mPropTarget, methodInstance.mMethodInstance, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9728,6 +9728,15 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
|
||||||
|
|
||||||
auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
|
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))
|
if ((methodInstance != NULL) && (mIsReified) && (!methodInstance->mIsReified))
|
||||||
{
|
{
|
||||||
// Can't use it, not reified
|
// Can't use it, not reified
|
||||||
|
@ -9741,6 +9750,8 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
|
||||||
return BfModuleMethodInstance(methodInstance, func);
|
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);
|
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]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -130,6 +182,11 @@ namespace Tests
|
||||||
|
|
||||||
IFaceA ifa = cba;
|
IFaceA ifa = cba;
|
||||||
Test.Assert(ifa.GetType() == typeof(ClassB));
|
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