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

Fixed autocomplete issues with nested calls

This commit is contained in:
Brian Fiete 2019-11-02 06:04:26 -07:00
parent e1656865bb
commit f10551e6f8
5 changed files with 70 additions and 41 deletions

View file

@ -1794,18 +1794,9 @@ void BfAutoComplete::CheckInvocation(BfAstNode* invocationNode, BfTokenNode* ope
if (doCapture) if (doCapture)
{ {
mIsCapturingMethodMatchInfo = true; mIsCapturingMethodMatchInfo = true;
if (mMethodMatchInfo == NULL)
mMethodMatchInfo = new MethodMatchInfo(); delete mMethodMatchInfo;
else mMethodMatchInfo = new MethodMatchInfo();
{
if (wasCapturingMethodMatchInfo)
{
// We're actually in an inner invocation now
delete mMethodMatchInfo;
mMethodMatchInfo = new MethodMatchInfo();
mMethodMatchInfo->mSrcPositions.Clear();
}
}
mMethodMatchInfo->mInvocationSrcIdx = target->GetSrcStart(); mMethodMatchInfo->mInvocationSrcIdx = target->GetSrcStart();
mMethodMatchInfo->mCurMethodInstance = mModule->mCurMethodInstance; mMethodMatchInfo->mCurMethodInstance = mModule->mCurMethodInstance;

View file

@ -140,8 +140,8 @@ public:
BfMethodInstance* mCurMethodInstance; BfMethodInstance* mCurMethodInstance;
Array<MethodMatchEntry> mInstanceList; Array<MethodMatchEntry> mInstanceList;
int mInvocationSrcIdx; int mInvocationSrcIdx;
int mBestIdx; int mBestIdx;
int mPrevBestIdx; int mPrevBestIdx;
bool mHadExactMatch; bool mHadExactMatch;
int mMostParamsMatched; int mMostParamsMatched;
Array<int> mSrcPositions; // start, commas, end Array<int> mSrcPositions; // start, commas, end
@ -152,8 +152,8 @@ public:
mInvocationSrcIdx = -1; mInvocationSrcIdx = -1;
mCurTypeInstance = NULL; mCurTypeInstance = NULL;
mCurMethodInstance = NULL; mCurMethodInstance = NULL;
mBestIdx = 0; mBestIdx = 0;
mPrevBestIdx = -1; mPrevBestIdx = -1;
mHadExactMatch = false; mHadExactMatch = false;
mMostParamsMatched = 0; mMostParamsMatched = 0;
} }

View file

@ -833,7 +833,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
RETURN_RESULTS; RETURN_RESULTS;
} }
BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType) BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute)
{ {
BfTypedValue argTypedValue = resolvedArg.mTypedValue; BfTypedValue argTypedValue = resolvedArg.mTypedValue;
if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0) if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0)
@ -909,9 +909,8 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
if ((resolvedArg.mExpectedType != checkType) || (resolvedArg.mExpectedType == NULL)) // Did our last check match for this type? if ((resolvedArg.mExpectedType != checkType) || (resolvedArg.mExpectedType == NULL)) // Did our last check match for this type?
{ {
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
SetAndRestoreValue<bool> prevIgnoreError(mModule->mIgnoreErrors, true); SetAndRestoreValue<bool> prevIgnoreError(mModule->mIgnoreErrors, true);
//SetAndRestoreValue<bool> prevNoBind(mModule->mCurMethodState->mNoBind, true);
bool prevNoBind = false; bool prevNoBind = false;
if (mModule->mCurMethodState != NULL) if (mModule->mCurMethodState != NULL)
{ {
@ -921,12 +920,28 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock(); auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock();
BfExprEvaluator exprEvaluator(mModule);
exprEvaluator.mExpectingType = checkType; BfExprEvaluator exprEvaluator(mModule);
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown); exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown | BfEvalExprFlags_NoAutoComplete);
if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0) if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr); exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr);
exprEvaluator.Evaluate(resolvedArg.mExpression);
auto expectType = checkType;
if (expectType != NULL)
{
if (expectType->IsRef())
{
auto refType = (BfRefType*)expectType;
expectType = refType->mElementType;
}
if (genericArgumentsSubstitute != NULL)
expectType = mModule->ResolveGenericType(expectType, *genericArgumentsSubstitute, true);
}
exprEvaluator.mExpectingType = expectType;
exprEvaluator.Evaluate(resolvedArg.mExpression);
argTypedValue = exprEvaluator.GetResult(); argTypedValue = exprEvaluator.GetResult();
if (mModule->mCurMethodState != NULL) if (mModule->mCurMethodState != NULL)
@ -1046,6 +1061,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
BfTypeVector* genericArgumentsSubstitute = NULL; BfTypeVector* genericArgumentsSubstitute = NULL;
int argIdx = 0; int argIdx = 0;
int argMatchCount = 0;
bool needInferGenericParams = (checkMethod->mGenericParams.size() != 0) && (!mHadExplicitGenericArguments); bool needInferGenericParams = (checkMethod->mGenericParams.size() != 0) && (!mHadExplicitGenericArguments);
int paramIdx = 0; int paramIdx = 0;
@ -1140,7 +1156,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
if (wantType->IsUnspecializedType()) if (wantType->IsUnspecializedType())
{ {
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType); BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType, genericArgumentsSubstitute);
if (!argTypedValue.IsUntypedValue()) if (!argTypedValue.IsUntypedValue())
{ {
auto type = argTypedValue.mType; auto type = argTypedValue.mType;
@ -1209,7 +1225,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
if (paramIdx >= (int) mArguments.size()) if (paramIdx >= (int) mArguments.size())
break; // No params break; // No params
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL); BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL, genericArgumentsSubstitute);
if (!argTypedValue) if (!argTypedValue)
goto NoMatch; goto NoMatch;
@ -1224,7 +1240,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType))) if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType)))
{ {
argIdx++; argIdx++;
paramIdx++; argMatchCount++;
paramIdx++;
break; break;
} }
@ -1238,12 +1255,13 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
while (argIdx < (int)mArguments.size()) while (argIdx < (int)mArguments.size())
{ {
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType); argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute);
if (!argTypedValue.HasType()) if (!argTypedValue.HasType())
goto NoMatch; goto NoMatch;
if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType)) if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType))
goto NoMatch; goto NoMatch;
argIdx++; argIdx++;
argMatchCount++;
} }
} }
else else
@ -1283,7 +1301,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
// We had a 'params' expression but this method didn't have a params slot in this parameter // We had a 'params' expression but this method didn't have a params slot in this parameter
goto NoMatch; goto NoMatch;
} }
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType); BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType, genericArgumentsSubstitute);
if (!argTypedValue.IsUntypedValue()) if (!argTypedValue.IsUntypedValue())
{ {
@ -1297,6 +1315,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
paramIdx++; paramIdx++;
argIdx++; argIdx++;
argMatchCount++;
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
{ {
@ -1430,21 +1449,30 @@ NoMatch:
if ((prevParamDiff >= 0) && ((paramDiff < 0) || (prevParamDiff < paramDiff))) if ((prevParamDiff >= 0) && ((paramDiff < 0) || (prevParamDiff < paramDiff)))
return false; return false;
// We search from the most specific type, so don't prefer a less specific type if (paramDiff == prevParamDiff)
if ((paramDiff == prevParamDiff) && (mBestMethodTypeInstance != typeInstance)) {
return false; if (argMatchCount < mBackupArgMatchCount)
return false;
else if (argMatchCount == mBackupArgMatchCount)
{
// We search from the most specific type, so don't prefer a less specific type
if (mBestMethodTypeInstance != typeInstance)
return false;
}
}
} }
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
{ {
auto methodMatchInfo = autoComplete->mMethodMatchInfo; auto methodMatchInfo = autoComplete->mMethodMatchInfo;
if ((methodMatchInfo->mPrevBestIdx == -1) && (!methodMatchInfo->mHadExactMatch)) if ((methodMatchInfo->mPrevBestIdx == -1) && (!methodMatchInfo->mHadExactMatch))
{ {
methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1; methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1;
} }
} }
mBackupMethodDef = checkMethod; mBackupMethodDef = checkMethod;
mBackupArgMatchCount = argMatchCount;
// Lie temporarily to store at least one candidate (but mBestMethodDef is still NULL) // Lie temporarily to store at least one candidate (but mBestMethodDef is still NULL)
hadMatch = true; hadMatch = true;
} }
@ -1950,6 +1978,8 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete()
{ {
if (mModule->mCompiler->mResolvePassData == NULL) if (mModule->mCompiler->mResolvePassData == NULL)
return NULL; return NULL;
if ((mBfEvalExprFlags & BfEvalExprFlags_NoAutoComplete) != 0)
return NULL;
// For local methods- only process autocomplete on capture phase // For local methods- only process autocomplete on capture phase
if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (!mModule->mCurMethodState->mClosureState->mCapturing)) if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (!mModule->mCurMethodState->mClosureState->mCapturing))
@ -7826,9 +7856,17 @@ void BfExprEvaluator::Visit(BfDefaultExpression* defaultExpr)
type = mModule->ResolveTypeRef(defaultExpr->mTypeRef); type = mModule->ResolveTypeRef(defaultExpr->mTypeRef);
if (type == NULL) if (type == NULL)
return; return;
BfDefaultValueKind defaultKind = BfDefaultValueKind_Const;
if (type->IsRef())
{
mModule->Fail(StrFormat("There is no default value for type '%s'", mModule->TypeToString(type).c_str()), defaultExpr);
defaultKind = BfDefaultValueKind_Addr;
}
mModule->ValidateAllocation(type, defaultExpr->mTypeRef); mModule->ValidateAllocation(type, defaultExpr->mTypeRef);
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = mModule->GetDefaultTypedValue(type); mResult = mModule->GetDefaultTypedValue(type, true, defaultKind);
} }
void BfExprEvaluator::Visit(BfUninitializedExpression* uninitialziedExpr) void BfExprEvaluator::Visit(BfUninitializedExpression* uninitialziedExpr)

View file

@ -142,6 +142,7 @@ public:
BfType* mSelfType; // Only when matching interfaces when 'Self' needs to refer back to the implementing type BfType* mSelfType; // Only when matching interfaces when 'Self' needs to refer back to the implementing type
BfMethodDef* mBackupMethodDef; BfMethodDef* mBackupMethodDef;
int mBackupArgMatchCount;
BfMethodDef* mBestMethodDef; BfMethodDef* mBestMethodDef;
BfTypeInstance* mBestMethodTypeInstance; BfTypeInstance* mBestMethodTypeInstance;
BfModuleMethodInstance mBestMethodInstance; BfModuleMethodInstance mBestMethodInstance;
@ -152,7 +153,7 @@ public:
Array<BfAmbiguousEntry> mAmbiguousEntries; Array<BfAmbiguousEntry> mAmbiguousEntries;
public: public:
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType); BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute);
bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue); bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue);
void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute, void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute,
BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute, BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute,

View file

@ -64,7 +64,8 @@ enum BfEvalExprFlags
BfEvalExprFlags_AllowRefExpr = 0x800, BfEvalExprFlags_AllowRefExpr = 0x800,
BfEvalExprFlags_AllowOutExpr = 0x1000, BfEvalExprFlags_AllowOutExpr = 0x1000,
BfEvalExprFlags_FieldInitializer = 0x2000, BfEvalExprFlags_FieldInitializer = 0x2000,
BfEvalExprFlags_VariableDeclaration = 0x4000 BfEvalExprFlags_VariableDeclaration = 0x4000,
BfEvalExprFlags_NoAutoComplete = 0x8000
}; };
enum BfCastFlags enum BfCastFlags
@ -1339,8 +1340,7 @@ public:
bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module
bool mWroteToLib; bool mWroteToLib;
bool mHadBuildError; bool mHadBuildError;
bool mHadBuildWarning; bool mHadBuildWarning;
bool mHadVarUsage;
bool mIgnoreErrors; bool mIgnoreErrors;
bool mIgnoreWarnings; bool mIgnoreWarnings;
bool mSetIllegalSrcPosition; bool mSetIllegalSrcPosition;
@ -1362,8 +1362,7 @@ public:
bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate); bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate);
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate); void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType); bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType);
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType); void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
void SetHadVarUsage();
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false); BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode); BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false); BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);