mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Reworked functions with explicit 'this'
This commit is contained in:
parent
9fde8a3c89
commit
3627f8c40f
15 changed files with 556 additions and 199 deletions
|
@ -138,6 +138,7 @@ BfAutoComplete::BfAutoComplete(BfResolveType resolveType)
|
|||
mIgnoreFixits = false;
|
||||
mHasFriendSet = false;
|
||||
mUncertain = false;
|
||||
mForceAllowNonStatic = false;
|
||||
mMethodMatchInfo = NULL;
|
||||
mIsGetDefinition =
|
||||
(resolveType == BfResolveType_GetSymbolInfo) ||
|
||||
|
@ -588,6 +589,9 @@ void BfAutoComplete::AddTypeMembers(BfTypeInstance* typeInst, bool addStatic, bo
|
|||
{
|
||||
bool isInterface = false;
|
||||
|
||||
if (mForceAllowNonStatic)
|
||||
addNonStatic = true;
|
||||
|
||||
auto activeTypeDef = mModule->GetActiveTypeDef();
|
||||
|
||||
if ((addStatic) && (mModule->mCurMethodInstance == NULL) && (typeInst->IsEnum()))
|
||||
|
|
|
@ -179,6 +179,7 @@ public:
|
|||
bool mIgnoreFixits;
|
||||
bool mHasFriendSet;
|
||||
bool mUncertain; // May be an unknown identifier, do not aggressively autocomplete
|
||||
bool mForceAllowNonStatic;
|
||||
int mCursorLineStart;
|
||||
int mCursorLineEnd;
|
||||
|
||||
|
|
|
@ -2135,7 +2135,7 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
|
|||
{
|
||||
auto depType = type->ToDependedType();
|
||||
auto typeInst = type->ToTypeInstance();
|
||||
|
||||
|
||||
if (depType != NULL)
|
||||
{
|
||||
extern BfModule* gLastCreatedModule;
|
||||
|
@ -4272,11 +4272,16 @@ void BfCompiler::ProcessAutocompleteTempType()
|
|||
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||
}
|
||||
|
||||
bool wantsProcess = !actualTypeDef->mIsFunction;
|
||||
|
||||
SetAndRestoreValue<BfFilePosition> prevFilePos(module->mCurFilePosition);
|
||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInst(module->mCurMethodInstance, methodInstance);
|
||||
module->DoMethodDeclaration(methodDeclaration, true);
|
||||
module->mIncompleteMethodCount++;
|
||||
module->ProcessMethod(methodInstance);
|
||||
module->DoMethodDeclaration(methodDeclaration, true, wantsProcess);
|
||||
if (wantsProcess)
|
||||
{
|
||||
module->mIncompleteMethodCount++;
|
||||
module->ProcessMethod(methodInstance);
|
||||
}
|
||||
|
||||
if (methodInstance->mIRFunction)
|
||||
{
|
||||
|
@ -4830,7 +4835,7 @@ void BfCompiler::GetSymbolReferences()
|
|||
CheckSymbolReferenceTypeRef(module, externConstraintDef.mTypeRef);
|
||||
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, rebuildMethodInstance->mIsUnspecialized);
|
||||
}
|
||||
|
||||
|
||||
rebuildModule->ProcessMethod(rebuildMethodInstance);
|
||||
}
|
||||
}
|
||||
|
@ -7420,7 +7425,7 @@ void BfCompiler::GenerateAutocompleteInfo()
|
|||
int dispParamIdx = 0;
|
||||
|
||||
StringT<64> paramName;
|
||||
for (int paramIdx = methodInstance->HasExplicitThis() ? -1 : 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
|
||||
for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
|
||||
{
|
||||
auto paramKind = methodInstance->GetParamKind(paramIdx);
|
||||
if ((paramKind == BfParamKind_ImplicitCapture) || (paramKind == BfParamKind_AppendIdx))
|
||||
|
|
|
@ -849,7 +849,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We need to verify lookups before we rebuild the type, because a type lookup change needs to count as a TypeDataChanged
|
||||
VerifyTypeLookups(typeInst);
|
||||
|
||||
|
|
|
@ -541,7 +541,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
|||
methodDef->mMethodType = BfMethodType_Normal;
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
methodDef->mIsStatic = mCurTypeDef->mIsFunction;
|
||||
|
||||
|
||||
auto attributes = mCurTypeDef->mTypeDeclaration->mAttributes;
|
||||
while (attributes != NULL)
|
||||
{
|
||||
|
@ -621,6 +621,12 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
|||
else //
|
||||
paramDef->mParamKind = BfParamKind_Params;
|
||||
|
||||
if ((mCurTypeDef->mIsFunction) && (paramIdx == 0) && (paramDef->mName == "this"))
|
||||
{
|
||||
paramDef->mParamKind = BfParamKind_ExplicitThis;
|
||||
methodDef->mIsStatic = false;
|
||||
}
|
||||
|
||||
if (auto dotTypeRef = BfNodeDynCast<BfDotTypeReference>(paramDef->mTypeRef))
|
||||
{
|
||||
if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot)
|
||||
|
@ -658,6 +664,22 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
|||
methodDef->mParams.push_back(paramDef);
|
||||
}
|
||||
|
||||
if ((mCurTypeDef->mIsFunction) && (!methodDef->mParams.IsEmpty()) && (methodDef->mParams[0]->mName == "this"))
|
||||
{
|
||||
methodDef->mIsStatic = false;
|
||||
methodDef->mHasExplicitThis = true;
|
||||
methodDef->mParams[0]->mParamKind = BfParamKind_ExplicitThis;
|
||||
|
||||
if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(methodDef->mParams[0]->mTypeRef))
|
||||
{
|
||||
if (refTypeRef->mRefToken->mToken != BfToken_Mut)
|
||||
{
|
||||
Fail("Only 'mut' is allowed here", refTypeRef->mRefToken);
|
||||
}
|
||||
methodDef->mIsMutating = true;
|
||||
}
|
||||
}
|
||||
|
||||
ParseAttributes(methodDeclaration->mAttributes, methodDef);
|
||||
return methodDef;
|
||||
}
|
||||
|
@ -1911,6 +1933,16 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
}
|
||||
}
|
||||
|
||||
bool needsDynamicCastMethod = !hasDynamicCastMethod;
|
||||
|
||||
if (mCurTypeDef->mIsFunction)
|
||||
{
|
||||
wantsToString = false;
|
||||
needsEqualsMethod = false;
|
||||
needsDefaultCtor = false;
|
||||
needsDynamicCastMethod = false;
|
||||
}
|
||||
|
||||
if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "");
|
||||
|
@ -1934,12 +1966,6 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
}
|
||||
|
||||
bool makeCtorPrivate = hasCtor;
|
||||
// if ((!mCurTypeDef->IsExtension()) && (mCurTypeDef->mMethods.empty()))
|
||||
// {
|
||||
// // This is a bit of a hack to ensure we actually generate debug info in the module
|
||||
// needsDefaultCtor = true;
|
||||
// makeCtorPrivate = true;
|
||||
// }
|
||||
|
||||
if (mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias)
|
||||
needsDefaultCtor = false;
|
||||
|
@ -1962,7 +1988,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
isAutocomplete = true;
|
||||
|
||||
//TODO: Don't do this for the autocomplete pass
|
||||
if ((!hasDynamicCastMethod) && (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (mCurTypeDef->mTypeCode != BfTypeCode_Extension) &&
|
||||
if ((needsDynamicCastMethod) && (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (mCurTypeDef->mTypeCode != BfTypeCode_Extension) &&
|
||||
(!mCurTypeDef->mIsStatic) && (!isAutocomplete) && (!isAlias))
|
||||
{
|
||||
AddDynamicCastMethods(mCurTypeDef);
|
||||
|
@ -2011,12 +2037,6 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
|
||||
if (hasToStringMethod)
|
||||
wantsToString = false;
|
||||
|
||||
if (mCurTypeDef->mIsFunction)
|
||||
{
|
||||
wantsToString = false;
|
||||
needsEqualsMethod = false;
|
||||
}
|
||||
|
||||
if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (!isPayloadEnum))
|
||||
{
|
||||
|
|
|
@ -542,6 +542,27 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
|
|||
InferGenericArgument(methodInstance, argInvokeMethod->GetParamType(argIdx), wantInvokeMethod->GetParamType(argIdx), BfIRValue());
|
||||
}
|
||||
}
|
||||
else if (argType->IsMethodRef())
|
||||
{
|
||||
auto methodTypeRef = (BfMethodRefType*)argType;
|
||||
if (!_AddToCheckedSet(argType, mCheckedTypeSet, alreadyChecked))
|
||||
return true;
|
||||
|
||||
auto argInvokeMethod = methodTypeRef->mMethodRef;
|
||||
auto delegateInfo = wantType->GetDelegateInfo();
|
||||
auto wantInvokeMethod = mModule->GetRawMethodByName(wantType->ToTypeInstance(), "Invoke");
|
||||
|
||||
if ((delegateInfo->mHasExplicitThis) && (argInvokeMethod->HasThis()))
|
||||
InferGenericArgument(methodInstance, argInvokeMethod->GetParamType(-1), delegateInfo->mParams[0], BfIRValue());
|
||||
|
||||
int wantInvokeOffset = delegateInfo->mHasExplicitThis ? 1 : 0;
|
||||
if ((argInvokeMethod != NULL) && (wantInvokeMethod != NULL) && (argInvokeMethod->GetParamCount() == wantInvokeMethod->GetParamCount() - wantInvokeOffset))
|
||||
{
|
||||
InferGenericArgument(methodInstance, argInvokeMethod->mReturnType, wantInvokeMethod->mReturnType, BfIRValue());
|
||||
for (int argIdx = 0; argIdx < (int)argInvokeMethod->GetParamCount(); argIdx++)
|
||||
InferGenericArgument(methodInstance, argInvokeMethod->GetParamType(argIdx), wantInvokeMethod->GetParamType(argIdx + wantInvokeOffset), BfIRValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1021,7 +1042,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
|||
RETURN_RESULTS;
|
||||
}
|
||||
|
||||
BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute)
|
||||
BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType)
|
||||
{
|
||||
BfTypedValue argTypedValue = resolvedArg.mTypedValue;
|
||||
if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0)
|
||||
|
@ -1032,13 +1053,13 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
|
|||
BF_ASSERT(resolvedArg.mExpression->IsA<BfDelegateBindExpression>());
|
||||
auto delegateBindExpr = BfNodeDynCast<BfDelegateBindExpression>(resolvedArg.mExpression);
|
||||
BfMethodInstance* boundMethodInstance = NULL;
|
||||
if (exprEvaluator.CanBindDelegate(delegateBindExpr, &boundMethodInstance))
|
||||
if (exprEvaluator.CanBindDelegate(delegateBindExpr, &boundMethodInstance, origCheckType, genericArgumentsSubstitute))
|
||||
{
|
||||
if (delegateBindExpr->mNewToken == NULL)
|
||||
{
|
||||
resolvedArg.mExpectedType = checkType;
|
||||
auto methodRefType = mModule->CreateMethodRefType(boundMethodInstance);
|
||||
mModule->AddDependency(methodRefType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_Calls);
|
||||
mModule->AddDependency(methodRefType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_Calls);
|
||||
mModule->AddCallDependency(boundMethodInstance);
|
||||
argTypedValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodRefType);
|
||||
}
|
||||
|
@ -1509,7 +1530,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
|||
if (argIdx == -1)
|
||||
argTypedValue = mTarget;
|
||||
else
|
||||
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType, genericArgumentsSubstitute);
|
||||
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType, genericArgumentsSubstitute, origCheckType);
|
||||
if (!argTypedValue.IsUntypedValue())
|
||||
{
|
||||
auto type = argTypedValue.mType;
|
||||
|
@ -2615,6 +2636,16 @@ void BfExprEvaluator::Visit(BfAttributedExpression* attribExpr)
|
|||
}
|
||||
VisitChild(attribExpr->mExpression);
|
||||
attributeState.mUsed = true;
|
||||
|
||||
if ((!mResult) ||
|
||||
((mResult) && (mResult.mType->IsVar())))
|
||||
{
|
||||
if (!mResult)
|
||||
mModule->Fail("Expression did not result in a value", attribExpr->mExpression);
|
||||
|
||||
// Make empty or 'var' resolve as 'false' because var is only valid if we threw errors
|
||||
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4894,7 +4925,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
|
|||
bool hadAttrs = false;
|
||||
int paramIdx = 0;
|
||||
bool doingThis = !methodDef->mIsStatic;
|
||||
int argIdx = 0;
|
||||
int argIdx = 0;
|
||||
|
||||
if (methodDef->mHasExplicitThis)
|
||||
paramIdx++;
|
||||
|
||||
int paramCount = methodInstance->GetParamCount();
|
||||
|
||||
|
@ -4986,13 +5020,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
|
|||
BfType* paramType = NULL;
|
||||
if (doingThis)
|
||||
{
|
||||
paramType = methodInstance->GetOwner();
|
||||
int thisIdx = methodInstance->GetThisIdx();
|
||||
paramType = methodInstance->GetThisType();
|
||||
if (paramType->IsValuelessType())
|
||||
{
|
||||
doingThis = false;
|
||||
continue;
|
||||
}
|
||||
bool isSplatted = methodInstance->GetParamIsSplat(-1); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
|
||||
bool isSplatted = methodInstance->GetParamIsSplat(thisIdx); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
|
||||
if (isSplatted)
|
||||
{
|
||||
BfTypeUtils::SplatIterate(_HandleParamType, paramType);
|
||||
|
@ -5357,7 +5392,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
|
|||
return;
|
||||
}
|
||||
|
||||
auto thisType = methodInstance->GetParamType(-1);
|
||||
auto thisType = methodInstance->GetThisType();
|
||||
PushArg(argVal, irArgs, !methodInstance->AllowsThisSplatting(), thisType->IsPointer());
|
||||
}
|
||||
|
||||
|
@ -5453,11 +5488,22 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
auto bindResult = prevBindResult.mPrevVal;
|
||||
if (bindResult->mBindType != NULL)
|
||||
{
|
||||
// Allow binding a function to a 'this' type even if no target is specified
|
||||
auto delegateInfo = bindResult->mBindType->GetDelegateInfo();
|
||||
if ((delegateInfo != NULL) && (delegateInfo->mFunctionThisType != NULL))
|
||||
if (delegateInfo != NULL)
|
||||
{
|
||||
// Allow binding a function to a 'this' type even if no target is specified
|
||||
target = mModule->GetDefaultTypedValue(delegateInfo->mFunctionThisType, false, BfDefaultValueKind_Addr);
|
||||
if (delegateInfo->mHasExplicitThis)
|
||||
{
|
||||
target = mModule->GetDefaultTypedValue(delegateInfo->mParams[0], false, BfDefaultValueKind_Addr);
|
||||
}
|
||||
}
|
||||
else if (bindResult->mBindType->IsFunction())
|
||||
{
|
||||
BfMethodInstance* invokeMethodInstance = mModule->GetRawMethodInstanceAtIdx(bindResult->mBindType->ToTypeInstance(), 0, "Invoke");
|
||||
if (!invokeMethodInstance->mMethodDef->mIsStatic)
|
||||
{
|
||||
target = mModule->GetDefaultTypedValue(invokeMethodInstance->GetThisType(), false, BfDefaultValueKind_Addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5555,12 +5601,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
if ((boxScopeData == NULL) && (mModule->mCurMethodState != NULL))
|
||||
boxScopeData = mModule->mCurMethodState->mCurScope;
|
||||
|
||||
if (methodInstance->HasExplicitThis())
|
||||
paramIdx = -1;
|
||||
|
||||
bool failed = false;
|
||||
while (true)
|
||||
{
|
||||
bool isThis = (paramIdx == -1) || ((methodDef->mHasExplicitThis) && (paramIdx == 0));
|
||||
bool isDirectPass = false;
|
||||
|
||||
if (paramIdx >= (int)methodInstance->GetParamCount())
|
||||
|
@ -6021,7 +6065,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
|
||||
if (argValue)
|
||||
{
|
||||
if ((paramIdx == -1) && (argValue.mType->IsRef()))
|
||||
if ((isThis) && (argValue.mType->IsRef()))
|
||||
{
|
||||
// Convert a 'ref this' to a 'this*'
|
||||
argValue.mType = mModule->CreatePointerType(argValue.mType->GetUnderlyingType());
|
||||
|
@ -6107,7 +6151,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
|
||||
if (argValue)
|
||||
{
|
||||
if (paramIdx == -1)
|
||||
if (isThis)
|
||||
PushThis(targetSrc, argValue, methodInstance, irArgs);
|
||||
else if (wantsSplat)
|
||||
SplatArgs(argValue, irArgs);
|
||||
|
@ -9485,7 +9529,11 @@ bool BfExprEvaluator::IsExactMethodMatch(BfMethodInstance* methodA, BfMethodInst
|
|||
return false;
|
||||
|
||||
int implicitParamCountA = methodA->GetImplicitParamCount();
|
||||
if (methodA->HasExplicitThis())
|
||||
implicitParamCountA++;
|
||||
int implicitParamCountB = methodB->GetImplicitParamCount();
|
||||
if (methodB->HasExplicitThis())
|
||||
implicitParamCountB++;
|
||||
|
||||
if (methodA->GetParamCount() - implicitParamCountA != methodB->GetParamCount() - implicitParamCountB)
|
||||
return false;
|
||||
|
@ -9517,15 +9565,21 @@ BfTypeInstance* BfExprEvaluator::VerifyBaseDelegateType(BfTypeInstance* baseDele
|
|||
return baseDelegateType;
|
||||
}
|
||||
|
||||
bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr, BfMethodInstance** boundMethod)
|
||||
bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr, BfMethodInstance** boundMethod, BfType* origMethodExpectingType, BfTypeVector* methodGenericArgumentsSubstitute)
|
||||
{
|
||||
if (mExpectingType == NULL)
|
||||
if ((mExpectingType == NULL) && (origMethodExpectingType == NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto typeInstance = mExpectingType->ToTypeInstance();
|
||||
if ((typeInstance == NULL) || (!typeInstance->mTypeDef->mIsDelegate))
|
||||
bool isGenericMatch = mExpectingType == NULL;
|
||||
auto expectingType = mExpectingType;
|
||||
if (expectingType == NULL)
|
||||
expectingType = origMethodExpectingType;
|
||||
|
||||
auto typeInstance = expectingType->ToTypeInstance();
|
||||
if ((typeInstance == NULL) ||
|
||||
((!typeInstance->mTypeDef->mIsDelegate) && (!typeInstance->mTypeDef->mIsFunction)))
|
||||
return false;
|
||||
|
||||
mModule->PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
||||
|
@ -9547,11 +9601,28 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr
|
|||
SizedArray<BfExpression*, 4> args;
|
||||
args.resize(methodInstance->GetParamCount());
|
||||
|
||||
auto _FixType = [&](BfType* type)
|
||||
{
|
||||
if (!isGenericMatch)
|
||||
return type;
|
||||
auto fixedType = mModule->ResolveGenericType(type, NULL, methodGenericArgumentsSubstitute);
|
||||
if (fixedType != NULL)
|
||||
return fixedType;
|
||||
return (BfType*)mModule->GetPrimitiveType(BfTypeCode_Var);
|
||||
};
|
||||
|
||||
auto _TypeMatches = [&](BfType* lhs, BfType* rhs)
|
||||
{
|
||||
if (lhs == rhs)
|
||||
return true;
|
||||
return lhs->IsVar();
|
||||
};
|
||||
|
||||
for (int i = 0; i < (int) methodInstance->GetParamCount(); i++)
|
||||
{
|
||||
auto typedValueExpr = &typedValueExprs[i];
|
||||
typedValueExpr->mTypedValue.mValue = BfIRValue(BfIRValueFlags_Value, -1);
|
||||
typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
|
||||
typedValueExpr->mTypedValue.mValue = BfIRValue(BfIRValueFlags_Value, -1);
|
||||
typedValueExpr->mTypedValue.mType = _FixType(methodInstance->GetParamType(i));
|
||||
typedValueExpr->mRefNode = NULL;
|
||||
args[i] = typedValueExpr;
|
||||
}
|
||||
|
@ -9562,6 +9633,7 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr
|
|||
|
||||
BfFunctionBindResult bindResult;
|
||||
bindResult.mSkipMutCheck = true; // Allow operating on copies
|
||||
bindResult.mBindType = expectingType;
|
||||
mFunctionBindResult = &bindResult;
|
||||
SetAndRestoreValue<bool> ignoreError(mModule->mIgnoreErrors, true);
|
||||
DoInvocation(delegateBindExpr->mTarget, delegateBindExpr, args, methodGenericArguments);
|
||||
|
@ -9570,7 +9642,25 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr
|
|||
return false;
|
||||
if (boundMethod != NULL)
|
||||
*boundMethod = bindResult.mMethodInstance;
|
||||
return IsExactMethodMatch(methodInstance, bindResult.mMethodInstance, true);
|
||||
|
||||
auto matchedMethod = bindResult.mMethodInstance;
|
||||
|
||||
if (!_TypeMatches(_FixType(methodInstance->mReturnType), matchedMethod->mReturnType))
|
||||
return false;
|
||||
|
||||
int implicitParamCountA = methodInstance->GetImplicitParamCount();
|
||||
int implicitParamCountB = matchedMethod->GetImplicitParamCount();
|
||||
|
||||
if (methodInstance->GetParamCount() - implicitParamCountA != matchedMethod->GetParamCount() - implicitParamCountB)
|
||||
return false;
|
||||
for (int i = 0; i < (int)methodInstance->GetParamCount() - implicitParamCountA; i++)
|
||||
{
|
||||
auto paramA = _FixType(methodInstance->GetParamType(i + implicitParamCountA));
|
||||
auto paramB = _FixType(matchedMethod->GetParamType(i + implicitParamCountB));
|
||||
if (!_TypeMatches(paramA, paramB))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BfTypedValue BfExprEvaluator::DoImplicitArgCapture(BfAstNode* refNode, BfIdentifierNode* identifierNode, int shadowIdx)
|
||||
|
@ -9928,14 +10018,15 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
}
|
||||
}
|
||||
|
||||
typedValueExprs.resize(methodInstance->GetParamCount());
|
||||
args.resize(methodInstance->GetParamCount());
|
||||
|
||||
for (int i = 0; i < (int)methodInstance->GetParamCount(); i++)
|
||||
int paramOffset = methodInstance->HasExplicitThis() ? 1 : 0;
|
||||
typedValueExprs.resize(methodInstance->GetParamCount() - paramOffset);
|
||||
args.resize(methodInstance->GetParamCount() - paramOffset);
|
||||
|
||||
for (int i = 0; i < (int)methodInstance->GetParamCount() - paramOffset; i++)
|
||||
{
|
||||
auto typedValueExpr = &typedValueExprs[i];
|
||||
typedValueExpr->mTypedValue.mValue = BfIRValue(BfIRValueFlags_Value, -1);
|
||||
typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
|
||||
typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i + paramOffset);
|
||||
typedValueExpr->mRefNode = NULL;
|
||||
args[i] = typedValueExpr;
|
||||
}
|
||||
|
@ -9950,8 +10041,12 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
return;
|
||||
}
|
||||
|
||||
if (GetAutoComplete() != NULL)
|
||||
auto autoComplete = GetAutoComplete();
|
||||
if (autoComplete != NULL)
|
||||
{
|
||||
SetAndRestoreValue<bool> prevForceAllowNonStatic(autoComplete->mForceAllowNonStatic, methodInstance->mMethodDef->mHasExplicitThis);
|
||||
GetAutoComplete()->CheckNode(delegateBindExpr->mTarget);
|
||||
}
|
||||
|
||||
if ((!delegateBindExpr->mTarget->IsA<BfIdentifierNode>()) &&
|
||||
(!delegateBindExpr->mTarget->IsA<BfMemberReferenceExpression>()))
|
||||
|
@ -19533,13 +19628,14 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
}
|
||||
else
|
||||
{
|
||||
auto convertedValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, resultType, BfCastFlags_NoBox);
|
||||
auto convertedValue = mModule->Cast(otherTypeSrc, *otherTypedValue, resultType, BfCastFlags_NoBox);
|
||||
if (!convertedValue)
|
||||
return;
|
||||
convertedValue = mModule->LoadValue(convertedValue);
|
||||
if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_StrictEquality))
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpEQ(resultTypedValue->mValue, convertedValue), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpEQ(resultTypedValue->mValue, convertedValue.mValue), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
else
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpNE(resultTypedValue->mValue, convertedValue), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpNE(resultTypedValue->mValue, convertedValue.mValue), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -169,7 +169,7 @@ public:
|
|||
Array<BfAmbiguousEntry> mAmbiguousEntries;
|
||||
|
||||
public:
|
||||
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute);
|
||||
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType = NULL);
|
||||
bool InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs);
|
||||
void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute,
|
||||
BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute,
|
||||
|
@ -401,7 +401,7 @@ public:
|
|||
void SetMethodElementType(BfAstNode* target);
|
||||
BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfIdentifierNode* identifierNode, int shadowIdx);
|
||||
BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfMethodInstance* methodInstance, int paramIdx, bool& failed, BfImplicitParamKind paramKind = BfImplicitParamKind_General, const BfTypedValue& methodRefTarget = BfTypedValue());
|
||||
bool CanBindDelegate(BfDelegateBindExpression* delegateBindExpr, BfMethodInstance** boundMethod = NULL);
|
||||
bool CanBindDelegate(BfDelegateBindExpression* delegateBindExpr, BfMethodInstance** boundMethod = NULL, BfType* origMethodExpectingType = NULL, BfTypeVector* methodGenericArgumentsSubstitute = NULL);
|
||||
bool IsExactMethodMatch(BfMethodInstance* methodA, BfMethodInstance* methodB, bool ignoreImplicitParams = false);
|
||||
BfTypeInstance* VerifyBaseDelegateType(BfTypeInstance* delegateType);
|
||||
void ConstResolve(BfExpression* expr);
|
||||
|
|
|
@ -311,14 +311,9 @@ void BfGNUMangler::MangleTypeInst(MangleContext& mangleContext, StringImpl& name
|
|||
else
|
||||
name += "N8functionI";
|
||||
SizedArray<BfType*, 8> typeVec;
|
||||
typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
{
|
||||
name += "_";
|
||||
name += "this";
|
||||
typeVec.push_back(delegateInfo->mFunctionThisType);
|
||||
}
|
||||
|
||||
typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
|
||||
if (methodDef->mIsMutating)
|
||||
name += "_mut_";
|
||||
for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
|
||||
{
|
||||
name += "_";
|
||||
|
@ -1175,18 +1170,11 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
|
|||
name += "?$delegate";
|
||||
else
|
||||
name += "?$function";
|
||||
if (methodDef->mIsMutating)
|
||||
name += "_mut_";
|
||||
SizedArray<BfType*, 8> typeVec;
|
||||
typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
|
||||
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
{
|
||||
name += "_";
|
||||
name += "this";
|
||||
typeVec.push_back(delegateInfo->mFunctionThisType);
|
||||
if ((delegateInfo->mFunctionThisType->IsValueType()) && (methodDef->mIsMutating))
|
||||
name += "_mut";
|
||||
}
|
||||
|
||||
|
||||
for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
|
||||
{
|
||||
name += "_";
|
||||
|
|
|
@ -2610,6 +2610,15 @@ void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementTyp
|
|||
}
|
||||
}
|
||||
|
||||
void BfModule::SetFail()
|
||||
{
|
||||
if (mIgnoreErrors)
|
||||
{
|
||||
if (mAttributeState != NULL)
|
||||
mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
|
||||
}
|
||||
}
|
||||
|
||||
BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent)
|
||||
{
|
||||
BP_ZONE("BfModule::Fail");
|
||||
|
@ -3074,10 +3083,17 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap
|
|||
return;
|
||||
|
||||
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsAutocompleteMethod))
|
||||
return;
|
||||
{
|
||||
if (userType->IsMethodRef())
|
||||
{
|
||||
// We cannot short-circuit dependencies because of method group ref counting
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if (usedType->IsSpecializedByAutoCompleteMethod())
|
||||
return;
|
||||
return;
|
||||
|
||||
// if (usedType->IsBoxed())
|
||||
// {
|
||||
|
@ -14790,7 +14806,7 @@ BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstanc
|
|||
auto methodDef = methodInstance->mMethodDef;
|
||||
BfTypeInstance* owner = NULL;
|
||||
if (!methodDef->mIsStatic)
|
||||
owner = methodInstance->GetParamType(-1)->ToTypeInstance();
|
||||
owner = methodInstance->GetThisType()->ToTypeInstance();
|
||||
if (owner == NULL)
|
||||
owner = methodInstance->GetOwner();
|
||||
|
||||
|
@ -14842,13 +14858,11 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
|
|||
int argIdx = 0;
|
||||
int paramIdx = 0;
|
||||
|
||||
if (methodInstance->HasThis())
|
||||
{
|
||||
paramIdx = -1;
|
||||
}
|
||||
if ((methodInstance->HasThis()) && (!methodDef->mHasExplicitThis))
|
||||
paramIdx = -1;
|
||||
|
||||
int argCount = methodInstance->GetIRFunctionParamCount(this);
|
||||
|
||||
|
||||
while (argIdx < argCount)
|
||||
{
|
||||
if (argIdx == methodInstance->GetStructRetIdx())
|
||||
|
@ -14859,22 +14873,22 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
|
|||
continue;
|
||||
}
|
||||
|
||||
while ((paramIdx != -1) && (methodInstance->IsParamSkipped(paramIdx)))
|
||||
bool isThis = (paramIdx == -1) || ((methodDef->mHasExplicitThis) && (paramIdx == 0));
|
||||
while ((!isThis) && (methodInstance->IsParamSkipped(paramIdx)))
|
||||
paramIdx++;
|
||||
|
||||
BfType* resolvedTypeRef = NULL;
|
||||
BfType* resolvedTypeRef2 = NULL;
|
||||
String paramName;
|
||||
bool isSplattable = false;
|
||||
bool tryLowering = true;
|
||||
bool isThis = paramIdx == -1;
|
||||
bool tryLowering = true;
|
||||
if (isThis)
|
||||
{
|
||||
paramName = "this";
|
||||
if (methodInstance->mIsClosure)
|
||||
resolvedTypeRef = mCurMethodState->mClosureState->mClosureType;
|
||||
else
|
||||
resolvedTypeRef = methodInstance->GetOwner();
|
||||
resolvedTypeRef = methodInstance->GetThisType();
|
||||
isSplattable = (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsThisSplatting());
|
||||
tryLowering = methodInstance->AllowsThisSplatting();
|
||||
}
|
||||
|
@ -14933,7 +14947,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
|
|||
}
|
||||
if ((resolvedTypeRef->IsComposite()) && (!resolvedTypeRef->IsTypedPrimitive()))
|
||||
{
|
||||
if (paramIdx == -1)
|
||||
if (isThis)
|
||||
{
|
||||
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoCapture);
|
||||
PopulateType(resolvedTypeRef, BfPopulateType_Data);
|
||||
|
@ -16965,6 +16979,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
}
|
||||
if (methodInstance->mIsIntrinsic)
|
||||
return;
|
||||
if (mCurTypeInstance->IsFunction())
|
||||
return;
|
||||
|
||||
auto prevActiveFunction = mBfIRBuilder->GetActiveFunction();
|
||||
mBfIRBuilder->SetActiveFunction(mCurMethodInstance->mIRFunction);
|
||||
|
@ -20318,7 +20334,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
implicitParamCount = (int)methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries.size();
|
||||
|
||||
methodInstance->mMethodDef->mParams.Reserve((int)methodDef->mParams.size());
|
||||
|
||||
|
||||
|
||||
bool hadDelegateParams = false;
|
||||
bool hadParams = false;
|
||||
for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size() + implicitParamCount; paramIdx++)
|
||||
|
@ -20379,9 +20396,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
BfType* unresolvedParamType = resolvedParamType;
|
||||
bool wasGenericParam = false;
|
||||
if (resolvedParamType == NULL)
|
||||
{
|
||||
resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration,
|
||||
(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue));
|
||||
{
|
||||
BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
|
||||
if (paramDef->mParamKind == BfParamKind_ExplicitThis)
|
||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut);
|
||||
resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags);
|
||||
if ((paramDef->mParamKind == BfParamKind_ExplicitThis) && (resolvedParamType != NULL) && (resolvedParamType->IsRef()))
|
||||
resolvedParamType = resolvedParamType->GetUnderlyingType();
|
||||
}
|
||||
if (resolvedParamType == NULL)
|
||||
{
|
||||
|
@ -20578,7 +20599,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
methodParam.mResolvedType = resolvedParamType;
|
||||
methodParam.mParamDefIdx = paramDefIdx;
|
||||
mCurMethodInstance->mParams.Add(methodParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hadDelegateParams)
|
||||
|
@ -20616,11 +20637,12 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
|
||||
int argIdx = 0;
|
||||
PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
|
||||
if (!methodDef->mIsStatic)
|
||||
if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis))
|
||||
{
|
||||
int thisIdx = methodDef->mHasExplicitThis ? 0 : -1;
|
||||
auto thisType = methodInstance->GetOwner();
|
||||
if (methodInstance->GetParamIsSplat(-1))
|
||||
argIdx += methodInstance->GetParamType(-1)->GetSplatCount();
|
||||
if (methodInstance->GetParamIsSplat(thisIdx))
|
||||
argIdx += methodInstance->GetParamType(thisIdx)->GetSplatCount();
|
||||
else if (!thisType->IsValuelessType())
|
||||
{
|
||||
BfTypeCode loweredTypeCode = BfTypeCode_None;
|
||||
|
@ -20636,25 +20658,44 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
if (methodInstance->GetStructRetIdx() != -1)
|
||||
argIdx++;
|
||||
|
||||
for (auto& methodParam : mCurMethodInstance->mParams)
|
||||
for (int paramIdx = 0; paramIdx < mCurMethodInstance->mParams.size(); paramIdx++)
|
||||
{
|
||||
if (methodParam.mResolvedType->IsMethodRef())
|
||||
auto& methodParam = mCurMethodInstance->mParams[paramIdx];
|
||||
|
||||
BfType* checkType = methodParam.mResolvedType;
|
||||
int checkArgIdx = argIdx;
|
||||
if ((paramIdx == 0) && (methodDef->mHasExplicitThis))
|
||||
{
|
||||
checkArgIdx = 0;
|
||||
checkType = methodInstance->GetThisType();
|
||||
}
|
||||
|
||||
if (checkType->IsMethodRef())
|
||||
{
|
||||
methodParam.mIsSplat = true;
|
||||
}
|
||||
else if ((methodParam.mResolvedType->IsComposite()) && (methodInstance->AllowsSplatting()))
|
||||
else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting()))
|
||||
{
|
||||
PopulateType(methodParam.mResolvedType, BfPopulateType_Data);
|
||||
if (methodParam.mResolvedType->IsSplattable())
|
||||
PopulateType(checkType, BfPopulateType_Data);
|
||||
if (checkType->IsSplattable())
|
||||
{
|
||||
int splatCount = methodParam.mResolvedType->GetSplatCount();
|
||||
if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
|
||||
int splatCount = checkType->GetSplatCount();
|
||||
if (checkArgIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
|
||||
{
|
||||
methodParam.mIsSplat = true;
|
||||
argIdx += splatCount;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!checkType->IsValuelessType())
|
||||
{
|
||||
BfTypeCode loweredTypeCode = BfTypeCode_None;
|
||||
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
|
||||
checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
|
||||
argIdx++;
|
||||
if (loweredTypeCode2 != BfTypeCode_None)
|
||||
argIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
argIdx++;
|
||||
|
|
|
@ -1420,6 +1420,7 @@ public:
|
|||
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
|
||||
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType);
|
||||
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
|
||||
void SetFail();
|
||||
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
|
||||
BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
|
||||
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
|
||||
|
|
|
@ -6331,6 +6331,7 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
|||
|
||||
bool hasTypeGenerics = false;
|
||||
auto returnType = ResolveGenericType(unspecializedDelegateInfo->mReturnType, typeGenericArguments, methodGenericArguments, allowFail);
|
||||
|
||||
if (returnType == NULL)
|
||||
return NULL;
|
||||
if (returnType->IsVar())
|
||||
|
@ -6338,6 +6339,7 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
|||
_CheckType(returnType);
|
||||
if (returnType->IsGenericParam())
|
||||
hasTypeGenerics |= ((BfGenericParamType*)returnType)->mGenericParamKind == BfGenericParamKind_Type;
|
||||
|
||||
Array<BfType*> paramTypes;
|
||||
for (auto param : unspecializedDelegateInfo->mParams)
|
||||
{
|
||||
|
@ -6420,13 +6422,16 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
|||
typeDef->mIsDelegate = unspecializedDelegateType->mTypeDef->mIsDelegate;
|
||||
typeDef->mIsFunction = unspecializedDelegateType->mTypeDef->mIsFunction;
|
||||
|
||||
BfMethodDef* unspecializedInvokeMethodDef = unspecializedDelegateType->mTypeDef->GetMethodByName("Invoke");
|
||||
|
||||
BfMethodDef* methodDef = new BfMethodDef();
|
||||
methodDef->mDeclaringType = typeDef;
|
||||
methodDef->mName = "Invoke";
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
methodDef->mIdx = 0;
|
||||
methodDef->mIsStatic = !typeDef->mIsDelegate;
|
||||
|
||||
methodDef->mIsStatic = !typeDef->mIsDelegate && !unspecializedDelegateInfo->mHasExplicitThis;
|
||||
methodDef->mHasExplicitThis = unspecializedDelegateInfo->mHasExplicitThis;
|
||||
|
||||
auto directTypeRef = BfAstNode::ZeroedAlloc<BfDirectTypeReference>();
|
||||
delegateInfo->mDirectAllocNodes.push_back(directTypeRef);
|
||||
if (typeDef->mIsDelegate)
|
||||
|
@ -6440,8 +6445,7 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
|||
directTypeRef->Init(returnType);
|
||||
methodDef->mReturnTypeRef = directTypeRef;
|
||||
delegateInfo->mReturnType = returnType;
|
||||
|
||||
BfMethodDef* unspecializedInvokeMethodDef = unspecializedDelegateType->mTypeDef->GetMethodByName("Invoke");
|
||||
delegateInfo->mHasExplicitThis = unspecializedDelegateInfo->mHasExplicitThis;
|
||||
|
||||
int paramIdx = 0;
|
||||
for (int paramIdx = 0; paramIdx < (int)paramTypes.size(); paramIdx++)
|
||||
|
@ -6469,11 +6473,20 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
|||
|
||||
typeDef->mMethods.push_back(methodDef);
|
||||
|
||||
//
|
||||
if (unspecializedInvokeMethodDef->mIsMutating)
|
||||
{
|
||||
if ((delegateInfo->mParams[0]->IsValueType()) || (delegateInfo->mParams[0]->IsGenericParam()))
|
||||
methodDef->mIsMutating = unspecializedInvokeMethodDef->mIsMutating;
|
||||
}
|
||||
|
||||
BfDefBuilder::AddMethod(typeDef, BfMethodType_Ctor, BfProtection_Public, false, "");
|
||||
|
||||
//
|
||||
|
||||
if (typeDef->mIsDelegate)
|
||||
{
|
||||
BfDefBuilder::AddMethod(typeDef, BfMethodType_Ctor, BfProtection_Public, false, "");
|
||||
BfDefBuilder::AddDynamicCastMethods(typeDef);
|
||||
}
|
||||
|
||||
delegateType->mContext = mContext;
|
||||
delegateType->mTypeDef = typeDef;
|
||||
|
@ -6904,8 +6917,8 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
|
|||
else if (resolvedTypeRef->IsDelegateFromTypeRef() || resolvedTypeRef->IsFunctionFromTypeRef())
|
||||
{
|
||||
auto delegateInfo = resolvedTypeRef->GetDelegateInfo();
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
AddDependency(delegateInfo->mFunctionThisType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference);
|
||||
// if (delegateInfo->mFunctionThisType != NULL)
|
||||
// AddDependency(delegateInfo->mFunctionThisType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference);
|
||||
AddDependency(delegateInfo->mReturnType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference);
|
||||
for (auto& param : delegateInfo->mParams)
|
||||
AddDependency(param, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference);
|
||||
|
@ -8903,8 +8916,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
}
|
||||
}
|
||||
hasMutSpecifier = true;
|
||||
functionThisType = refType->mElementType;
|
||||
functionThisType = refType->mElementType;
|
||||
}
|
||||
paramTypes.Add(functionThisType);
|
||||
_CheckType(functionThisType);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8980,11 +8995,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
methodDef->mName = "Invoke";
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
methodDef->mIdx = 0;
|
||||
methodDef->mIsStatic = !typeDef->mIsDelegate && (functionThisType == NULL);
|
||||
methodDef->mIsMutating = true;
|
||||
methodDef->mIsStatic = !typeDef->mIsDelegate && (functionThisType == NULL);
|
||||
methodDef->mHasExplicitThis = functionThisType != NULL;
|
||||
|
||||
if ((functionThisType != NULL) && (functionThisType->IsValueType()) && (!hasMutSpecifier))
|
||||
methodDef->mIsMutating = false;
|
||||
if ((functionThisType != NULL) && (hasMutSpecifier))
|
||||
{
|
||||
if ((functionThisType->IsValueType()) || (functionThisType->IsGenericParam()))
|
||||
methodDef->mIsMutating = true;
|
||||
}
|
||||
|
||||
auto directTypeRef = BfAstNode::ZeroedAlloc<BfDirectTypeReference>();
|
||||
delegateInfo->mDirectAllocNodes.push_back(directTypeRef);
|
||||
|
@ -8999,11 +9017,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
directTypeRef->Init(returnType);
|
||||
methodDef->mReturnTypeRef = directTypeRef;
|
||||
delegateInfo->mReturnType = returnType;
|
||||
delegateInfo->mFunctionThisType = functionThisType;
|
||||
delegateInfo->mHasExplicitThis = functionThisType != NULL;
|
||||
|
||||
auto hashVal = mContext->mResolvedTypes.Hash(typeRef, &lookupCtx);
|
||||
|
||||
int paramSrcOfs = (functionThisType != NULL) ? 1 : 0;
|
||||
//int paramSrcOfs = (functionThisType != NULL) ? 1 : 0;
|
||||
int paramSrcOfs = 0;
|
||||
for (int paramIdx = 0; paramIdx < (int)paramTypes.size(); paramIdx++)
|
||||
{
|
||||
auto param = delegateTypeRef->mParams[paramIdx + paramSrcOfs];
|
||||
|
@ -9026,8 +9045,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
|
||||
paramDef->mTypeRef = directTypeRef;
|
||||
paramDef->mName = paramName;
|
||||
methodDef->mParams.push_back(paramDef);
|
||||
|
||||
if ((paramIdx == 0) && (functionThisType != NULL))
|
||||
paramDef->mParamKind = BfParamKind_ExplicitThis;
|
||||
methodDef->mParams.push_back(paramDef);
|
||||
|
||||
delegateInfo->mParams.Add(paramType);
|
||||
}
|
||||
|
||||
|
@ -9041,10 +9062,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
}
|
||||
|
||||
//
|
||||
|
||||
BfDefBuilder::AddMethod(typeDef, BfMethodType_Ctor, BfProtection_Public, false, "");
|
||||
if (typeDef->mIsDelegate)
|
||||
|
||||
if (typeDef->mIsDelegate)
|
||||
{
|
||||
BfDefBuilder::AddMethod(typeDef, BfMethodType_Ctor, BfProtection_Public, false, "");
|
||||
BfDefBuilder::AddDynamicCastMethods(typeDef);
|
||||
}
|
||||
|
||||
delegateType->mContext = mContext;
|
||||
delegateType->mTypeDef = typeDef;
|
||||
|
@ -9052,8 +9075,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
resolvedEntry->mValue = delegateType;
|
||||
|
||||
AddDependency(directTypeRef->mType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
AddDependency(delegateInfo->mFunctionThisType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||
// if (delegateInfo->mFunctionThisType != NULL)
|
||||
// AddDependency(delegateInfo->mFunctionThisType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||
for (auto paramType : paramTypes)
|
||||
AddDependency(paramType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||
|
||||
|
@ -9376,14 +9399,13 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodI
|
|||
}
|
||||
else if (invokeMethodInstance->IsExactMatch(methodInstance, false, false))
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
auto thisType = methodInstance->GetParamType(-1);
|
||||
if (thisType != NULL)
|
||||
bool handled = false;
|
||||
if (methodInstance->HasThis())
|
||||
{
|
||||
auto thisType = methodInstance->GetThisType();
|
||||
if (invokeMethodInstance->HasExplicitThis())
|
||||
{
|
||||
auto invokeThisType = invokeMethodInstance->GetParamType(-1);
|
||||
auto invokeThisType = invokeMethodInstance->GetThisType();
|
||||
|
||||
bool thisWasPtr = false;
|
||||
if (thisType->IsPointer())
|
||||
|
@ -9416,6 +9438,7 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodI
|
|||
if ((!methodInstance->mMethodDef->mIsStatic) && (!invokeMethodInstance->HasExplicitThis()))
|
||||
{
|
||||
handled = true;
|
||||
auto thisType = methodInstance->GetParamType(-1);
|
||||
Fail(StrFormat("Non-static method '%s' cannot match '%s', consider adding '%s this' to the function parameters", MethodToString(methodInstance).c_str(), TypeToString(toType).c_str(), TypeToString(thisType).c_str()), srcNode);
|
||||
}
|
||||
|
||||
|
@ -9432,9 +9455,10 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodI
|
|||
}
|
||||
|
||||
BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags, BfCastResultFlags* resultFlags)
|
||||
{
|
||||
{
|
||||
bool silentFail = ((castFlags & BfCastFlags_SilentFail) != 0);
|
||||
bool explicitCast = (castFlags & BfCastFlags_Explicit) != 0;
|
||||
bool ignoreErrors = mIgnoreErrors || ((castFlags & BfCastFlags_SilentFail) != 0);
|
||||
bool ignoreErrors = mIgnoreErrors || ((castFlags & BfCastFlags_SilentFail) != 0);
|
||||
bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
|
||||
|
||||
if (typedVal.mType == toType)
|
||||
|
@ -9547,9 +9571,12 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
// void* -> intptr
|
||||
if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
|
||||
{
|
||||
if ((!ignoreErrors) && (!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
|
||||
{
|
||||
Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
if ((!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
|
||||
{
|
||||
if (!ignoreErrors)
|
||||
Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
}
|
||||
|
||||
auto toPrimitive = (BfPrimitiveType*)toType;
|
||||
|
@ -9559,9 +9586,12 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
// intptr -> void*
|
||||
if ((typedVal.mType->IsIntPtr()) && (toType->IsPointer()))
|
||||
{
|
||||
if ((!ignoreErrors) && (!toType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
|
||||
if ((!toType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
|
||||
{
|
||||
Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
if (!ignoreErrors)
|
||||
Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
}
|
||||
|
||||
return mBfIRBuilder->CreateIntToPtr(typedVal.mValue, mBfIRBuilder->MapType(toType));
|
||||
|
@ -10088,11 +10118,13 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
}
|
||||
|
||||
if (!ignoreErrors)
|
||||
{
|
||||
{
|
||||
String valStr;
|
||||
VariantToString(valStr, variantVal);
|
||||
Fail(StrFormat("Unable to cast '%s %s' to '%s'", TypeToString(typedVal.mType).c_str(), valStr.c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
}
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10553,8 +10585,13 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
{
|
||||
if (mayBeBox)
|
||||
{
|
||||
if ((!ignoreErrors) && (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL))
|
||||
mCompiler->mPassInstance->MoreInfo("See conversion operator", opMethodInstance->mMethodDef->GetRefNode());
|
||||
if (!ignoreErrors)
|
||||
{
|
||||
if (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL)
|
||||
mCompiler->mPassInstance->MoreInfo("See conversion operator", opMethodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
}
|
||||
|
||||
BfMethodInstance* methodInstance = GetRawMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef);
|
||||
|
@ -10620,6 +10657,8 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
const char* errStr = "Ambiguous conversion operators for casting from '%s' to '%s'";
|
||||
Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||
}
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
return BfIRValue();
|
||||
}
|
||||
|
||||
|
@ -10777,7 +10816,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
"Unable to cast '%s' to '%s'" :
|
||||
"Unable to implicitly cast '%s' to '%s'";
|
||||
|
||||
String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());
|
||||
String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());
|
||||
auto error = Fail(errStr, srcNode);
|
||||
if ((error != NULL) && (srcNode != NULL))
|
||||
{
|
||||
|
@ -10787,7 +10826,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
|
||||
|
||||
if (CastToValue(srcNode, typedVal, toType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail)))
|
||||
{
|
||||
{
|
||||
bool doWrap = false;
|
||||
if (auto unaryOpExpr = BfNodeDynCast<BfUnaryOperatorExpression>(srcNode))
|
||||
{
|
||||
|
@ -10805,7 +10844,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
if (doWrap)
|
||||
{
|
||||
mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit",
|
||||
StrFormat("(%s)\tcast|%s|%d|(%s)(|`%d|)", typeName.c_str(), parser->mFileName.c_str(), srcNode->GetSrcStart(), typeName.c_str(), srcNode->GetSrcLength()).c_str()));
|
||||
StrFormat("(%s)\tcast|%s|%d|(%s)(|`%d|)", typeName.c_str(), parser->mFileName.c_str(), srcNode->GetSrcStart(), typeName.c_str(), srcNode->GetSrcLength()).c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -10816,6 +10855,8 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (!silentFail)
|
||||
SetFail();
|
||||
return BfIRValue();
|
||||
}
|
||||
|
||||
|
@ -10986,6 +11027,7 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
|
|||
|
||||
if ((fromMethodInst != NULL) && (toMethodInst != NULL) &&
|
||||
(fromMethodInst->mMethodDef->mCallingConvention == toMethodInst->mMethodDef->mCallingConvention) &&
|
||||
(fromMethodInst->mMethodDef->mIsMutating == toMethodInst->mMethodDef->mIsMutating) &&
|
||||
(fromMethodInst->mReturnType == toMethodInst->mReturnType) &&
|
||||
(fromMethodInst->GetParamCount() == toMethodInst->GetParamCount()))
|
||||
{
|
||||
|
@ -11000,7 +11042,7 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
|
|||
}
|
||||
else
|
||||
{
|
||||
for (int paramIdx = fromMethodInst->HasExplicitThis() ? -1 : 0; paramIdx < (int)fromMethodInst->GetParamCount(); paramIdx++)
|
||||
for (int paramIdx = 0; paramIdx < (int)fromMethodInst->GetParamCount(); paramIdx++)
|
||||
{
|
||||
bool nameMatches = true;
|
||||
|
||||
|
@ -11550,16 +11592,7 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
DoTypeToString(str, delegateInfo->mReturnType, typeNameFlags, genericMethodNameOverrides);
|
||||
str += "(";
|
||||
|
||||
bool isFirstParam = true;
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
{
|
||||
if ((methodDef->mIsMutating) && (delegateInfo->mFunctionThisType->IsValueType()))
|
||||
str += "mut ";
|
||||
DoTypeToString(str, delegateInfo->mFunctionThisType, typeNameFlags, genericMethodNameOverrides);
|
||||
str += " this";
|
||||
isFirstParam = false;
|
||||
}
|
||||
|
||||
bool isFirstParam = true;//
|
||||
for (int paramIdx = 0; paramIdx < methodDef->mParams.size(); paramIdx++)
|
||||
{
|
||||
if (!isFirstParam)
|
||||
|
@ -11567,7 +11600,14 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
auto paramDef = methodDef->mParams[paramIdx];
|
||||
BfTypeNameFlags innerFlags = (BfTypeNameFlags)(typeNameFlags & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType));
|
||||
|
||||
DoTypeToString(str, delegateInfo->mParams[paramIdx], innerFlags, genericMethodNameOverrides);
|
||||
auto paramType = delegateInfo->mParams[paramIdx];
|
||||
if ((paramIdx == 0) && (delegateInfo->mHasExplicitThis))
|
||||
{
|
||||
if ((methodDef->mIsMutating) && (paramType->IsValueType()))
|
||||
str += "mut ";
|
||||
}
|
||||
|
||||
DoTypeToString(str, paramType, innerFlags, genericMethodNameOverrides);
|
||||
|
||||
if (!paramDef->mName.IsEmpty())
|
||||
{
|
||||
|
|
|
@ -768,6 +768,29 @@ bool BfMethodInstance::HasThis()
|
|||
return (!mMethodInstanceGroup->mOwner->IsValuelessType());
|
||||
}
|
||||
|
||||
BfType* BfMethodInstance::GetThisType()
|
||||
{
|
||||
BF_ASSERT(!mMethodDef->mIsStatic);
|
||||
if (mMethodDef->mHasExplicitThis)
|
||||
{
|
||||
auto thisType = mParams[0].mResolvedType;
|
||||
auto owner = GetOwner();
|
||||
if ((thisType->IsValueType()) && ((mMethodDef->mIsMutating) || (!AllowsSplatting())) && (!thisType->GetLoweredType(BfTypeUsage_Parameter)))
|
||||
return owner->mModule->CreatePointerType(thisType);
|
||||
return thisType;
|
||||
}
|
||||
return GetParamType(-1);
|
||||
}
|
||||
|
||||
int BfMethodInstance::GetThisIdx()
|
||||
{
|
||||
if (mMethodDef->mIsStatic)
|
||||
return -2;
|
||||
if (mMethodDef->mHasExplicitThis)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BfMethodInstance::HasExplicitThis()
|
||||
{
|
||||
if (mMethodDef->mIsStatic)
|
||||
|
@ -827,17 +850,18 @@ String BfMethodInstance::GetParamName(int paramIdx)
|
|||
}
|
||||
|
||||
BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
|
||||
{
|
||||
{
|
||||
if (paramIdx == -1)
|
||||
{
|
||||
if ((mMethodInfoEx != NULL) && (mMethodInfoEx->mClosureInstanceInfo != NULL) && (mMethodInfoEx->mClosureInstanceInfo->mThisOverride != NULL))
|
||||
return mMethodInfoEx->mClosureInstanceInfo->mThisOverride;
|
||||
BF_ASSERT(!mMethodDef->mIsStatic);
|
||||
auto owner = mMethodInstanceGroup->mOwner;
|
||||
auto delegateInfo = owner->GetDelegateInfo();
|
||||
BfType* thisType = owner;
|
||||
if ((delegateInfo != NULL) && (delegateInfo->mFunctionThisType != NULL))
|
||||
thisType = delegateInfo->mFunctionThisType;
|
||||
if (owner->IsFunction())
|
||||
{
|
||||
BF_FATAL("Wrong 'this' index");
|
||||
}
|
||||
if ((thisType->IsValueType()) && ((mMethodDef->mIsMutating) || (!AllowsSplatting())) && (!thisType->GetLoweredType(BfTypeUsage_Parameter)))
|
||||
return owner->mModule->CreatePointerType(thisType);
|
||||
return thisType;
|
||||
|
@ -1034,8 +1058,10 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
returnType = module->mBfIRBuilder->MapType(mReturnType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int paramIdx = -1; paramIdx < GetParamCount(); paramIdx++)
|
||||
{
|
||||
{
|
||||
BfType* checkType = NULL;
|
||||
if (paramIdx == -1)
|
||||
{
|
||||
|
@ -1048,7 +1074,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
else
|
||||
{
|
||||
if (HasExplicitThis())
|
||||
checkType = GetParamType(-1);
|
||||
checkType = GetParamType(0);
|
||||
else
|
||||
checkType = GetOwner();
|
||||
}
|
||||
|
@ -1102,14 +1128,14 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
}
|
||||
}
|
||||
|
||||
if ((paramIdx == 0) && (GetParamName(0) == "this") && (checkType->IsPointer()))
|
||||
{
|
||||
// We don't actually pass a this pointer for mut methods in valueless structs
|
||||
auto underlyingType = checkType->GetUnderlyingType();
|
||||
module->PopulateType(underlyingType, BfPopulateType_Data);
|
||||
if (underlyingType->IsValuelessType())
|
||||
continue;
|
||||
}
|
||||
// if ((paramIdx == 0) && (GetParamName(0) == "this") && (checkType->IsPointer()))
|
||||
// {
|
||||
// // We don't actually pass a this pointer for mut methods in valueless structs
|
||||
// auto underlyingType = checkType->GetUnderlyingType();
|
||||
// module->PopulateType(underlyingType, BfPopulateType_Data);
|
||||
// if (underlyingType->IsValuelessType())
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (checkType->CanBeValuelessType())
|
||||
module->PopulateType(checkType, BfPopulateType_Data);
|
||||
|
@ -1159,6 +1185,9 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
|
||||
if (checkType2 != NULL)
|
||||
_AddType(checkType2);
|
||||
|
||||
if ((paramIdx == -1) && (mMethodDef->mHasExplicitThis))
|
||||
paramIdx++; // Skip over the explicit 'this'
|
||||
}
|
||||
|
||||
if (GetStructRetIdx(forceStatic) == 1)
|
||||
|
@ -1200,7 +1229,7 @@ bool BfMethodInstance::IsExactMatch(BfMethodInstance* other, bool ignoreImplicit
|
|||
if (checkThis)
|
||||
{
|
||||
if (other->mMethodDef->mIsStatic != mMethodDef->mIsStatic)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
// {
|
||||
// // If we are static and we have to match a non-static method, allow us to do so if we have an explicitly defined 'this' param that matches
|
||||
|
@ -1227,13 +1256,18 @@ bool BfMethodInstance::IsExactMatch(BfMethodInstance* other, bool ignoreImplicit
|
|||
|
||||
if (!mMethodDef->mIsStatic)
|
||||
{
|
||||
if (GetParamType(-1) != other->GetParamType(-1))
|
||||
if (GetThisType() != other->GetThisType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mMethodDef->mHasExplicitThis)
|
||||
implicitParamCountA++;
|
||||
if (other->mMethodDef->mHasExplicitThis)
|
||||
implicitParamCountB++;
|
||||
|
||||
if (GetParamCount() - implicitParamCountA != other->GetParamCount() - implicitParamCountB)
|
||||
return false;
|
||||
for (int i = 0; i < (int)GetParamCount() - implicitParamCountA; i++)
|
||||
|
@ -2577,14 +2611,6 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef)
|
|||
BF_ASSERT(methodDef->mName == "Invoke");
|
||||
BF_ASSERT(delegateInfo->mParams.size() == methodDef->mParams.size());
|
||||
|
||||
if (delegateInfo->mFunctionThisType != NULL)
|
||||
{
|
||||
hashVal = ((hashVal ^ (Hash(delegateInfo->mFunctionThisType, ctx))) << 5) - hashVal;
|
||||
String paramName = "this";
|
||||
int nameHash = (int)Hash64(paramName.c_str(), (int)paramName.length());
|
||||
hashVal = ((hashVal ^ (nameHash)) << 5) - hashVal;
|
||||
}
|
||||
|
||||
for (int paramIdx = 0; paramIdx < delegateInfo->mParams.size(); paramIdx++)
|
||||
{
|
||||
// Parse attributes?
|
||||
|
@ -3300,6 +3326,10 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
|||
auto lhsMethodDef = lhsInst->mTypeDef->mMethods[0];
|
||||
auto rhsMethodDef = rhsInst->mTypeDef->mMethods[0];
|
||||
|
||||
if (lhsMethodDef->mCallingConvention != rhsMethodDef->mCallingConvention)
|
||||
return false;
|
||||
if (lhsMethodDef->mIsMutating != rhsMethodDef->mIsMutating)
|
||||
return false;
|
||||
if (lhsDelegateInfo->mReturnType != rhsDelegateInfo->mReturnType)
|
||||
return false;
|
||||
if (lhsDelegateInfo->mParams.size() != rhsDelegateInfo->mParams.size())
|
||||
|
@ -3701,44 +3731,42 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
|||
auto param0 = rhsDelegateType->mParams[0];
|
||||
if ((param0->mNameNode != NULL) && (param0->mNameNode->Equals("this")))
|
||||
{
|
||||
if (!lhsDelegateInfo->mHasExplicitThis)
|
||||
return false;
|
||||
|
||||
bool handled = false;
|
||||
auto lhsThisType = lhsDelegateInfo->mFunctionThisType;
|
||||
auto lhsThisType = lhsDelegateInfo->mParams[0];
|
||||
|
||||
auto rhsThisType = ctx->mModule->ResolveTypeRef(param0->mTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoWarnOnMut | BfResolveTypeRefFlag_AllowRef));
|
||||
bool wantsMutating = false;
|
||||
|
||||
if (rhsThisType->IsRef())
|
||||
{
|
||||
if (lhsThisType != rhsThisType->GetUnderlyingType())
|
||||
return false;
|
||||
if (!invokeMethodDef->mIsMutating)
|
||||
return false;
|
||||
wantsMutating = (lhsThisType->IsValueType()) || (lhsThisType->IsGenericParam());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lhsThisType != rhsThisType)
|
||||
return false;
|
||||
if ((invokeMethodDef->mIsMutating) && (lhsThisType->IsValueType()))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
if (invokeMethodDef->mIsMutating != wantsMutating)
|
||||
return false;
|
||||
|
||||
paramRefOfs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rhsIsDelegate)
|
||||
{
|
||||
if ((lhsDelegateInfo->mFunctionThisType == NULL) != (paramRefOfs == 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lhsDelegateInfo->mParams.size() != (int)rhsDelegateType->mParams.size() - paramRefOfs)
|
||||
if (lhsDelegateInfo->mParams.size() != (int)rhsDelegateType->mParams.size())
|
||||
return false;
|
||||
for (int paramIdx = 0; paramIdx < lhsDelegateInfo->mParams.size(); paramIdx++)
|
||||
for (int paramIdx = paramRefOfs; paramIdx < lhsDelegateInfo->mParams.size(); paramIdx++)
|
||||
{
|
||||
if (!Equals(lhsDelegateInfo->mParams[paramIdx], rhsDelegateType->mParams[paramIdx + paramRefOfs]->mTypeRef, ctx))
|
||||
if (!Equals(lhsDelegateInfo->mParams[paramIdx], rhsDelegateType->mParams[paramIdx]->mTypeRef, ctx))
|
||||
return false;
|
||||
StringView rhsParamName;
|
||||
if (rhsDelegateType->mParams[paramIdx + paramRefOfs]->mNameNode != NULL)
|
||||
rhsParamName = rhsDelegateType->mParams[paramIdx + paramRefOfs]->mNameNode->ToStringView();
|
||||
if (rhsDelegateType->mParams[paramIdx]->mNameNode != NULL)
|
||||
rhsParamName = rhsDelegateType->mParams[paramIdx]->mNameNode->ToStringView();
|
||||
if (invokeMethodDef->mParams[paramIdx]->mName != rhsParamName)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -416,15 +416,15 @@ class BfDelegateInfo
|
|||
{
|
||||
public:
|
||||
Array<BfAstNode*> mDirectAllocNodes;
|
||||
BfType* mReturnType;
|
||||
BfType* mFunctionThisType;
|
||||
BfType* mReturnType;
|
||||
Array<BfType*> mParams;
|
||||
bool mHasExplicitThis;
|
||||
|
||||
public:
|
||||
BfDelegateInfo()
|
||||
{
|
||||
mReturnType = NULL;
|
||||
mFunctionThisType = NULL;
|
||||
mHasExplicitThis = false;
|
||||
}
|
||||
|
||||
~BfDelegateInfo()
|
||||
|
@ -870,6 +870,8 @@ public:
|
|||
bool IsSpecializedByAutoCompleteMethod();
|
||||
bool HasExternConstraints();
|
||||
bool HasThis();
|
||||
BfType* GetThisType();
|
||||
int GetThisIdx();
|
||||
bool HasExplicitThis();
|
||||
bool HasParamsArray();
|
||||
int GetStructRetIdx(bool forceStatic = false);
|
||||
|
|
|
@ -458,7 +458,8 @@ struct BfCodeGenOptions
|
|||
|
||||
enum BfParamKind : uint8
|
||||
{
|
||||
BfParamKind_Normal,
|
||||
BfParamKind_Normal,
|
||||
BfParamKind_ExplicitThis,
|
||||
BfParamKind_Params,
|
||||
BfParamKind_DelegateParam,
|
||||
BfParamKind_ImplicitCapture,
|
||||
|
@ -725,6 +726,7 @@ public:
|
|||
bool mIsOperator;
|
||||
bool mIsExtern;
|
||||
bool mIsNoDiscard;
|
||||
bool mHasExplicitThis;
|
||||
BfCommutableKind mCommutableKind;
|
||||
BfCheckedKind mCheckedKind;
|
||||
BfImportKind mImportKind;
|
||||
|
@ -751,6 +753,7 @@ public:
|
|||
mIsOperator = false;
|
||||
mIsExtern = false;
|
||||
mIsNoDiscard = false;
|
||||
mHasExplicitThis = false;
|
||||
mBody = NULL;
|
||||
mExplicitInterface = NULL;
|
||||
mReturnTypeRef = NULL;
|
||||
|
|
|
@ -26,6 +26,17 @@ namespace Tests
|
|||
int mA = 123;
|
||||
int mB = 234;
|
||||
|
||||
public this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(int a, int b)
|
||||
{
|
||||
mA = a;
|
||||
mB = b;
|
||||
}
|
||||
|
||||
public int GetA(float f)
|
||||
{
|
||||
return mA + mB*100 + (int)f;
|
||||
|
@ -35,6 +46,98 @@ namespace Tests
|
|||
{
|
||||
return mA + mB*100 + (int)f;
|
||||
}
|
||||
|
||||
public StructA GetA3(float f)
|
||||
{
|
||||
StructA sa;
|
||||
sa.mA = mA + 1000;
|
||||
sa.mB = mB + 2000 + (int)f;
|
||||
return sa;
|
||||
}
|
||||
|
||||
public StructA GetA4(float f) mut
|
||||
{
|
||||
StructA sa;
|
||||
sa.mA = mA + 1000;
|
||||
sa.mB = mB + 2000 + (int)f;
|
||||
return sa;
|
||||
}
|
||||
}
|
||||
|
||||
struct StructB
|
||||
{
|
||||
function StructB Func(StructB this, float f);
|
||||
function StructB FuncMut(mut StructB this, float f);
|
||||
|
||||
int mA = 123;
|
||||
int mB = 234;
|
||||
int mC = 345;
|
||||
|
||||
public this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(int a, int b, int c)
|
||||
{
|
||||
mA = a;
|
||||
mB = b;
|
||||
mC = c;
|
||||
}
|
||||
|
||||
public int GetA(float f)
|
||||
{
|
||||
return mA + mB*100 + (int)f;
|
||||
}
|
||||
|
||||
public int GetA2(float f) mut
|
||||
{
|
||||
return mA + mB*100 + (int)f;
|
||||
}
|
||||
|
||||
public StructB GetA3(float f)
|
||||
{
|
||||
StructB sb;
|
||||
sb.mA = mA + 1000;
|
||||
sb.mB = mB + 2000 + (int)f;
|
||||
sb.mC = mC + 3000;
|
||||
return sb;
|
||||
}
|
||||
|
||||
public StructB GetA4(float f) mut
|
||||
{
|
||||
StructB sb;
|
||||
sb.mA = mA + 1000;
|
||||
sb.mB = mB + 2000 + (int)f;
|
||||
sb.mC = mC + 3000;
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static void Test()
|
||||
{
|
||||
StructB sb = .();
|
||||
|
||||
Func func0 = => GetA3;
|
||||
Test.Assert(func0(sb, 100.0f) == .(1123, 2334, 3345));
|
||||
function StructB (StructB this, float f) func1 = => GetA3;
|
||||
|
||||
Test.Assert(func0 == func1);
|
||||
func0 = func1;
|
||||
|
||||
FuncMut func2 = => GetA4;
|
||||
Test.Assert(func2(sb, 100.0f) == .(1123, 2334, 3345));
|
||||
function StructB (mut StructB this, float f) func3 = => GetA4;
|
||||
}
|
||||
}
|
||||
|
||||
public static int UseFunc0<T>(function int (T this, float f) func, T a, float b)
|
||||
{
|
||||
return func(a, b);
|
||||
}
|
||||
|
||||
public static int UseFunc1<T>(function int (mut T this, float f) func, mut T a, float b)
|
||||
{
|
||||
return func(a, b);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -42,6 +145,7 @@ namespace Tests
|
|||
{
|
||||
ClassA ca = scope .();
|
||||
StructA sa = .();
|
||||
StructB sb = .();
|
||||
|
||||
function int (ClassA this, float f) func0 = => ca.GetA;
|
||||
function int (ClassA this, float) func0b = func0;
|
||||
|
@ -50,10 +154,34 @@ namespace Tests
|
|||
Test.Assert(func0(ca, 100.0f) == 223);
|
||||
|
||||
function int (StructA this, float f) func1 = => sa.GetA;
|
||||
var func1b = func1;
|
||||
Test.Assert(func1(sa, 100.0f) == 23623);
|
||||
Test.Assert(!
|
||||
[IgnoreErrors(true)]
|
||||
{
|
||||
func1b = => sb.GetA;
|
||||
true
|
||||
});
|
||||
|
||||
function int (mut StructA this, float f) func2 = => sa.GetA2;
|
||||
Test.Assert(func2(mut sa, 100.0f) == 23623);
|
||||
Test.Assert(func2(sa, 100.0f) == 23623);
|
||||
|
||||
function StructA (StructA this, float f) func3 = => sa.GetA3;
|
||||
Test.Assert(func3(sa, 100.0f) == .(1123, 2334));
|
||||
|
||||
function StructA (mut StructA this, float f) func4 = => sa.GetA4;
|
||||
Test.Assert(func4(sa, 100.0f) == .(1123, 2334));
|
||||
|
||||
StructB.Test();
|
||||
|
||||
Test.Assert(UseFunc0(func0, ca, 100.0f) == 223);
|
||||
Test.Assert(UseFunc0(func1, sa, 100.0f) == 23623);
|
||||
Test.Assert(!
|
||||
[IgnoreErrors(true)]
|
||||
{
|
||||
UseFunc0(func2, sa, 100.0f);
|
||||
true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue